tensormesh.operator¶
Condenser¶
- class Condenser(dirichlet_mask: Tensor, dirichlet_value: Tensor | None = None)[源代码]¶
基类:
ModuleStatic-condensation operator for Dirichlet boundary conditions.
Partitions a global system \(K u = f\) into inner (free) DOFs and outer (Dirichlet) DOFs and condenses the prescribed values into the right-hand side:
\[K_{ii}\, u_i = f_i - K_{io}\, u_o.\]- 参数:
dirichlet_mask (Tensor) -- 1D boolean tensor of shape \([n_{\text{dof}}]\).
Truemarks DOFs whose value is prescribed.dirichlet_value (Tensor, optional) -- 1D tensor of shape \([n_{\text{dof}}]\) (a full vector — only the entries where
dirichlet_maskisTrueare read) or \([n_{\text{outer\_dof}}]\) (already restricted to the boundary). Defaults to all zeros.
- dirichlet_value¶
Prescribed values restricted to the boundary, shape \([n_{\text{outer\_dof}}]\).
- Type:
- inner_row, inner_col
Row/column indices of the inner block \(K_{ii}\) in local inner-DOF numbering. Populated lazily on the first call.
- Type:
Tensor or None
- ou2in_row, ou2in_col
Row/column indices of the coupling block \(K_{io}\) in local numbering. Populated lazily.
- Type:
Tensor or None
- is_inner_edge, is_ou2in_edge
Boolean masks over the matrix's COO edge list selecting the \(K_{ii}\) / \(K_{io}\) entries.
- Type:
Tensor or None
- is_inner_dof, is_outer_dof
Boolean masks over the global DOFs.
- Type:
Tensor or None
- n_inner_dof, n_outer_dof, n_dof
DOF counts.
- Type:
int or None
- layout_hash¶
Sparsity-pattern hash cached from the first input matrix; used to detect a pattern change on subsequent calls.
- Type:
int or None
- K_ou2in¶
Cached \(K_{io}\) block; reused by
condense_rhs().- Type:
SparseMatrix or None
备注
Condenseris atorch.nn.Module. All tensor-valued attributes (dirichlet_mask,dirichlet_value, and the lazily computed index buffers) are registered as PyTorch buffers, socondenser.to(device)/condenser.cuda()/condenser.cpu()move them together with the input system.The first call to
__call__lazily computes the inner / outer edge masks and caches them on the instance. Subsequent calls reuse the cached layout as long as the inputSparseMatrixhas the same sparsity pattern (checked viamatrix.layout_hash). The lazy buffers are registered withpersistent=Falseso they are not saved intostate_dict.示例
import torch from tensormesh import Mesh, Condenser from tensormesh.assemble import LaplaceElementAssembler mesh = Mesh.gen_rectangle(chara_length=0.2) K = LaplaceElementAssembler.from_mesh(mesh)() f = torch.ones(mesh.n_points, dtype=mesh.dtype) # Homogeneous Dirichlet on the whole boundary condenser = Condenser(mesh.boundary_mask) # Condense: returns (K_inner, f_inner) — note this is __call__, # NOT a separate "condense_matrix" method. K_inner, f_inner = condenser(K, f) # Solve the inner system and recover the full solution u_inner = K_inner.solve(f_inner) u = condenser.recover(u_inner)
For time-dependent boundary data, update the prescribed values between solves via
update_dirichlet(), then re-condense only the right-hand side withcondense_rhs()(cheaper than rebuildingK_inner).- __init__(dirichlet_mask: Tensor, dirichlet_value: Tensor | None = None)[源代码]¶
Initialize internal Module state, shared by both nn.Module and ScriptModule.
- update_dirichlet(dirichlet_value: Tensor)[源代码]¶
Replace the cached prescribed boundary values.
Useful for time-dependent or parameter-swept problems where only the right-hand side changes between solves; the cached \(K_{io}\) block (populated by
__call__) is preserved.- 参数:
dirichlet_value (Tensor) -- 1D tensor of shape \([n_{\text{dof}}]\) or \([n_{\text{outer\_dof}}]\), with the same conventions as the
dirichlet_valueargument to__init__().
- condense_rhs(rhs: Tensor) Tensor[源代码]¶
Condense the right-hand side only, reusing the cached matrix layout.
\[f_i \leftarrow f_i - K_{io}\, u_o.\]Use this after a first
__call__to re-condensefwhen the matrix is unchanged but the load vector changes (e.g. between time steps).- 参数:
rhs (Tensor) -- Global right-hand side of shape \([n_{\text{dof}}, \ldots]\).
- 返回:
Condensed right-hand side of shape \([n_{\text{inner\_dof}}, \ldots]\).
- 返回类型:
- 抛出:
AssertionError -- If
__call__has not been invoked yet: the operator has no cached \(K_{io}\) block to apply.
- recover(u: Tensor) Tensor[源代码]¶
Recover the full-DOF solution from an inner-DOF solution.
Scatters the condensed solution
uback into the free-DOF slots and writes the prescribed boundary values into the constrained slots.
- restrict(f: Tensor) Tensor[源代码]¶
Project a full-DOF vector down to inner DOFs.
Pure linear restriction \(f_i \leftarrow f|_{\text{inner}}\), with no Dirichlet-value correction. Use this when the right-hand side has no implicit Dirichlet contribution to subtract — for example, the per-stage right-hand side of a time-integration scheme such as
tensormesh.ode.ImplicitLinearRungeKutta, where the time-derivative at a Dirichlet DOF is zero by construction and so the \(-K_{io}\,u_o\) term incondense_rhs()would over-apply the boundary correction.Unlike
Condenser.__call__/condense_rhs(),restrictdoes not require the matrix layout to be cached first: it only needsdirichlet_mask.
- prolong(f_inner: Tensor) Tensor[源代码]¶
Lift an inner-DOF vector up to full DOF with zeros on the boundary.
Pure linear prolongation: inner entries are scattered into the free-DOF slots, constrained slots are filled with zero — not with
dirichlet_value. Use this when the quantity being lifted should vanish on the boundary regardless of the prescribed Dirichlet value, e.g. the per-stage slope of a time integrator (since a fixed-value DOF has zero time-derivative).Like
restrict(),prolongonly needsdirichlet_maskand does not require the matrix layout to be cached first.
BlochReducer¶
- class BlochReducer(points: Tensor | ndarray | Sequence, lattice_vectors: Tensor | ndarray | Sequence, dofs_per_node: int = 1, tol: float | None = None, sign: int = -1)[源代码]¶
基类:
ModuleBloch-Floquet periodic reduction of an assembled FEM operator.
- 参数:
points (array-like, shape
[n_nodes, dim]) -- Nodal coordinates of the unit-cell mesh. Opposite periodic faces must carry matching nodes (e.g. a mesh built withgmsh.model.mesh.setPeriodic); a node on the+a_jface is paired with its image one lattice vector back.lattice_vectors (array-like, shape
[n_lat, dim]) -- The periodic lattice vectorsa_j(1, 2 or 3 of them). Pass only the directions that are actually periodic — e.g. a single vector for a waveguide periodic in one direction.dofs_per_node (int, optional) --
Number of DOFs per node (1 for scalar acoustics/Helmholtz,
dimfor elasticity, 6 for a 3D frame). Default 1.The components are assumed node-major (component-interleaved): DOF
dof nodeilives at global indexi * dofs_per_node + d, so the global vector is[n0_x, n0_y, n1_x, n1_y, ...]. This is the layout TensorMesh's vector assemblers and projector produce -- theNodeAssemblerintegral is returnedflatten()-ed from shape[n_nodes, dofs_per_node]-- so a Bloch reduction of a vector operator assembled byLinearElasticityElementAssemblerlines up with itsK/Mwithout any DOF re-ordering.tol (float, optional) -- Absolute coordinate tolerance for node matching (default scales with the bounding box:
1e-7 * diag).sign (int, optional) -- Sign convention of the Floquet phase
exp(sign * i k·R);-1(default) givesu(r+R) = exp(-i k·R) u(r)on the master→slave map. The eigenvalues are independent of this choice.
- n_nodes, n_masters
Node counts before / after reduction.
- Type:
- n_dof, n_reduced_dof
DOF counts before / after reduction (
n_* * dofs_per_node).- Type:
备注
Like
Condenser, this is atorch.nn.Module; the pairing buffers move with.to(device). The pairing is computed once at construction (geometry only);reduce()is called per wavevector.- __init__(points: Tensor | ndarray | Sequence, lattice_vectors: Tensor | ndarray | Sequence, dofs_per_node: int = 1, tol: float | None = None, sign: int = -1)[源代码]¶
Initialize internal Module state, shared by both nn.Module and ScriptModule.
- reduce(matrix, k)[源代码]¶
Return the reduced operator
T(k)^H A T(k).- 参数:
matrix (SparseMatrix or Tensor) -- Assembled operator of shape
[n_dof, n_dof](real or complex). ASparseMatrixis reduced sparsely (COO index remap + coalesce) and returns aSparseMatrix; a densetorch.Tensoris reduced densely and returns a dense complextorch.Tensor(handy for hand-assembled systems such as a beam / truss lattice that does not go through the sparse assembler).k (array-like, shape
[dim]) -- Wavevector.
- 返回:
Reduced operator of shape
[n_reduced_dof, n_reduced_dof](complex).- 返回类型:
- reduce_system(K: SparseMatrix, M: SparseMatrix, k)[源代码]¶
Convenience: reduce a stiffness/mass pair,
(K_r, M_r).
- recover(u_reduced: Tensor, k) Tensor[源代码]¶
Scatter a reduced-DOF field back to all DOFs with the Floquet phase.
The scatter-back counterpart of
reduce(), named to mirrorrecover():u_full[i] = exp(sign i k·R_i) * u_reduced[master(i)].- 参数:
u_reduced (torch.Tensor, shape
[n_reduced_dof, ...])k (array-like, shape
[dim])