4.2.3. ModGlue – Combining Modules into Global Arrays
ModGlue_CombineModules is the single routine that transforms the
per-module variable descriptions registered by MV_AddVar /
MV_AddMeshVar / MV_AddModule (see Module Variables (ModVar)) into a
monolithic view of the coupled system. The output of the routine is a
ModGlueType structure whose Vars member holds globally indexed
arrays for every state, input, and output variable that belongs to a
specified set of modules. These global arrays underpin both the solver
Jacobian construction (Solver) and the linearization
procedure (Linearization).
Fig. 4.1 Complete data-structure hierarchy used by the glue code. Types shown on
the left (DatLoc, Field ID, Variable Flag) are referenced from
each ModVarType. ModDataType (centre, per module) is collected into
the top-level ModGlueType (right) by ModGlue_CombineModules.
4.2.3.1. The ModGlueType structure
ModGlueType is defined in modules/openfast-library/src/Glue_Types.f90:
type ModGlueType
character(ChanLen) :: Name ! Label (e.g. 'Solver', 'Lin')
type(ModDataType), allocatable :: ModData(:) ! Per-module view
type(ModVarsType) :: Vars ! Combined variable arrays
type(ModLinType) :: Lin ! Linearization matrices
type(VarMapType), allocatable :: VarMaps(:) ! Relevant mappings
end type ModGlueType
Key members:
Member |
Description |
|---|---|
|
One entry per module included in this glue instance. Each entry is a
filtered copy of the original |
|
Concatenated array of |
|
Concatenated array of |
|
Concatenated array of |
|
Total number of scalar values in each group (sum of |
|
Holds linearization operating-point arrays ( |
|
Filtered subset of the global |
4.2.3.2. The iLoc index range
After ModGlue_CombineModules returns, each variable in
ModGlue%Vars%x / %u / %y carries an iLoc(1:2) range that locates it
inside the glue-level data vectors. Specifically, for a variable at position
k in ModGlue%Vars%x:
iLoc(1)– index of its first scalar value in a length-Vars%Nxarray.iLoc(2)– index of its last scalar value.
This is the glue-local index after filtration; the corresponding
per-module position is still available through the variable’s iGlu range
(set earlier by FAST_SolverInit → CalcVarGlobalIndices).
The iLoc / iGlu separation means the same variable descriptor can live
simultaneously in the per-module ModData view, the solver m%Mod
view, and the linearization m%ModGlue view with consistent, non-overlapping
index ranges in each context.
4.2.3.3. What ModGlue_CombineModules does
The subroutine signature is:
subroutine ModGlue_CombineModules(ModGlue, ModDataAry, Mappings, &
iModAry, FlagFilter, Linearize, &
ErrStat, ErrMsg, Name)
Argument |
Intent |
Description |
|---|---|---|
|
|
The |
|
|
Full array of per-module data registered by the glue code. |
|
|
Full array of mesh and variable mappings. |
|
|
Ordered list of indices into |
|
|
Bitmask of |
|
|
When |
|
|
Human-readable label stored in |
The four main steps performed internally are:
Count and allocate. Iterate over each module in
iModAryand count how many variable descriptors (and how many total scalar values) pass theFlagFiltertest for each of the x, u, y groups. AllocateModGlue%Vars%x / %u / %yto exactly those sizes.Copy and re-index. For each module, copy the filtered
ModVarTypedescriptors intoModGlue%Varsand assign contiguousiLocranges so the glue-level index is consecutive across all modules. The per-moduleModGlue%ModData(i)%Varssub-arrays receive the same descriptors with the sameiLocso that scatter/gather routines can operate directly on global vectors. Linear name prefixes (e.g."ED ","BD_1 ") are prepended toLinNamesat this step to produce globally unique channel labels.Filter mappings. Iterate over the full
Mappingsarray and retain only those where bothiModSrcandiModDstappear iniModAry. Re-index the retained entries against the localModDataposition (not the globalModDataAryposition) and store them inModGlue%VarMaps.Allocate linearization storage (only when
Linearize=.true.). Allocate theLinoperating-point vectors (x,dx,u,y) and all six Jacobian matrices (dXdx,dXdu,dYdx,dYdu,dUdu,dUdy) dimensioned byVars%NxandVars%Nu / Ny.
4.2.3.4. Where ModGlue_CombineModules is called
The routine is called twice during OpenFAST initialisation, producing two
distinct ModGlueType instances with different variable selections:
4.2.3.4.1. m%Mod – the Solver glue module (in FAST_SolverInit)
iMod = [p%iModTC, p%iModOpt1] ! TC + Option-1 indices
call ModGlue_CombineModules(m%Mod, GlueModData, GlueModMaps, iMod, &
VF_Solve, .true., ErrStat2, ErrMsg2, &
Name='Solver')
Modules included: tight-coupling (TC) modules plus Option-1 modules.
Variable filter:
VF_Solve. This flag is set byFAST_SolverInit → SetVarSolveFlagson every variable that must appear in the Newton iteration: TC continuous states, motion/load mesh inputs/outputs involved in inter-module couplings, and any variable-to-variable mapped inputs/outputs (see Solver for the full selection criteria).Linearize:
.true.— the Jacobian matrices are allocated here because the solver’s Newton linear system reuses the same storage as the operating-point linearization.Result:
m%Mod%Vars%Nxequals the number of TC displacement/velocity scalars (p%NumQ);m%Mod%Vars%Nucovers all TC and Option-1 inputs flaggedVF_Solve. The Jacobian dimensionp%NumJ = p%NumQ + p%NumUfollows directly.
4.2.3.4.2. m_FAST%ModGlue – the Linearization glue module (in ModGlue_Init)
LinFlags = VF_Linearize + VF_Mapping + VF_Mesh
call ModGlue_CombineModules(m%ModGlue, m%ModData, m%Mappings, &
p%Lin%iMod, LinFlags, &
p_FAST%Linearize, ErrStat2, ErrMsg2, &
Name="Lin")
Modules included: all modules participating in linearization, in the canonical order set by
p%Lin%iMod(InflowWind → SeaState → ServoDyn → ElastoDyn → BeamDyn → AeroDyn → HydroDyn → SubDyn → MAP++ → MoorDyn).Variable filter:
VF_Linearize + VF_Mapping + VF_Mesh. TheVF_Linearizeflag is applied per variable according to theLinInputs/LinOutputssettings in the input file;VF_Mapping/VF_Meshensure that mesh-coupled variables are always included so that coupling Jacobians can be assembled even when a variable is not a formal linearization output.Linearize:
p_FAST%Linearize— only allocates the full full-system matrices when linearization is requested.Result:
m%ModGlue%Vars%Nx / %Nu / %Nygive the dimensions of the A, B, C, D, dUdu, dUdy matrices written to the.linfile.
4.2.3.5. How the global index enables matrix assembly
Because every variable descriptor carries its iLoc range in the glue
Vars array, scatter and gather operations on global data vectors become
trivial index-range assignments. For example, to pack a module’s state
vector into the global solver vector x_global:
do iVar = 1, size(ModData%Vars%x)
associate (Var => ModData%Vars%x(iVar))
x_global(Var%iLoc(1):Var%iLoc(2)) = x_mod(Var%iGlu(1):Var%iGlu(2))
end associate
end do
And the corresponding gather from the global Jacobian column into a
per-module sub-column requires no offset arithmetic: the iLoc index
already encodes the correct global position.
Similarly, the VarMaps array stored in ModGlueType makes the
Jacobian coupling terms self-contained. During
BuildJacobianTC / BuildJacobianIO (in FAST_Solver.f90) and
ModGlue_Linearize_OP (in FAST_ModGlue.f90), the loop is simply:
do i = 1, size(ModGlue%VarMaps)
! perturb source output, evaluate destination input change
! scatter result into J(iVarDst%iLoc, iVarSrc%iLoc)
end do
No module-specific knowledge is needed at this level — the ModGlueType
instance is fully self-describing.