Domain management

Having multiple coupled subdomains is very common in multiphyics problems. Furthermore it is also not uncommon to have mixed(-dimensional) grids, think e.g. about the Purkinje network and the myocardium in chamber electrophysiology simulations. To manage these cases Thunderbolt.jl comes with some utilities. The first one is the SimpleMesh, which is takes a [Ferrite.Grid] and extracts information about the subdomains. The subdomains are split up by element type to handle mixed grids properly.

This subdomain information can then be used to construct [Ferrite.SubDofHandler] to manage the field variables on subdomains:

Missing docstring.

Missing docstring for Thunderbolt.add_subdomain!. Check Documenter's build log for details.

Furthermore to manage data on subdomains we provide a non-uniform matrix-like data type.

Thunderbolt.DenseDataRangeType

Examples:

  • DenseDataRange{Vector{Int}, Vector{Int}} to map dofs (outer index) to elements (inner index)
  • DenseDataRange{Vector{Vec{3,Float64}}, Vector{Int}} to store fluxes per quadrature point (inner index) per element (outer index)
source
Missing docstring.

Missing docstring for Thunderbolt.get_data_for_index. Check Documenter's build log for details.

Two examples where this is used: The storate of element assembly and quadrature data on mixed grids.

Multidomain Assembly

The operators in Thunderbolt work very similar w.r.t. the management of multiple domains. The all follow the following pattern:

function update_operator(op, time)
    # Sanity check to see if the operator is internally consistent
    # e.g. are all fields are present in the associated dof handlers, ...
    check_internal_correctness(op)
    # Depending on the operator and matrix type we get the correct assembler
    assembler = instantiate_specific_assembler(op)
    for sdh in op.dh.subdofhandlers
        # We create a new or get a from the operator some scratch to make the assembly loop allocation free
        # and possibly to precompute some generic stuff
        weak_form_cache = setup_or_query_cache_for_subdomain(op, sdh)
        # This step also acts a function barrier and contains the hot loop over the elements on the subdomain
        # which actually fills the matrix
        assemble_on_subdomain!(assembler, sdh, weak_form_cache)
    end
    # Some assemblers need a finalization step, e.g. distributed assembly, COO assembly, EA collapse, ...
    finalize_assembly(assembler)