GridapSolvers.MultilevelTools

Nested subpartitions

One of the main difficulties of multilevel algorithms is dealing with the complexity of having multiple subcommunicators. We provide some tools to deal with it. In particular we introduce HierarchicalArrays.

GridapSolvers.MultilevelTools.HierarchicalArrayType
HierarchicalArray{T,A,B} <: AbstractVector{T}

Array of hierarchical (nested) distributed objects. Each level might live in a different subcommunicator. If a processor does not belong to subcommunicator ranks[i], then array[i] is nothing.

However, it assumes: - The subcommunicators are nested, so that ranks[i] contains ranks[i+1]. - The first subcommunicator does not have empty parts.

source
Base.mapFunction
Base.map(f::Function,args::Vararg{HierarchicalArray,N}) where N

Maps a function to a set of HierarchicalArrays. The function is applied only in the subcommunicators where the processor belongs to.

source
GridapSolvers.MultilevelTools.with_levelFunction
with_level(f::Function,a::HierarchicalArray,lev::Integer;default=nothing)

Applies a function to the lev-th level of a HierarchicalArray. If the processor does not belong to the subcommunicator of the lev-th level, then default is returned.

source

ModelHierarchies and FESpaceHierarchies

This objects are the multilevel counterparts of Gridap's DiscreteModel and FESpace.

GridapSolvers.MultilevelTools.ModelHierarchyType
const ModelHierarchy = HierarchicalArray{<:ModelHierarchyLevel}

A ModelHierarchy is a hierarchical array of ModelHierarchyLevel objects. It stores the adapted/redistributed models and the corresponding subcommunicators.

For convenience, implements some of the API of DiscreteModel.

source
GridapSolvers.MultilevelTools.CartesianModelHierarchyFunction
CartesianModelHierarchy(
  ranks::AbstractVector{<:Integer},
  np_per_level::Vector{<:NTuple{D,<:Integer}},
  domain::Tuple,
  nc::NTuple{D,<:Integer};
  nrefs::Union{<:Integer,Vector{<:Integer},Vector{<:NTuple{D,<:Integer}},NTuple{D,<:Integer}},
  map::Function = identity,
  isperiodic::NTuple{D,Bool} = Tuple(fill(false,D)),
  add_labels!::Function = (labels -> nothing),
) where D

Returns a ModelHierarchy with a Cartesian model as coarsest level. The i-th level will be distributed among np_per_level[i] processors. Two consecutive levels are refined by a factor of nrefs[i].

Parameters:

  • ranks: Initial communicator. Will be used to generate subcommunicators.
  • domain: Tuple containing the domain limits.
  • nc: Tuple containing the number of cells in each direction for the coarsest model.
  • np_per_level: Vector containing the number of processors we want to distribute each level into. Requires a tuple np = (np_1,...,np_d) for each level, then each level will be distributed among prod(np) processors with np_i processors in the i-th direction.
  • nrefs: Vector containing the refinement factor for each level. Has nlevs-1 entries, and each entry can either be an integer (homogeneous refinement) or a tuple with D integers (inhomogeneous refinement).
source
GridapSolvers.MultilevelTools.P4estCartesianModelHierarchyFunction
P4estCartesianModelHierarchy(
  ranks,np_per_level,domain,nc::NTuple{D,<:Integer};
  num_refs_coarse::Integer = 0,
  add_labels!::Function = (labels -> nothing),
  map::Function = identity,
  isperiodic::NTuple{D,Bool} = Tuple(fill(false,D))
) where D

Returns a ModelHierarchy with a Cartesian model as coarsest level, using GridapP4est.jl. The i-th level will be distributed among np_per_level[i] processors. The seed model is given by cmodel = CartesianDiscreteModel(domain,nc).

source
GridapSolvers.MultilevelTools.FESpaceHierarchyType
const FESpaceHierarchy = HierarchicalArray{<:FESpaceHierarchyLevel}

A FESpaceHierarchy is a hierarchical array of FESpaceHierarchyLevel objects. It stores the adapted/redistributed fe spaces and the corresponding subcommunicators.

For convenience, implements some of the API of FESpace.

source

Grid transfer operators

To move information between different levels, we will require grid transfer operators. Although any custom-made operator can be used, we provide some options.

Local projection maps

GridapSolvers.MultilevelTools.ReffeProjectionMapType
struct ReffeProjectionMap{T} <: LocalProjectionMap{T}
  op      :: Operation{T}
  reffe   :: Tuple{<:ReferenceFEName,Any,Any}
  qdegree :: Int
end

Map that projects a field/field-basis onto another local reference space given by a ReferenceFE.

Example:

model = CartesianDiscreteModel((0,1,0,1),(2,2))

reffe_h1 = ReferenceFE(QUAD,lagrangian,Float64,1,space=:Q)
reffe_l2 = ReferenceFE(QUAD,lagrangian,Float64,1,space=:P)
U = FESpace(model,reffe_h1)
u_h1 = interpolate(f,U)

Ω = Triangulation(model)
dΩ = Measure(Ω,2)

Π = LocalProjectionMap(reffe_l2)
u_l2 = Π(u_h1,dΩ)
source
GridapSolvers.MultilevelTools.SpaceProjectionMapType
struct SpaceProjectionMap{T} <: LocalProjectionMap{T}
  op      :: Operation{T}
  space   :: A
  qdegree :: Int
end

Map that projects a CellField onto another FESpace. Necessary when the arrival space has constraints (e.g. boundary conditions) that need to be taken into account.

source