Skip to content

[WIP] Mortar-based periodic boundary conditions#62

Draft
rcarson3 wants to merge 52 commits into
trdgl_solverfrom
mortar_pbcs
Draft

[WIP] Mortar-based periodic boundary conditions#62
rcarson3 wants to merge 52 commits into
trdgl_solverfrom
mortar_pbcs

Conversation

@rcarson3

Copy link
Copy Markdown
Member

So this has been completely driven Claude Opus 4.7 writing all of the code and tests for this feature as I'm in no way an expert on mortar methods, and I've been very much interested in supporting periodic boundary conditions in ExaConstit for a while. The code was largely inspired by https://doi.org/10.1016/j.cma.2021.113930 which was a really interesting paper I came across on periodic boundary conditions and a way to enforce periodic boundary conditions through mortar methods which allows you to have non-conforming mesh faces or heterogeneous materials across various faces.

So, I largely "vibe" coded in the sense that I did not write anything but directed where things should go, what assumptions it was making were bad, when it should be doing a deeper research of the field to ensure we were doing things correctly as well as many, many different things. The initial prototype of this code started as a python miniapp using pyMFEM where I could quickly iterate with it and verify what it was doing worked starting from 2D and moving up to 3D with a linear elastic problem or a bi-material elastic material with a soft and hard phase. After doing that, I felt comfortable moving onto the C++ port and bringing over all of the python tests to C++ to verify the port was working as expected. The C++ side of things took a lot of work as we needed scalable algorithms (largely for the constraint systems), GPU-capable algorithms (still getting there), usable preconditioners, support for non-conforming mesh faces, proper translation from the total lagrangian framework these methods were written in to the updated lagrangian framework, and then like a ton of tests to make sure things actually work and help to track bugs down later.

This is still a work in progress as I need to get it working with higher-order elements as we're currently limited to just linear elements. Outside of that, I'm also working on a number of extensions to the nonlinear / linear solvers so that we see faster convergences in some polycrystal simulations I've been running with only a handful of grains and linear tets, which are definitely a harder test for these models. Once I get a lot of this done, I will work on having Claude create some better / extensive standalone documentation to go with this new feature as this is not a small feature addition and there's a lot of things that need to be documented on how it works and what Claude was pulling from while working on this.

rcarson3 added 30 commits May 4, 2026 08:04
Probably should have captured more of the intermediate updates through-out this journey of "vibe-coding"...
However, I used Claude Opus 4.7 and Claude's project / github integration with its web chat to drive an initial implementation of a mortar based periodic boundary conditions. I initially had it work things out in pyMFEM and create a plan to build things up from 2D serial to parallel to creating a ton of tests to then moving onto 3D with more tests. Some of these tests involved multi-material elastic simulations to break up in homogeneity and to actually test the methods. Outside of the tests here, I did validate what it was doing with visualizations making sure the solutions at each stage of the way made sense and if not would iterate with Claude until we got something decent. After the python implementation looked more or less good enough, we moved over to C++. Here, I had it work on the initial port and verify that things matched up with the Python version. After we did that, I had it move on to a more scaleable set-up and assembly phase for the constraint matrix as it was initially doing everything on a single rank or broadcasting everything to all ranks. Once that seemed like in a good state, we moved onto an element assembly formulation as that seemed like a good potential path to get us on the GPU and that was verified against the existing sparse matrix / hypre implementation. An initial stab at GPU support also happened. I know this will need to be expanded on. Finally, I had it add support for 3D non-conforming mesh faces. It needed Axom's BVH and similar spatial search algorithms for this which is why we know support Axom. The solutions there seem to line up with the expected results and when the meshes and as the mesh gets closer to conformal the distortional displacement required in the solution approached 0 and matched the conformal variation which was a good indication that the method was doing what we would expect. Also, this work added a ton of new tests which is good but yeah there are a ton of new tests to work through...
For nonconformal tests added the checkerboard and stripe test. Outside that relaxed the F_tol test condition so the tests would pass.
Then the mortar saddle point API was updated to make it more useable for when ExaConstit would havee to use it.
Claude created a manager that controls all of the fun-ness that we'll need to manage for the Mortar PBCs in both the SystemDriver and elsewhere.
…t matrix

Had Claude add some functionality to create the boundary sub-mesh, add a simple function to compute the current deformation gradient, and then finally some other things to get out the Fbar and Fdot_bar terms.
… fact

The mortar method should now have several different capabilities to check the fluctuation field or the hill-mandel condition and a number of other things kinda related to this stuff.
…thod into SystemDriver and nonlinear solvers

This was over a couple different iterations with Claude but the above has most of the framework in-place to where we should be able to in the very near term test the new mortar-based periodic boundary conditions on real problems.
After lots of debugging finally got a working example with periodic boundary conditions when using ExaConstit directly. Initial tests are pretty much just an isotropic elastic examples using ExaCMech but it's a start. The good things is we do see converged results which is super awesome.
…ic boundary conditions

Had Claude add a number of useful validation / diagnostic type fields as part of the periodic boundary conditions.
Also had it add all of the affine and fluctuation fields for the velocity field so we can see how the PBCs have driven things to be different.
Pushing Claude to move towards "semi-periodic" BCSs so we don't end up with overly constrained systems and we can relax the constraint matrix to allow for more natural relaxation of faces for like in monotonic deformation modes
So, I found in testing that the default method of clamping all of the corner DOFs to be way to restrictive and wouldn't really allow me to do like monotonic tension tests easily. Therefore, I had Claude drive things so that we could have what is like semi-periodic BCs by allowing the constraint matrix to be set up based on which DOFs you actually want. Overall, the whole thing works and we now have something that should be useable by the broader community.
…ewton/Krylov wiring

  Add the Phase 5.11 saddle-residual scaling stack for mortar PBC solves,
  including the residual scaler, scaled saddle/Jacobian/preconditioner
  wrappers, trust-region dogleg support for scaled coordinates, and
  per-Newton-iteration diagnostic logging.

  This change also wires the scaling path through SystemDriver and the
  mortar manager, adds sub-block partition support for lambda rows, and
  extends the options path to configure saddle scaling from TOML.

  While debugging the new path, fix several solver-state and lifecycle
  issues that could make first-step behavior nondeterministic or unsafe:

  - zero Newton/Krylov correction buffers before inner solves so the
    linear solver never consumes stale data as an initial guess
  - propagate iterative_mode through wrapped solvers so zero-initial-guess
    semantics survive the wrapper stack
  - remove a duplicate physical residual evaluation in the scaling
    pre-attempt path; the residual callback is stateful and must not be
    probed twice before Newton starts
  - refresh scaled wrapper state, TRDOG offsets, and diagnostic wiring
    after periodic-BC spec changes that resize the lambda block
  - remove the temporary inspecting iterative solver used during
    root-cause analysis once the underlying initialization bug was fixed

  At a high level this commit introduces the new saddle scaling
  infrastructure, preserves diagnostic visibility for the scaled solve,
  and fixes the wrapper/solver initialization bugs that were causing
  inconsistent cycle-1 residual behavior and occasional MINRES NaNs.
  Add SimulationState accessors for boundary-submesh FE spaces and LOR-refined
  boundary submeshes, including lor_depth=1 aliasing and lor_depth>1 fresh
  refinement to avoid mutating the direct boundary cache.

  Update mesh option validation for Phase 6 LOR combinations and add a focused
  mortar_pbc test covering accessor aliasing, depth-2 refinement behavior, surface
  FES properties, and validation rules.
  Add a Phase 6 BoundaryClassifier3D constructor that consumes a pre-built
  boundary ParSubMesh and surface H1(P1) vector FE space. The new path reads
  coordinates, attributes, and TDOFs directly from the boundary submesh/FES,
  while preserving the existing parent-mesh constructor for legacy callers.

  Extend the boundary classifier test with parity coverage against the legacy
  constructor and rerun the classifier plus LOR boundary-submesh tests.
  Introduce SurfaceProjector as the setup-time mapping between parent
  volume true DOFs and boundary-submesh true DOFs for the unified Phase 6
  mortar PBC architecture. The projector builds snapped-coordinate maps
  from low-order boundary/LOR vertices to coincident parent boundary
  Lagrange nodes and exposes both direct lookup tables and diagnostic
  Mult/MultTranspose operations.

  Add focused mortar_pbc tests for p=1 direct projection and p=2
  once-refined LOR projection, including constant and linear field
  reproduction, local/global map consistency, and transpose scatter-add
  behavior. Register the projector in the production library and add the
  new test target to the mortar PBC test suite.
  Extend MortarConstraintOperator with a Phase 6 constructor that accepts a
  boundary-submesh classifier, SurfaceProjector, and parent volume FES. The
  operator now translates classifier-side submesh true DOFs to parent-FES
  true DOFs during setup, so import/export topology and flat row arrays are
  built against the runtime parent vector space while Mult and
  MultTranspose remain unchanged in the Krylov hot path.

  Preserve the legacy parent-classifier constructor as an identity
  projection path and share the setup implementation through Initialize().
  Document the parent-FES indexing contract, projector-mediated setup
  semantics, and ownership/lifetime behavior in the operator header.

  Add a focused direct-path regression test comparing the projector-backed
  operator against the legacy operator at p=1 / lor_depth=1, accounting for
  submesh row enumeration order while still verifying Mult values and
  MultTranspose parent-column accumulation.
  Extend ConstraintBuilder3D with a Phase 6 constructor that accepts a
  boundary/LOR-submesh classifier, SurfaceProjector, and parent volume FES.
  The builder now translates classifier-side submesh true DOFs into parent
  volume true DOFs when emitting constraint matrix columns, keeping the
  assembled HypreParMatrix path aligned with the projector-aware
  MortarConstraintOperator.

  Preserve the legacy constructor as an identity/direct path and update the
  builder documentation to describe the parent-FES column-space contract,
  projector ownership, and which APIs are affected. Build() now sizes the
  replicated matrix by the parent global true-vector size, and
  BuildHypreParMatrix() uses the parent FES true-DOF partition for its
  column starts when projector construction is used.

  Add a focused p=1 / lor_depth=1 regression test that builds the
  projector-backed submesh classifier path and verifies its assembled
  matrix action matches the legacy parent-classifier builder up to row
  permutation, while also checking the projected HypreParMatrix uses the
  parent FES column count.
  Migrate MortarPbcManager construction to the Phase 6 boundary/LOR
  pipeline. The manager now builds its classifier on the LOR boundary
  submesh, constructs a SurfaceProjector back to the parent volume FE
  space, and wires the projector-aware constraint builder and EA
  constraint operator into the saddle system.

  Add projector-aware corner-pinning helpers so both default and
  spec-filtered corner essential TDOF lists are returned in parent-FES
  local true-DOF numbering. This keeps mechanics Dirichlet application,
  constraint columns, and C^T residual contributions in the parent
  solution space while allowing mortar topology to live on the LOR
  surface.

  Extend the manager corner-pinning tests with direct-path comparisons
  between the legacy parent classifier and the new boundary-submesh plus
  SurfaceProjector path, including full XYZ and X-only filtered specs.
  Document the Phase 6 ownership and index-space contracts in the
  manager header and implementation.
  Move MortarSaddlePointSystem and MortarSaddlePreconditioner to store
  shared constraint-operator handles instead of raw references. This
  matches the Phase 6 manager ownership model, where the projector-aware
  MortarConstraintOperator is owned behind a shared_ptr and passed through
  the saddle solve stack.

  Keep reference-based compatibility constructors by wrapping references
  in non-owning shared_ptr aliases, so existing tests and legacy call
  sites continue to work during the migration. Update MortarPbcManager to
  pass its shared operator handle directly into MortarSaddlePointSystem.

  Add focused tests that construct the saddle system and saddle
  preconditioner from shared operator handles, reset the operator filter,
  and verify Refresh/SetOperator observe the updated lambda-block size.
  Also make the clipped triangular face-mortar conforming check compare
  sparse rows algebraically by row/column value rather than requiring
  identical CSR insertion structure.

  Verify by building and running the full mortar_pbc test suite; all 30
  registered mortar_pbc tests pass.
  Replace the arithmetic reconstruction of parent y/z true DOFs from an
  x-component true DOF in MortarConstraintOperator. The previous logic
  assumed a component-block global numbering layout, which is not valid
  for the byNODES vector spaces used by the mechanics FES. Under MPI this
  could make the EA import/export topology ask a peer rank for a component
  true DOF that the peer did not own.

  Cache the actual parent-side {x,y,z} true DOF tuple during operator
  initialization by translating BoundaryClassifier3D component tuples
  through SurfaceProjector. Use that cache when packing imported values
  and accumulating transpose contributions, preserving the node-level
  ownership invariant without assuming a global numbering formula.

  Extend mortar constraint operator coverage for MPI by making the small
  mesh construction test tolerate ranks with zero local lambda rows, by
  including Hypre offd columns in the MPI Schur diagonal comparison, and
  by running the P2 tet LOR affine constraint smoke test successfully at
  4 and 7 ranks.

  Verified with the full registered mortar_pbc CTest suite, the
  MortarConstraintOperator executable under flux at np=4 and np=7, and
  the reported 4-rank voce_ea mechanics reproducer past the previous
  peer-request assertion.
rcarson3 added 22 commits May 26, 2026 20:56
  Add Phase 6.1.D coverage for component-restricted periodic constraints
  on the projected P2 tetrahedral LOR path. The new operator test builds
  a P2 tet parent space, a once-refined linear boundary submesh, the
  submesh classifier, SurfaceProjector, projected ConstraintBuilder3D,
  and projected MortarConstraintOperator, then resets the operator to an
  X-only active spec.

  Verify that the filtered operator height matches the filtered builder
  row count, that row-factor metadata and RHS sizing match the reset
  operator, that all emitted rows are x-component rows, and that the
  manufactured affine field still satisfies the filtered constraint RHS.
  Run the same executable at np=1, np=4, and np=7 to cover the MPI
  import/export path under the reduced filter.

  Document the higher-order component-filter invariant in
  MortarConstraintOperator: projector-aware Reset keeps the parent-FES
  domain unchanged, reduces the lambda block to the filtered rows, and
  must preserve affine reproduction against filtered EmitRowFactors
  metadata.

  Verify by building all mortar_pbc targets and running the full
  registered mortar_pbc CTest suite; all 30 tests pass.
  Add AMGF solver option parsing and validation gates

  Introduce AMGF and AMGF_AUG_LAGRANGIAN as linear preconditioner choices and
  parse the companion AMGF options:
  - amgf_gamma
  - amgf_subspace_executor

  Reject AMGF configurations that cannot work with the current implementation:
  AMGF requires FULL assembly and CPU/OPENMP runtime because it needs assembled
  HypreParMatrix operators for BoomerAMG and the filtered subspace solve. This
  check runs before the existing GPU/EA/PA logic can silently rewrite the
  preconditioner to Jacobi.

  Document the new options in src/options.toml and add test_amgf_options to
  verify:
  - AMGF keyword parsing
  - AMGF_AUG_LAGRANGIAN keyword parsing
  - AMGF option TOML parsing
  - rejection of EA/PA/GPU AMGF configurations without silent Jacobi fallback
  - rejection of invalid subspace executor strings

  Tests:
  - ctest -R test_amgf_options --output-on-failure
  Add MortarConstraintOperator::GetConstraintCoupledDofIndices(), returning the
  sorted unique global displacement true DOFs that appear as nonzero columns in
  the active mortar constraint operator C.

  Build the index set lazily from the same filter-aware flat arrays used by
  Mult and MultTranspose. This keeps the AMGF index set consistent with:
  - active pair-label filters
  - component masks
  - projector/LOR parent-space TDOF translation
  - off-rank mortar imports
  - sentinel rows/components

  Invalidate the cache in Reset() so sub-XYZ periodicity changes rebuild the
  index set on demand.

  Update test_mortar_constraint_operator to compare the accessor against the
  reference HypreParMatrix nonzero-column set for both full and filtered
  constraint specs. This avoids stale geometric assumptions about higher-order
  legacy classifiers; higher-order coverage remains through the existing LOR
  projector path.

  Tests:
  - ctest -R test_mortar_constraint_operator --output-on-failure
  Add exaconstit::amgf::BuildBooleanRestrictionProlongation(), which converts

  The utility collectively unions rank-local coupled-DOF views before assigning
  compact AMGF columns. This is required because a rank-local constraint row can
  touch off-rank mortar-side displacement columns, while the Boolean column must
  be owned exactly once by the rank that owns the corresponding K row.

  Register the new utility in src/CMakeLists.txt and add test_amgf_utils to
  verify:
  - P has the expected Boolean Mult and MultTranspose behavior
  - P^T A P extracts the expected principal submatrix for a diagonal test matrix

  SurfaceProjector was reviewed for reuse. It remains the correct LOR bridge
  from classifier/submesh TDOFs to parent-volume TDOFs, and the new accessor
  benefits from that because it reads the already-translated flat arrays. It is
  not a substitute for this utility because AMGF requires a compact-column
  HypreParMatrix over the active coupled-DOF subset, while SurfaceProjector is
  an Operator trace map over the full boundary/LOR surface.

  Tests:
  - ctest -R test_amgf_utils --output-on-failure

  Current validation run for changed tests:

  ctest -R 'test_amgf_options|test_mortar_constraint_operator' --output-on-failure
  ctest -R test_amgf_utils --output-on-failure
  Introduce exaconstit::amgf::GinkgoDirectSubspaceSolver, an mfem::Solver
  adapter that lets MFEM's AMGFSolver apply a Ginkgo sparse direct solve on
  the filtered AMGF subspace operator. The adapter converts the local
  diagonal block of the HypreParMatrix subspace operator to a Ginkgo CSR
  matrix during SetOperator(), then applies a cached Ginkgo
  experimental::solver::Direct solve from Mult().

  Support both symmetric and nonsymmetric setup modes. The symmetric path
  uses Ginkgo Cholesky for the expected K-block / augmented-K-block cases,
  while the nonsymmetric path uses Ginkgo LU for future non-associated-flow
  tangents.

  Add MakeGinkgoExecutor() for AMGF subspace executor selection. The
  current implementation keeps AMGF host-resident: "auto" selects OpenMP
  when the configured Ginkgo package provides it and falls back to the
  reference executor otherwise; explicit GPU executor strings abort with a
  clear message because the hybrid GPU/full-assembly path is future work.
  The CMake configuration now exports EXACONSTIT_GINKGO_HAS_OMP when the
  Ginkgo package reports an OMP backend.

  Document the adapter limitations in the new mortar_pbc header. In
  particular, this partial step intentionally factors HypreParMatrix::GetDiag()
  only, matching the initial AMGF wiring skeleton and the current single-rank
  correctness tests. Distributed production subspace-solve behavior should be
  revisited when the full AMGFSolver integration is exercised across ranks.

  Add a focused unit test covering both the Cholesky and LU adapter paths on
  small HypreParMatrix systems. Register the test with the mortar_pbc CTest
  suite.

  Update the new AMGF utility/test matrix-construction paths to use MFEM
  memory-safe Read()/ReadI()/ReadJ()/ReadData() accessors instead of raw
  GetData()/GetI()/GetJ() pointer access, so these setup paths synchronize
  host data correctly if future full matrix assembly uses device-resident
  memory.
  Introduce mortar_pbc::MortarSaddlePreconditionerAMGF as the Path-A
  block preconditioner for the mortar saddle Jacobian. The class owns an
  mfem::AMGFSolver, keeps the Boolean AMGF transfer matrix alive, holds
  the caller-provided filtered-subspace solver, and configures BoomerAMG
  through the same systems-option path used by the existing full-assembly
  K-block AMG setup.

  SetOperator now validates that the saddle operator is a 2x2
  mfem::BlockOperator with a HypreParMatrix K block, routes K into AMGF,
  refreshes the Jacobi-style K probe, and preserves the existing Path-A
  Schur diagonal computation through MortarConstraintOperator::
  ComputeInvDiagSchur. The lower block is installed as a DiagonalScaler
  inside a BlockDiagonalPreconditioner. Path D constructor parameters are
  kept for the later augmented-Lagrangian step, but Path D currently
  aborts clearly instead of silently taking an incomplete path.

  Add a focused single-rank class-level unit test. The test builds the
  mortar constraint operator, constructs the Boolean AMGF transfer P,
  installs a Ginkgo direct subspace solver, verifies setup dimensions and
  gamma state, and checks that the AMGF preconditioner stores the same
  Path-A inverse Schur diagonal as the existing diagonal-probe path.

  Register the new source/header with exaconstit_static and add the new
  test to the mortar_pbc CTest suite.
  Add the SystemDriver branch for LinearSolver preconditioner AMGF on the
  mortar-PBC saddle path. The AMGF branch constructs the Ginkgo direct
  filtered-subspace solver and installs MortarSaddlePreconditionerAMGF as
  the saddle J_prec, while preserving the existing MortarSaddlePreconditioner
  path for all non-AMGF preconditioners.

  Extend MortarSaddlePreconditionerAMGF with a deferred-transfer constructor
  for production use. SystemDriver does not have the assembled Hypre K block
  when the saddle preconditioner is constructed, so the class now rebuilds
  the Boolean AMGF transfer operator in SetOperator() from the current K row
  partition and MortarConstraintOperator::GetConstraintCoupledDofIndices().
  The explicit-P constructor remains available for focused unit tests.

  Keep AMGF_AUG_LAGRANGIAN as an explicit early abort in SystemDriver. Path D
  requires the augmented residual/scaler wiring and remains a later partial
  step.

  Strengthen the AMGF saddle preconditioner test so it exercises Mult(), not
  only SetOperator(). The test uses warning-mode Hypre error handling only for
  its artificial pinned elasticity matrix; production construction still
  defaults to aborting on Hypre setup/solve errors. The test verifies finite
  AMGF upper-block output and exact preservation of the existing Path-A Schur
  diagonal action.
  Add a post-linear-solve diagnostic sink to ExaNewtonSolver and wire it
  into the mortar saddle Newton diagnostic logger. The logger now records
  linear_iterations, linear_final_norm, and linear_converged on the same
  per-Newton-iteration CSV row as the residual block decomposition.

  Remove the rejected Caliper-style Krylov iteration reporting from the
  SystemDriver path. The linear solve data now stays associated with the
  Newton iteration that produced it, and converged Newton rows with no
  linear solve are written explicitly with -1 sentinel values.

  Clarify AMGF filtered-subspace sizing: n_filter is the unique set of
  constraint-coupled displacement true DOFs, not the number of lambda
  constraint rows. Extend the AMGF preconditioner test to assert that
  relationship and print the n_filter/n_lam ratio with the correct label.

  Add a focused SaddleNewtonDiagnosticLogger test covering the new linear
  solve CSV columns and the no-linear-solve sentinel row.
  Add validation that prevents AMGF preconditioners from being paired with
  MINRES. MFEM's AMGFSolver is a filtered/multiplicative preconditioner and
  is not guaranteed to satisfy MINRES' symmetric preconditioner contract.

  Apply the check both to the K-block Krylov solver options and to the
  mortar SaddlePoint solver options when mortar PBC is active. This catches
  the actual AMGF mortar configuration rather than only the generic Krylov
  table.

  Extend the AMGF option test to cover rejected K-block MINRES, rejected
  mortar SaddlePoint MINRES, and accepted mortar SaddlePoint GMRES.
  Add a dedicated SaddlePointMethod option so the augmented-Lagrangian
  formulation is selected through [Solvers.SaddlePoint] rather than being
  encoded as an AMGF preconditioner variant. Parse method =
  "AUGMENTED_LAGRANGIAN" plus augmented_lagrangian_gamma, document the new
  deck shape, and print the selected saddle method in the options summary.

  Keep AMGF as a K-block preconditioner choice. The legacy
  AMGF_AUG_LAGRANGIAN spelling remains parsed for compatibility, but new
  Phase D wiring should use the saddle method switch and then apply the
  selected K-block preconditioner, whether AMG or AMGF, to K_gamma.

  Update the system-driver guard so augmented-Lagrangian requests fail
  explicitly until the Phase D operator/RHS path is implemented. Move the
  focused AMGF option coverage under test/mortar_pbc and extend it to cover
  saddle-method parsing and to verify that the augmented-Lagrangian method
  by itself does not inherit the AMGF + MINRES restriction.
  Add MortarConstraintOperator::BuildCTransposeC() as the Phase D setup
  hook for augmented-Lagrangian saddle solves. The method assembles the
  currently active EA constraint operator into a temporary HypreParMatrix
  from the flat row arrays, then forms C^T C with MFEM/Hypre transpose and
  parallel sparse matrix multiplication.

  Preserve the current mortar filter semantics during assembly: active
  pair labels and component masks from Reset are honored, sentinel true
  DOFs are skipped, and off-rank mortar-side columns are resolved through
  the existing import topology. The returned matrix uses the parent FES
  true-DOF row and column partition so it can be combined with the K block
  when K_gamma wiring is added.

  Extend the mortar constraint operator test to verify the assembled
  normal matrix action against the matrix-free reference C^T(Cu), including
  both the full XYZ constraint set and an X-only filtered constraint set.
  Register a Flux-backed np=4 CTest entry for the C^T C coverage so the
  off-rank column, Hypre transpose, and parallel matrix multiply paths are
  tested with multiple MPI ranks.
  Extend MortarSaddlePreconditioner with an opt-in augmented-Lagrangian
  setup path for the saddle solver method. In augmented mode the
  preconditioner builds K_gamma = K + gamma C^T C and refreshes the
  selected K-block preconditioner on K_gamma instead of K. This keeps the
  augmented-Lagrangian formulation independent of the K-block
  preconditioner choice, so AMG, Jacobi, ILU, and later AMGF can be
  tested against the same augmented saddle method.

  Replace the lambda-block action with the trivial gamma I scaling in
  augmented mode. Positive gamma overrides are used directly; non-positive
  gamma requests the trace-scaled default tr(K) / tr(C^T C) * n_lambda /
  n_u, with a defensive gamma=1 fallback for degenerate traces.

  Add mortar preconditioner coverage that uses a recording K-block solver
  to verify SetOperator receives K_gamma and verifies Mult applies both
  the recorded K_gamma upper-block action and the gamma-scaled lambda
  block.
  Enable the augmented-Lagrangian saddle method for the non-AMGF mortar
  preconditioner path. The driver now treats
  [Solvers.SaddlePoint] method = "AUGMENTED_LAGRANGIAN" as a saddle solver
  formulation choice and passes the configured augmented_lagrangian_gamma
  to MortarSaddlePreconditioner, where K_gamma and the gamma-I lambda
  block are built during preconditioner setup.

  Keep the AMGF preconditioner path separate. Requests that combine AMGF
  with the augmented saddle method now fail with a targeted runtime error
  until the AMGF-specific augmented setup is implemented, preserving the
  intended split between saddle method selection and K-block
  preconditioner selection.

  Document the standard versus augmented construction behavior at the
  driver call site so future AMGF wiring can follow the same option split.
  Introduce augmented-Lagrangian saddle wrappers for the Phase D Newton
  linear solve. The new operator wrapper preserves the physical mortar
  saddle residual returned by Mult, so nonlinear convergence checks,
  diagnostics, line search, and trust-region acceptance continue to use
  the true residual. Its GetGradient path returns an augmented Jacobian
  action that adds gamma C^T C to the displacement block.

  Add a matching RHS solver wrapper that applies the gamma C^T r_lambda
  shift immediately before the inner Krylov solve. The wrapper supports
  both unscaled and saddle-residual-scaled solve paths by temporarily
  mapping scaled right-hand sides back to physical units before applying
  the augmented RHS correction.

  Wire the wrappers through SystemDriver for the AUGMENTED_LAGRANGIAN
  saddle method, refresh them across active periodic-spec changes, and
  guard the current implementation to FULL assembly because K_gamma setup
  requires HypreParMatrix K blocks. Update MortarSaddlePreconditioner to
  unwrap augmented Jacobians before extracting K so the preconditioner
  builds K_gamma from the original mechanics block instead of adding
  gamma C^T C twice.

  Add focused mortar tests for the augmented Jacobian action and RHS
  shift, and register the test under test/mortar_pbc.
  Extend MortarSaddlePreconditionerAMGF so the AMGF K-block
  preconditioner can be used with the augmented-Lagrangian saddle method.
  In augmented mode the AMGF wrapper unwraps AugmentedLagrangianSaddleJacobian
  back to the original saddle BlockOperator, extracts the unaugmented K
  block, builds K_gamma = K + gamma C^T C, and refreshes AMGFSolver on
  K_gamma. This avoids double-counting the penalty term while keeping AMGF
  as a K-block preconditioner choice rather than a separate saddle method.

  Replace the AMGF lambda-block diagonal Schur approximation with gamma I
  when augmented mode is active. Positive gamma overrides are used directly;
  non-positive gamma requests the same trace-scaled default used by the
  generic mortar saddle preconditioner.

  Wire SystemDriver so AMGF is no longer rejected with
  [Solvers.SaddlePoint] method = "AUGMENTED_LAGRANGIAN". The saddle method
  now controls the augmented formulation, while [Solvers.Krylov]
  preconditioner = "AMGF" controls the K-block preconditioner.

  Add focused AMGF coverage for the augmented setup, including a 4-rank
  CTest registration to exercise distributed C^T C assembly and AMGF
  filtered-transfer construction. Expand the generic
  MortarSaddlePreconditioner documentation to match the verbose style used
  throughout src/mortar_pbc, including file-level design notes, helper
  documentation, setup comments, and private member documentation.
  Update the mortar SolveInit direct saddle solve so it uses the same
  augmented-Lagrangian linear algebra as the regular Newton path. When
  [Solvers.SaddlePoint] method = "AUGMENTED_LAGRANGIAN" is active, or the
  legacy AMGF_AUG_LAGRANGIAN preconditioner spelling is used, SolveInit now
  builds K_gamma = K + gamma C^T C and shifts the displacement RHS by
  gamma C^T r_lambda before calling SaddlePointSolver.

  Keep the physical constraint residual unchanged. The augmentation is
  applied only to the direct linear solve operator and RHS, matching the
  regular Newton wrapper path and preserving the interpretation of
  r_lambda = C x_prev - g.

  Refresh the K-Jacobi probe against the same operator passed to
  SaddlePointSolver: K in standard mode and K_gamma in augmented mode. Add
  local documentation for the SolveInit trace-scaled gamma default because
  this path bypasses the regular saddle preconditioner setup where gamma is
  normally selected.
  Teach the Newton linear-solve diagnostic extractor to unwrap
  AugmentedLagrangianRhsSolver and report diagnostics from its inner
  solver. The augmented RHS wrapper only applies the algebraic
  augmented-Lagrangian residual shift before delegating to the real
  Krylov solve, so the inner solver owns the meaningful iteration count,
  final residual norm, and convergence flag.

  This restores populated newton_iters.csv linear diagnostics for
  AUGMENTED_LAGRANGIAN saddle runs and makes Phase D integrated
  validation directly comparable across AMG standard, AMGF standard,
  AMG augmented, and AMGF augmented cases.
…s 6 and AMGF

The SurfaceProjector had a few issues where it had a few issues with assumptions related to the child and parent FES which were not necessarily correct anymore and this was evident with the tet meshes but not the auto-generated meshes. Next, a few issues were noted where it assumed all ranks would have data rather than there being some empty rank data sets.
The Gingko solver had a ton of issues in that I didn't realize it was only good for a single MPI rank even though their website made it sound like it could work over distributed ranks :/
So, I had Claude swap us over to SuperLU and copy over for the time being the MFEM parallel direct solver utility package. This works and does at least provide us with a path to get on the GPU with a direct sparse solver but still kinda sad couldn't leverage Gingko...
Outside of that through Claude / Codex, I found out that the non-conforming meshes had a pretty glaring issue. It turns out that there was never a ghost element layer accounted for which meant that the non-conformal stuff was missing contributions from elements not on the chosen processor...
Had Claude update the install scripts such that SuperLU is used instead of Gingko.
@rcarson3 rcarson3 changed the base branch from exaconstit-dev to trdgl_solver June 30, 2026 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant