diff --git a/docs/sphinx/changelog.rst b/docs/sphinx/changelog.rst index 51239cf..5bed0d5 100644 --- a/docs/sphinx/changelog.rst +++ b/docs/sphinx/changelog.rst @@ -47,11 +47,13 @@ Internal Changes - Using new error_tools check for error function (:pull:`100`). By `Nathan Miller`_. - Changed Jacobian, dRdF, and dRdD to row-major vectors (:pull:`101`). By `Nathan Miller`_. - Replaced queries to getUnknownVector purely to get the size of the vector (:pull:`109`). By `Nathan Miller`_. +- Added a better guess for the mass-change residual to improve convergence (:pull:`110`). By `Nathan Miller`_. Bug Fixes ========= - Corrected bug where the plastic state variable integration parameter was one minus the expected value (:pull:`71`). By `Nathan Miller`_. - Corrected issue where libxsmm is not being used but was still required to be installed (:pull:`93`). By `Nathan Miller`_. +- Residuals setting initial guesses now force a reset of the current configurations (:pull:`110`). By `Nathan Miller`_. ****************** 0.4.1 (01-24-2024) diff --git a/src/cpp/tardigrade_hydra.cpp b/src/cpp/tardigrade_hydra.cpp index 81026b7..aa92271 100644 --- a/src/cpp/tardigrade_hydra.cpp +++ b/src/cpp/tardigrade_hydra.cpp @@ -1248,6 +1248,8 @@ namespace tardigradeHydra{ floatVector X = tardigradeVectorTools::appendVectors( Xmat ); + bool resetRequired = false; + for ( auto residual_ptr = getResidualClasses( )->begin( ); residual_ptr != getResidualClasses( )->end( ); residual_ptr++ ){ std::vector< unsigned int > indices; @@ -1256,6 +1258,10 @@ namespace tardigradeHydra{ ( *residual_ptr )->suggestInitialIterateValues( indices, values ); + if ( indices.size( ) > 0 ){ + resetRequired = true; + } + for ( auto i = indices.begin( ); i != indices.end( ); i++ ){ X[ *i ] = values[ ( unsigned int )( i - indices.begin( ) ) ]; @@ -1264,7 +1270,16 @@ namespace tardigradeHydra{ } - setX( X ); + if ( resetRequired ){ + + updateUnknownVector( X ); + + } + else{ + + setX( X ); + + } } diff --git a/src/cpp/tardigrade_hydra.h b/src/cpp/tardigrade_hydra.h index 7a2e7e4..ad652b2 100644 --- a/src/cpp/tardigrade_hydra.h +++ b/src/cpp/tardigrade_hydra.h @@ -462,6 +462,9 @@ namespace tardigradeHydra{ * Function which is called which allows the residual to suggest initial values for given * configurations. This is called when the unknown vector is being initialized. If more than * one residual attempts to set the initial vector the last residual will override all of the others. + * + * After the initial iterate has been suggested, the iteration data is cleared so that the residual + * starts the iteration in a clean state. * * \param &indices: The indices of the unknown vector to set * \param &values: The values to be set in the unknown vector diff --git a/src/cpp/tardigrade_hydraMassChange.cpp b/src/cpp/tardigrade_hydraMassChange.cpp index 0382b0d..8800edf 100644 --- a/src/cpp/tardigrade_hydraMassChange.cpp +++ b/src/cpp/tardigrade_hydraMassChange.cpp @@ -1503,6 +1503,28 @@ namespace tardigradeHydra{ } + void residual::suggestInitialIterateValues( std::vector< unsigned int > &indices, + std::vector< floatType > &values ){ + /*! + * Suggest initial iterate values to try and improve convergence + * + * \param &indices: The indices of the unknown vector to suggest initial values + * \param &values: The values to suggest + */ + + const unsigned int sot_dim = hydra->getSOTDimension( ); + + const unsigned int configuration = *getMassChangeConfigurationIndex( ); + + const floatVector *massChangeDeformationGradient = get_massChangeDeformationGradient( ); + + indices = std::vector< unsigned int >( sot_dim, sot_dim * configuration ); + + for ( unsigned int i = 0; i < sot_dim; i++ ){ indices[ i ] += i; } + values = *massChangeDeformationGradient; + + } + } } diff --git a/src/cpp/tardigrade_hydraMassChange.h b/src/cpp/tardigrade_hydraMassChange.h index ab1ce09..4a12304 100644 --- a/src/cpp/tardigrade_hydraMassChange.h +++ b/src/cpp/tardigrade_hydraMassChange.h @@ -96,6 +96,9 @@ namespace tardigradeHydra{ const floatType *getIntegrationParameter( ){ return &_integrationParameter; } + virtual void suggestInitialIterateValues( std::vector< unsigned int > &indices, + std::vector< floatType > &values ) override; + protected: virtual void decomposeAdditionalDOF( ); diff --git a/src/cpp/tests/test_tardigrade_hydraMassChange.cpp b/src/cpp/tests/test_tardigrade_hydraMassChange.cpp index cf81909..fa0b594 100644 --- a/src/cpp/tests/test_tardigrade_hydraMassChange.cpp +++ b/src/cpp/tests/test_tardigrade_hydraMassChange.cpp @@ -4922,3 +4922,141 @@ BOOST_AUTO_TEST_CASE( test_residual_exampleModel ){ BOOST_CHECK( tardigradeVectorTools::fuzzyEquals( dStressdAdditionalDOF, RdStressdAdditionalDOF ) ); } + +BOOST_AUTO_TEST_CASE( test_residual_suggestInitialIterateValues ){ + + class residualMock : public tardigradeHydra::massChange::residual { + + public: + + using tardigradeHydra::massChange::residual::residual; + + floatVector massChangeDeformationGradient = { 0.111, 0.222, 0.333, 0.444, 0.555, 0.666, 0.777, 0.888, 0.999 }; + + protected: + + virtual void setMassChangeDeformationGradient( ) override{ + + set_massChangeDeformationGradient( massChangeDeformationGradient ); + + } + + floatVector initializeVector( unsigned int size ){ + + return floatVector( size, 0 ); + + } + + }; + + class hydraBaseMock : public tardigradeHydra::hydraBase { + + public: + + using tardigradeHydra::hydraBase::hydraBase; + + floatVector elasticityParameters = { 123.4, 56.7 }; + + floatVector massChangeParameters = { 0.78 }; + + tardigradeHydra::linearElasticity::residual elasticity; + + tardigradeHydra::residualBase plasticity; + + residualMock massChange; + + tardigradeHydra::residualBase remainder; + + void setResidualClasses( std::vector< tardigradeHydra::residualBase* > &residuals ){ + + tardigradeHydra::hydraBase::setResidualClasses( residuals ); + + } + + private: + + virtual void setResidualClasses( ){ + + std::vector< tardigradeHydra::residualBase* > residuals( 4 ); + + elasticity = tardigradeHydra::linearElasticity::residual( this, 9, elasticityParameters ); + + plasticity = tardigradeHydra::residualBase ( this, 9 ); + + massChange = residualMock( this, 9, 2, massChangeParameters ); + + remainder = tardigradeHydra::residualBase( this, 3 ); + + residuals[ 0 ] = &elasticity; + + residuals[ 1 ] = &plasticity; + + residuals[ 2 ] = &massChange; + + residuals[ 3 ] = &remainder; + + setResidualClasses( residuals ); + + } + + }; + + floatType time = 1.1; + + floatType deltaTime = 2.2; + + floatType temperature = 300.0; + + floatType previousTemperature = 320.4; + + floatVector deformationGradient = { 1.1, 0.1, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 }; + + floatVector previousDeformationGradient = { 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 }; + + floatVector additionalDOF = { 0.11, 0.22, 0.33, 0.44, 0.55 }; + + floatVector previousAdditionalDOF = { 0.12, 0.23, 0.36, 0.47, 0.58 }; + + floatVector previousStateVariables = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, + -1, -2, -3 }; + + floatVector parameters = { 123.4, 56.7, 0.78 }; + + floatVector unknownVector = { 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1.1, 0.12, 0.13, 0.14, 1.3, 0.15, 0.16, 0.17, 1.4, + 1.2, 0.21, 0.29, 0.23, 0.9, 0.11, 0.30, 0.25, 1.1, + 3, 4, 5 }; + + const unsigned int numConfigurations = 3; + + const unsigned int numNonLinearSolveStateVariables = 3; + + const unsigned int dimension = 3; + + hydraBaseMock hydra( time, deltaTime, temperature, previousTemperature, deformationGradient, previousDeformationGradient, + additionalDOF, previousAdditionalDOF, + previousStateVariables, parameters, numConfigurations, numNonLinearSolveStateVariables, dimension ); + + tardigradeHydra::unit_test::hydraBaseTester::updateUnknownVector( hydra, unknownVector ); + + residualMock R( &hydra, 9, 2, hydra.massChangeParameters ); + + std::vector< unsigned int > indices = { 18, 19, 20, 21, 22, 23, 24, 25, 26 }; + + floatVector values = { 0.111, 0.222, 0.333, 0.444, 0.555, 0.666, 0.777, 0.888, 0.999 }; + + std::vector< unsigned int > result_1; + std::vector< floatType > result_2; + + R.suggestInitialIterateValues( result_1, result_2 ); + + BOOST_CHECK( tardigradeVectorTools::fuzzyEquals( indices, result_1 ) ); + + BOOST_CHECK( tardigradeVectorTools::fuzzyEquals( values, result_2 ) ); + +}