irksome.ufl package

Submodules

irksome.ufl.deriv module

irksome.ufl.deriv.Dt(f, order=1)[source]

Short-hand function to produce a TimeDerivative of a given order.

exception irksome.ufl.deriv.IrksomeImportOrderException[source]

Bases: Exception

class irksome.ufl.deriv.TimeDerivative(f)[source]

Bases: Derivative

UFL node representing a time derivative of some quantity/field. Note: Currently form compilers do not understand how to process these nodes. Instead, Irksome pre-processes forms containing TimeDerivative nodes.

Initalise.

property ufl_free_indices
property ufl_index_dimensions
property ufl_shape
class irksome.ufl.deriv.TimeDerivativeRuleDispatcher(t=None, timedep_coeffs=None, **kwargs)[source]

Bases: DAGTraverser

Mapping rules to splat out time derivatives so that replacement should work on more complex problems.

Initialise.

process(o)[source]
process(o: TimeDerivative)
process(o: BaseForm)
process(o: Expr)

Process node by type.

Args:
o:

UFL expression to start DAG traversal from.

**kwargs:

Keyword arguments for the process singledispatchmethod.

Returns:

Processed Expr.

time_derivative(o)[source]
class irksome.ufl.deriv.TimeDerivativeRuleset(t=None, timedep_coeffs=None)[source]

Bases: GenericDerivativeRuleset

Apply AD rules to time derivative expressions.

Initialise.

constant(o)[source]
process(o)[source]
process(o: ConstantValue)
process(o: SpatialCoordinate)
process(o: Coefficient)
process(o: Argument)
process(o: TimeDerivative, f)
process(o: Variable, *operands)
process(o: ReferenceValue, *operands)
process(o: ReferenceGrad, *operands)
process(o: Indexed, *operands)
process(o: Grad, *operands)
process(o: Div, *operands)
process(o: Derivative, *operands)
process(o: Curl, *operands)
process(o: Conj, *operands)

Process o.

Args:

o: Expr to be processed.

Returns:

Processed object.

terminal(o)[source]
terminal_modifier(o, *operands)[source]
time_derivative(o, f)[source]
irksome.ufl.deriv.apply_time_derivatives(expression, t=None, timedep_coeffs=None)[source]
irksome.ufl.deriv.check_irksome_import_order()[source]

Check that irksome has been imported early enough.

Due to the inadequacies of the UFL type system, it is not possible to define a new UFL type once any ufl MultiFunction has been used.

This restriction can be removed once all MultiFunctions have been transitioned to ufl.corealg.dag_traverser.DAGTraverser.

irksome.ufl.deriv.expand_time_derivatives(expression, t=None, timedep_coeffs=None)[source]

irksome.ufl.estimate_degrees module

class irksome.ufl.estimate_degrees.TimeDegreeEstimator(degree_mapping=None, **kwargs)[source]

Bases: DAGTraverser

Time degree estimator.

This algorithm is exact for a few operators and heuristic for many.

Initialise.

add_degrees(v, *ops)[source]
conditional(v, c, *ops)[source]
form(o)[source]
formsum(o)[source]
integral(o)[source]
interpolate(o)[source]
math_function(v, a)[source]

Apply to math_function.

Using the heuristic: degree(sin(const)) == 0 degree(sin(a)) == degree(a)+2 which can be wildly inaccurate but at least gives a somewhat high integration degree.

max_degree(v, *ops)[source]
minmax(v, *ops)[source]
non_numeric(v, *args)[source]
not_handled(v, *ops)[source]
power(v, a, b)[source]

Apply to power.

If b is a positive integer: degree(a**b) == degree(a)*b otherwise use the heuristic: degree(a**b) == degree(a) + 2.

process(o)[source]
process(o: FormSum)
process(o: Interpolate)
process(o: Form)
process(o: Integral)
process(o: SpatialCoordinate)
process(o: ConstantValue)
process(o: Coefficient)
process(o: Cofunction)
process(o: Argument)
process(o: TimeDerivative, degree)
process(o: IndexSum, degree, *ops)
process(o: ComponentTensor, degree, *ops)
process(o: Variable, degree, *ops)
process(o: ReferenceValue, degree, *ops)
process(o: ReferenceGrad, degree, *ops)
process(o: Indexed, degree, *ops)
process(o: Grad, degree, *ops)
process(o: Div, degree, *ops)
process(o: Derivative, degree, *ops)
process(o: Curl, degree, *ops)
process(o: Conj, degree, *ops)
process(o: Abs, degree, *ops)
process(v: Inverse, *ops)
process(v: Determinant, *ops)
process(v: Transposed, *ops)
process(v: Trace, *ops)
process(v: Sym, *ops)
process(v: Skew, *ops)
process(v: Cofactor, *ops)
process(v: ExprMapping, *ops)
process(v: ExprList, *ops)
process(v: ListTensor, *ops)
process(v: Sum, *ops)
process(v: Cross, *ops)
process(v: Outer, *ops)
process(v: Dot, *ops)
process(v: Inner, *ops)
process(v: Product, *ops)
process(v: Division, *ops)
process(v: Power, a, b)
process(v: MathFunction, a)
process(v: Conditional, c, *ops)
process(v: MaxValue, *ops)
process(v: MinValue, *ops)
process(v: MultiIndex, *args)
process(v: Condition, *args)
process(v: Label, *args)

Process node by type.

Args:
o:

UFL expression to start DAG traversal from.

**kwargs:

Keyword arguments for the process singledispatchmethod.

Returns:

Processed Expr.

terminal(o)[source]
terminal_modifier(o, degree, *ops)[source]
time_derivative(o, degree)[source]
irksome.ufl.estimate_degrees.estimate_time_degree(expression, test_degree, trial_degree, t=None, timedep_coeffs=None)[source]
irksome.ufl.estimate_degrees.get_degree_mapping(expression, test_degree, trial_degree, t=None, timedep_coeffs=None)[source]

Map time-dependent terminals to their polynomial degree.

Parameters:
  • expression – a ufl.BaseForm or ufl.Expr.

  • test_degree – the temporal polynomial degree of the test space.

  • trial_degree – the temporal polynomial degree of the trial space.

  • t – the time variable as a Constant or Function in the Real space.

  • timedep_coeffs – a list of Function that depend on time.

Returns:

a dict mapping time-dependent terminals to their degree in time.

irksome.ufl.lag module

irksome.ufl.lag.lag(expr)[source]

Mark a sub-expression to be evaluated only at the start of the timestep during the implicit solve.

irksome.ufl.manipulation module

Manipulation of expressions containing TimeDerivative terms.

These can be used to do some basic checking of the suitability of a Form for use in Irksome (via check_integrals), and splitting out terms in the Form that contain a time derivative from those that don’t (via split_time_derivative_terms).

class irksome.ufl.manipulation.SplitTimeForm(time: BaseForm, remainder: BaseForm)[source]

Bases: NamedTuple

A container for a form split into time terms and a remainder.

Create new instance of SplitTimeForm(time, remainder)

remainder: BaseForm

Alias for field number 1

time: BaseForm

Alias for field number 0

irksome.ufl.manipulation.check_integrals(integrals: Sequence[Integral], t: Expr = None, timedep_coeffs: Sequence[Coefficient] = (), expect_time_derivative: bool = True)[source]

Check a list of integrals for linearity in the time derivative.

Parameters:
  • integrals – list of integrals.

  • timedep_coeffs – The time-dependent coefficients.

  • expect_time_derivative – Are we expecting to see a time derivative?

Raises:

ValueError – if we are expecting a time derivative and don’t see one, or time derivatives are applied nonlinearly, to more than one coefficient, or more than first order.

irksome.ufl.manipulation.has_nonlinear_time_derivative(F, u0)[source]

True iff F contains a TimeDerivative of an expression that is nonlinear in u0 – i.e. Dt(g(u0)) for some nonlinear g. These cases lose mass conservation when chain-ruled through the stage-derivative form, and require the conservative two-evaluation discretisation.

For each Dt(f) in the form, the Gateaux derivative of f with respect to u0 is taken in a trial direction. If the derivative still depends on u0, f is nonlinear in u0. This delegates the classification of linear operators (Grad, Div, Indexed, restrictions, ListTensor, ComponentTensor, …) to UFL’s own derivative machinery rather than maintaining a parallel exemption list inside Irksome.

Warning

The detection is syntactic: it checks whether u0 appears under Dt after differentiation. If a user creates an intermediate Function whose values were interpolated from an expression in u0 and then writes Dt(that_intermediate), the syntactic dependence on u0 is lost and this function will declare the form safe. The resulting discretisation is not mass-conservative. Always wrap the symbolic expression directly in Dt (as Dt(theta(u)), not Dt(theta_function)).

irksome.ufl.manipulation.remove_time_derivatives(F: Form)[source]

Helper function to strip all time derivatives from a Form

irksome.ufl.manipulation.split_time_derivative_terms(form: BaseForm, t: Expr = None, timedep_coeffs: Sequence[Coefficient] = ()) SplitTimeForm[source]

Split terms from a Form.

This splits a form (a sum of integrals) into those integrals which do contain a TimeDerivative acting on timedep_coeffs and those that don’t.

Parameters:
  • form – The form to split.

  • t – The time variable.

  • timedep_coeffs – The time-dependent coefficients.

Returns:

a SplitTimeForm tuple.

Raises:

ValueError – if the form does not apply anything other than first-order time derivatives to a single coefficient.

Module contents