Symbolic operator representation

Based on pymbolic.

Basic objects

Object types

Based on the mathematical quantity being represented, the following types of objects occur as part of a symbolic operator representation:

pyopencl.array.Array and meshmode.dof_array.DOFArray instances hold per-node degrees of freedom (and only those). Such instances do not occur on the symbolic side of pytential at all. They’re only visible either as bound inputs (see pytential.bind()) or outputs of evaluation. Which one is used depends on the meaning of the data being represented. If the data is associated with a Discretization, then DOFArray is used and otherwise Array is used.

DOF Description

class pytential.symbolic.primitives.DEFAULT_SOURCE[source]
class pytential.symbolic.primitives.DEFAULT_TARGET[source]
class pytential.symbolic.primitives.QBX_SOURCE_STAGE1[source]

Symbolic identifier for the Stage 1 discretization of a pytential.qbx.QBXLayerPotentialSource.

class pytential.symbolic.primitives.QBX_SOURCE_STAGE2[source]

Symbolic identifier for the Stage 2 discretization of a pytential.qbx.QBXLayerPotentialSource.

class pytential.symbolic.primitives.QBX_SOURCE_QUAD_STAGE2[source]

Symbolic identifier for the upsampled Stage 2 discretization of a pytential.qbx.QBXLayerPotentialSource.

class pytential.symbolic.primitives.GRANULARITY_NODE[source]

DOFs are per node.

class pytential.symbolic.primitives.GRANULARITY_CENTER[source]

DOFs interleaved per expansion center (two per node, one on each side).

class pytential.symbolic.primitives.GRANULARITY_ELEMENT[source]

DOFs per discretization element.

class pytential.symbolic.primitives.DOFDescriptor(geometry=None, discr_stage=None, granularity=None)[source]

A data structure specifying the meaning of a vector of degrees of freedom that is handled by pytential (a “DOF vector”). In particular, using geometry, this data structure describes the geometric object on which the (scalar) function described by the DOF vector exists. Using granularity, the data structure describes how the geometric object is discretized (e.g. conventional nodal data, per-element scalars, etc.)

geometry

An identifier for the geometry on which the DOFs exist. This can be a simple string or any other hashable identifier for the geometric object. The geometric objects are generally subclasses of PotentialSource, TargetBase or Discretization.

discr_stage

Specific to a pytential.source.LayerPotentialSourceBase, this describes on which of the discretizations the DOFs are defined. Can be one of QBX_SOURCE_STAGE1, QBX_SOURCE_STAGE2 or QBX_SOURCE_QUAD_STAGE2.

granularity

Describes the level of granularity of the DOF vector. Can be one of GRANULARITY_NODE (one DOF per node), GRANULARITY_CENTER (two DOFs per node, one per side) or GRANULARITY_ELEMENT (one DOF per element).

pytential.symbolic.primitives.as_dofdesc(desc)[source]

Placeholders

pytential.symbolic.primitives.var[source]

alias of pymbolic.primitives.Variable

pytential.symbolic.primitives.make_sym_mv(name, num_components)[source]
pytential.symbolic.primitives.make_sym_surface_mv(name, ambient_dim, dim, dofdesc=None)[source]

Functions

pytential.symbolic.primitives.real
pytential.symbolic.primitives.imag
pytential.symbolic.primitives.conj
pytential.symbolic.primitives.abs
pytential.symbolic.primitives.sqrt
pytential.symbolic.primitives.sin
pytential.symbolic.primitives.cos
pytential.symbolic.primitives.tan
pytential.symbolic.primitives.asin
pytential.symbolic.primitives.acos
pytential.symbolic.primitives.atan
pytential.symbolic.primitives.atan2
pytential.symbolic.primitives.sinh
pytential.symbolic.primitives.cosh
pytential.symbolic.primitives.tanh
pytential.symbolic.primitives.asinh
pytential.symbolic.primitives.acosh
pytential.symbolic.primitives.atanh
pytential.symbolic.primitives.exp
pytential.symbolic.primitives.log

Discretization properties

class pytential.symbolic.primitives.QWeight(dofdesc=None)[source]

Bare quadrature weights (without Jacobians).

pytential.symbolic.primitives.nodes(ambient_dim, dofdesc=None)[source]

Return a pymbolic.geometric_algebra.MultiVector of node locations.

pytential.symbolic.primitives.parametrization_derivative(ambient_dim, dim, dofdesc=None)[source]

Return a pymbolic.geometric_algebra.MultiVector representing the derivative of the reference-to-global parametrization.

pytential.symbolic.primitives.parametrization_derivative_matrix(ambient_dim, dim, dofdesc=None)[source]

Return a numpy.ndarray representing the derivative of the reference-to-global parametrization.

pytential.symbolic.primitives.pseudoscalar(ambient_dim, dim=None, dofdesc=None)[source]

Same as the outer product of all parametrization derivative columns.

pytential.symbolic.primitives.area_element(ambient_dim, dim=None, dofdesc=None)[source]
pytential.symbolic.primitives.sqrt_jac_q_weight(ambient_dim, dim=None, dofdesc=None)[source]
pytential.symbolic.primitives.normal(ambient_dim, dim=None, dofdesc=None)[source]

Exterior unit normals.

pytential.symbolic.primitives.mean_curvature(ambient_dim, dim=None, dofdesc=None)[source]

(Numerical) mean curvature.

pytential.symbolic.primitives.first_fundamental_form(ambient_dim, dim=None, dofdesc=None)[source]
pytential.symbolic.primitives.second_fundamental_form(ambient_dim, dim=None, dofdesc=None)[source]

Compute the second fundamental form of a surface. This is in reference to the reference-to-global mapping in use for each element.

Note

Some references assume that the second fundamental form is computed with respect to an orthonormal basis, which this is not.

pytential.symbolic.primitives.shape_operator(ambient_dim, dim=None, dofdesc=None)[source]
pytential.symbolic.primitives.expansion_radii(ambient_dim, dim=None, granularity=None, dofdesc=None)[source]
pytential.symbolic.primitives.expansion_centers(ambient_dim, side, dim=None, dofdesc=None)[source]
pytential.symbolic.primitives.h_max(ambient_dim, dim=None, dofdesc=None)[source]

Defines a maximum element size in the discretization.

pytential.symbolic.primitives.weights_and_area_elements(ambient_dim, dim=None, dofdesc=None)[source]

Combines area_element() and QWeight.

Elementary numerics

class pytential.symbolic.primitives.NumReferenceDerivative(ref_axes=None, operand=None, dofdesc=None)[source]

An operator that takes a derivative of operand with respect to the the element reference coordinates.

class pytential.symbolic.primitives.NodeSum(operand=None)[source]

Implements a global sum over all discretization nodes.

class pytential.symbolic.primitives.NodeMax(operand=None)[source]

Implements a global maximum over all discretization nodes.

class pytential.symbolic.primitives.NodeMin(operand=None)[source]

Implements a global minimum over all discretization nodes.

class pytential.symbolic.primitives.ElementwiseSum(operand=None, dofdesc=None)[source]

Returns a vector of DOFs with all entries on each element set to the sum of DOFs on that element.

class pytential.symbolic.primitives.ElementwiseMax(operand=None, dofdesc=None)[source]

Returns a vector of DOFs with all entries on each element set to the maximum of DOFs on that element.

pytential.symbolic.primitives.integral(ambient_dim, dim, operand, dofdesc=None)[source]

A volume integral of operand.

class pytential.symbolic.primitives.Ones(dofdesc=None)[source]

A DOF-vector that is constant one on the whole discretization.

pytential.symbolic.primitives.ones_vec(dim, dofdesc=None)[source]
pytential.symbolic.primitives.area(ambient_dim, dim, dofdesc=None)[source]
pytential.symbolic.primitives.mean(ambient_dim, dim, operand, dofdesc=None)[source]
class pytential.symbolic.primitives.IterativeInverse(expression, rhs, variable_name, extra_vars=None, dofdesc=None)[source]

Operators

class pytential.symbolic.primitives.Interpolation(from_dd, to_dd, operand)[source]

Interpolate quantity from a DOF described by from_dd to a DOF described by to_dd.

pytential.symbolic.primitives.interp(from_dd, to_dd, operand)[source]

Geometric Calculus (based on Geometric/Clifford Algebra)

class pytential.symbolic.primitives.Derivative[source]

Conventional Calculus

pytential.symbolic.primitives.dd_axis(axis, ambient_dim, operand)[source]

Return the derivative along (XYZ) axis axis (in ambient_dim-dimensional space) of operand.

pytential.symbolic.primitives.d_dx()
pytential.symbolic.primitives.d_dy()
pytential.symbolic.primitives.d_dz()
pytential.symbolic.primitives.grad_mv(ambient_dim, operand)[source]

Return the ambient_dim-dimensional gradient of operand as a pymbolic.geometric_algebra.MultiVector.

pytential.symbolic.primitives.grad(ambient_dim, operand)[source]

Return the ambient_dim-dimensional gradient of operand as a numpy.ndarray.

pytential.symbolic.primitives.laplace(ambient_dim, operand)[source]

Layer potentials

class pytential.symbolic.primitives.IntG(target_kernel, source_kernels, densities, qbx_forced_limit, source=None, target=None, kernel_arguments=None, **kwargs)[source]
\[\int_\Gamma T (\sum S_k G(x-y) \sigma_k(y)) dS_y\]

where \(\sigma_k\) is the k-th density, \(G\) is a Green’s function, \(S_k\) are source derivative operators and \(T\) is a target derivative operator.

pytential.symbolic.primitives.int_g_dsource(ambient_dim, dsource, kernel, density, qbx_forced_limit, source=None, target=None, kernel_arguments=None, **kwargs)[source]
\[\int_\Gamma \operatorname{dsource} \dot \nabla_y \dot g(x-y) \sigma(y) dS_y\]

where \(\sigma\) is density, and dsource, a multivector. Note that the first product in the integrand is a geometric product.

pytential.symbolic.primitives.dsource

A pymbolic.geometric_algebra.MultiVector.

pytential.symbolic.primitives.int_g_vec(kernel, density, qbx_forced_limit, source=None, target=None, kernel_arguments=None, **kwargs)[source]

Creates a vector of IntG objects from one kernel with source and target derivatives and maps a vector of densities into a vector of IntG objects.

Historically IntG objects supported only one source kernel and allowed multiple densities to get a vector of objects as a convenience function. Now that IntG objects supports multiple source kernels with one density associated to each source kernel, the previous interface would lead to ambiguity. This function is intended to preserve the “vectorizing” behavior of of the constructor of IntG for use cases where that is preferred.

pytential.symbolic.primitives.S(kernel, density, qbx_forced_limit=<class 'pytential.symbolic.primitives._unspecified'>, source=None, target=None, kernel_arguments=None, **kwargs)[source]
pytential.symbolic.primitives.Sp(kernel, *args, **kwargs)[source]
pytential.symbolic.primitives.Spp(kernel, *args, **kwargs)[source]
pytential.symbolic.primitives.D(kernel, *args, **kwargs)[source]
pytential.symbolic.primitives.Dp(kernel, *args, **kwargs)[source]
pytential.symbolic.primitives.normal_derivative(ambient_dim, operand, dim=None, dofdesc=None)[source]
pytential.symbolic.primitives.tangential_derivative(ambient_dim, operand, dim=None, dofdesc=None)[source]

“Conventional” Vector Calculus

pytential.symbolic.primitives.tangential_onb(ambient_dim, dim=None, dofdesc=None)[source]

Return a matrix of shape (ambient_dim, dim) with orthogonal columns spanning the tangential space of the surface of dofdesc.

pytential.symbolic.primitives.xyz_to_tangential(xyz_vec, dofdesc=None)[source]
pytential.symbolic.primitives.tangential_to_xyz(tangential_vec, dofdesc=None)[source]
pytential.symbolic.primitives.project_to_tangential(xyz_vec, dofdesc=None)[source]
pytential.symbolic.primitives.cross(vec_a, vec_b)[source]
pytential.symbolic.primitives.n_dot(vec, dofdesc=None)[source]
pytential.symbolic.primitives.n_cross(vec, dofdesc=None)[source]
pytential.symbolic.primitives.curl(vec)[source]

Pretty-printing expressions

pytential.symbolic.primitives.pretty(expr)[source]

Binding an operator to a discretization

class pytential.GeometryCollection(places, auto_where=None)[source]

A mapping from symbolic identifiers (“place IDs”, typically strings) to ‘geometries’, where a geometry can be a PotentialSource, a TargetBase or a Discretization.

This class is meant to hold a specific combination of sources and targets serve to host caches of information derived from them, e.g. FMM trees of subsets of them, as well as related common subexpressions such as metric terms.

Refinement of pytential.qbx.QBXLayerPotentialSource entries is performed on demand, i.e. on calls to get_discretization() with a specific discr_stage. To perform refinement explicitly, call pytential.qbx.refinement.refine_geometry_collection(), which allows more customization of the refinement process through parameters.

__init__(places, auto_where=None)[source]
Parameters
  • places – a scalar, tuple of or mapping of symbolic names to geometry objects. Supported objects are PotentialSource, TargetBase and Discretization. If this is a mapping, the keys that are strings must be valid Python identifiers. The tuple should contain only two entries, denoting the source and target geometries for layer potential evaluation, identified by auto_where.

  • auto_where – a single or a tuple of two DOFDescriptors, or values that can be converted to one using as_dofdesc(). The two descriptors are used to define the default source and target geometries for layer potential evaluations. By default, they are set to DEFAULT_SOURCE and DEFAULT_TARGET for sources and targets, respectively.

auto_source

Default DOFDescriptor for the source geometry.

auto_target

Default DOFDescriptor for the target geometry.

get_geometry(geometry)[source]
Parameters

geometry – the identifier of the geometry in the collection.

get_discretization(geometry, discr_stage=None)[source]

Get the geometry or discretization in the collection.

If a specific QBX stage discretization is requested, refinement is performed on demand and cached for subsequent calls.

Parameters
Returns

a geometry object in the collection or a Discretization corresponding to discr_stage.

get_connection(from_dd, to_dd)[source]

Construct a connection from from_dd to to_dd geometries.

Parameters
Returns

an object compatible with the DiscretizationConnection interface.

copy(places=None, auto_where=None)[source]

Get a shallow copy of the geometry collection.

merge(places)[source]

Merges two geometry collections and returns the new collection.

Parameters

places – a dict or GeometryCollection to merge with the current collection. If it is empty, a copy of the current collection is returned.

pytential.bind(places, expr, auto_where=None)[source]
Parameters
  • places – a pytential.GeometryCollection. Alternatively, any list or mapping that is a valid argument for its constructor can also be used.

  • auto_where – for simple source-to-self or source-to-target evaluations, find ‘where’ attributes automatically.

  • expr – one or multiple expressions consisting of primitives form pytential.symbolic.primitives (aka pytential.sym). Multiple expressions can be combined into one object to pass here in the form of a numpy object array

Returns

a pytential.symbolic.execution.BoundExpression

PDE operators

Scalar PDEs

class pytential.symbolic.pde.scalar.L2WeightedPDEOperator(kernel: sumpy.kernel.Kernel, use_l2_weighting: bool)[source]

\(L^2\)-weighting for scalar IEs.

\(L^2\)-weighting is performed to help with the solution of IEs that yield locally singular densities. It does this by matching the \(\ell^2\)-norm used by the iterative method (e.g. GMRES) with the (approximate) \(L^2\)-norm. Clearly, singular densities might not have finite \(\ell^2\)-norm, hampering convergence of the iterative method. See Bremer, J. On the Nyström discretization of integral equations on planar curves with corners. ACHA, 2011..

kernel
use_l2_weighting
get_weight(dofdesc=None)[source]
Returns

a symbolic expression for the weights (quadrature weights and area elements) on dofdesc if use_l2_weighting is True and 1 otherwise.

get_sqrt_weight(dofdesc=None)[source]
Returns

the square root of get_weight().

get_density_var(name: str)[source]
Parameters

name – a string name for the density.

Returns

a symbolic variable or array (problem dependent) corresponding to the density with the given name.

prepare_rhs(b)[source]

Modify the right-hand side (e.g. boundary conditions) to match the operator constructed in operator().

representation(u, qbx_forced_limit=None, **kwargs)[source]
Returns

a representation for the unknowns based on an integral equation with density u. If qbx_forced_limit denotes an on-surface evaluation, the corresponding jump relations are not added to the representation.

operator(u, **kwargs)[source]
Returns

a boundary integral operator with corresponding jump relations that can be used to solve for the density u.

__init__(kernel: sumpy.kernel.Kernel, use_l2_weighting: bool)[source]
class pytential.symbolic.pde.scalar.DirichletOperator(kernel: sumpy.kernel.Kernel, loc_sign: int, *, alpha: Optional[numbers.Number] = None, use_l2_weighting: bool = False, kernel_arguments: Optional[Dict[str, Any]] = None)[source]

IE operator and field representation for solving Dirichlet boundary value problems with scalar kernels (e.g. LaplaceKernel, HelmholtzKernel, YukawaKernel)

Note

When testing this as a potential matcher, note that it can only access potentials that come from charge distributions having no net charge. (This is true at least in 2D)

Inherits from L2WeightedPDEOperator.

is_unique_only_up_to_constant()[source]
representation(u, map_potentials=None, qbx_forced_limit=None, **kwargs)[source]
Parameters
  • u – symbolic variable for the density.

  • map_potentials – a callable that can be used to apply additional transformations on all the layer potentials in the representation, e.g. to take a target derivative.

  • kwargs – additional keyword arguments passed on to the layer potential constructor.

operator(u, **kwargs)[source]
Parameters
  • u – symbolic variable for the density.

  • kwargs – additional keyword arguments passed on to the layer potential constructor.

__init__(kernel: sumpy.kernel.Kernel, loc_sign: int, *, alpha: Optional[numbers.Number] = None, use_l2_weighting: bool = False, kernel_arguments: Optional[Dict[str, Any]] = None)[source]
Parameters
  • loc_sign\(+1\) for exterior or \(-1\) for interior problems.

  • alpha – a complex coefficient with positive imaginary part for the combined-field integral representation (CFIE) for the Helmholtz equation (based on Brakhage and Werner). For other kernels, it does does not offer any benefits.

class pytential.symbolic.pde.scalar.NeumannOperator(kernel: sumpy.kernel.Kernel, loc_sign: int, *, alpha: Optional[numbers.Number] = None, use_improved_operator: bool = True, use_l2_weighting: bool = False, kernel_arguments: Optional[Dict[str, Any]] = None)[source]

IE operator and field representation for solving Neumann boundary value problems with scalar kernels (e.g. LaplaceKernel, HelmholtzKernel, YukawaKernel)

Note

When testing this as a potential matcher, note that it can only access potentials that come from charge distributions having no net charge. (This is true at least in 2D)

Inherits from L2WeightedPDEOperator.

is_unique_only_up_to_constant()[source]
representation(u, map_potentials=None, qbx_forced_limit=None, **kwargs)[source]
Parameters
  • u – symbolic variable for the density.

  • map_potentials – a callable that can be used to apply additional transformations on all the layer potentials in the representation, e.g. to take a target derivative.

operator(u, **kwargs)[source]
Parameters
  • u – symbolic variable for the density.

  • kwargs – additional keyword arguments passed on to the layer potential constructor.

__init__(kernel: sumpy.kernel.Kernel, loc_sign: int, *, alpha: Optional[numbers.Number] = None, use_improved_operator: bool = True, use_l2_weighting: bool = False, kernel_arguments: Optional[Dict[str, Any]] = None)[source]
Parameters
  • loc_sign\(+1\) for exterior or \(-1\) for interior problems.

  • alpha – a complex coefficient with positive imaginary part for the combined-field integral representation (CFIE) for the Helmholtz equation (based on Brakhage and Werner). For other kernels, it does does not offer any benefits.

  • use_improved_operator – if True use the least singular operator available. Only used when alpha is not \(0\).

class pytential.symbolic.pde.scalar.BiharmonicClampedPlateOperator(kernel: sumpy.kernel.Kernel, loc_sign: int)[source]

IE operator and field representation for solving clamped plate Biharmonic equation where,

\[\begin{split}\begin{cases} \Delta^2 u = 0, & \quad \text{ on } D, \\ u = g_1, & \quad \text{ on } \partial D, \\ \mathbf{n} \cdot \nabla u = g_2, & \quad \text{ on } \partial D. \end{cases}\end{split}\]

This operator assumes that the boundary data \((g_1, g_2)\) are represented as column vectors and vertically stacked. For details on the formulation see Problem C in [Farkas1990].

Note

This operator supports only interior problem.

Farkas1990(1,2)

Farkas, Peter, Mathematical foundations for fast algorithms for the biharmonic equation, Technical Report 765, Department of Computer Science, Yale University, 1990, PDF.

representation(sigma, map_potentials=None, qbx_forced_limit=None, **kwargs)[source]
Parameters
  • sigma – symbolic variable for the density.

  • map_potentials – a callable that can be used to apply additional transformations on all the layer potentials in the representation, e.g. to take a target derivative.

  • kwargs – additional keyword arguments passed on to the layer potential constructor.

operator(sigma, **kwargs)[source]
Parameters
  • u – symbolic variable for the density.

  • kwargs – additional keyword arguments passed on to the layer potential constructor.

Returns

the second kind integral operator for the clamped plate problem from [Farkas1990].

__init__(kernel: sumpy.kernel.Kernel, loc_sign: int)[source]
Parameters

loc_sign\(+1\) for exterior or \(-1\) for interior problems.

Maxwell’s equations

pytential.symbolic.pde.maxwell.get_sym_maxwell_point_source(kernel, jxyz, k)[source]

Return a symbolic expression that, when bound to a pytential.source.PointPotentialSource will yield a field satisfying Maxwell’s equations.

Uses the sign convention \(\exp(-i \omega t)\) for the time dependency.

This will return an object of six entries, the first three of which represent the electric, and the second three of which represent the magnetic field. This satisfies the time-domain Maxwell’s equations as verified by sumpy.point_calculus.frequency_domain_maxwell().

pytential.symbolic.pde.maxwell.get_sym_maxwell_plane_wave(amplitude_vec, v, omega, epsilon=1, mu=1, dofdesc=None)[source]

Return a symbolic expression that, when bound to a pytential.source.PointPotentialSource will yield a field satisfying Maxwell’s equations.

Parameters
  • amplitude_vec – should be orthogonal to v. If it is not, it will be orthogonalized.

  • v – a three-vector representing the phase velocity of the wave (may be an object array of variables or a vector of concrete numbers) While v may mathematically be complex-valued, this function is for now only tested for real values.

  • omega – Accepts the “Helmholtz k” to be compatible with other parts of this module.

Uses the sign convention \(\exp(-1 \omega t)\) for the time dependency.

This will return an object of six entries, the first three of which represent the electric, and the second three of which represent the magnetic field. This satisfies the time-domain Maxwell’s equations as verified by sumpy.point_calculus.frequency_domain_maxwell().

class pytential.symbolic.pde.maxwell.PECChargeCurrentMFIEOperator(k=None)[source]

Magnetic Field Integral Equation operator with PEC boundary conditions, under the assumption of no surface charges.

See contrib/notes/mfie.tm in the repository for a derivation.

The arguments loc below decide between the exterior and the interior MFIE. The “exterior” (loc=1) MFIE enforces a zero field on the interior of the integration surface, whereas the “interior” MFIE (loc=-1) enforces a zero field on the exterior.

Uses the sign convention \(\exp(-1 \omega t)\) for the time dependency.

for the sinusoidal time dependency.

j_operator(loc, Jt)[source]
j_rhs(Hinc_xyz)[source]
rho_operator(loc, rho)[source]
rho_rhs(Jt, Einc_xyz)[source]
scattered_volume_field(Jt, rho, qbx_forced_limit=None)[source]

This will return an object array of six entries, the first three of which represent the electric, and the second three of which represent the magnetic field. This satisfies the time-domain Maxwell’s equations as verified by sumpy.point_calculus.frequency_domain_maxwell().

Stokes’ equations

class pytential.symbolic.stokes.StokesletWrapper(dim=None)[source]

Wrapper class for the StokesletKernel kernel.

This class is meant to shield the user from the messiness of writing out every term in the expansion of the double-indexed Stokeslet kernel applied to the density vector. The object is created to do some of the set-up and bookkeeping once, rather than every time we want to create a symbolic expression based on the kernel – say, once when we solve for the density, and once when we want a symbolic representation for the solution, for example.

The apply() function returns the integral expressions needed for the vector velocity resulting from convolution with the vector density, and is meant to work similarly to calling S() (which is IntG).

Similar functions are available for other useful things related to the flow: apply_pressure(), apply_derivative() (target derivative), apply_stress() (applies symmetric viscous stress tensor in the requested direction).

kernel_dict

The dictionary allows us to exploit symmetry – that \(S_{01}\) is identical to \(S_{10}\) – and avoid creating multiple expansions for the same kernel in a different ordering.

__init__(dim=None)[source]
apply(density_vec_sym, mu_sym, qbx_forced_limit)[source]

Symbolic expressions for integrating Stokeslet kernel.

Returns an object array of symbolic expressions for the vector resulting from integrating the dyadic Stokeslet kernel with variable density_vec_sym.

Parameters
  • density_vec_sym – a symbolic vector variable for the density vector.

  • mu_sym – a symbolic variable for the viscosity.

  • qbx_forced_limit – the qbx_forced_limit argument to be passed on to IntG.

apply_pressure(density_vec_sym, mu_sym, qbx_forced_limit)[source]

Symbolic expression for pressure field associated with the Stokeslet.

apply_derivative(deriv_dir, density_vec_sym, mu_sym, qbx_forced_limit)[source]

Symbolic derivative of velocity from Stokeslet.

Returns an object array of symbolic expressions for the vector resulting from integrating the deriv_dir target derivative of the dyadic Stokeslet kernel with variable density_vec_sym.

Parameters
  • deriv_dir – integer denoting the axis direction for the derivative.

  • density_vec_sym – a symbolic vector variable for the density vector.

  • mu_sym – a symbolic variable for the viscosity.

  • qbx_forced_limit – the qbx_forced_limit argument to be passed on to IntG.

apply_stress(density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit)[source]

Symbolic expression for viscous stress applied to a direction.

Returns a vector of symbolic expressions for the force resulting from the viscous stress

\[-p \delta_{ij} + \mu (\nabla_i u_j + \nabla_j u_i)\]

applied in the direction of dir_vec_sym.

Note that this computation is very similar to computing a double-layer potential with the Stresslet kernel in StressletWrapper. The difference is that here the direction vector is applied at the target points, while in the Stresslet the direction is applied at the source points.

Parameters
  • density_vec_sym – a symbolic vector variable for the density vector.

  • dir_vec_sym – a symbolic vector for the application direction.

  • mu_sym – a symbolic variable for the viscosity.

  • qbx_forced_limit – the qbx_forced_limit argument to be passed on to IntG.

class pytential.symbolic.stokes.StressletWrapper(dim=None)[source]

Wrapper class for the StressletKernel kernel.

This class is meant to shield the user from the messiness of writing out every term in the expansion of the triple-indexed Stresslet kernel applied to both a normal vector and the density vector. The object is created to do some of the set-up and bookkeeping once, rather than every time we want to create a symbolic expression based on the kernel – say, once when we solve for the density, and once when we want a symbolic representation for the solution, for example.

The apply() function returns the integral expressions needed for convolving the kernel with a vector density, and is meant to work similarly to S() (which is IntG).

Similar functions are available for other useful things related to the flow: apply_pressure(), apply_derivative() (target derivative), apply_stress() (applies symmetric viscous stress tensor in the requested direction).

kernel_dict

The dictionary allows us to exploit symmetry – that \(T_{012}\) is identical to \(T_{120}\) – and avoid creating multiple expansions for the same kernel in a different ordering.

__init__(dim=None)[source]
apply(density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit)[source]

Symbolic expressions for integrating Stresslet kernel.

Returns an object array of symbolic expressions for the vector resulting from integrating the dyadic Stresslet kernel with variable density_vec_sym and source direction vectors dir_vec_sym.

Parameters
  • density_vec_sym – a symbolic vector variable for the density vector.

  • dir_vec_sym – a symbolic vector variable for the direction vector.

  • mu_sym – a symbolic variable for the viscosity.

  • qbx_forced_limit – the qbx_forced_limit argument to be passed on to IntG.

apply_pressure(density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit)[source]

Symbolic expression for pressure field associated with the Stresslet.

apply_derivative(deriv_dir, density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit)[source]

Symbolic derivative of velocity from stresslet.

Returns an object array of symbolic expressions for the vector resulting from integrating the deriv_dir target derivative of the dyadic Stresslet kernel with variable density_vec_sym and source direction vectors dir_vec_sym.

Parameters
  • deriv_dir – integer denoting the axis direction for the derivative.

  • density_vec_sym – a symbolic vector variable for the density vector.

  • dir_vec_sym – a symbolic vector variable for the normal direction.

  • mu_sym – a symbolic variable for the viscosity.

  • qbx_forced_limit – the qbx_forced_limit argument to be passed on to IntG.

apply_stress(density_vec_sym, normal_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit)[source]

Symbolic expression for viscous stress applied to a direction.

Returns a vector of symbolic expressions for the force resulting from the viscous stress

\[-p \delta_{ij} + \mu (\nabla_i u_j + \nabla_j u_i)\]

applied in the direction of dir_vec_sym.

Parameters
  • density_vec_sym – a symbolic vector variable for the density vector.

  • normal_vec_sym – a symbolic vector variable for the normal vectors (outward facing normals at source locations).

  • dir_vec_sym – a symbolic vector for the application direction.

  • mu_sym – a symbolic variable for the viscosity.

  • qbx_forced_limit – the qbx_forced_limit argument to be passed on to IntG.

class pytential.symbolic.stokes.StokesOperator(ambient_dim, side)[source]
ambient_dim
side
__init__(ambient_dim, side)[source]
Parameters
  • ambient_dim – dimension of the ambient space.

  • side\(+1\) for exterior or \(-1\) for interior.

get_density_var(name='sigma')[source]
Returns

a symbolic vector corresponding to the density.

prepare_rhs(b, *, mu)[source]
Returns

a (potentially) modified right-hand side b that matches requirements of the representation.

operator(sigma)[source]
Returns

the integral operator that should be solved to obtain the density sigma.

velocity(sigma, *, normal, mu, qbx_forced_limit=None)[source]
Returns

a representation of the velocity field in the Stokes flow.

pressure(sigma, *, normal, mu, qbx_forced_limit=None)[source]
Returns

a representation of the pressure in the Stokes flow.

class pytential.symbolic.stokes.HsiaoKressExteriorStokesOperator(*, omega, alpha=None, eta=None)[source]

Representation for 2D Stokes Flow based on [HsiaoKress1985].

Inherits from StokesOperator.

HsiaoKress1985(1,2)

G. C. Hsiao and R. Kress, On an Integral Equation for the Two-Dimensional Exterior Stokes Problem, Applied Numerical Mathematics, Vol. 1, 1985, DOI.

__init__(*, omega, alpha=None, eta=None)[source]
Parameters
  • omega – farfield behaviour of the velocity field, as defined by \(A\) in [HsiaoKress1985] Equation 2.3.

  • alpha – real parameter \(\alpha > 0\).

  • eta – real parameter \(\eta > 0\). Choosing this parameter well can have a non-trivial effect on the conditioning.

class pytential.symbolic.stokes.HebekerExteriorStokesOperator(*, eta=None)[source]

Representation for 3D Stokes Flow based on [Hebeker1986].

Inherits from StokesOperator.

Hebeker1986

F. C. Hebeker, Efficient Boundary Element Methods for Three-Dimensional Exterior Viscous Flow, Numerical Methods for Partial Differential Equations, Vol. 2, 1986, DOI.

__init__(*, eta=None)[source]
Parameters

eta – a parameter \(\eta > 0\). Choosing this parameter well can have a non-trivial effect on the conditioning of the operator.

Internal affairs

Mappers

How a symbolic operator gets executed

class pytential.symbolic.execution.BoundExpression(places, sym_op_expr)[source]

An expression readied for evaluation by binding it to a GeometryCollection.

cost_per_stage(calibration_params, **kwargs)[source]
Parameters
  • queue – a pyopencl.CommandQueue object.

  • calibration_params – either a dict returned by estimate_kernel_specific_calibration_params, or a str “constant_one”.

Returns

a dict mapping from instruction to per-stage cost. Each per-stage cost is represented by a dict mapping from the stage name to the predicted time.

cost_per_box(calibration_params, **kwargs)[source]
Parameters
  • queue – a pyopencl.CommandQueue object.

  • calibration_params – either a dict returned by estimate_kernel_specific_calibration_params, or a str “constant_one”.

Returns

a dict mapping from instruction to per-box cost. Each per-box cost is represented by a numpy.ndarray or pyopencl.array.Array of shape (nboxes,), where the ith entry represents the cost of all stages for box i.

scipy_op(actx: arraycontext.impl.pyopencl.PyOpenCLArrayContext, arg_name, dtype, domains=None, **extra_args)[source]
Parameters

domains – a list of discretization identifiers or None values indicating the domains on which each component of the solution vector lives. None values indicate that the component is a scalar. If domains is None, DEFAULT_TARGET is required to be a key in places.

Returns

An object that (mostly) satisfies the scipy.sparse.linalg.LinearOperator protocol, except for accepting and returning pyopencl.array.Array arrays.

eval(context=None, timing_data=None, array_context: Optional[arraycontext.impl.pyopencl.PyOpenCLArrayContext] = None)[source]

Evaluate the expression in self, using the pyopencl.CommandQueue queue and the input variables given in the dictionary context.

Parameters
  • timing_data – A dictionary into which timing data will be inserted during evaluation. (experimental)

  • array_context – only needs to be supplied if no instances of DOFArray with a PyOpenCLArrayContext are supplied as part of context.

Returns

the value of the expression, as a scalar, pyopencl.array.Array, or an object array of these.

__call__(*args, **kwargs)[source]

Evaluate the expression in self, using the pyopencl.CommandQueue queue and the input variables given in the dictionary context.

Returns

the value of the expression, as a scalar, meshmode.dof_array.DOFArray, or an object array of these.

places

Created by calling pytential.bind().