Skip to content

Further cleanup in preparation for the Adaptive Estimate Interpolation algorithm#2082

Open
dragos-ana wants to merge 1 commit into
4C-multiphysics:mainfrom
dragos-ana:further-cleanup-local-newton
Open

Further cleanup in preparation for the Adaptive Estimate Interpolation algorithm#2082
dragos-ana wants to merge 1 commit into
4C-multiphysics:mainfrom
dragos-ana:further-cleanup-local-newton

Conversation

@dragos-ana

@dragos-ana dragos-ana commented Jun 14, 2026

Copy link
Copy Markdown
Contributor
  • The term 'constitutive update' is now used instead of 'return mapping' to avoid confusion, since our constitutive update also comprises the elastic predictor verification. Several frameworks in literature use 'return mapping' to comprise both stages, but return mapping is actually the second corrector stage only. We want to make this distinction clear in the code.
  • Added struct for tracking all deformation tensors used for the local integration routines. These are then employed consistently throughout the constitutive update routines.
  • Improved error handling by adding error registration settings, and only outputting detailed
    errors. Plastic strain rate derivative checks are now disabled by default, since the detecting overflow here is not straightforward and can overconstrain the computation.
    This has some implications for the substepping test -> changed results.
  • Several functions are guarded to only be evaluated if there are no evaluation errors currently.
  • Added tracking of plastic flow at each Gauss point to improve plasticity checks, such as the ones in
    the linearization and the update procedures.
  • The update procedures are run separately per Gauss point instead of over all Gauss points, to only loop once over the GP in the update method of the material.
  • Also added characteristic for viscoplastic laws: do they use yield surface or not? Important for the AEI procedures subsequently.
  • Incorporated further logic from the viscoplastic factor to the dedicated Local Newton manager, such as the solution, along with the tracking and checking of convergence quantities.
  • Added a dedicated unit tests file for the service methods of the inelastic deformation gradient factors.
  • In preparation for the AEI: a method dedicated to determining the Local Newton estimate was used. This method will serve as the entry point for the AEI, along with manage_evaluation, which will be responsible for re-estimation.
  • Substepping: now the deformation gradient is interpolated, instead of the right CG tensor. This is also done in preparation for the AEI, to enable combining it with substepping.

@dragos-ana dragos-ana requested a review from Copilot June 14, 2026 19:55
@dragos-ana dragos-ana changed the title Further cleanup Local Newton in preparation for the Adaptive Estimate Interpolation algorithm Further cleanup in preparation for the Adaptive Estimate Interpolation algorithm Jun 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR continues refactoring/cleanup of the finite-deformation viscoplastic constitutive update in preparation for Adaptive Estimate Interpolation (AEI), including clearer terminology (“constitutive update”), more consistent deformation-tensor handling, and more configurable error registration and Local Newton bookkeeping.

Changes:

  • Introduces ErrorRegistrationSettings and updates viscoplastic law interfaces/call sites to use configurable overflow registration (incl. updated unit tests).
  • Refactors the local integration workflow to use a dedicated LocalIntegrationDeformationTensors struct and enhances Local Newton bookkeeping/management.
  • Adds a dedicated unit test file for inelastic defgrad factor service utilities and updates regression expected results.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
unittests/mat/vplast/4C_vplast_reform_johnsoncook_test.cpp Updates tests for new error-registration-settings API and overflow-registration behavior.
unittests/mat/4C_inelastic_defgrad_factors_test.cpp Adjusts material test setup to include error registration settings; updates expected error messages/results.
unittests/mat/4C_inelastic_defgrad_factors_service_test.cpp Adds new unit tests for deformation-tensor struct and Local Newton manager service behavior.
tests/input_files/mat_iso_viscoplast_refJC_log_timint_substepping.4C.yaml Updates regression reference values due to constitutive-update/substepping changes.
src/mat/vplast/4C_mat_vplast_reform_johnsoncook.hpp Updates viscoplastic law interface (uses_yield_surface, new error settings, gp-based update hooks).
src/mat/vplast/4C_mat_vplast_reform_johnsoncook.cpp Implements error-registration-settings driven overflow checks in plastic strain rate (+ derivatives).
src/mat/vplast/4C_mat_vplast_law.hpp Extends base law API (uses_yield_surface, gp-based update/update_gp_state) and updates signatures.
src/mat/4C_mat_inelastic_defgrad_factors.hpp Renames “return mapping” to “constitutive update”; introduces error-free evaluation guard + new init estimate entry point.
src/mat/4C_mat_inelastic_defgrad_factors.cpp Major refactor: tensor struct usage, per-GP update logic, error messaging, substepping interpolation changes, packing of plastic-flow flags.
src/mat/4C_mat_inelastic_defgrad_factors_service.hpp Adds ErrorRegistrationSettings, expands LocalNewtonManager responsibilities, adds deformation-tensor helper struct.
src/mat/4C_mat_inelastic_defgrad_factors_service.cpp Implements new LocalNewtonManager methods and per-GP TimeStepQuantities::update.
src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp Moves overflow-related settings under a dedicated input group and updates material input spec docs.

Comment thread src/mat/4C_mat_inelastic_defgrad_factors.hpp
Comment thread src/mat/4C_mat_inelastic_defgrad_factors.cpp
Comment thread src/mat/4C_mat_inelastic_defgrad_factors.cpp Outdated
Comment thread src/mat/4C_mat_inelastic_defgrad_factors.cpp Outdated
Comment thread src/mat/4C_mat_inelastic_defgrad_factors.cpp
Comment thread src/mat/vplast/4C_mat_vplast_law.hpp Outdated
Comment thread src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp Outdated
Comment thread src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp
Comment thread src/mat/4C_mat_inelastic_defgrad_factors.cpp Outdated
Comment thread src/mat/4C_mat_inelastic_defgrad_factors.cpp Outdated
@dragos-ana dragos-ana force-pushed the further-cleanup-local-newton branch from 561c255 to 8f45c0d Compare June 14, 2026 21:17
@dragos-ana dragos-ana self-assigned this Jun 14, 2026
Comment thread src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp Outdated
@dragos-ana dragos-ana force-pushed the further-cleanup-local-newton branch 2 times, most recently from 59c8a51 to fe04870 Compare June 15, 2026 09:23
Comment thread src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp Outdated
Comment thread src/mat/4C_mat_inelastic_defgrad_factors.hpp Outdated
Comment thread src/mat/4C_mat_inelastic_defgrad_factors.cpp
Comment thread src/mat/4C_mat_inelastic_defgrad_factors.cpp
Comment thread unittests/mat/vplast/4C_vplast_reform_johnsoncook_test.cpp Outdated
for the Adaptive Estimate Interpolation:

- The term 'constitutive update' is now used instead
of 'return mapping' to avoid confusion, since our constitutive
update also comprises the elastic predictor verification.
Several frameworks in literature use 'return mapping' to comprise
both stages, but we want to make this clear here.
- Added struct for tracking all deformation tensors
used for the local integration routines. These are
then used consistently throughout the constitutive update
routines.
- Improved error handling by adding error registration
settings, and only outputting detailed
errors.
Plastic strain rate derivative checks are now disabled
by default, which has some implications for the substepping
test -> changed results.
Also, functions are guarded to only be evaluated if
there are no evaluation errors currently.
- Added tracking of plastic flow at each Gauss point
to improve plasticity checks, such as the ones in
the linearization and the update procedures.
The update procedures are run separately per Gauss point.
- Also added characteristic for viscoplastic laws: do they
use yield surface or not? Important for the AEI subsequently.
- Incorporated further logic from the viscoplastic
inelastic factor to the dedicated Local Newton manager,
such as solution and convergence quantities tracking and
checking.
- Added a dedicated unit tests file for the service of
inelastic deformation gradient factors.
- In preparation for the AEI: a method dedicated to
determining the Local Newton estimate was used. This method
will serve as the entry point for the AEI, along with
manage_evaluation, which will be responsible for re-estimation.
- Substepping: now the deformation gradient is interpolated,
instead of the right CG tensor. This is also done in preparation
for the AEI, to enable combining it with substepping.
@dragos-ana dragos-ana force-pushed the further-cleanup-local-newton branch from fe04870 to d2bfba3 Compare June 15, 2026 18:27

@lauraengelhardt lauraengelhardt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for cleaning up the formatting first 👍 That already removed a large part of the diff. I have one short question considering the test results.

I haven’t had time to fully review the rest of the PR yet, since all changes are contained in a single large commit (and also its late 😉). IMO, it would be very helpful to split changes into smaller commits - for example one for the error handling improvements, one for adding the unit tests, and one for the AEI preparation. This would make reviewing much easier 🙂 No need to do it here, but maybe something to keep in mind for the next PRs.

NODE: 8
QUANTITY: "stress_zz"
VALUE: 9.30776106016615358e+02
VALUE: 9.31099439481397212e+02

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for my understanding: Can I ask what is the reason for the change of these values. I wouldn't expect the result to change that much just from a pure cleanup.

@dragos-ana dragos-ana Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We trigger local substepping if overflow is identified based on the plastic strain increments and the increments of their derivatives. Previously, we registered overflow for both plastic strain increments and derivative increments; however, I have seen in previous weeks that this strategy can overly constrain the local time integration. I have therefore adapted the formulation to only check overflow based on the plastic strain increments by default, and not also based on the derivative increments. This means that the overflow checking mechanism has changed, which leads to differences in the triggered substepping. Hence the observed differences in the test results.

The changes are substantial, I agree. But this is a weakness of the substepping formulation, which is very fragile and inconsistent anyway in my opinion, and should be removed or deprecated in some way in upcoming PRs on this material.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result changes make sense to me and are also changes in the "right" direction, compared to the non-substepping test

@rjoussen rjoussen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exciting to see that we're moving towards AEI! If that helps you with merging the next step, I would also be fine with removing substepping first, and then add AEI on a cleaner state.

I left some comments and also have a more general question regarding overflow errors:

What exactly is the idea behind the "manual" overflow checking in the first place? In my simulations, I often end up setting these values super high so the simulation doesn't over-cautiously stop. As far as I know/remember, resulting nan-values are caught later on anyway. Or I guess formulated differently: Why are we setting a limit on these values when we could also just abort/trigger substepping/estimate adaptation when overflow actually happens?

NODE: 8
QUANTITY: "stress_zz"
VALUE: 9.30776106016615358e+02
VALUE: 9.31099439481397212e+02

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result changes make sense to me and are also changes in the "right" direction, compared to the non-substepping test


/// does the viscoplastic law use a yield surface formulation, or is it a no-yield-surface
/// law?
[[nodiscard]] virtual bool uses_yield_surface() const = 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'll need to see how this is actually used. Currently, I don't fully understand why viscoplastic laws without a strict yield surface require a different approach in the parent material. I would rather think the important distinction is whether or not viscoplastic laws manage their own history variables.

Comment on lines +195 to +208
* @brief Update history variables of the viscoplasticity law for next time step at a given
* Gauss point
*
* @param[in] gp Current Gauss point
*/
virtual void update() = 0;
virtual void update(const unsigned int gp) = 0;

/*!
* @brief Update the history variables for a specific GP after a converged substep
* (substepping procedure)
*
* @param[in] gp Gauss point
*/
virtual void update_gp_state(int gp) = 0;
virtual void update_gp_state(const unsigned int gp) = 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was of course here before, but these methods should either be unified if possible or have more expressive names. But its hard to assess without any code in these functions.

{.description = "Parameters used in the Local Newton--Raphson procedure "
"(viscoplastic corrector stage)",
.required = false}),
group("ERROR_REGISTRATION_SETTINGS",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
group("ERROR_REGISTRATION_SETTINGS",
group<ErrorRegistrationSettings>("ERROR_REGISTRATION_SETTINGS",

I think you can do something like this here and then use the .store function to get the constructed struct directly

Comment on lines +182 to +187
if (error_registration_settings.register_plastic_strain_incr_overflow)
{
FOUR_C_ASSERT_ALWAYS(error_registration_settings.max_plastic_strain_incr > 0.0,
"Maximum plastic strain increment must be > 0: current value = {}",
error_registration_settings.max_plastic_strain_incr);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is coming directly from the input, where it is validated already. So I dont think another assert is needed here.

Comment on lines 2005 to 2008
void manage_evaluation(
const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status,
InelasticDefgradTransvIsotropElastViscoplastUtils::EvaluationAction& eval_action) const;
InelasticDefgradTransvIsotropElastViscoplastUtils::EvaluationAction& eval_action);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this methods can stay const for now.

// called in the redundant evaluate call, which is already handled -> direct return
// without calling this function)
prepare_return_mapping();
prepare_constitutive_update();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will prepare_constitutive_update() do more in the future? Currently it is so small that I would be in favor of just doing the necessary things here explicitly. This way, its less hidden. On top of that, prepare* sound like something that needs to be done before the actual function call, which is not the case here.

deftensors.right_cg, temperature, iFinM_pred, plastic_strain_pred, err_status);
if ((err_status == ViscoplastUtils::ErrorType::no_errors) && (pred_is_sol))
{
// update inverse inelastic defgrad and plastic strain

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// update inverse inelastic defgrad and plastic strain
// update inverse inelastic defgrad and plastic strain
is_plastic_gp_[gp_] = false;

Comment on lines +3790 to +3804
if (err_status != ViscoplastUtils::ErrorType::no_errors)
{
// for substepping, we exit with the set error status and retry the computation with a smaller
// substep (eventually)
if (parameter()->use_local_substepping())
{
return Core::LinAlg::Matrix<10, 1>{Core::LinAlg::Initialization::zero};
}
// without substepping, we throw directly
else
{
FOUR_C_THROW(
"{}", get_error_warning_info("Could not compute initial estimate for the local Newton!"));
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this only makes sense if determine_local_newton_init_estimate will be able to set an error status.

// reset Local Newton iteration count
local_newton_manager_.set_iteration_count(0);
// initialize local Newton
local_newton_manager_.reset_iter();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to construct a local (in a programming sense) local_newton_manager in every local newton loop? This would probably prevent a lot of resetting everywhere. The only thing that would need to change is that the number of iterations are - in the end - only, written to a class variable per gp, such that they can be plotted.

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.

5 participants