◆ FORGE Suite
GitHubMechanical Neuroimaging Lab · Univ. of Delaware
Skip to content

How to Run a Forward Solve

Compute the displacement field a known material distribution would produce. This is the forward problem: useful for generating synthetic data, checking a mesh and its boundary conditions, and validating a material model.

For the reconstruction problem, see Your First Inversion instead.

If you already have a runfile describing the problem, this is the whole job:

julia
using Sentinel

config = parse_runfile("problem.dat")
setup  = setup_forward_problem(config, basedir)
# setup carries: grid, dh, cv_disp, cv_press, model, material, bcs, K, ...

setup_forward_problem reads every referenced file (.nod, .elm, .dsp, .mtr, .bnd, .bcs), builds the DOF handler, interpolates the material mesh, and assembles the stiffness matrix. See Configuring Inverse Runfiles for the file format.

Assembling by hand

Use this when you are building a problem programmatically rather than from files — for instance to generate synthetic data on a mesh you constructed.

julia
using Sentinel, Ferrite

# 1. Mesh and DOF handler
grid, full_conn = read_mesh_legacy("mesh.nod", "mesh.elm")
dh = setup_hex27_dofhandler(grid)

# 2. Cell values for integration (quadratic displacement, linear pressure)
ip = Lagrange{RefHexahedron, 2}()
qr = QuadratureRule{RefHexahedron}(3)
cv_disp  = CellValues(qr, ip)
cv_press = CellValues(qr, Lagrange{RefHexahedron, 1}())

# 3. Material model and properties
model = IsotropicIncompressible()
# ... build a GaussPointMaterial, or a Material plus GP2Mtr ...

# 4. Assemble the stiffness matrix at the drive frequency
K = allocate_stiffness(dh, model)
assemble_stiffness!(K, dh, cv_disp, cv_press, model, props, omega)

# 5. Apply boundary conditions
bcs = read_bcs_file("mesh.bcs")
f = zeros(ComplexF64, size(K, 1))
apply_dirichlet!(K, f, bcs, 1)          # displacement set 1

# 6. Solve
disp = Displacement()
init_displacement!(disp, ndofs(dh) ÷ 3, getncells(grid), 4, 1)
forward_solve!(disp, K, f, model, 1; solver = DirectSolver())

omega is the angular frequency, 2πf, not the frequency in hertz.

The mixed displacement–pressure formulation is why there are two sets of cell values: models with pressure DOFs interpolate displacement quadratically and pressure linearly. See the Mathematical Reference for the formulation and How to Choose a Material Model for which models are mixed.

Choosing a solver

forward_solve! takes any AbstractLinearSolver. DirectSolver is the straightforward choice; for repeated solves on the same sparsity pattern, CachedDirectSolver reuses the factorization. See Solver Backends for the full set and How to Tune Performance for which to pick at scale.

Next