void ReturnMappingModel::computeStress(const Elem & /*current_elem*/, unsigned qp, const SymmElasticityTensor & elasticityTensor, const SymmTensor & stress_old, SymmTensor & strain_increment, SymmTensor & stress_new, SymmTensor & inelastic_strain_increment) { // compute deviatoric trial stress SymmTensor dev_trial_stress(stress_new); dev_trial_stress.addDiag(-dev_trial_stress.trace()/3.0); // compute effective trial stress Real dts_squared = dev_trial_stress.doubleContraction(dev_trial_stress); Real effective_trial_stress = std::sqrt(1.5 * dts_squared); // compute effective strain increment SymmTensor dev_strain_increment(strain_increment); dev_strain_increment.addDiag(-strain_increment.trace()/3.0); _effective_strain_increment = dev_strain_increment.doubleContraction(dev_strain_increment); _effective_strain_increment = std::sqrt(2.0/3.0 * _effective_strain_increment); computeStressInitialize(qp, effective_trial_stress, elasticityTensor); // Use Newton sub-iteration to determine inelastic strain increment Real scalar = 0; unsigned int it = 0; Real residual = 10; Real norm_residual = 10; Real first_norm_residual = 10; std::string iter_output; while (it < _max_its && norm_residual > _absolute_tolerance && (norm_residual/first_norm_residual) > _relative_tolerance) { iterationInitialize(qp, scalar); residual = computeResidual(qp, effective_trial_stress, scalar); norm_residual = std::abs(residual); if (it == 0) { first_norm_residual = norm_residual; if (first_norm_residual == 0) { first_norm_residual = 1; } } scalar -= residual / computeDerivative(qp, effective_trial_stress, scalar); if (_output_iteration_info == true || _output_iteration_info_on_error == true) { iter_output = "In the element " + Moose::stringify(_current_elem->id()) + + " and the qp point " + Moose::stringify(qp) + ": \n" + + " iteration = " + Moose::stringify(it ) + "\n" + + " effective trial stress = " + Moose::stringify(effective_trial_stress) + "\n" + + " scalar effective inelastic strain = " + Moose::stringify(scalar) +"\n" + + " relative residual = " + Moose::stringify(norm_residual/first_norm_residual) + "\n" + + " relative tolerance = " + Moose::stringify(_relative_tolerance) + "\n" + + " absolute residual = " + Moose::stringify(norm_residual) + "\n" + + " absolute tolerance = " + Moose::stringify(_absolute_tolerance) + "\n"; } iterationFinalize(qp, scalar); ++it; } if (_output_iteration_info) _console << iter_output; if (it == _max_its && norm_residual > _absolute_tolerance && (norm_residual/first_norm_residual) > _relative_tolerance) { if (_output_iteration_info_on_error) { Moose::err << iter_output; } mooseError("Exceeded maximum iterations in ReturnMappingModel solve for material: " << _name << ". Rerun with 'output_iteration_info_on_error = true' for more information."); } // compute inelastic and elastic strain increments (avoid potential divide by zero - how should this be done)? if (effective_trial_stress < 0.01) { effective_trial_stress = 0.01; } inelastic_strain_increment = dev_trial_stress; inelastic_strain_increment *= (1.5*scalar/effective_trial_stress); strain_increment -= inelastic_strain_increment; // compute stress increment stress_new = elasticityTensor * strain_increment; // update stress stress_new += stress_old; computeStressFinalize(qp, inelastic_strain_increment); }
void RecomputeRadialReturn::computeStress(RankTwoTensor & strain_increment, RankTwoTensor & inelastic_strain_increment, RankTwoTensor & stress_new) { // Given the stretching, update the inelastic strain // Compute the stress in the intermediate configuration while retaining the stress history // compute the deviatoric trial stress and trial strain from the current intermediate configuration RankTwoTensor deviatoric_trial_stress = stress_new.deviatoric(); // compute the effective trial stress Real dev_trial_stress_squared = deviatoric_trial_stress.doubleContraction(deviatoric_trial_stress); Real effective_trial_stress = std::sqrt(3.0 / 2.0 * dev_trial_stress_squared); //If the effective trial stress is zero, so should the inelastic strain increment be zero //In that case skip the entire iteration if the effective trial stress is zero if (effective_trial_stress != 0.0) { computeStressInitialize(effective_trial_stress); // Use Newton sub-iteration to determine the scalar effective inelastic strain increment Real scalar_effective_inelastic_strain = 0; unsigned int iteration = 0; Real residual = 10; // use a large number here to guarantee at least one loop through while Real norm_residual = 10; Real first_norm_residual = 10; // create an output string with iteration information when errors occur std::string iteration_output; while (iteration < _max_its && norm_residual > _absolute_tolerance && (norm_residual/first_norm_residual) > _relative_tolerance) { iterationInitialize(scalar_effective_inelastic_strain); residual = computeResidual(effective_trial_stress, scalar_effective_inelastic_strain); norm_residual = std::abs(residual); if (iteration == 0) { first_norm_residual = norm_residual; if (first_norm_residual == 0) first_norm_residual = 1; } Real derivative = computeDerivative(effective_trial_stress, scalar_effective_inelastic_strain); scalar_effective_inelastic_strain -= residual / derivative; if (_output_iteration_info || _output_iteration_info_on_error) { iteration_output = "In the element " + Moose::stringify(_current_elem->id()) + + " and the qp point " + Moose::stringify(_qp) + ": \n" + + " iteration = " + Moose::stringify(iteration ) + "\n" + + " effective trial stress = " + Moose::stringify(effective_trial_stress) + "\n" + + " scalar effective inelastic strain = " + Moose::stringify(scalar_effective_inelastic_strain) +"\n" + + " relative residual = " + Moose::stringify(norm_residual/first_norm_residual) + "\n" + + " relative tolerance = " + Moose::stringify(_relative_tolerance) + "\n" + + " absolute residual = " + Moose::stringify(norm_residual) + "\n" + + " absolute tolerance = " + Moose::stringify(_absolute_tolerance) + "\n"; } iterationFinalize(scalar_effective_inelastic_strain); ++iteration; } if (_output_iteration_info) _console << iteration_output << std::endl; if (iteration == _max_its && norm_residual > _absolute_tolerance && (norm_residual/first_norm_residual) > _relative_tolerance) { if (_output_iteration_info_on_error) Moose::err << iteration_output; mooseError("Exceeded maximum iterations in RecomputeRadialReturn solve for material: " << _name << ". Rerun with 'output_iteration_info_on_error = true' for more information."); } // compute inelastic strain increments while avoiding a potential divide by zero inelastic_strain_increment = deviatoric_trial_stress; inelastic_strain_increment *= (3.0 / 2.0 * scalar_effective_inelastic_strain / effective_trial_stress); } else inelastic_strain_increment.zero(); strain_increment -= inelastic_strain_increment; stress_new = _elasticity_tensor[_qp] * (strain_increment + _elastic_strain_old[_qp]); computeStressFinalize(inelastic_strain_increment); }
void ReturnMappingModel::computeStress( const Elem & /*current_elem*/, unsigned qp, const SymmElasticityTensor & elasticityTensor, const SymmTensor & stress_old, SymmTensor & strain_increment, SymmTensor & stress_new, SymmTensor & inelastic_strain_increment ) { // compute deviatoric trial stress SymmTensor dev_trial_stress(stress_new); dev_trial_stress.addDiag( -dev_trial_stress.trace()/3.0 ); // compute effective trial stress Real dts_squared = dev_trial_stress.doubleContraction(dev_trial_stress); Real effective_trial_stress = std::sqrt(1.5 * dts_squared); // compute effective strain increment SymmTensor dev_strain_increment(strain_increment); dev_strain_increment.addDiag( -strain_increment.trace()/3.0); _effective_strain_increment = dev_strain_increment.doubleContraction(dev_strain_increment); _effective_strain_increment = std::sqrt(2.0/3.0 * _effective_strain_increment); computeStressInitialize(qp, effective_trial_stress, elasticityTensor); // Use Newton sub-iteration to determine inelastic strain increment Real scalar = 0; unsigned int it = 0; Real residual = 10; Real norm_residual = 10; Real first_norm_residual = 10; std::stringstream iter_output; while (it < _max_its && norm_residual > _absolute_tolerance && (norm_residual/first_norm_residual) > _relative_tolerance) { iterationInitialize( qp, scalar ); residual = computeResidual(qp, effective_trial_stress, scalar); norm_residual = std::abs(residual); if (it == 0) { first_norm_residual = norm_residual; if (first_norm_residual == 0) { first_norm_residual = 1; } } scalar -= residual / computeDerivative(qp, effective_trial_stress, scalar); if (_output_iteration_info == true || _output_iteration_info_on_error == true) { iter_output << " it=" << it << " trl_strs=" << effective_trial_stress << " scalar=" << scalar << " rel_res=" << norm_residual/first_norm_residual << " rel_tol=" << _relative_tolerance << " abs_res=" << norm_residual << " abs_tol=" << _absolute_tolerance << std::endl; } iterationFinalize( qp, scalar ); ++it; } if (_output_iteration_info) _console << iter_output.str(); if (it == _max_its && norm_residual > _absolute_tolerance && (norm_residual/first_norm_residual) > _relative_tolerance) { if (_output_iteration_info_on_error) { Moose::err << iter_output.str(); } mooseError("Max sub-newton iteration hit during nonlinear constitutive model solve! (" << _name << ")"); } // compute inelastic and elastic strain increments (avoid potential divide by zero - how should this be done)? if (effective_trial_stress < 0.01) { effective_trial_stress = 0.01; } inelastic_strain_increment = dev_trial_stress; inelastic_strain_increment *= (1.5*scalar/effective_trial_stress); strain_increment -= inelastic_strain_increment; // compute stress increment stress_new = elasticityTensor * strain_increment; // update stress stress_new += stress_old; computeStressFinalize(qp, inelastic_strain_increment); }