Loading...
Searching...
No Matches
<tt>form_lazy_expr</tt>

form expressions: concept and class hierarchy

# Description

This page explains the design of the class hierarchy used for the representation of `form` expressions and how they fit together. Casual users probably need not concern themselves with these details, but it may be useful for both advanced users and Rheolef's developers.

# Expression features

Expressions involving forms are computed in a lazy way: nothing is done until a conversion to the `form` class is explicitly required. Recall that `form` are represented by distributed sparse matrix. This approach allows many memory and computing time optimizations. Moreover, it enable new features, such as matrix inversion on the fly during assembly process when matrix are block diagonal at the element level. Such a feature is heavily used by hybrid discontinuous Galerkin and HHO methods. In these cases, complex expressions are evaluated in only one loop instead of several ones with temporary variables. Note that matrix-matrix products cannot be assembled efficiently in a lazy way, since the sparsity pattern is expected to change: in these cases, temporaries are used.

The efficient lazy implementation is obtained by using the expression template technique in C++. In consequence, if `a` is a `form`, then, for instance, `-a` and `lambda*a`, where `lambda` is a scalar, are no longer a `form` but a form expression. It leads to represent at compile time an expression tree by a hierarchy of classes. Each class represent a node of the expression tree while leaves, also called terminals, are the field themselves.

Any class representing an expression node tree derives from the `form_lazy_base` and is called here a `form_lazy`: it is represented by a C++ concept. Since concepts in C++ would be available only with the forthcoming 2020 standard, these concepts are actually represented by traits in Rheolef.

# Detailed specifications

The `form_lazy` concept is defined by:

       form_lazy:
            form
          | integrate (opt_domain form_test opts)
          | +- form_lazy
          | constant * form_lazy
          | form_lazy / constant
          | form_lazy +- form_lazy
          | form_lazy * form_lazy
          | trans (form_lazy)
          | inv (form_lazy)
          | lump (form_lazy)

The `opt_domain` stands for an optional domain specification and opts for an optional `integrate_option` variable. Finally, the `form_test` concept involved by the `integrate` call is defined by:

        form_test:
            field_test * field_trial
            field_trial * field_test

where `field_test` has been defined by `field_lazy` and `field_trial` is obtained by replacing `test` by `trial` in the field expression.

# Implementation

The implementation is similar to those of the `field_lazy` class hierarchy.