eval#
This submodule is responsible for conversion of system from its abstract syntax
tree (AST) representation, which is the job of mfv2d.kform
submodule,
into a form which can be understood and executed by C code in
mfv2d._mfv2d
.
This process is done in the following steps:
First, the AST is converted into Python bytecode-like objects (subtypes of
MatOp
).Resulting expression is simplified as much as possible by the
simplify_expression()
function.Simplified expression is translated into C compatible values (sequence of
int
,float
, andMatOpCode
values).
After this is done for each of the blocks of the in the system,
the two-dimensional square sequence can be passed to the
mfv2d._mfv2d.compute_element_matrix()
or
mfv2d._mfv2d.compute_element_vector()
functions.
Matrix Operations#
For the first step in instruction generation, subtypes of
the MatOp
type are used. These are all documented
bellow.
- class mfv2d.eval.MatOp[source]#
Matrix operations which can be created.
This is just a base class for all other matrix operations.
- class mfv2d.eval.MassMat(order: UnknownFormOrder, inv: bool)[source]#
Mass matrix multiplication.
Multiply by either mass matrix or its inverse.
- Parameters:
order (UnknownFormOrder) – Order of the k-form for the mass matrix.
inv (bool) – Should the matrix be inverted.
- order: UnknownFormOrder#
- class mfv2d.eval.Incidence(begin: UnknownFormOrder, dual: int)[source]#
Incidence matrix.
Specifies application of an incidence matrix.
- Parameters:
begin (UnknownFormOrder) – Order of the k-form for the incidence matrix from which to apply it.
dual (bool) – Should the incidence matrix be applied as the dual.
- begin: UnknownFormOrder#
- class mfv2d.eval.Push[source]#
Push the matrix on the stack.
Used for matrix multiplication and summation.
- class mfv2d.eval.MatMul[source]#
Multiply two matrices.
Multiply the current matrix with the one currently on the top of the stack.
- class mfv2d.eval.Scale(k: float)[source]#
Scale the matrix.
Mutliply the entire matrix with a constant.
- Parameters:
k (float) – Value of the constant by which to scale the matrix.
- class mfv2d.eval.Sum(count: int)[source]#
Sum matrices together.
Sum the top
count
matrices on the stack with the current matrix.- Parameters:
count (int) – Number of matrices to sum to the current matrix. As such must be greater than zero.
- class mfv2d.eval.InterProd(starting_order: UnknownFormOrder, field_index: int, dual: bool, adjoint: bool)[source]#
Compute interior product.
This is the most complicated operation.
- Parameters:
starting_order (UnknownFormOrder) – Order of the k-form to which the interior product should be applied.
field_index (int) – Index of the vector/scalar field from which the values of are taken.
dual (bool) – Should the dual interior product be applied instead of the primal.
adjoint (bool) – Should the adjoint interior product be applied, which is used by the Newton-Raphson solver.
- starting_order: UnknownFormOrder#
AST Translation#
The translation from the AST form into the Python bytecode
is performed by translate_equation()
function. This
is a thin wrapper around _translate_equation()
function,
which produces very sub-optimal bytecode. As such, the function
will (when specified) call simplify_expression()
to simplify
the bytecode before returning.
- mfv2d.eval.translate_equation(form: Term, vec_fields: Sequence[Function2D | KFormUnknown], newton: bool, simplify: bool) dict[Term, list[MatOp]] [source]#
Compute the matrix operations on individual forms.
Parameter#
- formTerm
Form to evaluate.
- vec_fieldsSequence of Function2D or KFormUnknown
Sequence to use when determining the index of vector fields passed to evaluation function.
- newtonbool
When
True
, non-linear terms will yield terms two terms used to determine the derivative. Otherwise, only the terms to evaluate the value are returned.- simplifybool, default: True
Simplify the expressions at the top level
- returns:
Dictionary mapping forms to either a matrix that represents the operation to perform on them, or
float
, if it should be multiplication with a constant.- rtype:
dict of KForm -> array or float
- mfv2d.eval._translate_equation(form: Term, vec_fields: Sequence[Function2D | KFormUnknown], newton: bool, transpose: bool) dict[Term, list[MatOp]] [source]#
Compute the matrix operations on individual forms.
Parameter#
- formTerm
Form to evaluate.
- vec_fieldsSequence of Function2D or KFormUnknown
Sequence to use when determining the index of vector fields passed to evaluation function.
- newtonbool
When
True
, non-linear terms will yield terms two terms used to determine the derivative. Otherwise, only the terms to evaluate the value are returned.- transposebool
Should instructions be transposed.
- returns:
Dictionary mapping forms to either a matrix that represents the operation to perform on them, or
float
, if it should be multiplication with a constant.- rtype:
dict of KForm -> array or float
To check if the AST was correctly translated, or when debugging,
the expected result can be obtained by a call to
print_eval_procedure()
which will convert the iterable of
MatOp
into a str
.
Bytecode Simplifictaion#
Simplifictaion of the bytecode is handled by the simplify_expression()
function. It mainly focuses on eliminating Identity
operations,
fusing together Scale
, or applying MassMat
to its
invers.
Conversion to C Bytecode#
Conversion into “C-friendly” bytecode is done by converting the MatOp
values into MatOpCode
, int
, or float
values.
- class mfv2d.eval.MatOpCode(*values)[source]#
Operation codes.
Notes
These values must be kept in sync with the
matrix_op_t
enum in the C code, since that is how Python and C communicate with each other.- INVALID = 0#
- IDENTITY = 1#
- MASS = 2#
- INCIDENCE = 3#
- PUSH = 4#
- MATMUL = 5#
- SCALE = 6#
- SUM = 7#
- INTERPROD = 8#
The actual translation is handled by the translate_to_c_instructions()
function.
Putting it All Togehter#
Since the steps and related function and types are never used outside of
converting AST code into C bytecode, the functionality is wrapped
by the translate_system()
function, which performs the conversion
of an entire mfv2d.kform.KFormSystem
into the bytecode.
- mfv2d.eval.translate_system(system: KFormSystem, vector_fields: Sequence[Function2D | KFormUnknown], newton: bool) Sequence[Sequence[Sequence[MatOpCode | int | float] | None]] [source]#
Create the two-dimensional instruction array for the C code to execute.
This is abstracted further into a CompiledSystem
type, which
automatically extracts linear, non-linear, right implicit, and left
implicit terms, which is what the solver actually needs.
- class mfv2d.eval.CompiledSystem(system: KFormSystem)[source]#
System of equations compiled.
This is a convenience class which first compiles the system and splits it into explicit, linear implicit, and non-linear implicit equations, which are then further used by different parts of the solver.
- Parameters:
system (KFormSystem) – System to compile.
- lhs_full: Sequence[Sequence[Sequence[MatOpCode | int | float] | None]]#
All left-hand side codes of the equations. When evaluated, this will produce the full left side of the equation.
- linear_codes: Sequence[Sequence[Sequence[MatOpCode | int | float] | None]]#
All left-hand side codes of the equations, which are linear.