Skip to content

Issue 525 FE Basis refactor implementation#561

Draft
zasexton wants to merge 17 commits into
SimVascular:mainfrom
zasexton:issue-525
Draft

Issue 525 FE Basis refactor implementation#561
zasexton wants to merge 17 commits into
SimVascular:mainfrom
zasexton:issue-525

Conversation

@zasexton
Copy link
Copy Markdown
Collaborator

@zasexton zasexton commented Jun 2, 2026

Current situation

Tracks #525.

The solver currently relies on legacy table-driven shape-function paths in nn.cpp, which makes basis evaluation, Hessian support, node-ordering validation, and parity testing difficult to extend. This PR introduces a self-contained FE Basis layer while preserving the existing solver-facing storage contracts.

Release Notes

  • Added a new FE Basis module with Lagrange and Serendipity basis support for mapped solver elements, including values, gradients, Hessians, node-ordering conventions, factory creation, and cache support.
  • Added FE math and quadrature utilities used by the new basis implementation.
  • Routed supported nn::get_gnn and nn::get_gn_nxx volume/face evaluations through the new FE Basis adapter.
  • Added SVMP_BASIS_MODE=auto|legacy|fe to compare legacy and FE Basis evaluation paths at runtime.
  • Added typed FE/basis exception paths for unsupported elements, invalid configurations, and backend failures.
  • Added a basis comparison harness for running pytest integration cases under legacy and FE modes and comparing outputs, timing, fields, and iteration data.
  • Build migration: solver code now requires a C++20-capable compiler.

Documentation

  • Added Documentation/basis-comparison-plan.md describing the legacy-vs-FE comparison protocol, metrics, output layout, and acceptance criteria.
  • Added Doxygen-style documentation to the new FE Basis, FE Math, and Quadrature APIs.
  • No solver XML migration is expected for users; basis mode selection is controlled through SVMP_BASIS_MODE.

Testing

  • Added GoogleTest coverage under tests/unitTests/FE/Basis for Lagrange/Serendipity basis evaluation, Hessians, cache/factory behavior, error paths, node ordering, solver adapter parity, and supported mapped element coverage.
  • Added GoogleTest coverage under tests/unitTests/FE/Math for matrix/vector operations, expression helpers, math constants, and dense linear algebra.

Code of Conduct & Contributing Guidelines

@zasexton zasexton self-assigned this Jun 2, 2026
@zasexton
Copy link
Copy Markdown
Collaborator Author

zasexton commented Jun 3, 2026

From the CI test cases we got the following:

  • macOS: 12 failed, 227 passed
  • Ubuntu: 21 failed, 218 passed
  • Failures are all FSI / FSI-ustruct pipe cases.

The affected meshes are HEX8. Current code allocated Nxx but did not populate HEX8 second derivatives; this branch now computes nonzero HEX8 Hessians via FE Basis. FSI uses those in Code/Source/solver/fsi.cpp:191, so the stored legacy reference VTUs no longer match.

@zasexton
Copy link
Copy Markdown
Collaborator Author

zasexton commented Jun 3, 2026

In the FSI fluid assembly, Nxx is passed into the element kernel and used in terms that contribute to the assembled equations, especially VMS/stabilization terms.

  • Code/Source/solver/fluid.cpp:1841: Nwxx is used to build uxx at lines 1841-
    1860.

  • Code/Source/solver/fluid.cpp:1880: uxx feeds d2u2.

  • Code/Source/solver/fluid.cpp:1933: uxx also feeds es_x, then mu_x at lines
    1948-1963.

  • Code/Source/solver/fluid.cpp:2027: d2u2 and mu_x enter rS.

  • Code/Source/solver/fluid.cpp:2037: rS enters up.

  • Code/Source/solver/fluid.cpp:2103: up-dependent quantities are used when
    assembling lR, the local residual, at lines 2103-2106.

That means:

  • in the current code, it solves a discrete problem where HEX8 second-derivative contributions are effectively zero or absent when using the old basis functions

  • when using the new FE Basis functions, it solves a different discrete problem where HEX8 mapped Hessian contributions are present

Therefore the Hessian is not just participating in the tangent assembly and may not necessarily converge on the same solution as the current reference vtu. This is also why we do not see such CI failures for test cases that use Tet elements because TET4 have zero reference second derivatives or for TET10 Hessian values are provided. For such elements, introduction of the new Basis function infrastructure did not cause a change in the residual being solved for these cases.

@zasexton
Copy link
Copy Markdown
Collaborator Author

zasexton commented Jun 3, 2026

Overall, we see that providing the non-zero Hessian values slightly increases the number of linear iterations required but does not impact the number of nonlinear iterations for the FSI test cases considered. More importantly, this difference in how the Hessian is used in the formulated residual suggested that the problem being solved is slightly different depending on if a user is providing brick elements versus TET10 (which shouldn't be the case)

convergence-iteration-behavior

@zasexton
Copy link
Copy Markdown
Collaborator Author

zasexton commented Jun 4, 2026

Confirmed. The difference in accuracy for the FSI test cases when employing the new FE Basis functions is due to the non-zero Hessian values for the reference elements. We can see that when we zero-out the values for the Hessian on the HEX8 cases that we recover the same behavior as the current solver. @ktbolt do you think it would make sense to update the reference solutions for these test cases or is there an alternative strategy that we should look at?

hex8-hessian-confirmation-by-case

@aabrown100-git
Copy link
Copy Markdown
Collaborator

@zasexton Were Hessians also zeroed out in the Fortran svFSI?

I think we should update reference solutions unless there is a good reason to use zero Hessians. @sujaldave, @hanzhao2020 Is there any reason (in VMS or something) to force $u_{xx}$ to be zero in HEX8 or higher order elements?

@zasexton
Copy link
Copy Markdown
Collaborator Author

zasexton commented Jun 4, 2026

@aabrown100-git yes, the Hessian was also effectively zero for the HEX8 in the original fortran svFSI. Only TET10, TRI6, QUD8, QUD9, and LIN2 had cases in the GETGNNxx subroutine. All other cases return the zero-initialized Hessian.

Regenerate affected FSI and FSI-ustruct HEX8 result_005.vtu references for the FE Basis path with nonzero HEX8 Hessian contributions.

Update the pipe_3d PETSc and Trilinos references to match the base pipe_3d reference, preserving the existing shared-reference pattern across linear algebra variants.
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.

2 participants