Migration Guide
This guide helps users transition from the Fortran MRE-Zone solver to Sentinel.jl.
File Format Compatibility
Sentinel reads and writes the same file formats as Fortran MRE-Zone:
| Format | Extension | Read | Write | Notes |
|---|---|---|---|---|
| Node coordinates | .nod | read_nod_file | write_nod_file | 3- or 4-column (with mtrltype) |
| Element connectivity | .elm | read_elm_file | write_elm_file | Hex27 or Tet4 |
| Displacement | .dsp | read_dsp_file | write_dsp_file | Complex 3-component |
| Material properties | .mtr | read_mtr_file | write_mtr_file | Per-property files |
| Pressure | .pre | read_pre_file | write_pre_file | Complex nodal/elemental |
| Boundary nodes | .bnd | read_bnd_file | write_bnd_file | Node index list |
| Boundary conditions | .bcs | read_bcs_file | write_bcs_file | Per-DOF conditions |
| Basis indices | .basis | read_basis_file | write_basis_file | Node subset for output |
| Mesh indices | .meshind | read_meshind_file | write_meshind_file | Structured grid indexing |
Runfile Support
Sentinel reads Fortran .dat runfiles directly:
config = parse_runfile("my_problem.dat")
setup = setup_forward_problem(config, basedir)The RunfileConfig struct stores all parsed data. Supported problem types:
problemtype=0: forward-onlyforwardtype=0: standard forward solveforwardtype=1: parameter test mode
Inverse problem runfiles (problemtype=1) will be supported in a future release.
Fortran to Julia Source Mapping
| Fortran Source | Julia Module | Description |
|---|---|---|
FEmaterial.f90 | types/materials.jl, properties.jl | Material types and property storage |
hex27.f90 | elements/*.jl | Element integration kernels |
tet4.f90 | elements/poroelastic.jl | Poroelastic tet4 kernel |
FEmesh.f90 | utils/material_mesh_interp.jl | GP2MTR mapping, material mesh |
fileio.f90 | io/file_io.jl | File I/O routines |
FEforward.f90 | forward/assembly.jl, solver.jl, adjoint.jl | Assembly, solve, adjoint |
FEgradient.f90 | inverse/gradient.jl | Adjoint gradient computation |
FEgaussnewton.f90 | optimization/*.jl | CG, GN, L-BFGS optimizers |
FEregularize.f90 | regularization/*.jl | All 10 regularization methods |
MRIhexmesh_v7p3.m | preprocessing/hex_mesh_generation.jl | Hex mesh from MRI |
WashU_DTI_Process.m | preprocessing/dti_processing.jl | DTI fiber processing |
API Correspondence
Assembly and Solve
| Fortran | Julia |
|---|---|
buildhex27stiffness | assemble_stiffness!(K, dh, cv_disp, cv_press, model, props, ω) |
applyBC | apply_dirichlet!(K, f, bcs, dispset) |
solvesystem | forward_solve!(disp, K, f, model, dispset; solver=...) |
adjointsystem | adjoint_solve!(adjnt, K, calc, meas, bcs, dispset; solver=...) |
Gradient and Optimization
| Fortran | Julia |
|---|---|
computegradient | compute_gradient!(grad, dh, cv_disp, calc, adjnt, model, material, gp2mtrs, meshes, ω) |
computeobjective | compute_objective(calc, meas) |
conjugategradient | conjugate_gradient!(material, ctx; max_iter, tol) |
gaussnewton | gauss_newton!(material, ctx; max_iter, tol) |
quasinewton | quasi_newton!(material, ctx; max_iter, tol, memory) |
Material Model Mapping
Fortran model | Julia Type | Integer |
|---|---|---|
model=1 | IsotropicIncompressible() | 1 |
model=2 | Orthotropic() | 2 |
model=3 | IsotropicCompressible() | 3 |
model=4 | Poroelastic() | 4 |
model=5 | TransverseIsotropicV1() | 5 |
model=6 | TransverseIsotropicV2() | 6 |
model=7 | GeneralizedAnisotropic() | 7 |
Convert between representations: material_model(3) returns IsotropicCompressible(), model_index(IsotropicCompressible()) returns 3.
Key Design Differences
Multiple Dispatch vs if/elseif
Fortran dispatches on material%model integer flags:
if (model == 1) then
call hex27_isotropic_incompressible(...)
elseif (model == 2) then
call hex27_orthotropic(...)
end ifJulia uses type dispatch:
element_stiffness!(Ke, cv, cp, ::IsotropicIncompressible, props, ω)
element_stiffness!(Ke, cv, cp, ::Orthotropic, props, ω)Ferrite.jl Integration
Shape functions, quadrature, DOF management, and assembly use Ferrite.jl instead of custom Fortran routines. This means:
The grid type is
Grid{3, Hexahedron, Float64}(8-corner-node cells)Full 27-node connectivity is stored separately
DOF numbering is managed by Ferrite's
DofHandler
Hex27 Node Ordering
Fortran and Ferrite use different local node orderings for hex27 elements. Permutation arrays FORTRAN_TO_FERRITE_HEX27 and FERRITE_TO_FORTRAN_HEX27 handle the conversion automatically during mesh I/O.
Complex Symmetric Matrices
Both Fortran and Julia produce complex symmetric stiffness matrices (norm(K - transpose(K)), not norm(K - K').
Solver Backends
| Fortran | Julia |
|---|---|
| MUMPS (built-in) | DirectSolver() (UMFPACK, default) |
MUMPSSolver() (via MUMPS.jl extension) |
The Julia DirectSolver uses SuiteSparse UMFPACK and is the default. For complex symmetric systems, MUMPS can exploit the symmetry for better performance on large problems.
What's New in Sentinel
VTK export:
export_vtkproduces files for ParaView visualizationJulia ecosystem: access to all Julia packages (plotting, AD, GPU)
Package extensions: MUMPS, CUDA, Metal, MPI as optional backends
Runfile round-trip:
parse_runfile/write_runfilefor Fortran interoperabilityPerformance: Julia is 1.3-2x faster than Fortran at typical problem sizes (6×6×6)
Not Yet Ported
The following Fortran features are planned for future milestones:
Zone-based domain decomposition (M6.1): overlapping zones for parallel assembly
MPI parallelism (M6.2): distributed assembly and solve
GPU acceleration (M6.3-6.4): CUDA and Metal backends
Inverse problem runfiles (
problemtype=1): currently forward-only