Simulation Setup

Contents

Simulation Setup#

Base Geometry State#

pystopt.simulation.as_state_container(cls: type) type[source]#

A decorator for subclasses of GeometryState.

It transforms the subclass into a dataclass with the minimum required arithmetic operations from arraycontext.

pystopt.simulation.reconstruct_discretization(actx: ArrayContext, orig_discr: Discretization, xlm: ndarray, *, keep_vertices: bool = False) Discretization[source]#

Reconstruct the geometry pointed at by dofdesc using the nodes from xlm.

The xlm variable must match the number of nodes or the spectral representation on the geometry described by dofdesc.

Parameters:

keep_vertices – if True, the vertices are reconstructed by interpolating from the nodes xlm. Otherwise, they are set to None and assumed to be unused in the new discretization.

Returns:

a new Discretization.

class pystopt.simulation.GeometryWrangler(places: pytential.GeometryCollection, dofdesc: pytential.symbolic.primitives.DOFDescriptor, is_spectral: bool)[source]#

Bases: object

ambient_dim#
places#

A GeometryCollection that contains all the geometries in the simulation. These are just used to describe the connectivity and initial state of the geometry.

dofdesc#

A DOFDescriptor for the discretization being evolved, optimized or otherwise modified.

is_spectral#

If True, the state is represented by the spectral coefficients of the geometry coordinates. Otherwise, the physical coordinates are used.

get_initial_state(actx: ArrayContext) GeometryState[source]#
Returns:

a GeometryState using the nodes of dofdesc as found in places.

to_state_type(ary: ArrayContainerT) ArrayContainerT[source]#

Projects ary to match the type of data in the GeometryState handled by this wrangler.

If is_spectral is True, ary is expected to be a DOFArray which will be projected to its spectral coefficients. Otherwise, it is returned as is.

from_state_type(ary: ArrayContainerT) ArrayContainerT[source]#

Projects ary from the type of data in the GeometryState handled by this wrangler back to physical space.

If is_spectral is True, ary is expected to be a SpectralDOFArray of spectral coefficients, which will be projected to physical space. Otherwise, it is returned as is.

class pystopt.simulation.GeometryState[source]#

Bases: object

x#

A set of nodes (or spectral coefficients for the same nodes) that describe the geometry from wrangler.

wrangler#
get_geometry_collection() pytential.GeometryCollection[source]#

Updates the discretization from GeometryWrangler.places using the nodes from x using reconstruct_discretization().

Returns:

a new GeometryCollection containing the updated discretization, while preserving all other geometries in the collection.

class pystopt.simulation.make_geometry_wrangler(places: pytential.GeometryCollection, *, dofdesc: pytential.symbolic.primitives.DOFDescriptorLike | None = None, is_spectral: bool = True)[source]#

Bases:

class pystopt.simulation.MeshQualityHistoryCallback(norm: ~typing.Callable[[~typing.Any], float] | None, memory: ~typing.List[int] = <factory>, timestamp: ~typing.List[int] = <factory>, volume: ~typing.List[float] = <factory>, area: ~typing.List[float] = <factory>, h_max: ~typing.List[float] = <factory>, h_avg: ~typing.List[float] = <factory>, h_std: ~typing.List[float] = <factory>)[source]#

Bases: PerformanceHistoryCallback

volume#

Total volume of the closed surfaces in the geometry.

area#

Total surface area of the closed surfaces in the geometry.

h_max#

Maximum element area.

h_avg#

Mean element area.

h_std#

Element area standard deviation.

Unsteady Evolution#

class pystopt.simulation.unsteady.GeometryEvolutionState[source]#

Bases: GeometryState

t#

Time at which the current state is computed. This is expected to be advanced by the time integrator together with the geometry. Note that, due to floating point operations, the time integrator \(t\) and this one may start diverging.

get_velocity_field()[source]#
get_tangential_forcing()[source]#
class pystopt.simulation.unsteady.GeometryEvolutionWrangler(places: pytential.GeometryCollection, dofdesc: pytential.symbolic.primitives.DOFDescriptor, is_spectral: bool, evolution: StokesEvolutionOperator, context: Dict[str, Any], stabilizer_name: str, stabilizer_arguments: Dict[str, Any], filter_type: FilterType, filter_arguments: Dict[str, Any])[source]#

Bases: GeometryWrangler

evolution#

A StokesEvolutionOperator that symbolically describes the right-hand side terms.

stabilizer_name#

The name of the stabilizer, see make_stabilizer_from_name().

stabilizer_arguments#

Passed to make_stabilizer_from_name().

filter_type#
filter_arguments#
apply_filter(actx: ArrayContext, places: pytential.GeometryCollection, ary: ArrayOrContainerT, *, force_spectral: bool | None = None) ArrayOrContainerT[source]#

Apply a filter to the given array ary.

By default, this function calls apply_filter_by_type() using filter_type and filter_arguments.

get_stabilizer()[source]#
Returns:

a PassiveStabilizer described by stabilizer_name. This can be used to compute a tangential velocity field. Note that a tangential forcing is only used if force_tangential_velocity is set on evolution.

evolution_source_term(t: float, state: GeometryEvolutionState) GeometryEvolutionState[source]#
estimate_time_step(t: float, state: GeometryEvolutionState) float | None[source]#
class pystopt.simulation.unsteady.StokesEvolutionState[source]#

Bases: StokesGeometryState, GeometryEvolutionState

class pystopt.simulation.unsteady.StokesEvolutionWrangler(places: pytential.GeometryCollection, dofdesc: pytential.symbolic.primitives.DOFDescriptor, is_spectral: bool, evolution: StokesEvolutionOperator, context: Dict[str, Any], stabilizer_name: str, stabilizer_arguments: Dict[str, Any], filter_type: FilterType, filter_arguments: Dict[str, Any], op: TwoPhaseStokesRepresentation, lambdas: Dict[str, float], gmres_arguments: Dict[str, Any])[source]#

Bases: StokesGeometryWrangler, GeometryEvolutionWrangler

pystopt.simulation.unsteady.quasi_evolve_stokes(actx: ArrayContext, wrangler: GeometryEvolutionWrangler, step: TimeWrangler, *, tmax: float | None = None, maxit: float | None = None, callback: CallbackManager | None = None, verbose: bool = True) GeometryEvolutionState[source]#
class pystopt.simulation.unsteady.AdjointGeometryEvolutionWrangler(forward: GeometryEvolutionWrangler)[source]#

Bases: object

forward#

A StokesEvolutionWrangler, whose properties and attributes are forwarded through this class.

cost#
cost_final#
ad#

An adjoint operator constructed from the forward operator and cost. This operator is used to compute the adjoint state at each time step.

get_sym_shape_gradient() pytential.symbolic.primitives.var[source]#
evaluate_shape_gradient(actx: ArrayContext, places: pytential.GeometryCollection, *, context: Dict[str, Any] | None = None) ndarray[source]#
get_sym_shape_gradient_final() pytential.symbolic.primitives.var[source]#
evaluate_shape_gradient_final(actx: ArrayContext, state: GeometryEvolutionState, *, context: Dict[str, Any] | None = None) ndarray[source]#
get_initial_state(actx: ArrayContext, state: GeometryEvolutionState) AdjointGeometryEvolutionState[source]#
evolution_source_term(t: float, state: GeometryEvolutionState, adjoint: AdjointGeometryEvolutionState) AdjointGeometryEvolutionState[source]#
class pystopt.simulation.unsteady.AdjointGeometryEvolutionState[source]#

Bases: object

evaluate_shape_gradient(state: GeometryEvolutionState)[source]#
class pystopt.simulation.unsteady.AdjointStokesEvolutionState[source]#

Bases: AdjointGeometryEvolutionState

get_adjoint_density(state: StokesEvolutionState)[source]#
class pystopt.simulation.unsteady.AdjointStokesEvolutionWrangler(forward: StokesEvolutionWrangler)[source]#

Bases: AdjointGeometryEvolutionWrangler

pystopt.simulation.unsteady.quasi_evolve_adjoint(actx: ArrayContext, wrangler: AdjointStokesEvolutionWrangler, step: TimeWrangler, *, tmax: float | None = None, maxit: float | None = None, callback: CallbackManager | None = None, force_gc: bool = True, verbose: bool = True) AdjointStokesEvolutionState[source]#
class pystopt.simulation.unsteady.StokesEvolutionCallbackManager(stop_file_name: Optional[pathlib.Path] = None, callbacks: Dict[str, pystopt.callbacks.CallbackCallable] = <factory>, short_circuit: bool = False, _force_gc: bool = True)[source]#

Bases: CallbackManager

class pystopt.simulation.unsteady.StokesEvolutionVisualizeCallback(norm: Callable[[Any], float] | None, visualize_file_series: Iterator[FileParts], overwrite: bool = False, frequency: int = 1)[source]#

Bases: VisualizeCallback

class pystopt.simulation.unsteady.StokesEvolutionHistoryCallback(norm: Optional[Callable[[Any], float]], memory: List[int] = <factory>, timestamp: List[int] = <factory>, volume: List[float] = <factory>, area: List[float] = <factory>, h_max: List[float] = <factory>, h_avg: List[float] = <factory>, h_std: List[float] = <factory>, deformation: List[float] = <factory>, u_dot_n: List[float] = <factory>, time: List[numpy.ndarray] = <factory>, centroid: List[numpy.ndarray] = <factory>)[source]#

Bases: StokesHistoryCallback

class pystopt.simulation.unsteady.AdjointStokesEvolutionCallbackManager(stop_file_name: Optional[pathlib.Path] = None, callbacks: Dict[str, pystopt.callbacks.CallbackCallable] = <factory>, short_circuit: bool = False, _force_gc: bool = True)[source]#

Bases: CallbackManager

class pystopt.simulation.unsteady.AdjointStokesEvolutionVisualizeCallback(norm: Callable[[Any], float] | None, visualize_file_series: Iterator[FileParts], overwrite: bool = False, frequency: int = 1)[source]#

Bases: VisualizeCallback

Unconstrained Shape Optimization#

These functions can be used to easily encapsulate and perform shape optimization without constraints. The general workflow using these classes is

wrangler = UnconstrainedShapeOptimizationWrangler(
    cost=cost,
    context=context,
    filter_type=OutputType.Unfiltered,
    filter_arguments={},
    )
state0 = wrangler.get_initial_state(actx)

from pystopt.optimize import minimize_steepest
result = minimize_steepest(
    fun=lambda x: x.cost,
    x0=state0,
    jac=lambda x: x.wrap(x.gradient),
    callback=UnconstrainedShapeOptimizationCallbackManager(...),
    options={"rtol": 1.0e-3}
    )

All the complexity of reconstructing the geometry, applying filters and computing the cost and gradient are handled by the wrangler and state classes. Furthermore, the reconstructed values are cached on the state, so they are never out of sync or unnecessarily recomputed.

pystopt.simulation.unconstrained.make_unconstrained_shape_optimization_wrangler(places: pytential.GeometryCollection, cost: ShapeFunctional, *, is_spectral: bool = True, dofdesc: pytential.symbolic.primitives.DOFDescriptorLike | None = None, context: Dict[str, Any] | None = None, filter_type: FilterType = FilterType.Unfiltered, filter_arguments: Dict[str, Any] | None = None) UnconstrainedShapeOptimizationWrangler[source]#

Construct a UnconstrainedShapeOptimizationWrangler.

class pystopt.simulation.unconstrained.UnconstrainedShapeOptimizationWrangler(places: pytential.GeometryCollection, dofdesc: pytential.symbolic.primitives.DOFDescriptor, is_spectral: bool, cost: ShapeFunctional, context: Dict[str, Any], filter_type: FilterType, filter_arguments: Dict[str, Any])[source]#

Bases: ShapeOptimizationWrangler

class pystopt.simulation.unconstrained.UnconstrainedShapeOptimizationState[source]#

Bases: ShapeOptimizationState

class pystopt.simulation.unconstrained.UnconstrainedShapeOptimizationCallbackManager(stop_file_name: Optional[pathlib.Path] = None, callbacks: Dict[str, pystopt.callbacks.CallbackCallable] = <factory>, short_circuit: bool = False, _force_gc: bool = True)[source]#

Bases: ShapeOptimizationCallbackManager

class pystopt.simulation.unconstrained.UnconstrainedShapeOptimizationVisualizeCallback(norm: Callable[[Any], float] | None, visualize_file_series: Iterator[FileParts], overwrite: bool = False, frequency: int = 1)[source]#

Bases: VisualizeCallback

Stokes-Constrained Shape Optimization#

pystopt.simulation.staticstokes.make_stokes_shape_optimization_wrangler(places: pytential.GeometryCollection, cost: ShapeFunctional, op: TwoPhaseStokesRepresentation, *, viscosity_ratio: float = 1.0, capillary_number: float = inf, is_spectral: bool = True, dofdesc: pytential.symbolic.primitives.DOFDescriptorLike | None = None, context: Dict[str, Any] | None = None, filter_type: FilterType = FilterType.Unfiltered, filter_arguments: Dict[str, Any] | None = None, gmres_arguments: Dict[str, Any] | None = None)[source]#

Construct a StokesShapeOptimizationWrangler.

The arguments are described in StokesShapeOptimizationWrangler.

class pystopt.simulation.staticstokes.StokesShapeOptimizationWrangler(places: pytential.GeometryCollection, dofdesc: pytential.symbolic.primitives.DOFDescriptor, is_spectral: bool, op: TwoPhaseStokesRepresentation, lambdas: Dict[str, float], context: Dict[str, Any], gmres_arguments: Dict[str, Any], filter_type: FilterType, filter_arguments: Dict[str, Any], cost: ShapeFunctional)[source]#

Bases: ShapeOptimizationWrangler, StokesGeometryWrangler

ad#

A TwoPhaseStokesRepresentation for the adjoint equations.

class pystopt.simulation.staticstokes.StokesShapeOptimizationState[source]#

Bases: ShapeOptimizationState, StokesGeometryState

get_adjoint_density() ndarray[source]#

The density in the boundary integral representation of the adjoint Stokes variables.

The adjoint operator is obtained from StokesShapeOptimizationWrangler.ad and solved.

Returns:

the adjoint density in the boundary integral representation.

get_adjoint_velocity() ndarray[source]#
Returns:

the adjoint velocity field for the current geometry.

class pystopt.simulation.staticstokes.StokesShapeOptimizationCallbackManager(stop_file_name: Optional[pathlib.Path] = None, callbacks: Dict[str, pystopt.callbacks.CallbackCallable] = <factory>, short_circuit: bool = False, _force_gc: bool = True)[source]#

Bases: ShapeOptimizationCallbackManager

class pystopt.simulation.staticstokes.StokesShapeOptimizationVisualizeCallback(norm: Callable[[Any], float] | None, visualize_file_series: Iterator[FileParts], overwrite: bool = False, frequency: int = 1)[source]#

Bases: VisualizeCallback

class pystopt.simulation.staticstokes.StokesShapeOptimizationHistoryCallback(norm: Optional[Callable[[Any], float]], memory: List[int] = <factory>, timestamp: List[int] = <factory>, f: List[float] = <factory>, g: List[float] = <factory>, d: List[float] = <factory>, alpha: List[float] = <factory>, volume: List[float] = <factory>, area: List[float] = <factory>, h_max: List[float] = <factory>, h_avg: List[float] = <factory>, h_std: List[float] = <factory>, deformation: List[float] = <factory>, u_dot_n: List[float] = <factory>)[source]#

Bases: StokesHistoryCallback, OptimizationHistoryCallback, PerformanceHistoryCallback

Quasi-static Stokes-Constrained Optimization#

class pystopt.simulation.quasistokes.StokesUnsteadyOptimizationWrangler(time: TimeWrangler, forward: StokesCostEvolutionWrangler, checkpoint_directory_series: Iterator[FileParts], overwrite: bool)[source]#

Bases: object

A wrangler for doing optimization on the quasi-static Stokes equations.

By default, this does not actually compute any cost and gradient for optimization, but only sets up the appropriate forward and adjoint evolution equations.

The optimization supports cost functionals of of the form

\[J = \int_0^T j_t(\mathbf{u}, \mathbf{X}) \,\mathrm{d}t + j_T(\mathbf{X}(T))\]

with a time-dependent component \(j_t\) (given by cost) and a final-time component \(j_T\) (given by cost_final).

ambient_dim#
dofdesc#
time#

A TimeWrangler used for the forward and adjoint evolution.

forward#

A StokesCostEvolutionWrangler describing the forward evolution.

adjoint#

A AdjointStokesCostEvolutionWrangler describing the adjoint evolution. This wrangler is completely defined from the forward problem and uses AdjointBoundaryCondition for the boundary condition.

checkpoint_directory_series#

A generator for directory names that will contain any output from the forward and adjoint evolution equations. This can also always return the same directory name, in which case it will overwrite the previous data.

get_initial_state(actx: ArrayContext) StokesUnsteadyOptimizationState[source]#
evolve_forward(state: StokesUnsteadyOptimizationState, wrangler: StokesCostEvolutionWrangler) StokesCostEvolutionState[source]#

Evolve the quasi-static Stokes equations forward in time from state using wrangler.

Parameters:

checkpoint_directory_name – a given directory to store checkpointed data and other visualization files.

Returns:

a StokesCostEvolutionState containing the geometry at the final time and the cost functional value, integrated over all the time interval.

evolve_adjoint(state: StokesUnsteadyOptimizationState, final_evolution_state: StokesCostEvolutionState, wrangler: AdjointStokesCostEvolutionWrangler) AdjointStokesCostEvolutionState[source]#

Evolve the quasi-static adjoint Stokes equations backward in time from state using wrangler, starting from the final solution of the forward problem final_evolution_state (as given by evolve_forward()).

Parameters:

checkpoint_directory_name – a given directory to read checkpointed data from and store other visualization files.

Returns:

an AdjointStokesCostEvolutionState containing the adjoint transverse field at \(t = 0\) and the gradient, integrated over all the time interval.

class pystopt.simulation.quasistokes.StokesUnsteadyOptimizationState(x: ndarray, wrangler: StokesUnsteadyOptimizationWrangler, array_context: ArrayContext)[source]#

Bases: object

wrangler#
checkpoint_directory_name#

Directory containing the checkpointed data for the forward problem.

cost#
gradient#
class pystopt.simulation.quasistokes.GeometryCostEvolutionWrangler(places: pytential.GeometryCollection, dofdesc: pytential.symbolic.primitives.DOFDescriptor, is_spectral: bool, evolution: StokesEvolutionOperator, context: Dict[str, Any], stabilizer_name: str, stabilizer_arguments: Dict[str, Any], filter_type: FilterType, filter_arguments: Dict[str, Any], cost: ShapeFunctional | None, cost_final: ShapeFunctional | None)[source]#

Bases: GeometryEvolutionWrangler

An evolution wrangler that handles costs of the form

\[J = J_t + J_T = \int_0^T g(t, \mathbf{X}) \,\mathrm{d}t + g_T(\mathbf{X})\]

with a term that considers contributions from the open time horizon \((0, T)\) and a term that considers the state at the final time. Either one of these can be omitted.

cost#

The time-dependent term \(J_t\) in the cost functional.

cost_final#

The final time term \(J_T\) in the cost functional.

evaluate_shape_cost(actx: ArrayContext, places: pytential.GeometryCollection, *, context: Dict[str, Any] | None = None) float[source]#
evaluate_shape_cost_final(actx: ArrayContext, places: pytential.GeometryCollection, *, context: Dict[str, Any] | None = None) float[source]#
class pystopt.simulation.quasistokes.GeometryCostEvolutionState[source]#

Bases: GeometryEvolutionState

A geometry evolved using a velocity field that also handles time-dependent cost functionals.

Given a cost functional of the form

\[J = \int_0^T g(t) \,\mathrm{d}t\]

we can alternatively express it as an ODE

\[\begin{split}\left\{ \begin{aligned} \frac{\mathrm{d} j}{t} =\,\, & g(t), \\ j(0) =\,\, & 0, \end{aligned} \right.\end{split}\]

such that \(J = j(T)\). This allows using the same time integrator as for the evolution equation and maintain the same order of convergence when computing the cost.

j#

The value of the cost integrated up to the current time, as explained above.

evaluate_cost()[source]#
evaluate_cost_final()[source]#
class pystopt.simulation.quasistokes.StokesCostEvolutionWrangler(places: pytential.GeometryCollection, dofdesc: pytential.symbolic.primitives.DOFDescriptor, is_spectral: bool, evolution: StokesEvolutionOperator, context: Dict[str, Any], stabilizer_name: str, stabilizer_arguments: Dict[str, Any], filter_type: FilterType, filter_arguments: Dict[str, Any], cost: ShapeFunctional | None, cost_final: ShapeFunctional | None, op: TwoPhaseStokesRepresentation, lambdas: Dict[str, float], gmres_arguments: Dict[str, Any])[source]#

Bases: StokesEvolutionWrangler, GeometryCostEvolutionWrangler

class pystopt.simulation.quasistokes.StokesCostEvolutionState[source]#

Bases: StokesEvolutionState, GeometryCostEvolutionState

class pystopt.simulation.quasistokes.AdjointStokesCostEvolutionWrangler(forward: StokesCostEvolutionWrangler)[source]#

Bases: AdjointStokesEvolutionWrangler

class pystopt.simulation.quasistokes.AdjointStokesCostEvolutionState[source]#

Bases: AdjointStokesEvolutionState

Helpers#

Mixin classes used to provide various functionality for shape optimization.

class pystopt.simulation.ShapeOptimizationWrangler(places: pytential.GeometryCollection, dofdesc: pytential.symbolic.primitives.DOFDescriptor, is_spectral: bool, cost: ShapeFunctional, context: Dict[str, Any], filter_type: FilterType, filter_arguments: Dict[str, Any])[source]#

Bases: GeometryWrangler

cost#

A ShapeFunctional used for the optimization.

context#

Additional symbolic variables used to define the cost functional that will be used in the evaluation.

filter_type#

The type of filter to be used of class FilterType.

filter_arguments#

Additional filter arguments, that actually define the filter in use.

apply_filter(actx: ArrayContext, places: pytential.GeometryCollection, ary: ArrayOrContainerT, *, force_spectral: bool | None = None) ArrayOrContainerT[source]#

Apply a filter to the given array ary.

By default, this function calls apply_filter_by_type() using filter_type and filter_arguments.

get_sym_shape_cost() pytential.symbolic.primitives.var[source]#

Symbolic expression for the shape cost functional.

Returns:

a fully tagged expression for the cost.

evaluate_shape_cost(actx: ArrayContext, places: pytential.GeometryCollection, *, context: Dict[str, Any] | None = None) float[source]#

Evaluates the cost functional from get_sym_shape_cost().

Returns:

the value of the cost functional.

get_sym_shape_gradient() ndarray[source]#

Symbolic expression for the shape gradient.

This functionality needs to be implemented by the subclasses, as the cost functional is not sufficient to define the gradient in the presence of constraints.

Returns:

a fully tagged expression for the gradient.

evaluate_shape_gradient(actx: ArrayContext, places: pytential.GeometryCollection, *, context: Dict[str, Any] | None = None, force_spectral: bool | None = None) ndarray[source]#

Evaluates the shape gradient from get_sym_shape_gradient().

By default, the filter from apply_filter() is applied to the gradient. No additional modifications are performed.

Returns:

the shape gradient for the problem, as set up.

class pystopt.simulation.ShapeOptimizationState[source]#

Bases: GeometryState

State vector for shape optimization.

Generic functions for obtaining the cost value and the gradient. In the general case, these functions just forward to the shape variants below and are here just to offer an abstract interface to follow.

evaluate_cost() float[source]#
evaluate_gradient() ndarray[source]#
evaluate_cost_gradient() ndarray[source]#

When the full (unparametrized) shape gradient is required, use the functions below.

evaluate_shape_cost() float[source]#
Returns:

the value of the cost functional at the current state.

evaluate_shape_gradient() ndarray[source]#
Returns:

the value of the (shape) gradient at the current state.

evaluate_shape_cost_gradient() Tuple[float, ndarray][source]#
Returns:

a tuple containing the cost and the gradient.

class pystopt.simulation.StokesGeometryWrangler(places: pytential.GeometryCollection, dofdesc: pytential.symbolic.primitives.DOFDescriptor, is_spectral: bool, op: TwoPhaseStokesRepresentation, lambdas: Dict[str, float], context: Dict[str, Any], gmres_arguments: Dict[str, Any], filter_type: FilterType, filter_arguments: Dict[str, Any])[source]#

Bases: GeometryWrangler

op#

A TwoPhaseStokesRepresentation.

lambdas#

A dict of viscosity ratios for the geometries of interest.

context#

Additional symbolic variable values used in evaluation.

gmres_arguments#

A dict of additional parameters passed on to single_layer_solve().

filter_type#

The type of filter to be used of class FilterType.

filter_arguments#

Additional filter arguments, that actually define the filter in use.

clear_density_cache() None[source]#
apply_filter(actx: ArrayContext, places: pytential.GeometryCollection, ary: ArrayOrContainerT, *, force_spectral: bool | None = None) ArrayOrContainerT[source]#

Apply a filter to the given array ary.

By default, this function calls apply_filter_by_type() using filter_type and filter_arguments.

get_stokes_solution(actx: ArrayContext, op: TwoPhaseStokesRepresentation, places: pytential.GeometryCollection, *, context: Dict[str, Any] | None = None, cached: bool = True) StokesSolution[source]#

Solves the Stokes problem on the given geometry in places.

Parameters:
  • op – a TwoPhaseStokesRepresentation of the problem that can be solved for the density. This is not necessarily the same as op.

  • cached – if True, the density resulting from the solve is cached and used as an initial guess for subsequent calls to this function. The cache can be cleared at any time using clear_density_cache().

class pystopt.simulation.StokesGeometryState[source]#

Bases: GeometryState

A GeometryState that contains the Stokes flow solution on the given geometry.

get_stokes_density() ndarray[source]#
Returns:

the density in the boundary integral representation.

get_stokes_velocity() ndarray[source]#
Returns:

the velocity field for the current geometry using the density from get_stokes_density().

Additional callbacks specifically for shape optimization.

class pystopt.simulation.ShapeOptimizationCallbackManager(stop_file_name: ~pathlib.Path | None = None, callbacks: ~typing.Dict[str, ~pystopt.callbacks.CallbackCallable] = <factory>, short_circuit: bool = False, _force_gc: bool = True)[source]#

Bases: CallbackManager

A callback manager that handles variables of the type ShapeOptimizationState.

In particular, it expects a keyword argument of the type CGCallbackInfo containing the optimization information.

__call__(*args: Any, **kwargs: Any) int[source]#

Calls all the callbacks in callbacks and aggregates their return values.

In addition to the input arguments, the manager also inserts the keyword ncalls, with the number of calls to this class.

Returns:

\(0\) to stop the optimization and another integer otherwise.

Additional callbacks specifically for the Stokes equations.

class pystopt.simulation.StokesHistoryCallback(norm: ~typing.Callable[[~typing.Any], float] | None, memory: ~typing.List[int] = <factory>, timestamp: ~typing.List[int] = <factory>, volume: ~typing.List[float] = <factory>, area: ~typing.List[float] = <factory>, h_max: ~typing.List[float] = <factory>, h_avg: ~typing.List[float] = <factory>, h_std: ~typing.List[float] = <factory>, deformation: ~typing.List[float] = <factory>, u_dot_n: ~typing.List[float] = <factory>)[source]#

Bases: MeshQualityHistoryCallback

deformation#

Deformation of the geometry in the \((x, y)\) plane.

u_dot_n#

Maximum absolute value of the normal velocity, i.e. \(\|\mathbf{u} \cdot \mathbf{n}\|_\infty\).