From 39d0d06bd5ea735d491c672b516c6b82ab299958 Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Wed, 3 Jun 2026 16:57:39 +0200 Subject: [PATCH 01/11] =?UTF-8?q?=F0=9F=90=9B=20allow=20to=20validate=20a?= =?UTF-8?q?=20timestep=20when=20allowNonConverged=20is=20enabled=20by=20pr?= =?UTF-8?q?eventing=20any=20timestep-cut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../physicsSolvers/NonlinearSolverParameters.cpp | 5 +++-- src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp b/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp index d50a3f79152..d80c6c6b832 100644 --- a/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp +++ b/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp @@ -104,8 +104,9 @@ NonlinearSolverParameters::NonlinearSolverParameters( string const & name, registerWrapper( viewKeysStruct::allowNonConvergedString(), &m_allowNonConverged ). setApplyDefaultValue( 0 ). setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Allow non-converged solution to be accepted. " - "(i.e. exit from the Newton loop without achieving the desired tolerance)" ); + setDescription( "Allow non-converged solution to be accepted " + "(i.e. exit from the Newton loop without achieving the desired tolerance). " + "With this parameter enabledthus timestep cuts never occur" ); registerWrapper( viewKeysStruct::timeStepDecreaseIterLimString(), &m_timeStepDecreaseIterLimit ). setApplyDefaultValue( 0.7 ). diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index 8d05dfd6958..fe634215f75 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -917,7 +917,7 @@ real64 PhysicsSolverBase::nonlinearImplicitStep( real64 const & time_n, } // end of configuration loop - if( isConfigurationLoopConverged ) + if( isConfigurationLoopConverged || allowNonConverged ) { // get out of outer loop break; From 743110d834ec441402942763a9a98acea6de70c4 Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Wed, 3 Jun 2026 18:01:30 +0200 Subject: [PATCH 02/11] =?UTF-8?q?=F0=9F=90=9B=20bugfix=20approach=20change?= =?UTF-8?q?:=20allow=20to=20validate=20a=20timestep=20when=20allowNonConve?= =?UTF-8?q?rged=20is=20enabled=20without=20preventing=20timestep-cuts,=20b?= =?UTF-8?q?ut=20at=20the=20last=20level=20of=20sub-steps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NonlinearSolverParameters.cpp | 6 +++--- .../physicsSolvers/PhysicsSolverBase.cpp | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp b/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp index d80c6c6b832..93955523260 100644 --- a/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp +++ b/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp @@ -104,9 +104,9 @@ NonlinearSolverParameters::NonlinearSolverParameters( string const & name, registerWrapper( viewKeysStruct::allowNonConvergedString(), &m_allowNonConverged ). setApplyDefaultValue( 0 ). setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Allow non-converged solution to be accepted " - "(i.e. exit from the Newton loop without achieving the desired tolerance). " - "With this parameter enabledthus timestep cuts never occur" ); + setDescription( "When enabled, the simulation can continue even with a non-converged solution (residuals exceeding the tolerance during the " + "newton loops) at the deepest level of sub-timesteps (maxSubSteps).\n" + "When disabled, the simulation will stop with an error when no converged solution has been found at the last sub-step level." ); registerWrapper( viewKeysStruct::timeStepDecreaseIterLimString(), &m_timeStepDecreaseIterLimit ). setApplyDefaultValue( 0.7 ). diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index fe634215f75..d5451370504 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -367,9 +367,19 @@ bool PhysicsSolverBase::execute( real64 const time_n, getName(), subStep, dtAccepted, nextDt, dtRemaining ) ); } } - GEOS_ERROR_IF( dtRemaining > 0.0, - "Maximum allowed number of sub-steps reached. Consider increasing maxSubSteps.", - getDataContext() ); + + if( m_nonlinearSolverParameters.m_allowNonConverged ) + { + GEOS_WARNING_IF( dtRemaining > 0.0, + "Maximum allowed number of sub-steps reached, non-converged solutions are allowed so the simulation continues with innacurate results.", + getDataContext(), getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::allowNonConvergedString()) ); + } + else + { + GEOS_ERROR_IF( dtRemaining > 0.0, + "Maximum allowed number of sub-steps reached. Consider increasing maxSubSteps.", + getDataContext() ); + } // Decide what to do with the next Dt for the event running the solver. m_nextDt = setNextDt( time_n + dt, nextDt, domain ); @@ -917,7 +927,7 @@ real64 PhysicsSolverBase::nonlinearImplicitStep( real64 const & time_n, } // end of configuration loop - if( isConfigurationLoopConverged || allowNonConverged ) + if( isConfigurationLoopConverged ) { // get out of outer loop break; From d2dae02ed71288b8ea9244f6cf69e0fa523818a8 Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Thu, 4 Jun 2026 09:43:48 +0200 Subject: [PATCH 03/11] =?UTF-8?q?=F0=9F=94=87=20only=20log=20this=20error/?= =?UTF-8?q?warning=20on=20rank=200=20as=20dtRemaining=20will=20be=20the=20?= =?UTF-8?q?same=20on=20all=20ranks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index d5451370504..cf6521b3af9 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -370,13 +370,13 @@ bool PhysicsSolverBase::execute( real64 const time_n, if( m_nonlinearSolverParameters.m_allowNonConverged ) { - GEOS_WARNING_IF( dtRemaining > 0.0, + GEOS_WARNING_IF( dtRemaining > 0.0 && MpiWrapper::commRank() == 0, "Maximum allowed number of sub-steps reached, non-converged solutions are allowed so the simulation continues with innacurate results.", getDataContext(), getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::allowNonConvergedString()) ); } else { - GEOS_ERROR_IF( dtRemaining > 0.0, + GEOS_ERROR_IF( dtRemaining > 0.0 && MpiWrapper::commRank() == 0, "Maximum allowed number of sub-steps reached. Consider increasing maxSubSteps.", getDataContext() ); } From 9e16b4594666c3588a90faec9f5fb375e95347ce Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Thu, 4 Jun 2026 10:50:51 +0200 Subject: [PATCH 04/11] =?UTF-8?q?=F0=9F=93=A6=20schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/coreComponents/schema/schema.xsd | 3 ++- src/coreComponents/schema/schema.xsd.other | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index bd776c2bac0..4e5e210fb83 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -2452,7 +2452,8 @@ Information output from lower logLevels is added with the desired log level - + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 355f061e7f5..11e08ccc206 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -526,7 +526,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + @@ -1603,7 +1603,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + From 3f38ea86f381afac3f8e9f18dff89d26640ec55e Mon Sep 17 00:00:00 2001 From: MelReyCG <122801580+MelReyCG@users.noreply.github.com> Date: Fri, 5 Jun 2026 16:57:10 +0200 Subject: [PATCH 05/11] Update src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp Co-authored-by: Dickson Kachuma <81433670+dkachuma@users.noreply.github.com> --- src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index cf6521b3af9..ad68e0d7ba7 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -371,7 +371,7 @@ bool PhysicsSolverBase::execute( real64 const time_n, if( m_nonlinearSolverParameters.m_allowNonConverged ) { GEOS_WARNING_IF( dtRemaining > 0.0 && MpiWrapper::commRank() == 0, - "Maximum allowed number of sub-steps reached, non-converged solutions are allowed so the simulation continues with innacurate results.", + "Maximum allowed number of sub-steps reached but non-converged solutions are allowed so the simulation will continue with potentially inaccurate results.", getDataContext(), getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::allowNonConvergedString()) ); } else From f11e30139de242e780455909e9ca6e846b7b5e75 Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Wed, 17 Jun 2026 16:03:19 +0200 Subject: [PATCH 06/11] =?UTF-8?q?=F0=9F=93=9D=20added=20warnings=20in=20ex?= =?UTF-8?q?amples?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...LM_multiphasePoromechanics_curvedFrac_smoke.xml | 1 + ...M_singlephasePoromechanics_curvedFrac_smoke.xml | 3 ++- .../PoroElastic_dfm_PEBICrack_smoke.xml | 3 ++- .../fluidFlow/unitTests/testFlowStatistics.cpp | 14 ++++++++------ 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/inputFiles/poromechanicsFractures/Contact/AugmentedLagrangianMultipliers/ALM_multiphasePoromechanics_curvedFrac_smoke.xml b/inputFiles/poromechanicsFractures/Contact/AugmentedLagrangianMultipliers/ALM_multiphasePoromechanics_curvedFrac_smoke.xml index b74322d75c0..bd3162df17b 100644 --- a/inputFiles/poromechanicsFractures/Contact/AugmentedLagrangianMultipliers/ALM_multiphasePoromechanics_curvedFrac_smoke.xml +++ b/inputFiles/poromechanicsFractures/Contact/AugmentedLagrangianMultipliers/ALM_multiphasePoromechanics_curvedFrac_smoke.xml @@ -63,6 +63,7 @@ discretization="fluidTPFA" targetRegions="{ Region, Reservoir, Fracture}" temperature="368.15" > + + targetRegions="{ Region, Reservoir, Fracture }" > + + targetRegions="{ Region, Fault}" > + + @@ -619,11 +621,11 @@ TestSet getTestSet() discretization="fluidTPFA" targetRegions="{ reservoir }" temperature="366.483" - useMass="1" - logLevel="1" > + useMass="1" + logLevel="1" > + allowNonConverged="1" /> @@ -891,11 +893,11 @@ TestSet getTestSet() discretization="fluidTPFA" targetRegions="{ reservoir }" temperature="366.483" - useMass="0" - logLevel="1" > + useMass="0" + logLevel="1" > + allowNonConverged="1" /> From a0f9e3a153cdfea632c83f06d15a247de3736ec1 Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Wed, 17 Jun 2026 16:03:21 +0200 Subject: [PATCH 07/11] =?UTF-8?q?=F0=9F=94=8A=20added=20warning=20at=20sta?= =?UTF-8?q?rt=20of=20simulation=20when=20'llowNonConverged=20is=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../physicsSolvers/NonlinearSolverParameters.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp b/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp index 93955523260..9e753900b4f 100644 --- a/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp +++ b/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp @@ -215,6 +215,14 @@ NonlinearSolverParameters::NonlinearSolverParameters( string const & name, void NonlinearSolverParameters::postInputInitialization() { + if( m_allowNonConverged > 0 ) + { + GEOS_WARNING( GEOS_FMT( "Solver '{}' has '{}' enabled.\nThe simulation will not stop on non-converged solutions, " + "result may contain inaccurate solutions that VIOLATE CONVERGENCE TOLERANCES.", + getParent().getName(), viewKeysStruct::allowNonConvergedString() ), + getWrapperDataContext( viewKeysStruct::allowNonConvergedString() ) ); + } + GEOS_ERROR_IF_LE_MSG( m_timeStepDecreaseIterLimit, m_timeStepIncreaseIterLimit, GEOS_FMT( "{} Value should be smaller than {}", viewKeysStruct::timeStepIncreaseIterLimString(), From 92943f55a6c6a83c346611ab2a352d42bffe3465 Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Wed, 17 Jun 2026 16:04:28 +0200 Subject: [PATCH 08/11] =?UTF-8?q?=F0=9F=94=8A=20more=20visible=20non-conve?= =?UTF-8?q?rgence=20message?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../physicsSolvers/PhysicsSolverBase.cpp | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index ad68e0d7ba7..9e8577387ff 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -217,17 +217,17 @@ void PhysicsSolverBase::registerDataOnMesh( Group & meshBodies ) forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, MeshLevel & mesh, string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< ElementSubRegionBase >( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) { - setConstitutiveNamesCallSuper( subRegion ); - setConstitutiveNames( subRegion ); - } ); + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< ElementSubRegionBase >( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + setConstitutiveNamesCallSuper( subRegion ); + setConstitutiveNames( subRegion ); + } ); - } ); + } ); } @@ -371,7 +371,7 @@ bool PhysicsSolverBase::execute( real64 const time_n, if( m_nonlinearSolverParameters.m_allowNonConverged ) { GEOS_WARNING_IF( dtRemaining > 0.0 && MpiWrapper::commRank() == 0, - "Maximum allowed number of sub-steps reached but non-converged solutions are allowed so the simulation will continue with potentially inaccurate results.", + "Maximum allowed number of sub-steps reached.\nNon-converged solutions are allowed, SIMULATION WILL CONTINUE WITH INACURATE RESULTS.", getDataContext(), getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::allowNonConvergedString()) ); } else @@ -1650,12 +1650,12 @@ Timestamp PhysicsSolverBase::getMeshModificationTimestamp( DomainPartition & dom forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, string_array const & ) - { - if( meshModificationTimestamp < mesh.getModificationTimestamp() ) { - meshModificationTimestamp = mesh.getModificationTimestamp(); - } - } ); + if( meshModificationTimestamp < mesh.getModificationTimestamp() ) + { + meshModificationTimestamp = mesh.getModificationTimestamp(); + } + } ); return meshModificationTimestamp; } @@ -1705,38 +1705,38 @@ bool PhysicsSolverBase::detectOscillations() const RAJA::forall< parallelDevicePolicy<> >( RAJA::TypedRangeSegment< localIndex >( 0, numDofs ), [=] GEOS_HOST_DEVICE ( localIndex const dof ) - { - bool oscillationDetected = true; - for( localIndex i = historySize - 1; i > historySize - oscillationCheckDepth; --i ) { - real64 dxCur = solutionHistory[i][dof]; - real64 dxPrev = solutionHistory[i-1][dof]; - - if( LvArray::math::abs( dxCur ) < oscillationTolerance || LvArray::math::abs( dxPrev ) < oscillationTolerance ) + bool oscillationDetected = true; + for( localIndex i = historySize - 1; i > historySize - oscillationCheckDepth; --i ) { - oscillationDetected = false; + real64 dxCur = solutionHistory[i][dof]; + real64 dxPrev = solutionHistory[i-1][dof]; + + if( LvArray::math::abs( dxCur ) < oscillationTolerance || LvArray::math::abs( dxPrev ) < oscillationTolerance ) + { + oscillationDetected = false; break; // solution changes are too small - } + } - real64 maxAbs = LvArray::math::max( LvArray::math::abs( dxCur ), LvArray::math::abs( dxPrev ) ); - if( LvArray::math::abs( dxCur + dxPrev ) / maxAbs > oscillationTolerance ) - { - oscillationDetected = false; + real64 maxAbs = LvArray::math::max( LvArray::math::abs( dxCur ), LvArray::math::abs( dxPrev ) ); + if( LvArray::math::abs( dxCur + dxPrev ) / maxAbs > oscillationTolerance ) + { + oscillationDetected = false; break; // solution changes are not oscillating - } + } - if( dxCur * dxPrev > 0 ) - { - oscillationDetected = false; + if( dxCur * dxPrev > 0 ) + { + oscillationDetected = false; break; // sign is not oscillating + } } - } - if( oscillationDetected ) - { - oscillationCount += 1; - } - } ); + if( oscillationDetected ) + { + oscillationCount += 1; + } + } ); real64 const f = static_cast< real64 >( MpiWrapper::sum( oscillationCount.get() ) ) / MpiWrapper::sum( numDofs ); From 740f34579d1f03d478a926fcb1cfb3c32fb9e4ea Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Wed, 17 Jun 2026 16:04:31 +0200 Subject: [PATCH 09/11] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20mistake=20in=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../physicsSolvers/SolverStatistics.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/coreComponents/physicsSolvers/SolverStatistics.hpp b/src/coreComponents/physicsSolvers/SolverStatistics.hpp index 334f1672c98..c3110f4612d 100644 --- a/src/coreComponents/physicsSolvers/SolverStatistics.hpp +++ b/src/coreComponents/physicsSolvers/SolverStatistics.hpp @@ -152,6 +152,13 @@ class IterationsStatistics : public dataRepository::Group void setFilename( string_view filename ) { m_iterationsFilename = filename; } + /** + * @brief Set the table title in the log. + * @param name The table as a string_view. + */ + void setTableName( string_view name ) + { m_tableIterationName = name; } + /** * @return A const string iteration filename @@ -166,13 +173,6 @@ class IterationsStatistics : public dataRepository::Group { return m_iterationsFilename; } - /** - * @brief Set the filename output file. - * @param name The filename as a string_view. - */ - void setTableName( string_view name ) - { m_tableIterationName = name; } - /** * @brief Output the statistics to the console in table format */ From 716744f429cb2a15ad63d7b8aa1a25e6f166f0e4 Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Wed, 17 Jun 2026 16:04:33 +0200 Subject: [PATCH 10/11] =?UTF-8?q?=F0=9F=90=9B=20perform=20the=20timestep?= =?UTF-8?q?=20cut=20at=20start=20of=20nonlinear=20solver=20loop,=20as=20it?= =?UTF-8?q?=20can=20perform=20a=20final=20cut=20in=20case=20of=20non=20con?= =?UTF-8?q?vergence=20->=20solver=20convergence=20capability=20may=20bette?= =?UTF-8?q?r=20be=20returned=20explicitely?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../physicsSolvers/PhysicsSolverBase.cpp | 31 ++++++--------- .../multiphysics/CoupledSolver.hpp | 39 +++++++++---------- 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index 9e8577387ff..1046d68507f 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -864,13 +864,19 @@ real64 PhysicsSolverBase::nonlinearImplicitStep( real64 const & time_n, // required. for( dtAttempt = 0; dtAttempt < maxNumberDtCuts; ++dtAttempt ) { - // reset the solver state, since we are restarting the time step if( dtAttempt > 0 ) { + // reset the solver state, since we are restarting the time step Timer timer( m_timers.get_inserted( "reset state" ) ); - resetStateToBeginningOfStep( domain ); resetConfigurationToBeginningOfStep( domain ); + + // previous attempt failed, we try cuttting the timestep + stepDt *= dtCutFactor; + m_numTimestepsSinceLastDtCut = 0; + GEOS_LOG_LEVEL_RANK_0 ( logInfo::TimeStep, GEOS_FMT( "New dt = {}", stepDt ) ); + getIterationStats().updateTimeStepCut(); + getIterationStats().writeIterationStatsToTable(); } // it's the simplest configuration that can be attempted whenever Newton's fails as a last resource. @@ -929,33 +935,20 @@ real64 PhysicsSolverBase::nonlinearImplicitStep( real64 const & time_n, if( isConfigurationLoopConverged ) { - // get out of outer loop - break; - } - else - { - // cut timestep, go back to beginning of step and restart the Newton loop - stepDt *= dtCutFactor; - m_numTimestepsSinceLastDtCut = 0; - GEOS_LOG_LEVEL_RANK_0 ( logInfo::TimeStep, GEOS_FMT( "New dt = {}", stepDt ) ); - - // notify the solver statistics counter that this is a time step cut - getIterationStats().updateTimeStepCut(); - getIterationStats().writeIterationStatsToTable(); + break; // we converged, get out of outer loop } } // end of outer loop (dt chopping strategy) + // if not converged & no timestep cut are permitted, we exit the loop if( !isConfigurationLoopConverged ) { - GEOS_LOG_RANK_0( "Convergence not achieved." ); - if( allowNonConverged ) { - GEOS_LOG_RANK_0( "The accepted solution may be inaccurate." ); + GEOS_LOG_RANK_0( "Convergence not achieved. The accepted solution residuals are out of tolerance bounds." ); } else { - GEOS_ERROR( "Nonconverged solutions not allowed. Terminating...", getDataContext() ); + GEOS_ERROR( "Convergence not achieved. Terminating...", getDataContext() ); } } diff --git a/src/coreComponents/physicsSolvers/multiphysics/CoupledSolver.hpp b/src/coreComponents/physicsSolvers/multiphysics/CoupledSolver.hpp index c5cddf6acd1..996e9ca150b 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CoupledSolver.hpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CoupledSolver.hpp @@ -505,6 +505,20 @@ class CoupledSolver : public PhysicsSolverBase // required. for( dtAttempt = 0; dtAttempt < maxNumberDtCuts; ++dtAttempt ) { + if (dtAttempt > 0) { + // cut timestep, go back to beginning of step and restart the Newton loop + stepDt *= dtCutFactor; + m_numTimestepsSinceLastDtCut = 0; + GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "New dt = {}", stepDt ) ); + + // notify the solver statistics counter that this is a time step cut + getIterationStats().updateTimeStepCut(); + forEachArgInTuple( m_solvers, [&]( auto & solver, auto ) + { + solver->getIterationStats().updateTimeStepCut(); + } ); + } + // TODO configuration loop // Reset the states of all solvers if any of them had to restart @@ -580,33 +594,18 @@ class CoupledSolver : public PhysicsSolverBase // get out of the time loop break; } - else - { - // cut timestep, go back to beginning of step and restart the Newton loop - stepDt *= dtCutFactor; - m_numTimestepsSinceLastDtCut = 0; - GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "New dt = {}", stepDt ) ); - - // notify the solver statistics counter that this is a time step cut - getIterationStats().updateTimeStepCut(); - forEachArgInTuple( m_solvers, [&]( auto & solver, auto ) - { - solver->getIterationStats().updateTimeStepCut(); - } ); - } } + // if still not converged & no timestep cut are permitted, we exit the loop - if( !isConverged ) + if( !isConfigurationLoopConverged ) { - GEOS_LOG_RANK_0( "Convergence not achieved." ); - - if( m_nonlinearSolverParameters.m_allowNonConverged > 0 ) + if( allowNonConverged ) { - GEOS_LOG_RANK_0( "The accepted solution may be inaccurate." ); + GEOS_LOG_RANK_0( "Convergence not achieved. The accepted solution residuals are out of tolerance bounds." ); } else { - GEOS_ERROR( "Nonconverged solutions not allowed. Terminating...", getDataContext() ); + GEOS_ERROR( "Convergence not achieved. Terminating...", getDataContext() ); } } From ed48ca5a93aec5d1662c173be793b09dd878ffe5 Mon Sep 17 00:00:00 2001 From: MelReyCG Date: Thu, 18 Jun 2026 09:57:24 +0200 Subject: [PATCH 11/11] =?UTF-8?q?=F0=9F=90=9B=20Changing=20approach,=20as?= =?UTF-8?q?=20return=20dt=20is=20repaired,=20not=20deactivating=20maxSubSt?= =?UTF-8?q?eps=20on=20allowNonConverged?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../physicsSolvers/PhysicsSolverBase.cpp | 122 +++++++++++------- 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index 1046d68507f..cf51f7872a1 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -358,28 +358,15 @@ bool PhysicsSolverBase::execute( real64 const time_n, GEOS_FMT( "{}: shortening time step to {} to match remaining time", getName(), nextDt ), m_nonlinearSolverParameters ); } - } - if( dtRemaining > 0.0 ) - { GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: sub-step = {}, accepted dt = {}, next dt = {}, remaining dt = {}", getName(), subStep, dtAccepted, nextDt, dtRemaining ) ); } } - - if( m_nonlinearSolverParameters.m_allowNonConverged ) - { - GEOS_WARNING_IF( dtRemaining > 0.0 && MpiWrapper::commRank() == 0, - "Maximum allowed number of sub-steps reached.\nNon-converged solutions are allowed, SIMULATION WILL CONTINUE WITH INACURATE RESULTS.", - getDataContext(), getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::allowNonConvergedString()) ); - } - else - { - GEOS_ERROR_IF( dtRemaining > 0.0 && MpiWrapper::commRank() == 0, - "Maximum allowed number of sub-steps reached. Consider increasing maxSubSteps.", - getDataContext() ); - } + GEOS_ERROR_IF( dtRemaining > 0.0, + "Maximum allowed number of sub-steps reached. Consider increasing maxSubSteps.", + getDataContext() ); // Decide what to do with the next Dt for the event running the solver. m_nextDt = setNextDt( time_n + dt, nextDt, domain ); @@ -837,10 +824,10 @@ real64 PhysicsSolverBase::eisenstatWalker( real64 const newNewtonNorm, return krylovTol; } -real64 PhysicsSolverBase::nonlinearImplicitStep( real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - DomainPartition & domain ) +StepResult PhysicsSolverBase::nonlinearImplicitStep( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + DomainPartition & domain ) { GEOS_MARK_FUNCTION; // dt may be cut during the course of this step, so we are keeping a local @@ -944,7 +931,8 @@ real64 PhysicsSolverBase::nonlinearImplicitStep( real64 const & time_n, { if( allowNonConverged ) { - GEOS_LOG_RANK_0( "Convergence not achieved. The accepted solution residuals are out of tolerance bounds." ); + if ( MpiWrapper::commRank() == 0 ) + recordNonConvergedTimestep( time_n, cycleNumber ); } else { @@ -956,6 +944,15 @@ real64 PhysicsSolverBase::nonlinearImplicitStep( real64 const & time_n, return stepDt; } +void PhysicsSolverBase::recordNonConvergedTimestep( globalIndex const cycleNumber, + real64 const time_n ) +{ + GEOS_WARNING( dtRemaining > 0.0 && MpiWrapper::commRank() == 0, + "Maximum allowed number of sub-steps reached.\nNon-converged solutions are allowed, SIMULATION WILL CONTINUE WITH INACURATE RESULTS.", + getDataContext(), getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::allowNonConvergedString()) ); + // TODO record non-converged timestep, cycle, residual... +} + bool PhysicsSolverBase::solveNonlinearSystem( real64 const & time_n, real64 const & stepDt, integer const cycleNumber, @@ -1622,6 +1619,33 @@ void PhysicsSolverBase::cleanup( real64 const GEOS_UNUSED_PARAM( time_n ), getIterationStats().closeFile(); getConvergenceStats().closeFile(); + if( m_nonlinearSolverParameters.m_allowNonConverged && m_nonConvergedCycleNumbers.size() > 0 ) + { // TODO : relocate where non-convergence data is stored + globalIndex const numNonConverged = m_nonConvergedCycleNumbers.size(); + + TableLayout nonConvLayout( GEOS_FMT( "{} NON-CONVERGED TIMESTEPS", getName()), + { "Cycle", "Time (s)", "Residual" } ); + + TableTextFormatter const nonConvFormatter( nonConvLayout ); + + TableData nonConvData; + for( globalIndex i = 0; i < numNonConverged; ++i ) + { + real64 const timeVal = i < m_nonConvergedTimes.size() ? m_nonConvergedTimes[i] : 0.0; + real64 const residVal = i < m_nonConvergedResiduals.size() ? m_nonConvergedResiduals[i] : 0.0; + nonConvData.addRow( m_nonConvergedCycleNumbers[i], timeVal, residVal ); + } + + std::string const tableStr = nonConvFormatter.toString( nonConvData ); + + GEOS_WARNING( GEOS_FMT( "WARNING: Simulation ended with non-converged timesteps:\n" + "- Results contain NON-PHYSICAL values and are likely invalid for use.\n" + "- The simulation has not been aborted because 'allowNonConverged' was active on this solver.\n" + "{}\n", + tableStr ), + ); + } + for( auto & timer : m_timers ) { real64 const time = std::chrono::duration< double >( timer.second ).count(); @@ -1643,12 +1667,12 @@ Timestamp PhysicsSolverBase::getMeshModificationTimestamp( DomainPartition & dom forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, string_array const & ) + { + if( meshModificationTimestamp < mesh.getModificationTimestamp() ) { - if( meshModificationTimestamp < mesh.getModificationTimestamp() ) - { - meshModificationTimestamp = mesh.getModificationTimestamp(); - } - } ); + meshModificationTimestamp = mesh.getModificationTimestamp(); + } + } ); return meshModificationTimestamp; } @@ -1698,38 +1722,38 @@ bool PhysicsSolverBase::detectOscillations() const RAJA::forall< parallelDevicePolicy<> >( RAJA::TypedRangeSegment< localIndex >( 0, numDofs ), [=] GEOS_HOST_DEVICE ( localIndex const dof ) + { + bool oscillationDetected = true; + for( localIndex i = historySize - 1; i > historySize - oscillationCheckDepth; --i ) { - bool oscillationDetected = true; - for( localIndex i = historySize - 1; i > historySize - oscillationCheckDepth; --i ) - { - real64 dxCur = solutionHistory[i][dof]; - real64 dxPrev = solutionHistory[i-1][dof]; + real64 dxCur = solutionHistory[i][dof]; + real64 dxPrev = solutionHistory[i-1][dof]; - if( LvArray::math::abs( dxCur ) < oscillationTolerance || LvArray::math::abs( dxPrev ) < oscillationTolerance ) - { - oscillationDetected = false; + if( LvArray::math::abs( dxCur ) < oscillationTolerance || LvArray::math::abs( dxPrev ) < oscillationTolerance ) + { + oscillationDetected = false; break; // solution changes are too small - } + } - real64 maxAbs = LvArray::math::max( LvArray::math::abs( dxCur ), LvArray::math::abs( dxPrev ) ); - if( LvArray::math::abs( dxCur + dxPrev ) / maxAbs > oscillationTolerance ) - { - oscillationDetected = false; + real64 maxAbs = LvArray::math::max( LvArray::math::abs( dxCur ), LvArray::math::abs( dxPrev ) ); + if( LvArray::math::abs( dxCur + dxPrev ) / maxAbs > oscillationTolerance ) + { + oscillationDetected = false; break; // solution changes are not oscillating - } - - if( dxCur * dxPrev > 0 ) - { - oscillationDetected = false; - break; // sign is not oscillating - } } - if( oscillationDetected ) + if( dxCur * dxPrev > 0 ) { - oscillationCount += 1; + oscillationDetected = false; + break; // sign is not oscillating } - } ); + } + + if( oscillationDetected ) + { + oscillationCount += 1; + } + } ); real64 const f = static_cast< real64 >( MpiWrapper::sum( oscillationCount.get() ) ) / MpiWrapper::sum( numDofs );