kform#
This submodule is provides types which allow for creating a description of the system to solve using Python’s operator overloading. It also allows for caching any syntax errors with it. It could be even further improved in the future if Python’s generic typing will ever support inheritence for generic types.
Different \(k\)-Form Types#
Most of this module’s contents consists of types that allow describing
aforementioned \(k\)-form relations. These are all subtypes of the
Term
type. It only describes how to describe/print a term and
nothing more.
- class mfv2d.kform.Term(label: str)[source]#
Represents a term in the k-form expressions.
This type contains the most basic functionality and is mainly intended to help with type hints.
- Parameters:
label (str) – How to identify the term.
Next is the basic KForm
type. In addition to its label it also
has its order. This can have a value of 0, 1, or 2. It has quite a few
useful operators implemented.
- class mfv2d.kform.KForm(label: str, order: UnknownFormOrder)[source]#
Differential K form.
It is described by and order and identifier, that is used to print it. It offers the following overloaded operations:
*
with anotherKForm
results inKInnerProduct
*
with a callable results inKInteriorProduct
~
will result in aKHodge
of itself
Its exterior derivative is also availabel through the
KForm.derivative()
method.- Parameters:
- __mul__(other: KForm, /) KInnerProduct [source]#
- __mul__(other: Function2D, /) KInteriorProduct
Inner product with a weight.
- __rmul__(other: KForm, /) KInnerProduct [source]#
- __rmul__(other: Function2D, /) KInteriorProduct
Inner product with a weight.
- property core_form: KWeight | KFormUnknown#
Most basic form, be it unknown or weight.
- property derivative: KFormDerivative#
Derivative of the form.
- order: UnknownFormOrder#
- property primal_order: UnknownFormOrder#
Order in primal basis.
To describe order of a form older functions made use of just taking the
integers and assuming they were in the desired range. Newly written code should
instead make use of UnknownFormOrder
type, which is an enum.
- class mfv2d.kform.UnknownFormOrder(*values)[source]#
Orders of unknown differential forms.
This enum is intended to replace just passing integers for the order of forms, since this is easier to catch by type-checkers.
- FORM_ORDER_0 = 1#
- FORM_ORDER_1 = 2#
- FORM_ORDER_2 = 3#
- property dual: UnknownFormOrder#
Return what the dual of the form is.
For a system, these UnknownFormOrder
can be stored in
UnknownOrderings
. This is just a glorified tuple
.
- class mfv2d.kform.UnknownOrderings(*orders: UnknownFormOrder)[source]#
Type for storing ordering of unknowns within an element.
It is intended to just be a sequence of the form orders.
- form_orders: tuple[UnknownFormOrder, ...]#
To denote variables that should be solved for, KFormUnknown
are used. They also can be used for non-linear interior products
using the ^
operator.
- class mfv2d.kform.KFormUnknown(label: str, order: UnknownFormOrder, dual: bool = False)[source]#
Differential form which is to be computed.
- Parameters:
dual (bool, default: False) – Is the form represented by the dual or primal basis.
- __xor__(other: KFormUnknown | KHodge)[source]#
Return a non-linear interior product term.
- property core_form: KFormUnknown#
Most basic form, be it unknown or weight.
- property primal_order: UnknownFormOrder#
Order of the mass matrix which needs to be used.
Each unknown form can also be used to create a weight form with
the type KWeight
throught the KFormUnknown.weight()
method. These are used for forming interior products, as well as
forming either element projections
(described by KElementProjection
) or boundary projections
for weak boundary conditions (described by KBoundaryProjection
).
- class mfv2d.kform.KWeight(label: str, order: UnknownFormOrder, base_form: KFormUnknown)[source]#
Differential K form represented with the dual basis.
Provides operators for forming element and boundary projections throught the
@
and^
operators respectively.- Parameters:
- __matmul__(other: Callable | Literal[0], /) KElementProjection [source]#
Create projection for the right hand side.
- __mul__(other: KForm, /) KInnerProduct [source]#
- __mul__(other: Callable | Literal[0], /) KElementProjection
Inner product with a weight.
- __rmul__(other: KForm, /) KInnerProduct [source]#
- __rmul__(other: Callable | Literal[0], /) KElementProjection
Inner product with a weight.
- __xor__(other: Callable) KBoundaryProjection [source]#
Create boundary projection for the right hand side.
- base_form: KFormUnknown#
- property primal_order: UnknownFormOrder#
Order of the mass matrix which needs to be used.
\(k\)-forms resulting from different operations also each have a different type:
For the Hodge operator,
KHodge
type is usedFor the derivative
KFormDerivative
is usedFor the interor product with a vector function
KInteriorProduct
For the interor product with an unknown form
KInteriorProductNonlinear
- class mfv2d.kform.KHodge(form: KForm)[source]#
Hodge represents a transformation from primal to dual basis.
A continuous Hodge \(\star\) is defined as a mapping, which transfers a k-form on an n-dimensional manifold into a (n-k)-form:
\[\star: \Lambda^{(k)} \leftarrow \Lambda^{(n - k)}\]The discrete version of the Hodge also maps a k-form onto a (n-k) form, but with a very specific choice of basis. If a polynomial can be written in terms of primal basis matrix \(\boldsymbol{\Psi}^{(k)}\) and degree-of-freedom vector \(\vec{p}^{(k)}\), which are defined by equations (1) and (2), then the duals are defined by \(khodge-dual\). This allows for the resulting system to be sparser, at the cost of having to obtain the primal values in post-processing.
(1)#\[\boldsymbol{\Psi}^{(k)} = \begin{bmatrix} \psi_0 (\vec{\xi}) & \cdots & \psi_n (\vec{\xi}) \end{bmatrix}\](2)#\[\begin{split}\vec{p}^{(k)} = \begin{bmatrix} p^0 \\ \vdots \\ p^n \end{bmatrix}\end{split}\](3)#\[\begin{align} \tilde{\boldsymbol{\Psi}}^{(n - k)} = \boldsymbol{\Psi}^{(k)} \left(\mathbb{M}^{(k)}\right)^{-1} && \vec{\tilde{p}}^{(n - k)} = \mathbb{M}^{(k)} \vec{p}^{(k)} \end{align}\]- Parameters:
form (KForm) – Form which the Hodge should be applied to. Note that applying the Hodge twice is the identity operation.
- property core_form: KWeight | KFormUnknown#
Most basic form, be it unknown or weight.
- property primal_order: UnknownFormOrder#
Order of the mass matrix which needs to be used.
- class mfv2d.kform.KFormDerivative(form: KForm)[source]#
Exterior derivative of a form.
An exterior derivative maps a differential k-form into a (k + 1) form:
\[\mathrm{d}: p^{(k)} \in \Lambda^{(k)}(\mathcal{M}) \leftarrow q^{(k + 1)} \in \Lambda^{(k + 1)}(\mathcal{M})\]This operation is expressed in terms of a so called incidence matrix \(\mathbb{E}^{(k, k + 1)}\), which maps degrees of freedom from basis of k-forms to those of (k + 1)-forms
Note that applying the operator \(\mathrm{d}\) twice will always result in a form which is zero everywhere:
\[\mathrm{d}\left( \mathrm{d} p^{(k)} \right) = 0\]- Parameters:
form (KForm) – The form of which the derivative is to be taken.
- property core_form: KWeight | KFormUnknown#
Most basic form, be it unknown or weight.
- property primal_order: UnknownFormOrder#
Order in primal basis.
- class mfv2d.kform.KInteriorProduct(label: str, order: UnknownFormOrder, form: KForm, vector_field: Function2D)[source]#
Represents an interior product of a K-form with a tangent vector field.
- property core_form: KWeight | KFormUnknown#
Most basic form, be it unknown or weight.
- property primal_order: UnknownFormOrder#
Return the order of the primal.
- vector_field: Function2D#
- class mfv2d.kform.KInteriorProductNonlinear(label: str, order: UnknownFormOrder, form: KFormUnknown | KHodge, form_field: KFormUnknown)[source]#
Represents an interior product of a K-form with a lowered 1-form.
In two dimentions there are at total of four different types of interior products:
primal 1-form
primal 2-form
dual 1-form
dual 2-form
These all correspond to a different operation:
primal 1-form: scalar cross product
primal 2-form: multiplication with a vector field
dual 1-form: dot product
dual 2-form: vector cross product
- property core_form: KWeight | KFormUnknown#
Most basic form, be it unknown or weight.
- form: KFormUnknown | KHodge#
- form_field: KFormUnknown#
- property primal_order: UnknownFormOrder#
Return the order of the primal.
Forming Expressions#
From these basic building blocks, TermEvaluatable
objects can
be created. These represent an expression, which can be evaluated,
provided degrees of freedom of associated KFormUnknown
are known.
Quite a few operators are implemented on it, which allow for scaling,
adding, or subtracting these together.
- class mfv2d.kform.TermEvaluatable(label: str, weight: KWeight)[source]#
Terms which can be evaluated as blocks of the system matrix.
This is a base class for all terms which can be evaluated as blocks of the system.
- __add__(other: TermEvaluatable, /) KSum [source]#
Add the term to another.
- __eq__(other: TermEvaluatable | None | Literal[0], /) KEquation [source]#
- __eq__(other, /) bool
Check equality or form an equation.
- __radd__(other: TermEvaluatable, /) KSum [source]#
Add the term to another.
- __rsub__(other: TermEvaluatable, /) KSum [source]#
Subtract the combination to another.
- __sub__(other: TermEvaluatable, /) KSum [source]#
Subtract the term from another.
- property unknowns: tuple[KFormUnknown, ...]#
Return all unknowns in the term.
- property vector_fields: tuple[Function2D | KFormUnknown, ...]#
Return all vector fields.
The most basic of these is the KInnerProduct
, which represents
an inner product between a weight form and an unknown form.
- class mfv2d.kform.KInnerProduct(a: KForm, b: KForm, /)[source]#
Inner product of a primal and dual form.
An inner product must be taken with primal and dual forms of the same k-order. The discrete version of an inner product of two k-forms is expressed as a discrete inner product on the mass matrix:
\[\left< p^{(k)}, q^{(k)} \right> = \int_{\mathcal{K}} p^{(k)} \wedge \star q^{(k)} = \vec{p}^T \mathbb{M}^k \vec{q}\]- property unknowns: tuple[KFormUnknown, ...]#
Return all unknowns in the sum.
- property vector_fields: tuple[Function2D | KFormUnknown, ...]#
Return all vector fields in the sum.
Next is the family of KExplicit
terms. These do not depend on any
unknown forms and can as such be evaluated explicity. These also may only
appear on the right side of any KEquation
formed.
- class mfv2d.kform.KExplicit(label: str, weight: KWeight, func: Callable | None = None)[source]#
Base class for explicit terms.
This type just implements some common functionality.
- property unknowns: tuple[KFormUnknown, ...]#
Return all unknowns (there are none).
- property vector_fields: tuple[Function2D | KFormUnknown, ...]#
Return all vector fields (there are none).
First of the KExplicit
subtypes is the KElementProjection
,
which is used to represent the L^2
projection on the element.
- class mfv2d.kform.KElementProjection(label: str, weight: KWeight, func: Callable | None = None)[source]#
Element integral of the function with the basis.
This is used to form the right side of the systems of equations coming from a forcing function.
Second is the the KBoundaryProjection
, which represents a boundary
integral for an element. It is used to describe weak boundary conditions.
- class mfv2d.kform.KBoundaryProjection(label: str, weight: KWeight, func: Callable | None = None)[source]#
Boundary integral of a forcing.
This is intended to be used to define boundary conditions. Given that the function to be projected is denoted by \(f\) and the weight function is denoted by \(w\), this term represents the integral
\[\int_{\partial \Omega} f^{(k)} \wedge \star w^{(k + 1)}\]Such terms typically arise from weak boundary conditions.
As the last TermEvaluatable
subtype there is KSum
type.
This represents a linear combination of other TermEvaluatable
types. It is actually a linear combination of the terms, as each can
have its own coefficient. When two KSum
objects are added together,
they are concatenated, so KSum
should never contain another
KSum
. All terms in the sum must use the exact same weight form.
- class mfv2d.kform.KSum(*pairs: tuple[float, TermEvaluatable])[source]#
Linear combination of differential form inner products.
- Parameters:
*pairs (tuple of float and KFormInnerProduct) – Coefficients and the inner products.
- property implicit_terms: tuple[tuple[float, TermEvaluatable], ...]#
Get all implicit terms.
- split_terms_linear_nonlinear() tuple[KSum | None, KSum | None] [source]#
Split the sum into linear implicit and non-linear implicit terms.
- Returns:
KSum – All linear terms. If there are no linear implicit terms, it is None instead.
KSum – All non-linear terms. If there are no non-linear implicit terms, it is None instead.
- property unknowns: tuple[KFormUnknown, ...]#
Return all unknowns in the sum.
- property vector_fields: tuple[Function2D | KFormUnknown, ...]#
Return all vector fields in the sum.
Equations and Systems#
When two expressions are related as being equal with the ==
operator,
the result is a KEquation
. It consists of a left and right side.
The left must contain at least one KInnerProduct
term and no
KExplicit
terms. Both sides must also use a matching weight form.
- class mfv2d.kform.KEquation(left: KSum, right: KSum)[source]#
Equation of differential forms and weights, consisting of a left and a right side.
The equation represents an equation where all the implicit terms are on the left side and all explicit ones are on the right side.
- Parameters:
left (KSum or KInnerProduct) – Term representing the implicit part of the equation with all the unknown forms.
right (KFormProjection) – The form representing the explicit part of the equation.
A collection of equations form a KFormSystem
. This type also provides
useful utilities for identifying different terms, extracting vector fileds,
weights, unknowns, and others.
- class mfv2d.kform.KFormSystem(*equations: KEquation, sorting: Callable[[KForm], Any] | None = None)[source]#
System of equations of differential forms, which are optionally sorted.
This is a collection of equations, which fully describe a problem to be solved for the degrees of freedom of differential forms.
- Parameters:
- unknown_forms: tuple[KFormUnknown, ...]#
- vector_fields: tuple[Function2D | KFormUnknown, ...]#