Geodesic elliptic material vortices
Background
The following functions implement an LCS methodology developed in the following papers:
Our implementation here follows conceptually Karrasch, Huhn, and Haller, 2015, and is described in detail in the preprint TBD. Depending on the indefinite metric tensor field used, the functions below yield the following types of coherent structures:
- black-hole/Lagrangian coherent vortices (Haller & Beron-Vera, 2012)
- elliptic objective Eulerian coherent structures (OECSs) (Serra & Haller, 2016)
- material diffusive transport barriers (Haller, Karrasch, and Kogelbauer, 2018)
The general procedure is the following. Assume $T$ is the symmetric tensor field of interest, say, (i) the Cauchy-Green strain tensor field $C$, (ii) the rate-of-strain tensor field $S$, or (iii) the averaged diffusion-weighted Cauchy-Green tensor field $\bar{C}_D$; cf. the references above. Denote by $0<\lambda_1\leq\lambda_2$ the eigenvalue and by $\xi_1$ and $\xi_2$ the corresponding eigenvector fields of $T$. Then the direction fields of interest are given by
\[\eta_{\lambda}^{\pm} := \sqrt{\frac{\lambda_2 - \lambda}{\lambda_2-\lambda_1}}\xi_1 \pm \sqrt{\frac{\lambda - \lambda_1}{\lambda_2-\lambda_1}}\xi_2.\]
Tensor singularities are defined as points at which $\lambda_2=\lambda_1$, i.e., at which the two characteristic directions $\xi_1$ and $\xi_2$ are not well-defined. As described and exploited in Karrasch et al., 2015, non-negligible tensor singularities express themselves by an angle gap when tracking (the angle of) tensor eigenvector fields along closed paths surrounding the singularity. Our approach here avoids computing singularities directly, but rather computes the index for each grid cell and then combines nearby singularities, i.e., adds non-vanishing indices of nearby grid cells.
In summary, the implementation consists of the following steps:
- compute the index for each grid cell and combine nearby singular grid cells to "singularity candidates";
- look for elliptic singularity candidates (and potentially isolated wedge pairs);
- place an eastwards oriented Poincaré section at the pair center;
- for each point on the discretized Poincaré section, scan through the given parameter interval such that the corresponding η-orbit closes at that point;
- if desired: for each Poincaré section, take the outermost closed orbit as the coherent vortex barrier (if there exist any).
Function documentation
Meta-functions
The fully automated high-level functions are:
CoherentStructures.ellipticLCS
— FunctionellipticLCS(T::AbstractMatrix, xspan, yspan, p; kwargs...)
Computes elliptic LCSs as null-geodesics of the Lorentzian metric tensor field given by shifted versions of T
on the 2D computational grid spanned by xspan
and yspan
. p
is a LCSParameters
-type container of computational parameters. Returns a list of EllipticBarrier
-type objects.
Keyword arguments
outermost=true
: only the outermost barriers, i.e., the vortex boundaries are returned, otherwise all detected transport barrieres;verbose=true
: show intermediate computational information;unique_vortices=true
: filter out vortices enclosed by other vortices;suggested_centers=[]
: suggest vortex centers (of typeSingularity
);debug=false
: whether to use the debug mode, which avoids parallelization for more precise error messages;singularity_predicate = nothing
: provide an optional callback to reject certain singularity candidates.
CoherentStructures.constrainedLCS
— FunctionconstrainedLCS(T::AbstractMatrix, xspan, yspan, p; kwargs...)
constrainedLCS(T::AxisArray, p; kwargs...)
Computes constrained transport barriers as closed orbits of the transport vector field on the 2D computational grid spanned by xspan
and yspan
. p
is an LCSParameters
-type container of computational parameters. Returns a list of EllipticBarrier
-type objects.
The keyword arguments and their default values are:
outermost=true
: only the outermost barriers, i.e., the vortex boundaries are returned, otherwise all detected transport barrieres;verbose=true
: show intermediate computational informationdebug=false
: whether to use the debug mode, which avoids parallelization for more precise error messages.
CoherentStructures.materialbarriers
— Functionmaterialbarriers(odefun, xspan, yspan, tspan, lcsp;
on_torus=false, δ=1e-6, tolerance=1e-6, p=SciMLBase.NullParameters(), kwargs...)
Calculate material barriers to diffusive and stochastic transport on the material domain spanned by xspan
and yspan
, where the averaged weighted CG tensor is computed at the time instance contained in tspan
. The argument lcsp
must be of type LCSParameters
, and contains parameters used for the elliptic vortex detection.
One of their arguments is a list of parameters used in the LCS detection. This list is combined in a data type called LCSParameters
. The output is a list of EllipticBarrier
s and a list of Singularity
s. There is an option to retrieve all closed barriers (outermost=false
), in contrast to extracting only the outermost vortex boundaries (outermost=true
), which is more efficient.
The meta-functions consist of two steps: first, the index theory-based determination of where to search for closed orbits,, cf. Index theory-based placement of Poincaré sections; second, the closed orbit computation, cf. Closed orbit detection.
Specific types
These are the specifically introduced types for elliptic LCS computations.
CoherentStructures.LCSParameters
— TypeContainer for parameters used in elliptic LCS computations.
Fields
boxradius
: "radius" of localization square for closed orbit detectionindexradius=1e-1boxradius
: radius for singularity type detectionmerge_heuristics
: a list ofMergeHeuristic
s for combining singularitiesn_seeds=100
: number of seed points on the Poincaré sectionpmin=0.7
: lower bound on the parameter in the $\eta$-fieldpmax=2.0
: upper bound on the parameter in the $\eta$-fieldrdist=1e-4boxradius
: required return distances for closed orbitstolerance_ode=1e-8boxradius
: absolute and relative tolerance in orbit integrationmaxiters_ode::Int=2000
: maximum number of integration stepsmax_orbit_length=8boxradius
: maximum length of orbit lengthmaxiters_bisection::Int=20
: maximum steps in bisection procedureonly_enclosing::Bool=true
: whether the orbit must enclose the starting point of the Poincaré sectiononly_smooth::Bool=true
: whether or not to reject orbits with "corners".only_uniform::Bool=true
: whether or not to reject orbits that are not uniform
Example
p = LCSParameters(2.5)
LCSParameters(2.5, 0.25, true, 100, 0.7, 2.0, 0.00025, 2.5e-8, 1000, 20.0, 30)
CoherentStructures.EllipticBarrier
— TypeThis is a container for coherent vortex boundaries. An object barrier
of type EllipticBarrier
can be easily plotted by plot(barrier.curve)
, or plot!([figure, ]barrier.curve)
if it is to be overlaid over an existing plot.
Fields
curve
: a vector of tuples, contains the coordinates of coherent vortex boundary points;core
: location of the vortex core;p
: contains the parameter value of the direction field $\eta_{\lambda}^{\pm}$, for which thecurve
is a closed orbit;s
: aBool
value, which encodes the sign in the formula of the direction field $\eta_{\lambda}^{\pm}$ via the formula $(-1)^s$.
CoherentStructures.EllipticVortex
— TypeThis is a container for an elliptic vortex, as represented by the vortex's center
and a list barriers
of all computed EllipticBarrier
s.
Fields
center
: location of the vortex center;barriers
: vector ofEllipticBarrier
s.
CoherentStructures.MergeHeuristic
— Typeabstract type MergeHeuristic
Abstract supertype for merge heuristics, which currently include Combine
, Combine20
, Combine20Aggressive
, Combine31
.
Another one is Singularity
, which comes along with some convenience functions.
CoherentStructures.Singularity
— TypeContainer type for critical points of vector fields or singularities of line fields.
Fields
coords::SVector{2}
: coordinates of the singularityindex::Rational
: index of the singularity
CoherentStructures.getcoords
— Functiongetcoords(singularities)
Extracts the coordinates of singularities
, a vector of Singularity
s. Returns a vector of SVector
s.
CoherentStructures.getindices
— Functiongetindices(singularities)
Extracts the indices of singularities
, a vector of Singularity
s.
Index theory-based placement of Poincaré sections
This is performed by singularity_detection
for line fields (such as eigenvector fields of symmetric positive-definite tensor fields) and by critical_point_detection
for classic vector fields.
CoherentStructures.singularity_detection
— Functionsingularity_detection(T, xspan, yspan, combine_distance; merge_heuristics=(Combine20(),)) -> Vector{Singularity}
singularity_detection(T::AxisArray, combine_distance; merge_heuristics=(Combine20(),)) -> Vector{Singularity}
Calculate line-field singularities of the first eigenvector of T
by taking a discrete differential-geometric approach. Singularities are calculated on each cell. Singularities with distance less or equal to combine_distance
are combined by averaging the coordinates and adding the respective indices. The heuristics listed in merge_heuristics
are used to merge singularities, cf. LCSParameters
.
Return a vector of Singularity
s.
CoherentStructures.critical_point_detection
— Functioncritical_point_detection(vs, xspan, yspan, combine_distance, dist=S1Dist();
merge_heuristics=(combine_20,)) -> Vector{Singularity}
critical_point_detection(vs::AxisArray, combine_distance, dist=S1Dist();
merge_heuristics=(combine_20,)) -> Vector{Singularity}
Computes critical points of a vector/line field vs
, potentially given as an AxisArray
. Critical points with distance less or equal to combine_distance
are combined by averaging the coordinates and adding the respective indices. The argument dist
is a signed distance function for angles: choose S1Dist()
for vector fields, and P1Dist()
for line fields; cf. compute_singularities
. MergeHeuristic
s listed in merge_heuristics
, cf. LCSParameters
, are applied to combine singularities.
Returns a vector of Singularity
s.
This function takes three steps. The first two are:
CoherentStructures.compute_singularities
— Functioncompute_singularities(v, xspan, yspan, dist=S1Dist()) -> Vector{Singularity}
compute_singularities(v::AxisArray, dist=S1Dist()) -> Vector{Singularity}
Computes critical points and singularities of vector and line fields v
, respectively. The argument dist
is a signed distance function for angles. Choose s1dist
(default) for vector fields, and p1dist
for line fields.
CoherentStructures.Combine
— TypeCombine(dist)(sing_coordinates) -> Vector{Singularity}
This function does the equivalent of: build a graph where singularities are vertices, and two vertices share an edge iff the coordinates of the corresponding vertices (given by sing_coordinates
) have a distance leq dist
. Find all connected components of this graph, and return a list of their mean coordinate and sum of sing_indices
.
The third step is a postprocessing step, in which detected singularities are merged according to different heuristics.
CoherentStructures.Combine20
— TypeCombine20()(singularities)
Determines singularities which are mutually closest neighbors and combines them as one, while adding their indices.
CoherentStructures.Combine31
— TypeCombine31()(singularities)
Takes the list of singularities in singularities
and combines them so that any -1/2 singularity whose three nearest neighbors are 1/2 singularities becomes an elliptic region, provided that the -1/2 singularity is in the triangle spanned by the wedges. This configuration is common for OECS, applying to material barriers on a large turbulent example yielded only about an additional 1% material barriers.
CoherentStructures.Combine20Aggressive
— TypeCombine20Aggressive()(singularities)
A heuristic for combining singularities which is likely to have a lot of false positives.
The function compute_singularities
requires one of two signed distance functions for angles. These are S1Dist
for vector fields, and P1Dist
for line fields.
CoherentStructures.S1Dist
— TypeS1Dist()(α, β)
Computes the signed length of the angle of the shortest circle segment going from angle β
to angle α
, as computed on the full circle.
Examples
julia> dist = S1Dist();
julia> dist(π/2, 0)
1.5707963267948966
julia> dist(0, π/2)
-1.5707963267948966
CoherentStructures.P1Dist
— TypeP1Dist()(α, β)
Computes the signed length of the angle of the shortest circle segment going from angle β
to angle α [± π]
, as computed on the half circle.
Examples
julia> dist = P1Dist();
julia> dist(π, 0)
0.0
From all virtual/merged singularities those with a suitable index are selected. Around each elliptic singularity the tensor field is localized and passed on for closed orbit detection.
Closed orbit detection
CoherentStructures.compute_returning_orbit
— Functioncompute_returning_orbit(vf, seed::SVector{2}, save::Bool=false, maxiters=2000, tolerance=1e-8, max_orbit_length=20.0)
Computes returning orbits under the velocity field vf
, originating from seed
. The optional argument save
controls whether intermediate locations of the returning orbit should be saved. Returns a tuple of orbit
and statuscode
(0
for success, 1
for maxiters
reached, 2
for out of bounds error, 3 for other error).
CoherentStructures.compute_closed_orbits
— Functioncompute_closed_orbits(ps, ηfield, cache; kwargs...)
Compute the (outermost) closed orbit for a given Poincaré section ps
, a vector field constructor ηfield
, and an LCScache cache
.
Keyword arguments
rev=true
: determines whether closed orbits are sought from the outside inwards (true
) or from the inside outwards (false
);p::LCSParameters
: an object holding the parameters for the LCS computation; seeLCSParameters
.
Convenience functions
First of all, Singularity
, EllipticBarrier
and EllipticVortex
objects can be passed as initial conditions to the flow
function, which returns a (time-resolved) vector of corresponding objects. Moreover, we have advection with adaptive point insertion (known in oceanography as "Dritschel advection") and some more convenience functions.
CoherentStructures.FlowGrowParams
— Typestruct FlowGrowParams
Container for parameters used in point-inserting flow computations; see flowgrow
.
Fields
maxcurv=0.3
: maximal bound on the absolute value of the discrete curvature;mindist=0.1
: least acceptable distance between two consecutive points;maxdist=1.0
: maximal acceptable distance between two consecutive points.
CoherentStructures.flowgrow
— Functionflowgrow(odefun, curve, tspan, params; kwargs...)
Advect curve
with point insertion by the ODE with right hand side odefun
over the time interval tspan
, evaluated at each element of tspan
. This method is known in oceanography as Dritschel's method. The point insertion method is controlled by the parameters stored in params::FlowGrowParams
; cf. FlowGrowParams
. Keyword arguments kwargs
are passed to the flow
function.
Convenience methods for EllipticBarrier
and [EllipticVortex
] objects in place of curve
exist. In this case, the method returns a vector of length length(tspan)
of corresponding objects.
CoherentStructures.area
— Functionarea(polygon)
Compute the enclosed area of polygon
, which can be of type Vector{SVector{2}}
, EllipticBarrier
or EllipticVortex
. In the latter case, the enclosed area of the outermost (i.e., the last EllipticBarrier
in the barriers
field) is computed.
CoherentStructures.centroid
— Functioncentroid(polygon)
Compute the center (of mass) of polygon
, which can be of type Vector{SVector{2}}
, EllipticBarrier
or EllipticVortex
. In the latter case, the center of the outermost (i.e., the last EllipticBarrier
in the barriers
field) is computed.
CoherentStructures.clockwise
— Functionclockwise(barrier, velocity, t0; p=nothing) -> Bool
clockwise(vortex, velocity, t0; p=nothing) -> Bool
Determine whether a given vortex
or barrier
is instantaneously (at t0
) rotating clockwise due to the velocity field velocity
. The keyword argument p
is a parameter passed to velocity
, for instance the interpolant of the interpolating velocity field interp_rhs
.
Clockwise-rotating vortices correspond to anticyclones in the Northern hemisphere and to cyclones in the Southern hemisphere.
Base.extrema
— MethodBase.extrema(barrier) -> (LL, UR)
Base.extrema(vortex) -> (LL, UR)
Compute an axis-aligned, rectangular bounding box around an EllipticVortex
or an EllipticBarrier
. Returns the coordinates of the lower left corner LL
and of the upper right corner UR
.
CoherentStructures.isinside
— Functionisinside(p, polygon)
Determine whether the point p
(or Singularity
) lies inside polygon
, which can be of type Vector{SVector{2}}
, EllipticBarrier
or EllipticVortex
. In the latter case, the outermost (i.e., the last EllipticBarrier
in the barriers
field) is used.