void Multigrid::smooth() { double a1, a2, a3, a4; double b1, b2, b3, b4; double a, b; for (int i = 1; i <= Nx; i++) for (int j = 1; j <= Ny; j++) { a1 = ddx_east_p(i, j); a2 = ddx_west_p(i, j); a3 = ddy_north_p(i, j); a4 = ddy_south_p(i, j); b1 = ddx_east_r(i, j); b2 = ddx_west_r(i, j); b3 = ddy_north_r(i, j); b4 = ddy_south_r(i, j); a = (a1 - a2)/dx + (a3 - a4)/dy + isSolid[i][j]; b = (b1 - b2)/dx + (b3 - b4)/dy; u[i][j] = (R[i][j]/a - b/a)*(1.0 - isSolid[i][j]); } computeResidual(); n++; return; }
// This is a recursive function which calls itselfs and sub routines of MultiGridSolver void MultiGridSolver::mgmSolve(const size_t& level) { //std::cout << " Level : " << level << " mgmSolve() \n "; assert(level >0 && level <= numLevel_) ; // if(level!=1) // { applyPreSmoothing(level); // Before going to coaser level lets smoothen the solution by applying RBGS Guass Seidel neu1_ times computeResidual(level); // Before going to the coaser level, let us compute the error at the current level if(level!=1) // We can get any further coarse if level is one applyRestriction(level); // Restrict the error term and assign it to f_ // } // Its time to go to the coaser level :) if(level == 1) // This is the end of recursion, Compute Solution { //std::cout << "Exact solution\n"; applyRBGS_Iter(level); // Apply Red Black Guass Seidel to compute the exact solution at coarsest level } else { mgmSolve(level-1); // If we have not reached at the coarsest level keep going down applyInterpolation(level-1); // Lets see how much we have improved the error by going to the Coaser level, Lets come back to finer level and add the effect; } // if(level!=1) applyPostSmoothing(level); // Lets smotthen the solution a bit }
int main(int argc, char** argv) { // Get user parameters. Opm::parameter::ParameterGroup param(argc, argv, false); // Create the Equelle runtime. EquelleRuntimeCPU er(param); ensureRequirements(er); // ============= Generated code starts here ================ const Scalar k = er.inputScalarWithDefault("k", double(0.3)); const CollOfScalar u_initial = er.inputCollectionOfScalar("u_initial", er.allCells()); const CollOfFace dirichlet_boundary = er.inputDomainSubsetOf("dirichlet_boundary", er.boundaryFaces()); const CollOfScalar dirichlet_val = er.inputCollectionOfScalar("dirichlet_val", dirichlet_boundary); const CollOfScalar vol = er.norm(er.allCells()); const CollOfFace interior_faces = er.interiorFaces(); const CollOfCell first = er.firstCell(interior_faces); const CollOfCell second = er.secondCell(interior_faces); const CollOfScalar itrans = (k * (er.norm(interior_faces) / er.norm((er.centroid(first) - er.centroid(second))))); const CollOfFace bf = er.boundaryFaces(); const CollOfCell bf_cells = er.trinaryIf(er.isEmpty(er.firstCell(bf)), er.secondCell(bf), er.firstCell(bf)); const CollOfScalar bf_sign = er.trinaryIf(er.isEmpty(er.firstCell(bf)), er.operatorExtend(-double(1), bf), er.operatorExtend(double(1), bf)); const CollOfScalar btrans = (k * (er.norm(bf) / er.norm((er.centroid(bf) - er.centroid(bf_cells))))); const CollOfScalar dir_sign = er.operatorOn(bf_sign, er.boundaryFaces(), dirichlet_boundary); std::function<CollOfScalar(const CollOfScalar&)> computeInteriorFlux = [&](const CollOfScalar& u) -> CollOfScalar { return (-itrans * er.gradient(u)); }; std::function<CollOfScalar(const CollOfScalar&)> computeBoundaryFlux = [&](const CollOfScalar& u) -> CollOfScalar { const CollOfScalar u_dirbdycells = er.operatorOn(u, er.allCells(), er.operatorOn(bf_cells, er.boundaryFaces(), dirichlet_boundary)); const CollOfScalar dir_fluxes = ((er.operatorOn(btrans, er.boundaryFaces(), dirichlet_boundary) * dir_sign) * (u_dirbdycells - dirichlet_val)); return er.operatorExtend(dir_fluxes, dirichlet_boundary, er.boundaryFaces()); }; std::function<CollOfScalar(const CollOfScalar&, const CollOfScalar&, const Scalar&)> computeResidual = [&](const CollOfScalar& u, const CollOfScalar& u0, const Scalar& dt) -> CollOfScalar { const CollOfScalar ifluxes = computeInteriorFlux(u); const CollOfScalar bfluxes = computeBoundaryFlux(u); const CollOfScalar fluxes = (er.operatorExtend(ifluxes, er.interiorFaces(), er.allFaces()) + er.operatorExtend(bfluxes, er.boundaryFaces(), er.allFaces())); const CollOfScalar residual = ((u - u0) + ((dt / vol) * er.divergence(fluxes))); return residual; }; const SeqOfScalar timesteps = er.inputSequenceOfScalar("timesteps"); CollOfScalar u0; u0 = u_initial; for (const Scalar& dt : timesteps) { std::function<CollOfScalar(const CollOfScalar&)> computeResidualLocal = [&](const CollOfScalar& u) -> CollOfScalar { return computeResidual(u, u0, dt); }; const CollOfScalar u_guess = u0; const CollOfScalar u = er.newtonSolve(computeResidualLocal, u_guess); er.output("u", u); er.output("maximum of u", er.maxReduce(u)); u0 = u; } // ============= Generated code ends here ================ return 0; }
void Multigrid::solve() { smooth(); computeResidual(); while (error() > tol() & n < maxIter()) iterate(); if (n == maxIter()) cout << "Multigrid reached maximum number of iterations" << endl; }
bool operator()( const T* const cam_RtK, // [R;t;K] const T* const pos_3dpoint, T* out_residuals) const { computeResidual( cam_RtK, // => cam_R & cam_RtK[3], // => cam_t & cam_RtK[6], // => cam_K pos_3dpoint, m_pos_2dpoint, out_residuals); return true; }
bool operator()( const T* const cam_K, const T* const cam_Rt, const T* const pos_3dpoint, T* out_residuals) const { computeResidual( cam_Rt, // => cam_R & cam_Rt[3], // => cam_t cam_K, pos_3dpoint, m_pos_2dpoint, out_residuals ); return true; }
bool operator()( const T* const cam_RtK, // [R;t;K] T* out_residuals) const { T pos_3dpoint[3]; pos_3dpoint[0] = T(m_pos_3dpoint[0]); pos_3dpoint[1] = T(m_pos_3dpoint[1]); pos_3dpoint[2] = T(m_pos_3dpoint[2]); computeResidual( cam_RtK, // => cam_R & cam_RtK[3], // => cam_t & cam_RtK[6], // => cam_K [f,ppx,ppy] pos_3dpoint, m_pos_2dpoint, out_residuals); return true; }
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); }
bool FrictionalContactProblem::calculateSlip(const NumericVector<Number>& ghosted_solution, std::vector<SlipData> * iterative_slip) { NonlinearSystem & nonlinear_sys = getNonlinearSystem(); unsigned int dim = nonlinear_sys.subproblem().mesh().dimension(); MooseVariable * residual_x_var = &getVariable(0,_residual_x); MooseVariable * residual_y_var = &getVariable(0,_residual_y); MooseVariable * residual_z_var = NULL; MooseVariable * diag_stiff_x_var = &getVariable(0,_diag_stiff_x); MooseVariable * diag_stiff_y_var = &getVariable(0,_diag_stiff_y); MooseVariable * diag_stiff_z_var = NULL; MooseVariable * inc_slip_x_var = &getVariable(0,_inc_slip_x); MooseVariable * inc_slip_y_var = &getVariable(0,_inc_slip_y); MooseVariable * inc_slip_z_var = NULL; if (dim == 3) { residual_z_var = &getVariable(0,_residual_z); diag_stiff_z_var = &getVariable(0,_diag_stiff_z); inc_slip_z_var = &getVariable(0,_inc_slip_z); } bool updatedSolution = false; _slip_residual = 0.0; _it_slip_norm = 0.0; _inc_slip_norm = 0.0; TransientNonlinearImplicitSystem & system = getNonlinearSystem().sys(); if (iterative_slip) iterative_slip->clear(); if (getDisplacedProblem() && _interaction_params.size() > 0) { computeResidual(system, ghosted_solution, *system.rhs); _num_contact_nodes = 0; _num_slipping = 0; _num_slipped_too_far = 0; GeometricSearchData & displaced_geom_search_data = getDisplacedProblem()->geomSearchData(); std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *> * penetration_locators = &displaced_geom_search_data._penetration_locators; AuxiliarySystem & aux_sys = getAuxiliarySystem(); const NumericVector<Number> & aux_solution = *aux_sys.currentSolution(); for (std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *>::iterator plit = penetration_locators->begin(); plit != penetration_locators->end(); ++plit) { PenetrationLocator & pen_loc = *plit->second; std::set<dof_id_type> & has_penetrated = pen_loc._has_penetrated; bool frictional_contact_this_interaction = false; std::map<std::pair<int,int>,InteractionParams>::iterator ipit; std::pair<int,int> ms_pair(pen_loc._master_boundary,pen_loc._slave_boundary); ipit = _interaction_params.find(ms_pair); if (ipit != _interaction_params.end()) frictional_contact_this_interaction = true; if (frictional_contact_this_interaction) { InteractionParams & interaction_params = ipit->second; Real slip_factor = interaction_params._slip_factor; Real slip_too_far_factor = interaction_params._slip_too_far_factor; Real friction_coefficient = interaction_params._friction_coefficient; std::vector<dof_id_type> & slave_nodes = pen_loc._nearest_node._slave_nodes; for (unsigned int i=0; i<slave_nodes.size(); i++) { dof_id_type slave_node_num = slave_nodes[i]; if (pen_loc._penetration_info[slave_node_num]) { PenetrationInfo & info = *pen_loc._penetration_info[slave_node_num]; const Node * node = info._node; if (node->processor_id() == processor_id()) { std::set<dof_id_type>::iterator hpit = has_penetrated.find(slave_node_num); if (hpit != has_penetrated.end()) { _num_contact_nodes++; VectorValue<dof_id_type> residual_dofs(node->dof_number(aux_sys.number(), residual_x_var->number(), 0), node->dof_number(aux_sys.number(), residual_y_var->number(), 0), (residual_z_var ? node->dof_number(aux_sys.number(), residual_z_var->number(), 0) : 0)); VectorValue<dof_id_type> diag_stiff_dofs(node->dof_number(aux_sys.number(), diag_stiff_x_var->number(), 0), node->dof_number(aux_sys.number(), diag_stiff_y_var->number(), 0), (diag_stiff_z_var ? node->dof_number(aux_sys.number(), diag_stiff_z_var->number(), 0) : 0)); VectorValue<dof_id_type> inc_slip_dofs(node->dof_number(aux_sys.number(), inc_slip_x_var->number(), 0), node->dof_number(aux_sys.number(), inc_slip_y_var->number(), 0), (inc_slip_z_var ? node->dof_number(aux_sys.number(), inc_slip_z_var->number(), 0) : 0)); RealVectorValue res_vec; RealVectorValue stiff_vec; RealVectorValue slip_inc_vec; for (unsigned int i=0; i<dim; ++i) { res_vec(i) = aux_solution(residual_dofs(i)); stiff_vec(i) = aux_solution(diag_stiff_dofs(i)); slip_inc_vec(i) = aux_solution(inc_slip_dofs(i)); } RealVectorValue slip_iterative(0.0,0.0,0.0); Real interaction_slip_residual = 0.0; // _console<<"inc slip: "<<slip_inc_vec<<std::endl; // _console<<"info slip: "<<info._incremental_slip<<std::endl; // ContactState state = calculateInteractionSlip(slip_iterative, interaction_slip_residual, info._normal, res_vec, info._incremental_slip, stiff_vec, friction_coefficient, slip_factor, slip_too_far_factor, dim); ContactState state = calculateInteractionSlip(slip_iterative, interaction_slip_residual, info._normal, res_vec, slip_inc_vec, stiff_vec, friction_coefficient, slip_factor, slip_too_far_factor, dim); // _console<<"iter slip: "<<slip_iterative<<std::endl; _slip_residual += interaction_slip_residual*interaction_slip_residual; if (state == SLIPPING || state == SLIPPED_TOO_FAR) { _num_slipping++; if (state == SLIPPED_TOO_FAR) _num_slipped_too_far++; for (unsigned int i=0; i<dim; ++i) { SlipData sd(node,i,slip_iterative(i)); if (iterative_slip) iterative_slip->push_back(sd); _it_slip_norm += slip_iterative(i)*slip_iterative(i); _inc_slip_norm += (slip_inc_vec(i)+slip_iterative(i))*(slip_inc_vec(i)+slip_iterative(i)); } } } } } } } } _communicator.sum(_num_contact_nodes); _communicator.sum(_num_slipping); _communicator.sum(_num_slipped_too_far); _communicator.sum(_slip_residual); _slip_residual = std::sqrt(_slip_residual); _communicator.sum(_it_slip_norm); _it_slip_norm = std::sqrt(_it_slip_norm); _communicator.sum(_inc_slip_norm); _inc_slip_norm = std::sqrt(_inc_slip_norm); if (_num_slipping > 0) updatedSolution = true; } return updatedSolution; }
void HeightMipmap::buildResiduals(int level) { int nTiles = max(1, (baseLevelSize / this->tileSize) >> (maxLevel - level)); int nTilesPerFile = min(nTiles, 16); int tileSize = min(topLevelSize << level, this->tileSize); printf("Build residuals level %d...\n", level); currentLevel = level; reset(baseLevelSize >> (maxLevel - currentLevel), baseLevelSize >> (maxLevel - currentLevel), min(topLevelSize << currentLevel, this->tileSize)); float *parentTile = new float[(this->tileSize + 5) * (this->tileSize + 5)]; float *currentTile = new float[(this->tileSize + 5) * (this->tileSize + 5)]; float *residualTile = new float[(this->tileSize + 5) * (this->tileSize + 5)]; unsigned char *encodedResidual = new unsigned char[(this->tileSize + 5) * (this->tileSize + 5) * 2]; float maxRR = 0.0; float maxEE = 0.0; for (int dy = 0; dy < nTiles / nTilesPerFile; ++dy) { for (int dx = 0; dx < nTiles / nTilesPerFile; ++dx) { char buf[256]; sprintf(buf, "%s/residual-%.2d-%.4d-%.4d.tiff", cache.c_str(), level, dx, dy); if (flog(buf)) { TIFF* f = TIFFOpen(buf, "wb"); for (int ny = 0; ny < nTilesPerFile; ++ny) { for (int nx = 0; nx < nTilesPerFile; ++nx) { int tx = nx + dx * nTilesPerFile; int ty = ny + dy * nTilesPerFile; float maxR, meanR, maxErr; getApproxTile(level - 1, tx / 2, ty / 2, parentTile); getTile(level, tx, ty, currentTile); computeResidual(parentTile, currentTile, level, tx, ty, residualTile, maxR, meanR); encodeResidual(level, residualTile, encodedResidual); computeApproxTile(parentTile, residualTile, level, tx, ty, currentTile, maxErr); if (level < maxLevel) { saveApproxTile(level, tx, ty, currentTile); } TIFFSetField(f, TIFFTAG_IMAGEWIDTH, tileSize + 5); TIFFSetField(f, TIFFTAG_IMAGELENGTH, tileSize + 5); TIFFSetField(f, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(f, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT); TIFFSetField(f, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(f, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); /*TIFFSetField(f, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(f, TIFFTAG_BITSPERSAMPLE, 16);*/ TIFFSetField(f, TIFFTAG_SAMPLESPERPIXEL, 2); TIFFSetField(f, TIFFTAG_BITSPERSAMPLE, 8); TIFFWriteEncodedStrip(f, 0, encodedResidual, (tileSize + 5) * (tileSize + 5) * 2); TIFFWriteDirectory(f); maxRR = max(maxR, maxRR); maxEE = max(maxErr, maxEE); } } TIFFClose(f); printf("%f max residual, %f max err\n", maxRR, maxEE); } } } delete[] parentTile; delete[] currentTile; delete[] residualTile; delete[] encodedResidual; }
void Solver::SORCycle(GridFunction* gridfunction, GridFunctionType& rhs, const PointType& h){ MultiIndexType dim = gridfunction->GetGridDimension(); MultiIndexType bread (0,0); MultiIndexType eread (dim[0]-1,dim[1]-1); MultiIndexType bwrite (1,1); MultiIndexType ewrite (dim[0]-2,dim[1]-2); Computation pc (param); //Initialization of the residual. Just choose a value, that should be a bad error. RealType res = 10e20; int iterationCounter = 0; // SOR-cycling until error is small enough, or the number of iterations gets to high: RealType neighbours_x, neighbours_y; /* std::cout<<"direct before SOR:" <<std::endl; gridfunction->PlotGrid(); std::cout<<std::endl; */ while (iterationCounter < param.iterMax && res > param.eps ) { pc.setBoundaryP(*gridfunction); /* std::cout<<"after boundary-setting:" <<std::endl; gridfunction->PlotGrid(); std::cout<<std::endl; */ for (IndexType i = 1; i <= dim[0]-2; i++) { for (IndexType j = 1; j <= dim[1]-2; j++) { //help-values "neighbours_x" and "neighbours_y" for better overview neighbours_x = (gridfunction->GetGridFunction()[i+1][j] + gridfunction->GetGridFunction()[i-1][j]) / h[0] / h[0]; neighbours_y = (gridfunction->GetGridFunction()[i][j+1] + gridfunction->GetGridFunction()[i][j-1]) / h[1] / h[1]; //SOR-iteration gridfunction->SetGridFunction(i,j,(1.0 - param.omg)*gridfunction->GetGridFunction()[i][j] + param.omg /(2.0*(1/h[0]/h[0]+1/h[1]/h[1])) * (neighbours_x + neighbours_y - rhs[i][j])); } } iterationCounter++; pc.setBoundaryP(*gridfunction); res = computeResidual(*gridfunction, rhs, h); /* std::cout<<"after SOR:" <<std::endl; gridfunction->PlotGrid(); std::cout<<std::endl; */ } if (iterationCounter >= param.iterMax) std::cout<<"iteration abort with error res = "<<res<<std::endl; }
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 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); }