From f98cc9df36e3ef9c58e849333f138ae12dfda685 Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Mon, 15 Jul 2024 18:01:03 -0600 Subject: [PATCH 1/2] FEAT: Added Levenberg-Marquardt solve in the case of a convergence failure --- src/cpp/tardigrade_hydra.cpp | 21 +++++- src/cpp/tardigrade_hydra.h | 4 +- src/cpp/tests/test_tardigrade_hydra.cpp | 90 +++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 3 deletions(-) diff --git a/src/cpp/tardigrade_hydra.cpp b/src/cpp/tardigrade_hydra.cpp index 7590565..cc73706 100644 --- a/src/cpp/tardigrade_hydra.cpp +++ b/src/cpp/tardigrade_hydra.cpp @@ -1866,7 +1866,26 @@ namespace tardigradeHydra{ } catch( const convergence_error &e ){ - throw; + //Try a Levenberg-Marquardt solve if there is a convergence error + setRankDeficientError( false ); + + setUseLevenbergMarquardt( true ); + + try{ + + solveNonLinearProblem( ); + + } + catch( const convergence_error &e ){ + + throw; + + } + catch( std::exception &e ){ + + TARDIGRADE_ERROR_TOOLS_CATCH( throw; ) + + } } catch( std::exception &e ){ diff --git a/src/cpp/tardigrade_hydra.h b/src/cpp/tardigrade_hydra.h index c6978d8..f37da40 100644 --- a/src/cpp/tardigrade_hydra.h +++ b/src/cpp/tardigrade_hydra.h @@ -948,6 +948,8 @@ namespace tardigradeHydra{ virtual void formPreconditioner( ); + virtual void solveNonLinearProblem( ); + virtual void formMaxRowPreconditioner( ); virtual void initializeUnknownVector( ); @@ -1216,8 +1218,6 @@ namespace tardigradeHydra{ void setPreviousFirstConfigurationJacobians( ); - void solveNonLinearProblem( ); - void performPreconditionedSolve( floatVector &deltaX_tr ); void solveNewtonUpdate( floatVector &deltaX_tr ); diff --git a/src/cpp/tests/test_tardigrade_hydra.cpp b/src/cpp/tests/test_tardigrade_hydra.cpp index da48b8d..3b2da67 100644 --- a/src/cpp/tests/test_tardigrade_hydra.cpp +++ b/src/cpp/tests/test_tardigrade_hydra.cpp @@ -5676,3 +5676,93 @@ BOOST_AUTO_TEST_CASE( test_hydraBase_updateUnknownVector, * boost::unit_test::to BOOST_TEST( hydra.checkProject( ) ); } + +BOOST_AUTO_TEST_CASE( test_hydraBase_evaluate, * boost::unit_test::tolerance( DEFAULT_TEST_TOLERANCE ) ){ + + class residualMock : public tardigradeHydra::residualBase{ + + public: + + bool project_called = false; + + using tardigradeHydra::residualBase::residualBase; + + virtual void projectSuggestedX( std::vector< double > &trialX, + const std::vector< double > &Xp ) override{ + + project_called = true; + + } + + }; + + class hydraBaseMock : public tardigradeHydra::hydraBase{ + + public: + + residualMock r1; + + residualMock r2; + + using tardigradeHydra::hydraBase::hydraBase; + + unsigned int num_calls = 0; + + protected: + + virtual void solveNonLinearProblem( ) override{ + + num_calls++; + + throw tardigradeHydra::convergence_error( "failure to converge" ); + + } + + using tardigradeHydra::hydraBase::setResidualClasses; + + }; + + floatType time = 1.1; + + floatType deltaTime = 2.2; + + floatType temperature = 5.3; + + floatType previousTemperature = 23.4; + + floatVector deformationGradient = { 1.05, 0, 0, + 0.00, 1, 0, + 0.00, 1, 1}; + + floatVector previousDeformationGradient = { -0.21576496, -0.31364397, 0.45809941, + -0.12285551, -0.88064421, -0.20391149, + 0.47599081, -0.63501654, -0.64909649 }; + + floatVector previousStateVariables = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + floatVector parameters = { 123.4, 56.7 }; + + unsigned int numConfigurations = 2; + + unsigned int numNonLinearSolveStateVariables = 0; + + unsigned int dimension = 3; + + floatVector unknownVector = { 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2 }; + + hydraBaseMock hydra( time, deltaTime, temperature, previousTemperature, deformationGradient, previousDeformationGradient, + { }, { }, + previousStateVariables, parameters, numConfigurations, numNonLinearSolveStateVariables, dimension ); + +// try{hydra.evaluate();}catch(std::exception &e){tardigradeErrorTools::printNestedExceptions(e);} +// + BOOST_CHECK_THROW( hydra.evaluate( ), tardigradeHydra::convergence_error ); + + BOOST_TEST( *hydra.getUseLevenbergMarquardt( ) ); + + BOOST_TEST( !( *hydra.getRankDeficientError( ) ) ); + + BOOST_TEST( hydra.num_calls == 2 ); + +} From 6d82e80b5c67d9803ecc2ca9fb1c74c368297c83 Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Mon, 15 Jul 2024 18:01:50 -0600 Subject: [PATCH 2/2] MAINT: Updated changelog --- docs/sphinx/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sphinx/changelog.rst b/docs/sphinx/changelog.rst index a501780..c2a2f60 100644 --- a/docs/sphinx/changelog.rst +++ b/docs/sphinx/changelog.rst @@ -13,6 +13,7 @@ New Features ============ - Added projection operators to the residualBase (:pull:`133`). By `Nathan Miller`_. - Allow the user to turn off rank-deficient errors (:pull:`134`). By `Nathan Miller`_. +- Added a Levenberg-Marquardt solve in the case of a convergence failure (:pull:`135`). By `Nathan Miller`_. ****************** 0.4.3 (07-12-2024)