SavedState disableInvalidParameters() { #ifdef _WIN32 SavedState ret; ret.previousThreadLocalHandler = _set_thread_local_invalid_parameter_handler( [](const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t) {}); ret.previousCrtReportMode = _CrtSetReportMode(_CRT_ASSERT, 0); return ret; #else return SavedState(); #endif }
//-------------------------------------------------------------------------------- // SolveConstitutiveEquations // - Solves the constitutive equation given the applied strain rate; i.e., // find the stress state that is compatible with the strain rate defined. // // Applying Newton Raphson to solve the the stress state given the strain state of // the system. // //-------------------------------------------------------------------------------- EigenRep SolveConstitutiveEquations( const EigenRep & InitialStressState, // initial guess, either from Sach's or previous iteration const vector<EigenRep> & SchmidtTensors, const vector<Float> & CRSS, const vector<Float> & GammaDotBase, // reference shear rate const vector<int> & RateSensitivity, const EigenRep & StrainRate, // Current strain rate - constant from caller Float EpsilonConvergence, Float MaxResolvedStress, int MaxNumIterations ) { const Float Coeff = 0.2; // global fudge factor EigenRep CurrentStressState = InitialStressState; int RemainingIterations = MaxNumIterations; EigenRep NewStressState = InitialStressState; EigenRep SavedState(0, 0, 0, 0, 0); // used to return to old state while( RemainingIterations > 0 ) { bool AdmissibleStartPointFound = false; std::vector<Float> RSS( SchmidtTensors.size(), 0 ); // This is really RSS / tau do // refresh critical resolved shear stress. // check to see if it is outside of the yield // surface, and therefore inadmissible { AdmissibleStartPointFound = true; for( int i = 0; i < SchmidtTensors.size(); i ++ ) { RSS[i] = InnerProduct( SchmidtTensors[i], CurrentStressState) / CRSS[i]; if( std::fabs( RSS[i] ) < 1e-10 ) RSS[i] = 0; if( std::fabs( RSS[i] ) > MaxResolvedStress ) AdmissibleStartPointFound = false; } if( !AdmissibleStartPointFound ) CurrentStressState = SavedState + ( CurrentStressState - SavedState ) * Coeff; RemainingIterations --; if( RemainingIterations < 0 ) return NewStressState; } while ( !AdmissibleStartPointFound ); std::vector<Float> GammaDot( SchmidtTensors.size(), 0 ); // This is really RSS / tau for( int i = 0; i < SchmidtTensors.size(); i ++ ) { if( RateSensitivity[i] -1 > 0 ) GammaDot[i] = GammaDotBase[i] * std::pow( std::fabs( RSS[i] ), static_cast<int>( RateSensitivity[i] - 1 ) ); else GammaDot[i] = GammaDotBase[i]; } // Construct residual vector R(Sigma), where Sigma is stress. R(Sigma) is a 5d vector EigenRep Residual( 0, 0, 0, 0, 0 ); // current estimate SMatrix5x5 ResidualJacobian; ResidualJacobian.SetZero(); for( int i = 0; i < SchmidtTensors.size(); i ++ ) { Residual += SchmidtTensors[i] * GammaDot[i] * RSS[i]; // Residual = StrainRate - sum_{k} [ m^{k}_i * |r_ss/ crss|^n ] // Construct F', or the Jacobian ResidualJacobian -= OuterProduct( SchmidtTensors[i], SchmidtTensors[i] ) * RateSensitivity[i] * GammaDot[i] / CRSS[i]; } Residual = Residual - StrainRate ; // need the negative residual, instead of E - R SavedState = CurrentStressState; EigenRep Delta_Stress = LU_Solver( ResidualJacobian, Residual ); // <----------- Need to hangle error from this NewStressState = CurrentStressState + Delta_Stress; Float RelativeError = static_cast<Float>(2) * Delta_Stress.Norm() / ( NewStressState + CurrentStressState ).Norm(); CurrentStressState = NewStressState; if( RelativeError < EpsilonConvergence ) { break; } } // end while return NewStressState; }