Module: MSolve#

Semi-implicit thin film solver for second order differential equations of form:

\[ \frac{\eta}{\Delta t} - G_{ij} \eta_{,ij}= rhs \]

Defined Types#

type_msolve

Variable

Type

Dimension

Mmsolve,Vmsolve,Ymsolve

real64

dimension(:, :, :, :)

delop

real64

dimension(:, :, :, :)

bc

complex real64

dimension(:, :, :, :)

BCTop,BCBot

int32

-

type_mupro_MsolveContext#

Variable

Type

Dimension

Meaning

gradient_coefficient

real64

(3)

Gradient coefficient

BCTop

int32

-

BC for film surface

BCBot

int32

-

BC for film substrate interface

sysArray

type_msolve

-

Necessary information for the solver

type_mupro_MsolveSolveContext#

Variable

Type

Dimension

Meaning

rin

real64

(z,y,x)

The right hand side of the equation

pout

real64

(z,y,x)

The evolved order parameter distribution

dt

real64

-

Marching step for each simulation

sysArray

type_msolve

-

sysArray from the msolve_setup

The validator contract (added 2026-08-06, T2)#

Both context types carry a status-returning validator alongside the terminating guards (mupro_require_fft, the PR-025c binding preconditions):

  • context%validate_setup(status) on type_mupro_MsolveContext (msolve.f90:689). Checks what setup_mpi_msolve actually reads: an associated sysArray (the state is allocated on the caller’s target — the PR-025 UB), not-already-set-up (Mmsolve allocation is unconditional), the FFT extents and both wave-vector sets (3D for delop, 2D for rmk), a film of nonzero thickness (dz > 0, k2 > k1(hh1-hh2)**3 divides), a finite positive dt (it divides under a square root, and an infinite dt passes > 0 while sending rmk to zero, which then divides as rmk**4), finite gradient coefficients, not-all-zero (the context default meaning “no material”), and gradient_coefficient(3) > 0 (divides under the root).

  • context%validate_solve(status) on type_mupro_MsolveSolveContext (msolve.f90:817). Checks what msolve_mpi reads: a live FFT plan and its plate-solution coefficients, mqk3_3, at least four film layers (k2 - k1 >= 3 — the one-sided stencils read rin(k1..k1+3) and rin(k2-3..k2); for interior films they merely cross the boundary and produce meaningless numbers rather than crashing, which is why the refusal wording names the geometry), bound rin/pout with the local slab shape, a state that came from the setup (allocated arrays, dt > 0, d33 > 0 — both divide), state shapes matching the current grid, the legacy-dt agreement (tolerance 1.0e-12, mirrored from the solve’s own guard), and the BC flags in 1…4 — checked here and not at setup, because setup only copies them while the solve dispatches on them with a terminating else.

Deliberately unchecked, each awaiting the owner (see TASK.md): negative gradient_coefficient(1)/(2) (setup completes finitely on them at small dt; refusing them is a physics judgement), and the k2-k1 >= 3 wording above is on the same sign-off list.

Every refusal is paired with an accepting baseline in tests/unit/test_l2_msolve.f90; the two-context split means each validator is tested against the type its routine takes.

Defined Subroutines#

mupro_msolve_setup#

Preparation for the msolve solver

call mupro_msolve_setup(context)

Argument

Type(Intent)

Meaning

context

type_mupro_MsolveContext(INOUT)

The msolve setup context

mupro_msolve_solve#

Evolve the Time-Dependent Ginzburg Landau equation semi-implicitly, march forward the order parameter distribution for one time step.

call mupro_msolve_solve(context)

Argument

Type(Intent)

Dimension

context

type_mupro_MsolveSolveContext(INOUT)

The msolve solver context