Skip to content

ALE_Finite_Strain_Plasticity: fix deal.II 9.7 assertion, build cleanly, and run under MPI#252

Open
maieneuro wants to merge 2 commits into
dealii:masterfrom
maieneuro:master
Open

ALE_Finite_Strain_Plasticity: fix deal.II 9.7 assertion, build cleanly, and run under MPI#252
maieneuro wants to merge 2 commits into
dealii:masterfrom
maieneuro:master

Conversation

@maieneuro

Copy link
Copy Markdown
Contributor

Summary

Fixes the assertion reported in #237 and makes the
ALE_Finite_Strain_Plasticity code-gallery example build warning-free and
run correctly (serial and parallel) against deal.II 9.7.

The example previously aborted immediately in Debug, and (once that was
resolved) hit two further latent, parallel-only failures. All are fixed
here across two commits.

Correctness fixes

1. ComponentMask size mismatch (the assertion from #237)
mech_fe was declared as FESystem(FE_Q, dim, FE_Q, 2), giving dim+2
components, while the rest of the program consistently assumes dim+1
(displacement + angular twist): the ComponentMasks,
LBCSystem<dim, Number, dim+1>, the zero_function, Material<dim+1>,
the FEValuesExtractors (displacements 0..dim-1, angular velocity at
dim) and the output component names/interpretations. The extra
component made

component_mask.represents_n_components(fe.n_components())

fail inside VectorTools::interpolate_boundary_values(). Changed the
multiplicity 2 -> 1 so the FE has dim+1 components, matching
everything else.

2. Singular MixedFEProjector over mech_fe
Removed a dead projector setup whose result (mech_fe_projectors) was
never used. Building an L2 projector over the full mech_fe (12 dofs/cell
for Q1) from only 4 quadrature points yields a rank-deficient mass matrix,
which aborted in FullMatrix::gauss_jordan() once the ComponentMask
assertion was past.

3. compress() on ghosted vectors (parallel abort)
previous_deformation, previous_time_derivative and current_increment
carry ghost elements (reinit with locally_relevant_dofs) and are
read-only. The code assigned a locally-owned vector into them and then
called compress(), which 9.7 forbids
(has_ghost_elements() == false). Assigning owned -> ghosted already does
the ghost import, so these compress() calls were both unnecessary and
illegal, matching the existing pattern in
NewtonStepSystem::advance_time(). Removed the 11 offending calls; kept
compress() on locally-owned vectors.

4. Out-of-bounds MPI buffer access in remap_material_state_variables
(parallel abort)

The point-to-point exchange passed buffer addresses as
&group.at(i)[0]. When a rank exchanges no points with rank i that
buffer is empty, and operator[](0) on an empty std::vector aborts
under _GLIBCXX_ASSERTIONS (enabled in deal.II Debug). Replaced all 12
&..._groups.at(i)[0] buffer arguments with .data(), which is well
defined for empty vectors.

Warning cleanup

Debug and Release now compile with zero project warnings:

  • -Wdeprecated-declarations: use the returning form of
    extract_locally_relevant_dofs() and the two-index-set
    AffineConstraints::reinit().
  • -Wsuggest-override: added override to the Material /
    Function / std::exception overrides.
  • -Wreorder: fixed member-init order in
    BoundaryUnidirectionalPenaltySpec and ScaleComponentFunction.
  • -Wsign-compare: cast boundary_id() comparisons to
    types::boundary_id.
  • -Wcatch-value: catch MaterialDomainException by const reference.
  • -Wunused-*: tagged genuinely-unused locals/parameters
    [[maybe_unused]] (preserving computations), dropped an unused local,
    and elided unused parameter names in stub methods.

Testing

  • Debug and Release build with 0 errors / 0 project warnings
    (deal.II 9.7).
  • mpirun -n 4 and mpirun -n 18 run the full nonlinear solve
    (mesh-motion -> mechanical Newton iterations -> contact) without aborting.

Commits

  • ALE_Finite_Strain_Plasticity: fix ComponentMask assertion and clean up build
  • ALE_Finite_Strain_Plasticity: fix parallel (MPI) runtime aborts

maieneuro added 2 commits July 3, 2026 00:16
…p build

Fixes the assertion reported in dealii#237 and makes the
example build warning-free in both Debug and Release with deal.II 9.7.

Correctness fixes
-----------------
* Mechanical FE component count: mech_fe was declared as
  FESystem(FE_Q, dim, FE_Q, 2), giving dim+2 components, while the rest of
  the program consistently assumes dim+1 (displacement + angular twist):
  the ComponentMasks, LBCSystem<dim, Number, dim+1>, the zero_function,
  Material<dim+1>, the FEValuesExtractors (displacements 0..dim-1, angular
  velocity at dim) and the output component names/interpretations. The
  extra component made
    component_mask.represents_n_components(fe.n_components())
  fail inside VectorTools::interpolate_boundary_values(), aborting in
  Debug during apply_constraints(). Changed the multiplicity 2 -> 1 so the
  FE has dim+1 components, matching everything else.

* Removed a dead, singular MixedFEProjector setup over mech_fe. The result
  (mech_fe_projectors) was never used, and assembling an L2 projector over
  the full mech_fe (dim+1 components, 12 dofs/cell for Q1) from only 4
  quadrature points yields a rank-deficient mass matrix, which aborted in
  FullMatrix::gauss_jordan() once the ComponentMask assertion was past.
  With this removed the example runs the time-stepping loop.

Warning cleanup (Debug and Release now compile with zero project warnings)
--------------------------------------------------------------------------
* -Wdeprecated-declarations: DoFSystem now uses the returning form of
  DoFTools::extract_locally_relevant_dofs() and the two-index-set
  AffineConstraints::reinit().
* -Wsuggest-override: added override to the Material overrides in
  ThermoPlasticMaterial and ExponentialHardeningElastoplasticMaterial, and
  to the Function / std::exception subclasses.
* -Wreorder: fixed member initialization order in
  BoundaryUnidirectionalPenaltySpec and ScaleComponentFunction.
* -Wsign-compare: cast boundary_id() comparisons against the int keys of
  the boundary-load / convection appliers to types::boundary_id.
* -Wcatch-value: catch MaterialDomainException by const reference.
* -Wunused-variable / -Wunused-but-set-variable / -Wunused-parameter:
  tagged genuinely-unused locals and parameters with [[maybe_unused]]
  (preserving the computations), dropped an unused local in main.cpp, and
  elided unused parameter names in stub material methods.
The example built and ran serially but aborted under mpirun. Two latent
parallel-only bugs, both surfaced by deal.II 9.7 Debug (which enables
libstdc++ assertions), are fixed here.

compress() on ghosted vectors
-----------------------------
previous_deformation, previous_time_derivative and current_increment are
reinit'd with locally_relevant_dofs, i.e. they carry ghost elements and
are read-only. run() and the line-search loops assigned a locally-owned
vector into them and then called compress(), which deal.II 9.7 forbids:

    has_ghost_elements() == false

Assigning owned -> ghosted already performs the ghost import, so the
compress() calls were both unnecessary and illegal. This mirrors the
established pattern in NewtonStepSystem::advance_time(), which does
"ghosted = owned" (and "ghosted += ghosted", "ghosted = 0") with no
compress(). Removed the 11 compress() calls made on ghosted vectors;
kept the ones on locally-owned vectors (Newton_step_residual,
temp_locally_owned_increment, total_residual, ...).

Out-of-bounds MPI buffer access in remap_material_state_variables
-----------------------------------------------------------------
The point-to-point exchange of material state and deformation gradients
passed buffer addresses as &group.at(i)[0]. When a rank exchanges no
points with rank i the corresponding per-rank buffer is empty, and
operator[](0) on an empty std::vector aborts under _GLIBCXX_ASSERTIONS
(deal.II Debug). The MPI count is 0 in that case so no data is actually
read, but forming the address is still undefined behavior. Replaced all
12 &..._groups.at(i)[0] buffer arguments with ..._groups.at(i).data(),
which is well defined for empty vectors.

Verified: mpirun -n 4 and -n 18 now run the full nonlinear solve
(mesh-motion, mechanical Newton iterations, contact) without aborting;
Debug and Release still build with zero project warnings.
@marcfehling

marcfehling commented Jul 3, 2026

Copy link
Copy Markdown
Member

Thank you for the quick response! Your changes looks reasonable.

Unfortunately, the program still triggers some assertions.

$ mpirun -np 2 ./PlasticityLab 

--------------------------------------------------------
An error occurred in line <2297> of file <dealii/include/deal.II/lac/trilinos_vector.h> in function
    dealii::TrilinosWrappers::MPI::Vector& dealii::TrilinosWrappers::MPI::Vector::operator=(dealii::TrilinosScalar)
The violated condition was: 
    !has_ghost_elements()
Additional information: 
    You are trying an operation on a vector that is only allowed if the
    vector has no ghost elements, but the vector you are operating on does
    have ghost elements.
    
    Specifically, there are two kinds of operations that are typically not
    allowed on vectors with ghost elements. First, vectors with ghost
    elements are read-only and cannot appear in operations that write into
    these vectors with the exception of setting the entire vector to zero.
    Second, reduction operations (such as computing the norm of a vector,
    or taking dot products between vectors) are not allowed to ensure that
    each vector element is counted only once (as opposed to once for the
    owner of the element plus once for each process on which the element
    is stored as a ghost copy).
    
    See the glossary entry on 'Ghosted vectors' for more information.

Stacktrace:
-----------
#0  ./PlasticityLab: dealii::TrilinosWrappers::MPI::Vector::operator=(double)
#1  ./PlasticityLab: PlasticityLab::PlasticityLabProg<2, double>::run()
#2  ./PlasticityLab: main
--------------------------------------------------------

@marcfehling marcfehling mentioned this pull request Jul 3, 2026
33 tasks
@bangerth

bangerth commented Jul 3, 2026

Copy link
Copy Markdown
Member

Perhaps we can merge this PR by itself already given that it fixes real issues that prevent the code to run in sequential computations?

@bangerth

bangerth commented Jul 3, 2026

Copy link
Copy Markdown
Member

For the record, the failing assertion is in a statement of the form

  vector = scalar;

which is only allowed if the scalar is zero and if vector does not have ghost entries. In fact, with the current deal.II version, it is also allowed if scalar==0 and if the vector does have ghost entries. So I suspect that this happens in a statement like

    therm_nonlinear_system.previous_deformation = ambient_temperature;

in which the right hand side is nonzero. For cases like this, you need to first create a fully distributed vector, assign it the ambient_temperature value, and then assign that vector to the ghosted vector here.

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.

3 participants