Meshing#
Spectral Meshes#
- class pystopt.mesh.SpectralConnectionBatch(from_group_index: int, node_indices: ndarray)[source]#
Bases:
UniqueConnectionBatch
Describes transporting elements on a spectral mesh.
- class pystopt.mesh.SpectralConnectionElementGroup(noutputs: int, batches: Tuple[UniqueConnectionBatch, ...])[source]#
Bases:
ABC
,UniqueConnectionElementGroup
Holds batches and spectral element information.
- dim#
- spat_shape#
Shape of the spatial grid.
- abstract to_spectral(actx: ArrayContext, ary: Any) Any [source]#
Transforms an array of shape
spat_shape
into its spectral coefficients.- Parameters:
ary – an array of type
arraycontext.ArrayContext.array_types
.- Returns:
an array of type
arraycontext.ArrayContext.array_types
.
- abstract from_spectral(actx: ArrayContext, ary: Any) Any [source]#
Transforms an array of spectral coefficients of shape (
nspec
, 1) back to its spatial representation.- Parameters:
ary – an array of type
arraycontext.ArrayContext.array_types
.- Returns:
an array of type
arraycontext.ArrayContext.array_types
.
- class pystopt.mesh.SpectralGridConnection(*args: Any, **kwargs: Any)[source]#
Bases:
DiscretizationConnection
Transports from the spectral grid to the spectral coefficients.
- groups#
A
tuple
ofSpectralConnectionElementGroup
s used for the connection to the spectral grid.
- pystopt.mesh.make_spectral_connections(discr: SpectralDiscretization, specgroups: Tuple[SpectralConnectionElementGroup, ...]) Tuple[DiscretizationConnection, DiscretizationConnection] [source]#
- pystopt.mesh.update_spectral_connections_for_factory(to_discr: SpectralDiscretization, from_discr: SpectralDiscretization, group_factory: meshmode.discretization.poly_element.ElementGroupFactory | None = None) Tuple[DiscretizationConnection, DiscretizationConnection] [source]#
- class pystopt.mesh.SpectralDiscretization(*args: Any, **kwargs: Any)[source]#
Bases:
Discretization
- specgroups#
A
list
ofSpectralConnectionElementGroup
that are used into_spectral_conn
andfrom_spectral_conn
.
- to_spectral_conn#
A
DiscretizationConnection
used to transport from the discretization DOFs to the spectral coefficients.
- from_spectral_conn#
A
DiscretizationConnection
used to transport from the spectral coefficients to the discretization DOFs.
- spectral_num_reference_derivative(ref_axes: Tuple[int, ...], ary: ArrayOrContainerT) ArrayOrContainerT [source]#
Takes derivatives by doing a roundtrip through spectral space.
- Parameters:
ref_axes – a
list
of axis indices, e.g. in 1D a list of[0, 0, 0]
would take the third derivative of ary.
Fourier (2D)#
- class pystopt.mesh.FourierConnectionBatch(from_group_index: int, node_indices: ndarray)[source]#
Bases:
SpectralConnectionBatch
- class pystopt.mesh.FourierConnectionElementGroup(noutputs: int, batches: Tuple[FourierConnectionBatch, ...], is_real: bool = False)[source]#
- class pystopt.mesh.FourierDiscretization(*args: Any, **kwargs: Any)[source]#
Bases:
SpectralDiscretization
- pystopt.mesh.make_fourier_discretization(actx: ArrayContext, nelements: int | Tuple[int, ...], *, curve_fn: Callable[[ndarray], ndarray], order: int, group_factory: meshmode.discretization.poly_element.ElementGroupFactory | None = None, mesh_unit_nodes: ndarray | None = None, use_spectral_derivative: bool = True, is_real: bool = False) Tuple[FourierDiscretization, ndarray] [source]#
- pystopt.mesh.fourier.find_modes_for_tolerance(actx: ArrayContext, curve_fn: Callable[[ndarray], ndarray], *, rtol: float = 1e-08, kmin: int = 1, step: int = 2) int [source]#
Finds a minimum number of nodes required to represent a given curve.
The implementation uses a simple iterative approach where for each \(k\), the geometry is interpolated to a fine grid and compared to the exact geometry provided by curve_fn. If the relative \(\ell^2\) error is sufficiently small, the algorithms is stopped.
- Parameters:
rtol – relative tolerance in error between the geometry approximated with a given \(k\) modes and the exact geometry.
kmin – starting number of modes.
step – increase in number of Fourier modes each time the error is too large.
- Returns:
an approximate number of Fourier modes required to represent the geometry described by curve_fn to the given relative tolerance rtol.
- pystopt.mesh.fourier.visualize_fourier_modes(fig_or_filename: str | bytes | PathLike[str] | IOBase, actx: ArrayContext, discr: FourierDiscretization, names_and_fields: Sequence[Tuple[str, Any]], *, markers: Sequence[str] | None = None, n_max_modes: float | None = None, semilogy: bool = True, overwrite: bool = False) None [source]#
Write out the Fourier modes of the given fields.
- Arg:
fig_or_filename: if a
matplotlib.figure.Figure
, then the fields are added to the current axis.- Parameters:
n_max_modes – number of modes to plot, regardless of the number of modes in the discr. If the discretization has a complex FFT, then the slice
-n_max_modes:n_max_modes
is plotted.semilogy – if True, the modes are plotted in a log scale.
Spherical Harmonics (3D)#
- class pystopt.mesh.SphericalHarmonicConnectionBatch(from_group_index: int, node_indices: ndarray, itheta: slice | None = None, theta: ndarray | None = None, phi: ndarray | None = None)[source]#
Bases:
SpectralConnectionBatch
- class pystopt.mesh.SphericalHarmonicConnectionElementGroup(batches: Sequence[SphericalHarmonicConnectionBatch], sh: Any, neltheta: int, nelphi: int, is_real: bool = True)[source]#
Bases:
SpectralConnectionElementGroup
- sh#
An instance of the
shtns
main data structure.
- class pystopt.mesh.SphericalHarmonicDiscretization(*args: Any, **kwargs: Any)[source]#
Bases:
SpectralDiscretization
- pystopt.mesh.make_spharm_discretization(actx: ArrayContext, nellon: int, nellat: int, *, surface_fn: Callable[[ndarray, ndarray], ndarray], order: int, lmax: int | None = None, mmax: int | None = None, polar_opt: float = 1e-10, stol: float = 1e-10, group_factory: meshmode.discretization.poly_element.ElementGroupFactory | None = None, mesh_unit_nodes: bool | ndarray = False, use_spectral_derivative: bool = True, _visualize: bool = False) Discretization [source]#
- Parameters:
nellon – (approximate) number of elements in the longitudinal direction with \(\phi \in [0, 2 \pi)\).
nellat – (approximate) number of elements in the latitudinal direction with \(\theta \in [0, \pi)\).
surface_fn – a
Callable
that takes \((\theta, \phi)\) and returns and array of shape(3, ...)
.order – desired order of the discretization.
mesh_unit_nodes – if this is True then the unit nodes of the provided group_factory are used. If False, equidistant nodes are unused. Otherwise, if a specific set of unit nodes is provided, it is used as is.
lmax – maximum spherical harmonic degree.
mmax – maximum spherical harmonic order.
polar_opt – tolerance for singularities near poles.
stol – if in debug mode, this tolerance is used to check how well the spherical harmonics approximate the surface by doing a roundtrip.
- pystopt.mesh.spharm.visualize_spharm_modes(fig_or_filename: str | bytes | PathLike[str] | IOBase, discr: SphericalHarmonicDiscretization, names_and_fields: Sequence[Tuple[str, DOFArrayT]], *, semilogy: bool = True, mode: str = 'imshow', component: str = 'abs', layout: str = 'horizontal', max_degree_or_order: int | None = None, overwrite: bool = False) None [source]#
Visualize spherical harmonic modes of a given set of arrays.
The mode can be one of:
"imshow"
, which plots all the modes usingimshow
."byorder"
, which uses line plots to plot \(f^m_{\cdot}\) for each order \(m\), i.e. a vertical slice throughimshow
."bydegree"
, which uses line plots to plot \(f^{\cdot}_n\) for each degree \(n\), i.e. a horizontal slice throughimshow
.
- Parameters:
mode – type of the plot to use in the visualization.
component – can be one of
"real"
,"imag"
or"abs"
, to visualize the real, imaginary or absolute value of each component.layout – can be one of
"horizontal"
or"vertical"
and is used to determine how to stack the multiple arrays in names_and_fields.max_degree_or_order – a cutoff used when mode is
"bydegree"
or"byorder"
to determine the maximum value to plot.
Generation#
- class pystopt.mesh.MeshGenerator(name: str | None = None, mesh_order: int | None = None, target_order: int | None = None, group_factory_cls: Type[meshmode.discretization.poly_element.ElementGroupFactory] = meshmode.discretization.poly_element.InterpolatoryQuadratureGroupFactory, mesh_unit_nodes: ndarray | None = None, use_default_mesh_unit_nodes: bool = True, use_spectral_derivative: bool = True, offset: ndarray | None = None, transform_matrix: float | ndarray | None = None)[source]#
Bases:
ABC
- dim#
- ambient_dim#
- name#
- mesh_order#
- target_order#
- group_factory_cls#
- mesh_unit_nodes#
- use_default_mesh_unit_nodes#
- use_spectral_derivative#
- offset#
- transform_matrix#
- pystopt.mesh.get_mesh_generator_from_name(name, **kwargs)[source]#
Construct a specific mesh generator from its name.
circle = build_mesh_from_name("circle", radius=np.pi) mesh = circle.get_mesh(resolution=32, mesh_order=4)
- Parameters:
name – name of one of the existing mesh generators.
kwargs – any additional arguments that can be passed to the generator.
- Returns:
- pystopt.mesh.generate_discretization(gen: Any, actx: ArrayContext, resolution: int | Tuple[int, ...]) Discretization [source]#
- pystopt.mesh.generate_discretization(gen: FourierGenerator, actx: ArrayContext, resolution: int | Tuple[int, ...]) Discretization
- pystopt.mesh.generate_discretization(gen: SPHARMGenerator, actx: ArrayContext, resolution: int | Tuple[int, ...]) Discretization
- class pystopt.mesh.FourierGenerator(name: str = '_fourier_unknown', mesh_order: int | None = None, target_order: int | None = None, group_factory_cls: Type[meshmode.discretization.poly_element.ElementGroupFactory] = meshmode.discretization.poly_element.InterpolatoryQuadratureGroupFactory, mesh_unit_nodes: ndarray | None = None, use_default_mesh_unit_nodes: bool = True, use_spectral_derivative: bool = True, offset: ndarray | None = None, transform_matrix: float | ndarray | None = None, curve: Callable[[ndarray], ndarray] | None = None, rfft: bool = False)[source]#
Bases:
MeshGenerator
- curve#
- class pystopt.mesh.SPHARMGenerator(name: str = '_spharm_unknown', mesh_order: int | None = None, target_order: int | None = None, group_factory_cls: Type[meshmode.discretization.poly_element.ElementGroupFactory] = meshmode.discretization.poly_element.InterpolatoryQuadratureGroupFactory, mesh_unit_nodes: ndarray | None = None, use_default_mesh_unit_nodes: bool = True, use_spectral_derivative: bool = True, offset: ndarray | None = None, transform_matrix: float | ndarray | None = None, surface: Callable[[ndarray, ndarray], ndarray] | None = None, lmax: int | None = None, mmax: int | None = None, polar_opt: float | None = 1e-10)[source]#
Bases:
MeshGenerator
- surface#
- lmax#
- mmax#
- polar_opt#
- pystopt.mesh.generation.ellipse_from_axes(t: ndarray, *, a: float = 2.0, b: float = 1.0) ndarray [source]#
Generate an ellipse parametrized by t given its axes.
\[\begin{split}\begin{bmatrix} r(t) \cos 2 \pi t \\ r(t) \sin 2 \pi t \end{bmatrix}, \quad \text{where } r(t) = \frac{a b}{\sqrt{(b \cos 2 \pi t)^2 + (a \sin 2 \pi t)^2}}\end{split}\]- Parameters:
a – major axis.
b – minor axis.
- pystopt.mesh.generation.fourier_ufo(t: ndarray, *, a: float = 3.0, b: float = 1.0, k: int = 4) ndarray [source]#
Generate a potato parametrized by t.
\[\begin{split}\begin{bmatrix} r(t) \cos 2 \pi t \\ r(t) \sin 2 \pi t \end{bmatrix}, \quad \text{where } r(t) = \sqrt{(b \cos 2 \pi t)^2 + (a \sin 2 \pi t)^2} + \cos^2 (2 \pi k t)\end{split}\]
- pystopt.mesh.generation.spharm_sphere(theta: ndarray, phi: ndarray, *, radius: float = 1.0) ndarray [source]#
Generate a sphere parametrized by \((\theta, \phi)\).
\[\begin{split}\begin{bmatrix} r \sin \theta \cos \phi \\ r \sin \theta \sin \phi \\ r \cos \theta \end{bmatrix}\end{split}\]- Parameters:
radius – sphere radius.
- pystopt.mesh.generation.spharm_spheroid(theta: ndarray, phi: ndarray, *, radius: float = 1.0, aspect_ratio: float = 2.0) ndarray [source]#
Generate a spheroid parametrized by \((\theta, \phi)\).
\[\begin{split}\begin{bmatrix} r \sin \theta \cos \phi \\ r \sin \theta \sin \phi \\ \alpha r \cos \theta \end{bmatrix}\end{split}\]where \(\alpha\) is the aspect ratio.
- Parameters:
radius – spheroid radius.
aspect_ratio – aspect ratio of the spheroid.
- pystopt.mesh.generation.spharm_ufo(theta: ndarray, phi: ndarray, *, k: float = 4.0, a: float = 2.0, b: float = 1.0, aspect_ratio: float = 0.5) ndarray [source]#
Generate a potato parametrized by \((\theta, \phi)\).
\[\begin{split}\begin{bmatrix} r(\theta) \sin \theta \cos \phi \\ r(\theta) \sin \theta \sin \phi \\ \alpha r(\theta) \cos \theta \end{bmatrix}, \quad \text{where } r(\theta) = \sqrt{(b \cos \theta)^2 + (a \sin \theta)^2} + \cos^2 (k \theta)\end{split}\]where \(\alpha\) is the aspect ratio.
- pystopt.mesh.generation.spharm_urchin(theta: ndarray, phi: ndarray, *, m: int = 2, n: int = 3, k: float = 3.0) ndarray [source]#
Generate a potato parametrized by \((\theta, \phi)\).
\[\begin{split}\begin{bmatrix} r(\theta, \phi) \sin \theta \cos \phi \\ r(\theta, \phi) \sin \theta \sin \phi \\ r(\theta, \phi) \cos \theta \end{bmatrix}, \quad \text{where } r(\theta, \phi) = 1 + \exp \big(-k Y^m_n(\theta, \phi)\big)\end{split}\]where \(Y^m_n\) is the spherical harmonic of order \(m\) and degree \(n\).
Reconstruction#
- pystopt.mesh.update_discr_mesh_from_nodes(actx: ArrayContext, discr: SpectralDiscretization, nodes: ndarray, *, keep_vertices: bool = True, atol: float | None = None) Mesh [source]#
- Parameters:
discr – previous
SpectralDiscretization
.nodes – a node array with the same number of DOFs as the one in discr.
keep_vertices – if True, the nodes are also used to reconstruct the vertices. As the discretization is discontinuous, vertices are averaged over all elements to obtain a unique value.
atol – a floating point tolerance used to check if the unit nodes of the discretization groups are the same as the unit nodes of the mesh element groups.
- Returns:
a
Mesh
with the same structure as discr.mesh, but with nodes interpolated from nodes.
- pystopt.mesh.update_discr_from_nodes(actx: ArrayContext, discr: SpectralDiscretization, nodes: ndarray, *, group_factory: meshmode.discretization.poly_element.ElementGroupFactory | None = None, keep_vertices: bool = False) SpectralDiscretization [source]#
- Parameters:
discr – previous
Discretization
.nodes – a node array with the same number of DOFs as the one in discr.
group_factory – a group factory used to construct the new discretization (should match the one used to construct discr in most cases). A default is provided if discr has a single group from
meshmode.discretization.poly_element
.
- Returns:
a
Discretization
with the same structure (i.e. number of groups, DOFs, etc) as discr, but with nodes interpolated from nodes.
- pystopt.mesh.update_discr_from_spectral(actx: ArrayContext, discr: SpectralDiscretization, xlm: ndarray, *, group_factory: meshmode.discretization.poly_element.ElementGroupFactory | None = None, keep_vertices: bool = False) SpectralDiscretization [source]#
- Parameters:
discr – a
SpectralDiscretization
.xlm – a
DOFArray
of spectral coefficients for the new nodes.group_factory – element group factory for the polynomial discretization.
- pystopt.mesh.merge_disjoint_spectral_discretizations(actx, discretizations)[source]#
- Parameters:
discretizations – a
list
ofSpectralDiscretization
s.- Returns:
A single
SpectralDiscretization
, where all the meshes have been merged usingmerge_disjoint_meshes()
.
- pystopt.mesh.generate_random_discr_array(actx: ArrayContext, generator: MeshGenerator, ndiscrs: int, *, resolution: int, radius: float, bbox: ndarray | None = None, origin: ndarray | None = None, gap: float | None = None, allowed_failures: int = 100, rng: Generator | None = None) SpectralDiscretization [source]#
Constructs a random and disjoint set of discretizations in bbox.
If a bounding box bbox is not provided, one is approximated from ndiscrs, radius and gap, such that approximately
ndiscrs**(1/dim)
discretizations can fit in each dimension.- Parameters:
ndiscrs – desired number of discretizations to generate.
bbox – bounding box in which to generate the discretizations. The bounding box an array of shape
(2, dim)
and is described in terms of its closest (to \(-\infty\)) and furthest (to \(+\infty\)) corners (i.e. lower left and upper right in 2d).allowed_failures – discretizations are generated randomly inside the bounding box and can overlap (based on radius). If an overlap occurs, another attempt is made. Then, allowed_failures controls how many attempts can be made before failing.
origin – origin of the bounding box, which is is closest point to \(-\infty\). If bbox is provided, this value is ignored.
radius – radius of the smallest ball that contains the unshifted geometry from generator.
gap – approximate gap (based on radius) between the discretization in the lattice.
resolution – passed on to
generate_discretization()
.
- pystopt.mesh.generate_uniform_discr_array(actx: ArrayContext, generator: MeshGenerator, shape: Tuple[int, ...], *, resolution: int, radius: float, origin: ndarray | None = None, mask: ndarray | None = None, gap: float | None = None) SpectralDiscretization [source]#
Constructs a merged uniform lattice of repeated discretizations from generator.
- Parameters:
shape – the number of repetitions of the discretization in each dimension.
origin – origin (or center) of the lattice.
mask – an array of size
np.prod(shape)
, which can be used to remove certain entries in the lattice.radius – radius of the smallest ball that contains the unshifted geometry from generator.
gap – approximate gap (based on radius) between the discretization in the lattice.
Connections#
- class pystopt.mesh.UniqueConnectionBatch(from_group_index: int, node_indices: ndarray)[source]#
Bases:
object
- nelements#
- nunit_nodes#
- node_indices#
An array of size
(nelements, nunit_nodes)
mapping the nodes in each element to a unique numbering.
- from_group_index#
An integer indicating to which element group in from_discr the data should be interpolated.
- class pystopt.mesh.UniqueConnectionInterpolationBatch(from_group_index: int, node_indices: ndarray, to_resampling_mat: Any, from_resampling_mat: Any)[source]#
Bases:
UniqueConnectionBatch
- to_resampling_mat#
- from_resampling_mat#
Both
to_resampling_mat
andfrom_resampling_mat
are frozen matrices used to interpolate the unit nodes in each element.
- class pystopt.mesh.UniqueConnectionElementGroup(noutputs: int, batches: Tuple[UniqueConnectionBatch, ...])[source]#
Bases:
object
- dim#
- nelements#
- noutputs#
Number of unique degrees of freedom in the group.
- batches#
A list of
UniqueConnectionBatch
s describing the transport to the unique degrees of freedom and back. It is assumed that theUniqueConnectionBatch.node_indices
from the batches fill allnoutputs
.
- class pystopt.mesh.UniqueDOFConnectionBase(*args: Any, **kwargs: Any)[source]#
Bases:
DiscretizationConnection
- class pystopt.mesh.ToUniqueDOFConnection(*args: Any, **kwargs: Any)[source]#
Bases:
UniqueDOFConnectionBase
- class pystopt.mesh.FromUniqueDOFConnection(*args: Any, **kwargs: Any)[source]#
Bases:
UniqueDOFConnectionBase
- pystopt.mesh.make_to_mesh_connection(actx: ArrayContext, discr: Discretization) DiscretizationConnection [source]#
- pystopt.mesh.make_from_mesh_connection(actx: ArrayContext, discr: Discretization) DiscretizationConnection [source]#
- pystopt.mesh.make_to_unique_mesh_vertex_connection(discr: Discretization) ToUniqueDOFConnection [source]#
- pystopt.mesh.make_from_unique_mesh_vertex_connection(discr: Discretization) FromUniqueDOFConnection [source]#
- pystopt.mesh.make_unique_mesh_vertex_connections(discr: Discretization) Tuple[ToUniqueDOFConnection, FromUniqueDOFConnection] [source]#
- pystopt.mesh.make_same_layout_connection(actx, to_discr, from_discr)[source]#
A version of
make_same_mesh_connection()
that only checks that the two discretizations have the same layout, not exactly the same underlying meshes.In this case, the layout is implied by the types of the mesh element groups and the number of elements in each group.
Stabilization#
- class pystopt.stabilization.PassiveStabilizerCallable(*args, **kwargs)[source]#
Bases:
Protocol
A callable used by
CustomPassiveStabilizer
that follows the signature ofmake_velocity_field()
.- __call__(actx: ArrayContext, places: pytential.GeometryCollection, velocity: ndarray, *, dofdesc: pytential.symbolic.primitives.DOFDescriptor) ndarray [source]#
Call self as a function.
- class pystopt.stabilization.PassiveStabilizer[source]#
Bases:
object
Passive stabilization of a discretization / mesh is done by constructing a tangential velocity field that improves the mesh quality.
- discr#
- make_velocity_field(actx: ArrayContext, places: pytential.GeometryCollection, velocity: ndarray, *, dofdesc: pytential.symbolic.primitives.DOFDescriptor) ndarray [source]#
This method is called by
__call__()
to construct the velocity field. It is not meant to be called directly, but as a way for subclasses to provide the basic functionality.- Returns:
a velocity field on dofdesc.
- __call__(places: pytential.GeometryCollection, velocity: ndarray, *, force_normalize: bool = False, scale_to_velocity: bool = False, dofdesc: pytential.symbolic.primitives.DOFDescriptorLike | None = None) ndarray [source]#
- Parameters:
velocity – a given initial velocity field. Its tangential components can be used as an initial guess for passive stabilization.
force_tangential – if True, projects the velocity field obtained from
make_velocity_field()
to the tangent space.force_normalize – if True, normalizes the velocity field obtained from
make_velocity_field()
in the standard \(\ell^\infty\) norm.sale_to_velocity – if True scales the velocity field obtained from
make_velocity_field()
to have the same \(\ell^\infty\) norm as velocity.
- Returns:
a tangential velocity field on dofdesc.
- class pystopt.stabilization.CustomPassiveStabilizer(func: PassiveStabilizerCallable)[source]#
Bases:
PassiveStabilizer
- __init__(func: PassiveStabilizerCallable)[source]#
- pystopt.stabilization.make_stabilizer_from_name(name: str, **kwargs: Any) PassiveStabilizer [source]#
Build passive or active stabilizers.
- Parameters:
name – a string name for the stabilizer.
kwargs – a
dict
of arguments to pass to the constructor.
- class pystopt.stabilization.Loewenberg1996Stabilizer(*, vlambda: float = 1.0, alpha: float | None = None, beta: float | None = None, gamma: float | None = None)[source]#
Bases:
PassiveStabilizer
Implements the tangential forcing from [Loewenberg1996].
The tangential velocity field is given by
\[\mathbf{w}_i \triangleq N^{\gamma} \frac{1}{1 + \lambda} \sum_{j} \left\{ 1 + \alpha \frac{\|\mathbf{x}_i - \mathbf{x}_j\|}{h(\mathbf{x}_j)} + \beta \kappa_j^{\gamma} \right\} \Delta S_j (\mathbf{x}_i - \mathbf{x}_j),\]where \(N\) is the number of vertices in the geometry, \(\lambda\) is the viscosity ratio and \(\Delta S_j\) is the dual area around the vertex \(\mathbf{x}_j\). In [Loewenberg1996], the authors take \(\gamma = 3/2, \alpha = 4\) and \(\beta = 1\).
- alpha#
- beta#
- gamma#
- __init__(*, vlambda: float = 1.0, alpha: float | None = None, beta: float | None = None, gamma: float | None = None) None [source]#
- __call__(places: pytential.GeometryCollection, velocity: ndarray, *, force_normalize: bool = False, scale_to_velocity: bool = False, dofdesc: pytential.symbolic.primitives.DOFDescriptorLike | None = None) ndarray #
- Parameters:
velocity – a given initial velocity field. Its tangential components can be used as an initial guess for passive stabilization.
force_tangential – if True, projects the velocity field obtained from
make_velocity_field()
to the tangent space.force_normalize – if True, normalizes the velocity field obtained from
make_velocity_field()
in the standard \(\ell^\infty\) norm.sale_to_velocity – if True scales the velocity field obtained from
make_velocity_field()
to have the same \(\ell^\infty\) norm as velocity.
- Returns:
a tangential velocity field on dofdesc.
- class pystopt.stabilization.Loewenberg2001Stabilizer(*, alpha: float | None = None)[source]#
Bases:
PassiveStabilizer
Implements the tangential forcing from [loewenberg2001].
[loewenberg2001]V. Cristini, J. Bławzdziewicz, M. Loewenberg, An Adaptive Mesh Algorithm for Evolving Surfaces: Simulations of Drop Breakup and Coalescence, Journal of Computational Physics, Vol. 168, pp. 445–463, 2001, DOI.
- alpha#
- class pystopt.stabilization.Kropinski2001Stabilizer(*, alpha: float | None = None, beta: float | None = None)[source]#
Bases:
PassiveStabilizer
Implements the tangential forcing from [Kropinski2001].
The class implements a combination of the forcing \(\mathbf{T}_1\) from Equation 20, which seeks to maintain the arclength of each element, and the forcing \(\mathbf{T}_2\) from Equation 21, which seeks to cluster points in regions of higher curvature. The final forcing is
\[\mathbf{w} = \alpha \mathbf{T}_1 + \beta \mathbf{T}_2,\]where the coefficients are given by
alpha
andbeta
.[Kropinski2001]M. C. A. Kropinski, An Efficient Numerical Method for Studying Interfacial Motion in Two-Dimensional Creeping Flows, Journal of Computational Physics, Vol. 171, pp. 479–508, 2001, DOI.
- alpha#
- beta#
- __call__(places: pytential.GeometryCollection, velocity: ndarray, *, force_normalize: bool = False, scale_to_velocity: bool = False, dofdesc: pytential.symbolic.primitives.DOFDescriptorLike | None = None) ndarray #
- Parameters:
velocity – a given initial velocity field. Its tangential components can be used as an initial guess for passive stabilization.
force_tangential – if True, projects the velocity field obtained from
make_velocity_field()
to the tangent space.force_normalize – if True, normalizes the velocity field obtained from
make_velocity_field()
in the standard \(\ell^\infty\) norm.sale_to_velocity – if True scales the velocity field obtained from
make_velocity_field()
to have the same \(\ell^\infty\) norm as velocity.
- Returns:
a tangential velocity field on dofdesc.
- class pystopt.stabilization.Veerapaneni2011Stabilizer(*, optimized: bool = False, nmax: int | None = None, alpha: Callable[[ArrayContext, SpectralConnectionElementGroup], Any] | None = None)[source]#
Bases:
PassiveStabilizer
Implements the tangential forcing from [Veerapaneni2011].
The forcing is given as the gradient of the functional
\[E[\mathbf{x}] = \frac{1}{2} \sum_{n, m} (1 - \alpha^m_n)^2 \langle \mathbf{x}, Y^m_n \rangle^2,\]where \(Y^m_n\) are the spherical harmonics and \(\langle \cdot, \cdot \rangle\) is the inner product on the unit sphere. Unlike [Veerapaneni2011], we use \(1 - \alpha^m_n\), where \(\alpha^m_n\) are the coefficients of a corresponding filter operator.
- alpha#
- __init__(*, optimized: bool = False, nmax: int | None = None, alpha: Callable[[ArrayContext, SpectralConnectionElementGroup], Any] | None = None) None [source]#
- Parameters:
nmax – maximum spherical harmonic degree. If no attenuation alpha is given, then this is used in the default ideal filter, otherwise it is ignored.
alpha – a callable used to obtain the attenuation factor. By default, an ideal filter in the degree \(n\) of the Spherical Harmonics is used.