void ComputeReturnMappingStress::updateQpStress(RankTwoTensor & strain_increment, RankTwoTensor & stress_new) { if (_output_iteration_info == true) { _console << std::endl << "iteration output for ComputeReturnMappingStress solve:" << " time=" <<_t << " int_pt=" << _qp << std::endl; } RankTwoTensor elastic_strain_increment; Real l2norm_delta_stress, first_l2norm_delta_stress; unsigned int counter = 0; std::vector<RankTwoTensor> inelastic_strain_increment; inelastic_strain_increment.resize(_models.size()); for (unsigned i_rmm = 0; i_rmm < _models.size(); ++i_rmm) inelastic_strain_increment[i_rmm].zero(); RankTwoTensor stress_max, stress_min; do { for (unsigned i_rmm = 0; i_rmm < _models.size(); ++i_rmm) { _models[i_rmm]->setQp(_qp); elastic_strain_increment = strain_increment; for (unsigned j_rmm = 0; j_rmm < _models.size(); ++j_rmm) if (i_rmm != j_rmm) elastic_strain_increment -= inelastic_strain_increment[j_rmm]; stress_new = _elasticity_tensor[_qp] * (elastic_strain_increment + _elastic_strain_old[_qp]); _models[i_rmm]->updateStress(elastic_strain_increment, inelastic_strain_increment[i_rmm], stress_new); if (i_rmm == 0) { stress_max = stress_new; stress_min = stress_new; } else { for (unsigned int i = 0; i < LIBMESH_DIM; ++i) { for (unsigned int j = 0; j < LIBMESH_DIM; ++j) { if (stress_new(i,j) > stress_max(i,j)) stress_max(i,j) = stress_new(i,j); else if (stress_min(i,j) > stress_new(i,j)) stress_min(i,j) = stress_new(i,j); } } } } // now check convergence in the stress: // once the change in stress is within tolerance after each recompute material // consider the stress to be converged RankTwoTensor delta_stress(stress_max - stress_min); l2norm_delta_stress = delta_stress.L2norm(); if (counter == 0) first_l2norm_delta_stress = l2norm_delta_stress; if (_output_iteration_info == true) { _console << "stress iteration number = " << counter << "\n" << " relative l2 norm delta stress = " << (0 == first_l2norm_delta_stress ? 0 : l2norm_delta_stress/first_l2norm_delta_stress) << "\n" << " stress convergence relative tolerance = " << _relative_tolerance <<"\n" << " absolute l2 norm delta stress = " << l2norm_delta_stress << "\n" << " stress converengen absolute tolerance = " << _absolute_tolerance << std::endl; } ++counter; } while (counter < _max_its && l2norm_delta_stress > _absolute_tolerance && (l2norm_delta_stress / first_l2norm_delta_stress) > _relative_tolerance && _models.size() != 1); if (counter == _max_its && l2norm_delta_stress > _absolute_tolerance && (l2norm_delta_stress / first_l2norm_delta_stress) > _relative_tolerance) mooseError("Max stress iteration hit during ComputeReturnMappingStress solve!"); strain_increment = elastic_strain_increment; }
Real MechanicalContactConstraint::computeQpJacobian(Moose::ConstraintJacobianType type) { PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()]; const Real penalty = getPenalty(*pinfo); switch (type) { case Moose::SlaveSlave: switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_DEFAULT: { double curr_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); //TODO: Need off-diagonal term/s return (-curr_jac + _phi_slave[_j][_qp] * penalty * _test_slave[_i][_qp]) * pinfo->_normal(_component) * pinfo->_normal(_component); } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: //TODO: Need off-diagonal terms return _phi_slave[_j][_qp] * penalty * _test_slave[_i][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: switch (_formulation) { case CF_DEFAULT: { double curr_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); return -curr_jac + _phi_slave[_j][_qp] * penalty * _test_slave[_i][_qp]; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return _phi_slave[_j][_qp] * penalty * _test_slave[_i][_qp]; default: mooseError("Invalid contact formulation"); } default: mooseError("Invalid or unavailable contact model"); } case Moose::SlaveMaster: switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_DEFAULT: { Node * curr_master_node = _current_master->get_node(_j); double curr_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), curr_master_node->dof_number(0, _vars(_component), 0)); //TODO: Need off-diagonal terms return (-curr_jac - _phi_master[_j][_qp] * penalty * _test_slave[_i][_qp]) * pinfo->_normal(_component) * pinfo->_normal(_component); } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: //TODO: Need off-diagonal terms return -_phi_master[_j][_qp] * penalty * _test_slave[_i][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: switch (_formulation) { case CF_DEFAULT: { Node * curr_master_node = _current_master->get_node(_j); double curr_jac = (*_jacobian)( _current_node->dof_number(0, _vars(_component), 0), curr_master_node->dof_number(0, _vars(_component), 0)); return -curr_jac - _phi_master[_j][_qp] * penalty * _test_slave[_i][_qp]; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return -_phi_master[_j][_qp] * penalty * _test_slave[_i][_qp]; default: mooseError("Invalid contact formulation"); } default: mooseError("Invalid or unavailable contact model"); } case Moose::MasterSlave: switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_DEFAULT: { //TODO: Need off-diagonal terms double slave_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); //TODO: To get off-diagonal terms correct using an approach like this, we would need to assemble in the rows for //all displacement components times their components of the normal vector. return slave_jac * _test_master[_i][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: //TODO: Need off-diagonal terms return -_test_master[_i][_qp] * penalty * _phi_slave[_j][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: switch (_formulation) { case CF_DEFAULT: { double slave_jac = (*_jacobian)(_current_node->dof_number(0, _vars(_component), 0), _connected_dof_indices[_j]); return slave_jac * _test_master[_i][_qp]; } case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return -_test_master[_i][_qp] * penalty * _phi_slave[_j][_qp]; default: mooseError("Invalid contact formulation"); } default: mooseError("Invalid or unavailable contact model"); } case Moose::MasterMaster: switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_DEFAULT: return 0; case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: //TODO: Need off-diagonal terms return _test_master[_i][_qp] * penalty * _phi_master[_j][_qp] * pinfo->_normal(_component) * pinfo->_normal(_component); default: mooseError("Invalid contact formulation"); } case CM_COULOMB: case CM_GLUED: switch (_formulation) { case CF_DEFAULT: return 0; case CF_PENALTY: case CF_AUGMENTED_LAGRANGE: return _test_master[_i][_qp] * penalty * _phi_master[_j][_qp]; default: mooseError("Invalid contact formulation"); } default: mooseError("Invalid or unavailable contact model"); } } return 0; }
Real HEMFluidProperties::molarMass() const { mooseError(name(), ": molarMass is not implemented"); }
void AddSideSetsFromBoundingBox::modify() { // this modifier is not designed for working with distributed mesh _mesh_ptr->errorIfDistributedMesh("BreakBoundaryOnSubdomain"); // Check that we have access to the mesh if (!_mesh_ptr) mooseError("_mesh_ptr must be initialized before calling SubdomainBoundingBox::modify()"); // Reference the the libMesh::MeshBase MeshBase & mesh = _mesh_ptr->getMesh(); // Get a reference to our BoundaryInfo object for later use BoundaryInfo & boundary_info = mesh.get_boundary_info(); bool found_element = false; bool found_side_sets = false; if (!_boundary_id_overlap) { // Loop over the elements for (const auto & elem : mesh.active_element_ptr_range()) { // boolean if element centroid is in bounding box bool contains = _bounding_box.contains_point(elem->centroid()); // check if active elements are found in the bounding box if (contains) { found_element = true; // loop over sides of elements within bounding box for (unsigned int side = 0; side < elem->n_sides(); side++) // loop over provided boundary vector to check all side sets for all boundary ids for (unsigned int boundary_id_number = 0; boundary_id_number < _boundary_id_old.size(); boundary_id_number++) // check if side has same boundary id that you are looking for if (boundary_info.has_boundary_id( elem, side, boundary_info.get_id_by_name(_boundary_id_old[boundary_id_number]))) { // assign new boundary value to boundary which meets meshmodifier criteria boundary_info.add_side(elem, side, _boundary_id_new); found_side_sets = true; } } } if (!found_element) mooseError("No elements found within the bounding box"); if (!found_side_sets) mooseError("No side sets found on active elements within the bounding box"); } else if (_boundary_id_overlap) { if (_boundary_id_old.size() < 2) mooseError("boundary_id_old out of bounds: ", _boundary_id_old.size(), " Must be 2 boundary inputs or more."); bool found_node = false; const bool inside = (_location == "INSIDE"); // Loop over the elements and assign node set id to nodes within the bounding box for (auto node = mesh.active_nodes_begin(); node != mesh.active_nodes_end(); ++node) { // check if nodes are inside of bounding box if (_bounding_box.contains_point(**node) == inside) { // read out boundary ids for nodes std::vector<short int> boundary_id_list = boundary_info.boundary_ids(*node); std::vector<boundary_id_type> boundary_id_old_list = _mesh_ptr->getBoundaryIDs(_boundary_id_old); // sort boundary ids on node and sort boundary ids provided in input file std::sort(boundary_id_list.begin(), boundary_id_list.end()); std::sort(boundary_id_old_list.begin(), boundary_id_old_list.end()); // check if input boundary ids are all contained in the node // if true, write new boundary id on respective node if (std::includes(boundary_id_list.begin(), boundary_id_list.end(), boundary_id_old_list.begin(), boundary_id_old_list.end())) { boundary_info.add_node(*node, _boundary_id_new); found_node = true; } } } if (!found_node) mooseError("No nodes found within the bounding box"); } }
void AddExtraNodeset::modify() { // make sure the input is not empty bool data_valid = false; if (_pars.isParamValid("nodes")) if (getParam<std::vector<unsigned int> >("nodes").size() != 0) data_valid = true; if (_pars.isParamValid("coord")) { unsigned int n_coord = getParam<std::vector<Real> >("coord").size(); if (n_coord % _mesh_ptr->dimension() != 0) mooseError("Size of node coordinates does not match the mesh dimension"); if (n_coord !=0) data_valid = true; } if (!data_valid) mooseError("Node set can not be empty!"); // Get the BoundaryIDs from the mesh std::vector<BoundaryName> boundary_names = boundaryNames(); std::vector<BoundaryID> boundary_ids(boundaryIDs().begin(), boundaryIDs().end()); // Get a reference to our BoundaryInfo object BoundaryInfo & boundary_info = _mesh_ptr->getMesh().get_boundary_info(); // add nodes with their ids const std::vector<unsigned int> & nodes = getParam<std::vector<unsigned int> >("nodes"); for (unsigned int i=0; i<nodes.size(); i++) for (unsigned int j=0; j<boundary_ids.size(); ++j) boundary_info.add_node(nodes[i], boundary_ids[j]); // add nodes with their coordinates const std::vector<Real> & coord = getParam<std::vector<Real> >("coord"); unsigned int dim = _mesh_ptr->dimension(); unsigned int n_nodes = coord.size() / dim; for (unsigned int i=0; i<n_nodes; i++) { Point p; for (unsigned int j=0; j<dim; j++) p(j) = coord[i*dim+j]; const Elem* elem = _mesh_ptr->getMesh().point_locator() (p); if (!elem) mooseError("Unable to locate the following point within the domain, please check its coordinates:\n" << p); bool on_node = false; for (unsigned int j=0; j<elem->n_nodes(); j++) { const Node* node = elem->get_node(j); Point q; for (unsigned int k=0; k<dim; k++) q(k) = (*node)(k); if (p.absolute_fuzzy_equals(q, getParam<Real>("tolerance"))) { for (unsigned int j=0; j<boundary_ids.size(); ++j) boundary_info.add_node(node, boundary_ids[j]); on_node = true; break; } } if (!on_node) mooseError("Point can not be located!"); } for (unsigned int i=0; i<boundary_ids.size(); ++i) boundary_info.sideset_name(boundary_ids[i]) = boundary_names[i]; }
Real SinglePhaseFluidProperties::henryConstant(Real /*temperature*/) const { mooseError(name(), ": henryConstant() is not implemented"); }
Real SinglePhaseFluidProperties::k_from_v_e(Real, Real) const { mooseError(name(), ": ", __PRETTY_FUNCTION__, " not implemented."); }
Real MaterialTensorCalculator::getTensorQuantity(const SymmTensor & tensor, const Point & curr_point, RealVectorValue &direction) { direction.zero(); Real value = 0.0; switch (_quantity) { case 0: value = MaterialTensorCalculatorTools::component(tensor, _index, direction); break; case 1: value = MaterialTensorCalculatorTools::vonMisesStress(tensor); break; case 2: value = MaterialTensorCalculatorTools::equivalentPlasticStrain(tensor); break; case 3: value = MaterialTensorCalculatorTools::hydrostatic(tensor); break; case 4: value = MaterialTensorCalculatorTools::directionValueTensor(tensor, _direction); break; case 5: value = MaterialTensorCalculatorTools::hoopStress(tensor, _p1, _p2, curr_point, direction); break; case 6: value = MaterialTensorCalculatorTools::radialStress(tensor, _p1, _p2, curr_point, direction); break; case 7: value = MaterialTensorCalculatorTools::axialStress(tensor, _p1, _p2, direction); break; case 8: value = MaterialTensorCalculatorTools::maxPrinciple(tensor, direction); break; case 9: value = MaterialTensorCalculatorTools::midPrinciple(tensor, direction); break; case 10: value = MaterialTensorCalculatorTools::minPrinciple(tensor, direction); break; case 11: value = MaterialTensorCalculatorTools::firstInvariant(tensor); break; case 12: value = MaterialTensorCalculatorTools::secondInvariant(tensor); break; case 13: value = MaterialTensorCalculatorTools::thirdInvariant(tensor); break; case 14: value = MaterialTensorCalculatorTools::triaxialityStress(tensor); break; case 15: value = MaterialTensorCalculatorTools::volumetricStrain(tensor); break; default: mooseError("Unknown quantity in MaterialTensorAux: " + _quantity_moose_enum.operator std::string()); } return value; }
RealVectorValue MooseParsedFunction::vectorValue(Real /*t*/, const Point & /*p*/) const { mooseError("The vectorValue method is not defined in ParsedFunction"); }
std::unique_ptr<MeshBase> SideSetsFromBoundingBoxGenerator::generate() { std::unique_ptr<MeshBase> mesh = std::move(_input); // Get a reference to our BoundaryInfo object for later use BoundaryInfo & boundary_info = mesh->get_boundary_info(); boundary_info.build_node_list_from_side_list(); bool found_element = false; bool found_side_sets = false; if (!_boundary_id_overlap) { // Loop over the elements for (const auto & elem : mesh->active_element_ptr_range()) { // boolean if element centroid is in bounding box bool contains = _bounding_box.contains_point(elem->centroid()); // check if active elements are found in the bounding box if (contains) { found_element = true; // loop over sides of elements within bounding box for (unsigned int side = 0; side < elem->n_sides(); side++) // loop over provided boundary vector to check all side sets for all boundary ids for (unsigned int boundary_id_number = 0; boundary_id_number < _boundary_id_old.size(); boundary_id_number++) // check if side has same boundary id that you are looking for if (boundary_info.has_boundary_id( elem, side, boundary_info.get_id_by_name(_boundary_id_old[boundary_id_number]))) { // assign new boundary value to boundary which meets meshmodifier criteria boundary_info.add_side(elem, side, _boundary_id_new); found_side_sets = true; } } } if (!found_element) mooseError("No elements found within the bounding box"); if (!found_side_sets) mooseError("No side sets found on active elements within the bounding box"); } else if (_boundary_id_overlap) { if (_boundary_id_old.size() < 2) mooseError("boundary_id_old out of bounds: ", _boundary_id_old.size(), " Must be 2 boundary inputs or more."); bool found_node = false; const bool inside = (_location == "INSIDE"); // Loop over the elements and assign node set id to nodes within the bounding box for (auto node = mesh->active_nodes_begin(); node != mesh->active_nodes_end(); ++node) { // check if nodes are inside of bounding box if (_bounding_box.contains_point(**node) == inside) { // read out boundary ids for nodes std::vector<boundary_id_type> boundary_id_list; boundary_info.boundary_ids(*node, boundary_id_list); std::vector<boundary_id_type> boundary_id_old_list = MooseMeshUtils::getBoundaryIDs(*mesh, _boundary_id_old, true); // sort boundary ids on node and sort boundary ids provided in input file std::sort(boundary_id_list.begin(), boundary_id_list.end()); std::sort(boundary_id_old_list.begin(), boundary_id_old_list.end()); // check if input boundary ids are all contained in the node // if true, write new boundary id on respective node if (std::includes(boundary_id_list.begin(), boundary_id_list.end(), boundary_id_old_list.begin(), boundary_id_old_list.end())) { boundary_info.add_node(*node, _boundary_id_new); found_node = true; } } } if (!found_node) mooseError("No nodes found within the bounding box"); } return dynamic_pointer_cast<MeshBase>(mesh); }
/* *Solves for incremental plastic rate of deformation tensor and stress in unrotated frame. *Input: Strain incrment, 4th order elasticity tensor, stress tensor in previous incrmenent and *plastic rate of deformation tensor. */ void FiniteStrainRatePlasticMaterial::returnMap(const RankTwoTensor & sig_old, const RankTwoTensor & delta_d, const RankFourTensor & E_ijkl, RankTwoTensor & dp, RankTwoTensor & sig) { RankTwoTensor sig_new, delta_dp, dpn; RankTwoTensor flow_tensor, flow_dirn; RankTwoTensor resid,ddsig; RankFourTensor dr_dsig, dr_dsig_inv; Real flow_incr, flow_incr_tmp; Real err1, err3, tol1, tol3; unsigned int iterisohard, iter, maxiterisohard = 20, maxiter = 50; Real eqvpstrain; Real yield_stress, yield_stress_prev; tol1 = 1e-10; tol3 = 1e-6; iterisohard = 0; eqvpstrain = std::pow(2.0/3.0,0.5) * dp.L2norm(); yield_stress = getYieldStress(eqvpstrain); err3 = 1.1 * tol3; while (err3 > tol3 && iterisohard < maxiterisohard) //Hardness update iteration { iterisohard++; iter = 0; delta_dp.zero(); sig_new = sig_old + E_ijkl * delta_d; flow_incr=_ref_pe_rate*_dt * std::pow(macaulayBracket(getSigEqv(sig_new) / yield_stress - 1.0), _exponent); getFlowTensor(sig_new, yield_stress, flow_tensor); flow_dirn = flow_tensor; resid = flow_dirn * flow_incr - delta_dp; err1 = resid.L2norm(); while (err1 > tol1 && iter < maxiter) //Stress update iteration (hardness fixed) { iter++; getJac(sig_new, E_ijkl, flow_incr, yield_stress, dr_dsig); //Jacobian dr_dsig_inv = dr_dsig.invSymm(); ddsig = -dr_dsig_inv * resid; sig_new += ddsig; //Update stress delta_dp -= E_ijkl.invSymm() * ddsig; //Update plastic rate of deformation tensor flow_incr_tmp = _ref_pe_rate * _dt * std::pow(macaulayBracket(getSigEqv(sig_new) / yield_stress - 1.0), _exponent); if (flow_incr_tmp < 0.0) //negative flow increment not allowed mooseError("Constitutive Error-Negative flow increment: Reduce time increment."); flow_incr = flow_incr_tmp; getFlowTensor(sig_new, yield_stress, flow_tensor); flow_dirn = flow_tensor; resid = flow_dirn * flow_incr - delta_dp; //Residual err1=resid.L2norm(); } if (iter>=maxiter)//Convergence failure mooseError("Constitutive Error-Too many iterations: Reduce time increment.\n"); //Convergence failure dpn = dp + delta_dp; eqvpstrain = std::pow(2.0/3.0, 0.5) * dpn.L2norm(); yield_stress_prev = yield_stress; yield_stress = getYieldStress(eqvpstrain); err3 = std::abs(yield_stress-yield_stress_prev); } if (iterisohard>=maxiterisohard) mooseError("Constitutive Error-Too many iterations in Hardness Update:Reduce time increment.\n"); //Convergence failure dp = dpn; //Plastic rate of deformation tensor in unrotated configuration sig = sig_new; }
PeacemanBorehole::PeacemanBorehole(const InputParameters & parameters) : DiracKernel(parameters), _re_constant(getParam<Real>("re_constant")), _well_constant(getParam<Real>("well_constant")), _borehole_length(getParam<Real>("borehole_length")), _borehole_direction(getParam<RealVectorValue>("borehole_direction")), _point_file(getParam<std::string>("point_file")), _character(getFunction("character")), _p_bot(getParam<Real>("bottom_pressure")), _unit_weight(getParam<RealVectorValue>("unit_weight")), _total_outflow_mass(const_cast<RichardsSumQuantity &>(getUserObject<RichardsSumQuantity>("SumQuantityUO"))) { // zero the outflow mass _total_outflow_mass.zero(); // open file std::ifstream file(_point_file.c_str()); if (!file.good()) mooseError("Error opening file '" + _point_file + "' from a Peaceman-type Borehole."); // construct the arrays of radius, x, y and z std::vector<Real> scratch; while (parseNextLineReals(file, scratch)) { if (scratch.size() >= 2) { _rs.push_back(scratch[0]); _xs.push_back(scratch[1]); if (scratch.size() >= 3) _ys.push_back(scratch[2]); else _ys.push_back(0.0); if (scratch.size() >= 4) _zs.push_back(scratch[3]); else _zs.push_back(0.0); } } file.close(); const int num_pts = _zs.size(); _bottom_point(0) = _xs[num_pts - 1]; _bottom_point(1) = _ys[num_pts - 1]; _bottom_point(2) = _zs[num_pts - 1]; // construct the line-segment lengths between each point _half_seg_len.resize(std::max(num_pts-1, 1)); for (unsigned int i = 0 ; i + 1 < _xs.size(); ++i) { _half_seg_len[i] = 0.5*std::sqrt(std::pow(_xs[i+1] - _xs[i], 2) + std::pow(_ys[i+1] - _ys[i], 2) + std::pow(_zs[i+1] - _zs[i], 2)); if (_half_seg_len[i] == 0) mooseError("Peaceman-type borehole has a zero-segment length at (x,y,z) = " << _xs[i] << " " << _ys[i] << " " << _zs[i] << "\n"); } if (num_pts == 1) _half_seg_len[0] = _borehole_length; // construct the rotation matrix needed to rotate the permeability _rot_matrix.resize(std::max(num_pts-1, 1)); for (unsigned int i = 0 ; i + 1 < _xs.size(); ++i) { const RealVectorValue v2(_xs[i+1] - _xs[i], _ys[i+1] - _ys[i], _zs[i+1] - _zs[i]); _rot_matrix[i] = RotationMatrix::rotVecToZ(v2); } if (num_pts == 1) _rot_matrix[0] = RotationMatrix::rotVecToZ(_borehole_direction); }
Real PeacemanBorehole::wellConstant(const RealTensorValue & perm, const RealTensorValue & rot, const Real & half_len, const Elem * ele, const Real & rad) // Peaceman's form for the borehole well constant { if (_well_constant > 0) return _well_constant; // rot_perm has its "2" component lying along the half segment // we want to determine the eigenvectors of rot(0:1, 0:1), since, when // rotated back to the original frame we will determine the element // lengths along these directions const RealTensorValue rot_perm = (rot*perm)*rot.transpose(); const Real trace2D = rot_perm(0,0) + rot_perm(1,1); const Real det2D = rot_perm(0,0)*rot_perm(1,1) - rot_perm(0,1)*rot_perm(1,0); const Real sq = std::sqrt(std::max(0.25*trace2D*trace2D - det2D, 0.0)); // the std::max accounts for wierdo precision loss const Real eig_val1 = 0.5*trace2D + sq; const Real eig_val2 = 0.5*trace2D - sq; RealVectorValue eig_vec1, eig_vec2; if (sq > std::abs(trace2D)*1E-7) // matrix is not a multiple of the identity (1E-7 accounts for precision in a crude way) { if (rot_perm(1,0) != 0) { eig_vec1(0) = eig_val1 - rot_perm(1,1); eig_vec1(1) = rot_perm(1,0); eig_vec2(0) = eig_val2 - rot_perm(1,1); eig_vec2(1) = rot_perm(1,0); } else if (rot_perm(0,1) != 0) { eig_vec1(0) = rot_perm(0,1); eig_vec1(1) = eig_val1 - rot_perm(0,0); eig_vec2(0) = rot_perm(0,1); eig_vec2(1) = eig_val2 - rot_perm(0,0); } else // off diagonal terms are both zero { eig_vec1(0) = 1; eig_vec2(1) = 1; } } else // matrix is basically a multiple of the identity { eig_vec1(0) = 1; eig_vec2(1) = 1; } // finally, rotate these to original frame and normalise eig_vec1 = rot.transpose()*eig_vec1; eig_vec1 /= std::sqrt(eig_vec1*eig_vec1); eig_vec2 = rot.transpose()*eig_vec2; eig_vec2 /= std::sqrt(eig_vec2*eig_vec2); // find the "length" of the element in these directions // TODO - probably better to use variance than max&min Real max1 = eig_vec1*ele->point(0); Real max2 = eig_vec2*ele->point(0); Real min1 = max1; Real min2 = max2; Real proj; for (unsigned int i = 1; i < ele->n_nodes(); i++) { proj = eig_vec1*ele->point(i); max1 = (max1 < proj) ? proj : max1; min1 = (min1 < proj) ? min1 : proj; proj = eig_vec2*ele->point(i); max2 = (max2 < proj) ? proj : max2; min2 = (min2 < proj) ? min2 : proj; } const Real ll1 = max1 - min1; const Real ll2 = max2 - min2; const Real r0 = _re_constant*std::sqrt( std::sqrt(eig_val1/eig_val2)*std::pow(ll2, 2) + std::sqrt(eig_val2/eig_val1)*std::pow(ll1, 2)) / ( std::pow(eig_val1/eig_val2, 0.25) + std::pow(eig_val2/eig_val1, 0.25) ); const Real effective_perm = std::sqrt(det2D); const Real halfPi = acos(0.0); if (r0 <= rad) mooseError("The effective element size (about 0.2-times-true-ele-size) for an element containing a Peaceman-type borehole must be (much) larger than the borehole radius for the Peaceman formulation to be correct. Your element has effective size " << r0 << " and the borehole radius is " << rad << "\n"); return 4*halfPi*effective_perm*half_len/std::log(r0/rad); }
void ActionWarehouse::addActionBlock(Action * action) { /** * Note: This routine uses the XTerm colors directly which is not advised for general purpose output coloring. * Most users should prefer using Problem::colorText() which respects the "color_output" option for terminals * that do not support coloring. Since this routine is intended for debugging only and runs before several * objects exist in the system, we are just using the constants directly. */ std::string registered_identifier = action->getParams().get<std::string>("registered_identifier"); std::set<std::string> tasks; if (_show_parser) Moose::err << COLOR_DEFAULT << "Parsing Syntax: " << COLOR_GREEN << action->name() << '\n' << COLOR_DEFAULT << "Building Action: " << COLOR_DEFAULT << action->type() << '\n' << COLOR_DEFAULT << "Registered Identifier: " << COLOR_GREEN << registered_identifier << '\n' << COLOR_DEFAULT << "Specific Task: " << COLOR_CYAN << action->specificTaskName() << '\n'; /** * We need to see if the current Action satisfies multiple tasks. There are a few cases to consider: * * 1. The current Action is registered with multiple syntax blocks. In this case we can only use the * current instance to satisfy the specific task listed for this syntax block. We can detect this * case by inspecting whether it has a "specific task name" set in the Action instance. * * 2. This action does not have a valid "registered identifier" set in the Action instance. This means * that this Action was not built by the Parser. It was most likely created through a Meta-Action. * In this case, the ActionFactory itself would have already set the task it found from the build * info used to construct the Action. * * 3. The current Action is registered with only a single syntax block. In this case we can simply * re-use the current instance to act and satisfy _all_ registered tasks. This is the normal * case where we have a Parser-built Action that does not have a specific task name to satisfy. * We will use the Action "type" to retrieve the list of tasks that this Action may satisfy. */ if (action->specificTaskName() != "") // Case 1 tasks.insert(action->specificTaskName()); else if (registered_identifier == "") // Case 2 { std::set<std::string> local_tasks = action->getAllTasks(); mooseAssert(local_tasks.size() == 1, "More than one task inside of the " << action->name()); tasks.insert(*local_tasks.begin()); } else // Case 3 tasks = _action_factory.getTasksByAction(action->type()); //TODO: Now we need to weed out the double registrations! for (std::set<std::string>::iterator it = tasks.begin(); it != tasks.end(); ++it) { const std::string & task = *it; // Some error checking if (!_syntax.hasTask(task)) mooseError("A(n) " << task << " is not a registered task"); // Make sure that the ObjectAction task and Action task are consistent // otherwise that means that is action was built by the wrong type MooseObjectAction * moa = dynamic_cast<MooseObjectAction *>(action); if (moa) { InputParameters mparams = moa->getObjectParams(); if (mparams.have_parameter<std::string>("_moose_base")) { const std::string & base = mparams.get<std::string>("_moose_base"); if (!_syntax.verifyMooseObjectTask(base, *it)) mooseError("Task " << *it << " is not registered to build " << base << " derived objects"); } else mooseError("Unable to locate registered base parameter for " << moa->getMooseObjectType()); } // Add the current task to current action action->appendTask(*it); if (_show_parser) Moose::err << COLOR_YELLOW << "Adding Action: " << COLOR_DEFAULT << action->type() << " (" << COLOR_YELLOW << *it << COLOR_DEFAULT << ")\n"; // Add it to the warehouse _action_blocks[*it].push_back(action); } if (_show_parser) Moose::err << std::endl; }
void SinglePhaseFluidProperties::mu_drhoT_from_rho_T(Real, Real, Real, Real &, Real &, Real &) const { mooseError(name(), ": mu_drhoT_from_rho_T is not implemented."); }
Real PorousFlowFluxLimitedTVDAdvection::computeQpResidual() { mooseError("PorousFlowFluxLimitedTVDAdvection::computeQpResidual() called\n"); return 0.0; }
Real SinglePhaseFluidProperties::k_from_rho_T(Real /*density*/, Real /*temperature*/) const { mooseError(name(), ": k_from_rho_T is not implemented."); }
void ComputeLinearElasticStress::initialSetup() { if (hasMaterialProperty<RankTwoTensor>(_base_name + "strain_increment")) mooseError("This linear elastic stress calculation only works for small strains"); }
Real SinglePhaseFluidProperties::vaporPressure(Real /*temperature*/) const { mooseError(name(), ": vaporPressure() is not implemented"); }
Real NaClFluidProperties::c_from_p_T(Real /*pressure*/, Real /*temperature*/) const { mooseError(name(), ": c() is not implemented"); }
void SinglePhaseFluidProperties::s_from_h_p(Real, Real, Real &, Real &, Real &) const { mooseError(name(), ": ", __PRETTY_FUNCTION__, " not implemented."); }
void GrainTracker::trackGrains() { // Don't track grains if the current simulation step is before the specified tracking step if (_t_step < _tracking_step) return; // Reset Status on active unique grains std::vector<unsigned int> map_sizes(_maps_size); for (std::map<unsigned int, UniqueGrain *>::iterator grain_it = _unique_grains.begin(); grain_it != _unique_grains.end(); ++grain_it) { if (grain_it->second->status != INACTIVE) { grain_it->second->status = NOT_MARKED; map_sizes[grain_it->second->variable_idx]++; } } // Print out info on the number of unique grains per variable vs the incoming bubble set sizes if (_t_step > _tracking_step) { for (unsigned int map_num = 0; map_num < _maps_size; ++map_num) { Moose::out << "\nGrains active index " << map_num << ": " << map_sizes[map_num] << " -> " << _bubble_sets[map_num].size(); if (map_sizes[map_num] != _bubble_sets[map_num].size()) Moose::out << "**"; } Moose::out << std::endl; } std::vector<UniqueGrain *> new_grains; new_grains.reserve(_unique_grains.size()); // Loop over all the current regions and build our unique grain structures for (unsigned int map_num = 0; map_num < _maps_size; ++map_num) { for (std::list<BubbleData>::const_iterator it1 = _bubble_sets[map_num].begin(); it1 != _bubble_sets[map_num].end(); ++it1) { std::vector<BoundingSphereInfo *> sphere_ptrs; unsigned int curr_var = it1->_var_idx; for (std::list<BoundingSphereInfo *>::iterator it2 = _bounding_spheres[map_num].begin(); it2 != _bounding_spheres[map_num].end(); /* No increment here! */) { /** * See which of the bounding spheres belong to the current region (bubble set) by looking at a * member node id. A single region may have multiple bounding spheres as members if it spans * periodic boundaries */ if (it1->_entity_ids.find((*it2)->member_node_id) != it1->_entity_ids.end()) { // Transfer ownership of the bounding sphere info to "sphere_ptrs" which will be stored in the unique grain sphere_ptrs.push_back(*it2); // Now delete the current BoundingSpherestructure so that it won't be inspected or reused _bounding_spheres[map_num].erase(it2++); } else ++it2; } // Create our new grains from this timestep that we will use to match up against the existing grains new_grains.push_back(new UniqueGrain(curr_var, sphere_ptrs, &it1->_entity_ids, NOT_MARKED)); } } /** * If it's the first time through this routine for the simulation, we will generate the unique grain * numbers using a simple counter. These will be the unique grain numbers that we must track for * the remainder of the simulation. */ if (_t_step == _tracking_step) // Start tracking when the time_step == the tracking_step { if (_ebsd_reader) { Real grain_num = _ebsd_reader->getGrainNum(); std::vector<Point> center_points(grain_num); for (unsigned int gr=0; gr < grain_num; ++gr) { const EBSDReader::EBSDAvgData & d = _ebsd_reader->getAvgData(gr); center_points[gr] = d.p; Moose::out << "EBSD Grain " << gr << " " << center_points[gr] << '\n'; } // To find the minimum distance we will use the boundingRegionDistance routine. // To do that, we need to build BoundingSphereObjects with a few dummy values, radius and node_id will be ignored BoundingSphereInfo ebsd_sphere(0, Point(0, 0, 0), 1); std::vector<BoundingSphereInfo *> ebsd_vector(1); ebsd_vector[0] = &ebsd_sphere; std::set<unsigned int> used_indices; std::map<unsigned int, unsigned int> error_indices; if (grain_num != new_grains.size()) mooseWarning("Mismatch:\nEBSD centers: " << grain_num << " Grain Tracker Centers: " << new_grains.size()); unsigned int next_index = grain_num+1; for (unsigned int i = 0; i < new_grains.size(); ++i) { Real min_centroid_diff = std::numeric_limits<Real>::max(); unsigned int closest_match_idx = 0; //Point center_of_mass = centerOfMass(*new_grains[i]); for (unsigned int j = 0; j<center_points.size(); ++j) { // Update the ebsd sphere to be used in the boundingRegionDistance calculation ebsd_sphere.b_sphere.center() = center_points[j]; Real curr_centroid_diff = boundingRegionDistance(ebsd_vector, new_grains[i]->sphere_ptrs, true); //Real curr_centroid_diff = (center_points[j] - center_of_mass).size(); if (curr_centroid_diff <= min_centroid_diff) { closest_match_idx = j; min_centroid_diff = curr_centroid_diff; } } if (used_indices.find(closest_match_idx) != used_indices.end()) { Moose::out << "Re-assigning center " << closest_match_idx << " -> " << next_index << " " << center_points[closest_match_idx] << " absolute distance: " << min_centroid_diff << '\n'; _unique_grains[next_index] = new_grains[i]; _unique_grain_to_ebsd_num[next_index] = closest_match_idx+1; ++next_index; } else { Moose::out << "Assigning center " << closest_match_idx << " " << center_points[closest_match_idx] << " absolute distance: " << min_centroid_diff << '\n'; _unique_grains[closest_match_idx+1] = new_grains[i]; _unique_grain_to_ebsd_num[closest_match_idx+1] = closest_match_idx+1; used_indices.insert(closest_match_idx); } } if (!error_indices.empty()) { for (std::map<unsigned int, UniqueGrain *>::const_iterator grain_it = _unique_grains.begin(); grain_it != _unique_grains.end(); ++grain_it) Moose::out << "Grain " << grain_it->first << ": " << center_points[grain_it->first - 1] << '\n'; Moose::out << "Error Indices:\n"; for (std::map<unsigned int, unsigned int>::const_iterator it = error_indices.begin(); it != error_indices.end(); ++it) Moose::out << "Grain " << it->first << '(' << it->second << ')' << ": " << center_points[it->second] << '\n'; mooseError("Error with ESBD Mapping (see above unused indices)"); } print(); } else { for (unsigned int i = 1; i <= new_grains.size(); ++i) { new_grains[i-1]->status = MARKED; _unique_grains[i] = new_grains[i-1]; // Transfer ownership of the memory } } return; // Return early - no matching or tracking to do } /** * To track grains across timesteps, we will loop over our unique grains and link each one up with one of our new * unique grains. The criteria for doing this will be to find the unique grain in the new list with a matching variable * index whose centroid is closest to this unique grain. */ std::map<unsigned int, std::vector<unsigned int> > new_grain_idx_to_existing_grain_idx; for (std::map<unsigned int, UniqueGrain *>::iterator curr_it = _unique_grains.begin(); curr_it != _unique_grains.end(); ++curr_it) { if (curr_it->second->status == INACTIVE) // Don't try to find matches for inactive grains continue; unsigned int closest_match_idx; // bool found_one = false; Real min_centroid_diff = std::numeric_limits<Real>::max(); for (unsigned int new_grain_idx = 0; new_grain_idx<new_grains.size(); ++new_grain_idx) { if (curr_it->second->variable_idx == new_grains[new_grain_idx]->variable_idx) // Do the variables indicies match? { Real curr_centroid_diff = boundingRegionDistance(curr_it->second->sphere_ptrs, new_grains[new_grain_idx]->sphere_ptrs, true); if (curr_centroid_diff <= min_centroid_diff) { // found_one = true; closest_match_idx = new_grain_idx; min_centroid_diff = curr_centroid_diff; } } } // Keep track of which new grains the existing ones want to map to new_grain_idx_to_existing_grain_idx[closest_match_idx].push_back(curr_it->first); } /** * It's possible that multiple existing grains will map to a single new grain. This will happen any time a grain disappears during this timestep. * We need to figure out the rightful owner in this case and inactivate the old grain. */ for (std::map<unsigned int, std::vector<unsigned int> >::iterator it = new_grain_idx_to_existing_grain_idx.begin(); it != new_grain_idx_to_existing_grain_idx.end(); ++it) { // If there is only a single mapping - we've found the correct grain if (it->second.size() == 1) { unsigned int curr_idx = (it->second)[0]; delete _unique_grains[curr_idx]; // clean-up old grain new_grains[it->first]->status = MARKED; // Mark it _unique_grains[curr_idx] = new_grains[it->first]; // transfer ownership of new grain } // More than one existing grain is mapping to a new one else { Real min_centroid_diff = std::numeric_limits<Real>::max(); unsigned int min_idx = 0; for (unsigned int i = 0; i < it->second.size(); ++i) { Real curr_centroid_diff = boundingRegionDistance(new_grains[it->first]->sphere_ptrs, _unique_grains[(it->second)[i]]->sphere_ptrs, true); if (curr_centroid_diff <= min_centroid_diff) { min_idx = i; min_centroid_diff = curr_centroid_diff; } } // One more time over the competing indices. We will mark the non-winners as inactive and transfer ownership to the winner (the closest centroid). for (unsigned int i = 0; i < it->second.size(); ++i) { unsigned int curr_idx = (it->second)[i]; if (i == min_idx) { delete _unique_grains[curr_idx]; // clean-up old grain new_grains[it->first]->status = MARKED; // Mark it _unique_grains[curr_idx] = new_grains[it->first]; // transfer ownership of new grain } else { Moose::out << "Marking Grain " << curr_idx << " as INACTIVE (varible index: " << _unique_grains[curr_idx]->variable_idx << ")\n"; _unique_grains[curr_idx]->status = INACTIVE; } } } } /** * Next we need to look at our new list and see which grains weren't matched up. These are new grains. */ for (unsigned int i = 0; i < new_grains.size(); ++i) if (new_grains[i]->status == NOT_MARKED) { Moose::out << COLOR_YELLOW << "*****************************************************************************\n" << "Couldn't find a matching grain while working on variable index: " << new_grains[i]->variable_idx << "\nCreating new unique grain: " << _unique_grains.size() + 1 << "\n*****************************************************************************\n" << COLOR_DEFAULT; new_grains[i]->status = MARKED; _unique_grains[_unique_grains.size() + 1] = new_grains[i]; // transfer ownership } /** * Finally we need to mark any grains in the unique list that aren't marked as inactive. These are the variables that * unique grains that didn't match up to any bounding sphere. Should only happen if it's the last active grain for * this particular variable. */ for (std::map<unsigned int, UniqueGrain *>::iterator it = _unique_grains.begin(); it != _unique_grains.end(); ++it) if (it->second->status == NOT_MARKED) { Moose::out << "Marking Grain " << it->first << " as INACTIVE (varible index: " << it->second->variable_idx << ")\n"; it->second->status = INACTIVE; } // Sanity check to make sure that we consumed all of the bounding sphere datastructures for (unsigned int map_num = 0; map_num < _maps_size; ++map_num) if (!_bounding_spheres[map_num].empty()) mooseError("BoundingSpheres where not completely used by the GrainTracker"); }
void ContactAction::act() { if (!_problem->getDisplacedProblem()) mooseError("Contact requires updated coordinates. Use the 'displacements = ...' line in the " "Mesh block."); std::string action_name = MooseUtils::shortName(name()); std::vector<NonlinearVariableName> displacements; if (isParamValid("displacements")) displacements = getParam<std::vector<NonlinearVariableName>>("displacements"); else { // Legacy parameter scheme for displacements if (!isParamValid("disp_x")) mooseError("Specify displacement variables using the `displacements` parameter."); displacements.push_back(getParam<NonlinearVariableName>("disp_x")); if (isParamValid("disp_y")) { displacements.push_back(getParam<NonlinearVariableName>("disp_y")); if (isParamValid("disp_z")) displacements.push_back(getParam<NonlinearVariableName>("disp_z")); } mooseDeprecated("use the `displacements` parameter rather than the `disp_*` parameters (those " "will go away with the deprecation of the Solid Mechanics module)."); } // Determine number of dimensions const unsigned int ndisp = displacements.size(); // convert vector of NonlinearVariableName to vector of VariableName std::vector<VariableName> coupled_displacements(ndisp); for (unsigned int i = 0; i < ndisp; ++i) coupled_displacements[i] = displacements[i]; if (_current_task == "add_dirac_kernel") { // MechanicalContactConstraint has to be added after the init_problem task, so it cannot be // added for the add_constraint task. if (_system == "Constraint") { InputParameters params = _factory.getValidParams("MechanicalContactConstraint"); params.applyParameters(parameters(), {"displacements", "formulation"}); params.set<std::string>("formulation") = _formulation; params.set<std::vector<VariableName>>("nodal_area") = {"nodal_area_" + name()}; params.set<std::vector<VariableName>>("displacements") = coupled_displacements; params.set<BoundaryName>("boundary") = _master; params.set<bool>("use_displaced_mesh") = true; for (unsigned int i = 0; i < ndisp; ++i) { std::string name = action_name + "_constraint_" + Moose::stringify(i); params.set<unsigned int>("component") = i; params.set<NonlinearVariableName>("variable") = displacements[i]; params.set<std::vector<VariableName>>("master_variable") = {coupled_displacements[i]}; _problem->addConstraint("MechanicalContactConstraint", name, params); } } if (_system == "DiracKernel") { { InputParameters params = _factory.getValidParams("ContactMaster"); params.applyParameters(parameters(), {"displacements", "formulation"}); params.set<std::string>("formulation") = _formulation; params.set<std::vector<VariableName>>("nodal_area") = {"nodal_area_" + name()}; params.set<std::vector<VariableName>>("displacements") = coupled_displacements; params.set<BoundaryName>("boundary") = _master; params.set<bool>("use_displaced_mesh") = true; for (unsigned int i = 0; i < ndisp; ++i) { std::string name = action_name + "_master_" + Moose::stringify(i); params.set<unsigned int>("component") = i; params.set<NonlinearVariableName>("variable") = displacements[i]; _problem->addDiracKernel("ContactMaster", name, params); } } { InputParameters params = _factory.getValidParams("SlaveConstraint"); params.applyParameters(parameters(), {"displacements", "formulation"}); params.set<std::string>("formulation") = _formulation; params.set<std::vector<VariableName>>("nodal_area") = {"nodal_area_" + name()}; params.set<std::vector<VariableName>>("displacements") = coupled_displacements; params.set<BoundaryName>("boundary") = _slave; params.set<bool>("use_displaced_mesh") = true; for (unsigned int i = 0; i < ndisp; ++i) { std::string name = action_name + "_slave_" + Moose::stringify(i); params.set<unsigned int>("component") = i; params.set<NonlinearVariableName>("variable") = displacements[i]; _problem->addDiracKernel("SlaveConstraint", name, params); } } } } }
void SinglePhaseFluidProperties::s_from_p_T(Real, Real, Real &, Real &, Real &) const { mooseError(name(), ": s_from_p_T is not implemented"); }
void MechanicalContactConstraint::computeContactForce(PenetrationInfo * pinfo) { std::map<unsigned int, Real> & lagrange_multiplier = _penetration_locator._lagrange_multiplier; const Node * node = pinfo->_node; RealVectorValue res_vec; // Build up residual vector for (unsigned int i=0; i<_mesh_dimension; ++i) { long int dof_number = node->dof_number(0, _vars(i), 0); res_vec(i) = _residual_copy(dof_number); } RealVectorValue distance_vec(_mesh.node(node->id()) - pinfo->_closest_point); const Real penalty = getPenalty(*pinfo); RealVectorValue pen_force(penalty * distance_vec); RealVectorValue tan_residual(0,0,0); switch (_model) { case CM_FRICTIONLESS: switch (_formulation) { case CF_DEFAULT: pinfo->_contact_force = -pinfo->_normal * (pinfo->_normal * res_vec); break; case CF_PENALTY: pinfo->_contact_force = pinfo->_normal * (pinfo->_normal * pen_force); break; case CF_AUGMENTED_LAGRANGE: pinfo->_contact_force = (pinfo->_normal * (pinfo->_normal * ( pen_force + lagrange_multiplier[node->id()] * pinfo->_normal))); //( pen_force + (lagrange_multiplier[node->id()]/distance_vec.size())*distance_vec))); break; default: mooseError("Invalid contact formulation"); break; } pinfo->_mech_status=PenetrationInfo::MS_SLIPPING; break; case CM_COULOMB: switch (_formulation) { case CF_DEFAULT: pinfo->_contact_force = -res_vec; break; case CF_PENALTY: { distance_vec = pinfo->_incremental_slip + (pinfo->_normal * (_mesh.node(node->id()) - pinfo->_closest_point)) * pinfo->_normal; pen_force = penalty * distance_vec; // Frictional capacity // const Real capacity( _friction_coefficient * (pen_force * pinfo->_normal < 0 ? -pen_force * pinfo->_normal : 0) ); const Real capacity( _friction_coefficient * (res_vec * pinfo->_normal > 0 ? res_vec * pinfo->_normal : 0) ); // Elastic predictor pinfo->_contact_force = pen_force + (pinfo->_contact_force_old - pinfo->_normal*(pinfo->_normal*pinfo->_contact_force_old)); RealVectorValue contact_force_normal( (pinfo->_contact_force*pinfo->_normal) * pinfo->_normal ); RealVectorValue contact_force_tangential( pinfo->_contact_force - contact_force_normal ); // Tangential magnitude of elastic predictor const Real tan_mag( contact_force_tangential.size() ); if ( tan_mag > capacity ) { pinfo->_contact_force = contact_force_normal + capacity * contact_force_tangential / tan_mag; pinfo->_mech_status=PenetrationInfo::MS_SLIPPING; } else pinfo->_mech_status=PenetrationInfo::MS_STICKING; break; } case CF_AUGMENTED_LAGRANGE: pinfo->_contact_force = pen_force + lagrange_multiplier[node->id()]*distance_vec/distance_vec.size(); break; default: mooseError("Invalid contact formulation"); break; } break; case CM_GLUED: switch (_formulation) { case CF_DEFAULT: pinfo->_contact_force = -res_vec; break; case CF_PENALTY: pinfo->_contact_force = pen_force; break; case CF_AUGMENTED_LAGRANGE: pinfo->_contact_force = pen_force + lagrange_multiplier[node->id()]*distance_vec/distance_vec.size(); break; default: mooseError("Invalid contact formulation"); break; } pinfo->_mech_status=PenetrationInfo::MS_STICKING; break; default: mooseError("Invalid or unavailable contact model"); break; } }
Real SinglePhaseFluidProperties::criticalDensity() const { mooseError(name(), ": criticalDensity() is not implemented"); }
void FormattedTable::makeGnuplot(const std::string & base_file, const std::string & format) { // TODO: run this once at end of simulation, right now it runs every iteration // TODO: do I need to be more careful escaping column names? // Note: open and close the files each time, having open files may mess with gnuplot // supported filetypes: ps, png std::string extension, terminal; if (format == "png") { extension = ".png"; terminal = "png"; } else if (format == "ps") { extension = ".ps"; terminal = "postscript"; } else if (format == "gif") { extension = ".gif"; terminal = "gif"; } else mooseError("gnuplot format \"" + format + "\" is not supported."); // Write the data to disk std::string dat_name = base_file + ".dat"; std::ofstream datfile; datfile.open(dat_name.c_str(), std::ios::trunc | std::ios::out); datfile << "# time"; for (const auto & col_name : _column_names) datfile << '\t' << col_name; datfile << '\n'; for (auto & i : _data) { datfile << i.first; for (const auto & col_name : _column_names) { std::map<std::string, Real> & tmp = i.second; datfile << '\t' << tmp[col_name]; } datfile << '\n'; } datfile.flush(); datfile.close(); // Write the gnuplot script std::string gp_name = base_file + ".gp"; std::ofstream gpfile; gpfile.open(gp_name.c_str(), std::ios::trunc | std::ios::out); gpfile << gnuplot::before_terminal << terminal << gnuplot::before_ext << extension << gnuplot::after_ext; // plot all postprocessors in one plot int column = 2; for (const auto & col_name : _column_names) { gpfile << " '" << dat_name << "' using 1:" << column << " title '" << col_name << "' with linespoints"; column++; if (column - 2 < static_cast<int>(_column_names.size())) gpfile << ", \\\n"; } gpfile << "\n\n"; // plot the postprocessors individually column = 2; for (const auto & col_name : _column_names) { gpfile << "set output '" << col_name << extension << "'\n"; gpfile << "set ylabel '" << col_name << "'\n"; gpfile << "plot '" << dat_name << "' using 1:" << column << " title '" << col_name << "' with linespoints\n\n"; column++; } gpfile.flush(); gpfile.close(); // Run the gnuplot script /* We aren't going to run gnuplot automatically if (!system(NULL)) mooseError("No way to run gnuplot on this computer"); std::string command = "gnuplot " + gp_name; if (system(command.c_str())) mooseError("gnuplot command failed"); */ }
Real SinglePhaseFluidProperties::triplePointTemperature() const { mooseError(name(), ": triplePointTemperature() is not implemented"); }
void PLC_LSH::computeCreep( const SymmTensor & strain_increment, SymmTensor & creep_strain_increment, SymmTensor & stress_new ) { // 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); // Use Newton sub-iteration to determine effective creep strain increment Real exponential(1); if (_has_temp) { exponential = std::exp(-_activation_energy/(_gas_constant *_temperature[_qp])); } Real expTime = std::pow(_t, _m_exponent); Real del_p = 0; unsigned int it = 0; Real creep_residual = 10; Real norm_creep_residual = 10; Real first_norm_creep_residual = 10; while (it < _max_its && norm_creep_residual > _absolute_tolerance && (norm_creep_residual/first_norm_creep_residual) > _relative_tolerance) { Real phi = _coefficient*std::pow(effective_trial_stress - 3*_shear_modulus*del_p, _n_exponent)* exponential*expTime; Real dphi_ddelp = -3*_coefficient*_shear_modulus*_n_exponent* std::pow(effective_trial_stress-3*_shear_modulus*del_p, _n_exponent-1)*exponential*expTime; creep_residual = phi - del_p/_dt; norm_creep_residual = std::abs(creep_residual); if (it == 0) { first_norm_creep_residual = norm_creep_residual; } del_p += creep_residual / (1/_dt - dphi_ddelp); if (_output_iteration_info == true) { _console << "crp_it=" << it << " trl_strs=" << effective_trial_stress << " phi=" << phi << " dphi=" << dphi_ddelp << " del_p=" << del_p << " rel_res=" << norm_creep_residual/first_norm_creep_residual << " rel_tol=" << _relative_tolerance << " abs_res=" << norm_creep_residual << " abs_tol=" << _absolute_tolerance << std::endl; } ++it; } if (it == _max_its && norm_creep_residual > _absolute_tolerance && (norm_creep_residual/first_norm_creep_residual) > _relative_tolerance) { mooseError("Max sub-newton iteration hit during creep solve!"); } // compute creep 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; } creep_strain_increment = dev_trial_stress; creep_strain_increment *= (1.5*del_p/effective_trial_stress); SymmTensor elastic_strain_increment(strain_increment); elastic_strain_increment -= creep_strain_increment; // compute stress increment stress_new = *elasticityTensor() * elastic_strain_increment; // update stress and creep strain stress_new += _stress_old; _creep_strain[_qp] = creep_strain_increment; _creep_strain[_qp] += _creep_strain_old[_qp]; }
void MultiAppNearestNodeTransfer::execute() { _console << "Beginning NearestNodeTransfer " << _name << std::endl; switch (_direction) { case TO_MULTIAPP: { FEProblem & from_problem = *_multi_app->problem(); MooseVariable & from_var = from_problem.getVariable(0, _from_var_name); MeshBase * from_mesh = NULL; if (_displaced_source_mesh && from_problem.getDisplacedProblem()) { mooseError("Cannot use a NearestNode transfer from a displaced mesh to a MultiApp!"); from_mesh = &from_problem.getDisplacedProblem()->mesh().getMesh(); } else from_mesh = &from_problem.mesh().getMesh(); SystemBase & from_system_base = from_var.sys(); System & from_sys = from_system_base.system(); unsigned int from_sys_num = from_sys.number(); // Only works with a serialized mesh to transfer from! mooseAssert(from_sys.get_mesh().is_serial(), "MultiAppNearestNodeTransfer only works with SerialMesh!"); unsigned int from_var_num = from_sys.variable_number(from_var.name()); // EquationSystems & from_es = from_sys.get_equation_systems(); //Create a serialized version of the solution vector NumericVector<Number> * serialized_solution = NumericVector<Number>::build(from_sys.comm()).release(); serialized_solution->init(from_sys.n_dofs(), false, SERIAL); // Need to pull down a full copy of this vector on every processor so we can get values in parallel from_sys.solution->localize(*serialized_solution); for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++) { if (_multi_app->hasLocalApp(i)) { MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm()); // Loop over the master nodes and set the value of the variable System * to_sys = find_sys(_multi_app->appProblem(i)->es(), _to_var_name); unsigned int sys_num = to_sys->number(); unsigned int var_num = to_sys->variable_number(_to_var_name); NumericVector<Real> & solution = _multi_app->appTransferVector(i, _to_var_name); MeshBase * mesh = NULL; if (_displaced_target_mesh && _multi_app->appProblem(i)->getDisplacedProblem()) mesh = &_multi_app->appProblem(i)->getDisplacedProblem()->mesh().getMesh(); else mesh = &_multi_app->appProblem(i)->mesh().getMesh(); bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE; if (is_nodal) { MeshBase::const_node_iterator node_it = mesh->local_nodes_begin(); MeshBase::const_node_iterator node_end = mesh->local_nodes_end(); for (; node_it != node_end; ++node_it) { Node * node = *node_it; Point actual_position = *node+_multi_app->position(i); if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node { // The zero only works for LAGRANGE! dof_id_type dof = node->dof_number(sys_num, var_num, 0); // Swap back Moose::swapLibMeshComm(swapped); Real distance = 0; // Just to satisfy the last argument MeshBase::const_node_iterator from_nodes_begin = from_mesh->nodes_begin(); MeshBase::const_node_iterator from_nodes_end = from_mesh->nodes_end(); Node * nearest_node = NULL; if (_fixed_meshes) { if (_node_map.find(node->id()) == _node_map.end()) // Haven't cached it yet { nearest_node = getNearestNode(actual_position, distance, from_nodes_begin, from_nodes_end); _node_map[node->id()] = nearest_node; _distance_map[node->id()] = distance; } else { nearest_node = _node_map[node->id()]; //distance = _distance_map[node->id()]; } } else nearest_node = getNearestNode(actual_position, distance, from_nodes_begin, from_nodes_end); // Assuming LAGRANGE! dof_id_type from_dof = nearest_node->dof_number(from_sys_num, from_var_num, 0); Real from_value = (*serialized_solution)(from_dof); // Swap again swapped = Moose::swapLibMeshComm(_multi_app->comm()); solution.set(dof, from_value); } } } else // Elemental { MeshBase::const_element_iterator elem_it = mesh->local_elements_begin(); MeshBase::const_element_iterator elem_end = mesh->local_elements_end(); for (; elem_it != elem_end; ++elem_it) { Elem * elem = *elem_it; Point centroid = elem->centroid(); Point actual_position = centroid+_multi_app->position(i); if (elem->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this elem { // The zero only works for LAGRANGE! dof_id_type dof = elem->dof_number(sys_num, var_num, 0); // Swap back Moose::swapLibMeshComm(swapped); Real distance = 0; // Just to satisfy the last argument MeshBase::const_node_iterator from_nodes_begin = from_mesh->nodes_begin(); MeshBase::const_node_iterator from_nodes_end = from_mesh->nodes_end(); Node * nearest_node = NULL; if (_fixed_meshes) { if (_node_map.find(elem->id()) == _node_map.end()) // Haven't cached it yet { nearest_node = getNearestNode(actual_position, distance, from_nodes_begin, from_nodes_end); _node_map[elem->id()] = nearest_node; _distance_map[elem->id()] = distance; } else { nearest_node = _node_map[elem->id()]; //distance = _distance_map[elem->id()]; } } else nearest_node = getNearestNode(actual_position, distance, from_nodes_begin, from_nodes_end); // Assuming LAGRANGE! dof_id_type from_dof = nearest_node->dof_number(from_sys_num, from_var_num, 0); Real from_value = (*serialized_solution)(from_dof); // Swap again swapped = Moose::swapLibMeshComm(_multi_app->comm()); solution.set(dof, from_value); } } } solution.close(); to_sys->update(); // Swap back Moose::swapLibMeshComm(swapped); } } delete serialized_solution; break; } case FROM_MULTIAPP: { FEProblem & to_problem = *_multi_app->problem(); MooseVariable & to_var = to_problem.getVariable(0, _to_var_name); SystemBase & to_system_base = to_var.sys(); System & to_sys = to_system_base.system(); NumericVector<Real> & to_solution = *to_sys.solution; unsigned int to_sys_num = to_sys.number(); // Only works with a serialized mesh to transfer to! mooseAssert(to_sys.get_mesh().is_serial(), "MultiAppNearestNodeTransfer only works with SerialMesh!"); unsigned int to_var_num = to_sys.variable_number(to_var.name()); // EquationSystems & to_es = to_sys.get_equation_systems(); MeshBase * to_mesh = NULL; if (_displaced_target_mesh && to_problem.getDisplacedProblem()) to_mesh = &to_problem.getDisplacedProblem()->mesh().getMesh(); else to_mesh = &to_problem.mesh().getMesh(); bool is_nodal = to_sys.variable_type(to_var_num) == FEType(); dof_id_type n_nodes = to_mesh->n_nodes(); dof_id_type n_elems = to_mesh->n_elem(); ///// All of the following are indexed off to_node->id() or to_elem->id() ///// // Minimum distances from each node in the "to" mesh to a node in std::vector<Real> min_distances; // The node ids in the "from" mesh that this processor has found to be the minimum distances to the "to" nodes std::vector<dof_id_type> min_nodes; // After the call to maxloc() this will tell us which processor actually has the minimum std::vector<unsigned int> min_procs; // The global multiapp ID that this processor found had the minimum distance node in it. std::vector<unsigned int> min_apps; if (is_nodal) { min_distances.resize(n_nodes, std::numeric_limits<Real>::max()); min_nodes.resize(n_nodes); min_procs.resize(n_nodes); min_apps.resize(n_nodes); } else { min_distances.resize(n_elems, std::numeric_limits<Real>::max()); min_nodes.resize(n_elems); min_procs.resize(n_elems); min_apps.resize(n_elems); } for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++) { if (!_multi_app->hasLocalApp(i)) continue; MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm()); FEProblem & from_problem = *_multi_app->appProblem(i); MooseVariable & from_var = from_problem.getVariable(0, _from_var_name); SystemBase & from_system_base = from_var.sys(); System & from_sys = from_system_base.system(); // Only works with a serialized mesh to transfer from! mooseAssert(from_sys.get_mesh().is_serial(), "MultiAppNearestNodeTransfer only works with SerialMesh!"); // unsigned int from_var_num = from_sys.variable_number(from_var.name()); // EquationSystems & from_es = from_sys.get_equation_systems(); MeshBase * from_mesh = NULL; if (_displaced_source_mesh && from_problem.getDisplacedProblem()) from_mesh = &from_problem.getDisplacedProblem()->mesh().getMesh(); else from_mesh = &from_problem.mesh().getMesh(); MeshTools::BoundingBox app_box = MeshTools::processor_bounding_box(*from_mesh, from_mesh->processor_id()); Point app_position = _multi_app->position(i); Moose::swapLibMeshComm(swapped); if (is_nodal) { MeshBase::const_node_iterator to_node_it = to_mesh->nodes_begin(); MeshBase::const_node_iterator to_node_end = to_mesh->nodes_end(); for (; to_node_it != to_node_end; ++to_node_it) { Node * to_node = *to_node_it; dof_id_type to_node_id = to_node->id(); Real current_distance = 0; MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm()); MeshBase::const_node_iterator from_nodes_begin = from_mesh->local_nodes_begin(); MeshBase::const_node_iterator from_nodes_end = from_mesh->local_nodes_end(); Node * nearest_node = NULL; if (_fixed_meshes) { if (_node_map.find(to_node->id()) == _node_map.end()) // Haven't cached it yet { nearest_node = getNearestNode(*to_node-app_position, current_distance, from_nodes_begin, from_nodes_end); _node_map[to_node->id()] = nearest_node; _distance_map[to_node->id()] = current_distance; } else { nearest_node = _node_map[to_node->id()]; current_distance = _distance_map[to_node->id()]; } } else nearest_node = getNearestNode(*to_node-app_position, current_distance, from_nodes_begin, from_nodes_end); Moose::swapLibMeshComm(swapped); // TODO: Logic bug when we are using caching. "current_distance" is set by a call to getNearestNode which is // skipped in that case. We shouldn't be relying on it or stuffing it in another data structure if (current_distance < min_distances[to_node->id()]) { min_distances[to_node_id] = current_distance; min_nodes[to_node_id] = nearest_node->id(); min_apps[to_node_id] = i; } } } else // Elemental { MeshBase::const_element_iterator to_elem_it = to_mesh->elements_begin(); MeshBase::const_element_iterator to_elem_end = to_mesh->elements_end(); for (; to_elem_it != to_elem_end; ++to_elem_it) { Elem * to_elem = *to_elem_it; dof_id_type to_elem_id = to_elem->id(); Point actual_position = to_elem->centroid()-app_position; Real current_distance = 0; MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm()); MeshBase::const_node_iterator from_nodes_begin = from_mesh->local_nodes_begin(); MeshBase::const_node_iterator from_nodes_end = from_mesh->local_nodes_end(); Node * nearest_node = NULL; if (_fixed_meshes) { if (_node_map.find(to_elem->id()) == _node_map.end()) // Haven't cached it yet { nearest_node = getNearestNode(actual_position, current_distance, from_nodes_begin, from_nodes_end); _node_map[to_elem->id()] = nearest_node; _distance_map[to_elem->id()] = current_distance; } else { nearest_node = _node_map[to_elem->id()]; current_distance = _distance_map[to_elem->id()]; } } else nearest_node = getNearestNode(actual_position, current_distance, from_nodes_begin, from_nodes_end); Moose::swapLibMeshComm(swapped); // TODO: Logic bug when we are using caching. "current_distance" is set by a call to getNearestNode which is // skipped in that case. We shouldn't be relying on it or stuffing it in another data structure if (current_distance < min_distances[to_elem->id()]) { min_distances[to_elem_id] = current_distance; min_nodes[to_elem_id] = nearest_node->id(); min_apps[to_elem_id] = i; } } } } /* // We're going to need serialized solution vectors for each app // We could try to only do it for the apps that have mins in them... // but it's tough because this is a collective operation... so that would have to be coordinated std::vector<NumericVector<Number> *> serialized_from_solutions(_multi_app->numGlobalApps()); if (_multi_app->hasApp()) { // Swap MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm()); for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++) { if (!_multi_app->hasLocalApp(i)) continue; FEProblem & from_problem = *_multi_app->appProblem(i); MooseVariable & from_var = from_problem.getVariable(0, _from_var_name); SystemBase & from_system_base = from_var.sys(); System & from_sys = from_system_base.system(); //Create a serialized version of the solution vector serialized_from_solutions[i] = NumericVector<Number>::build().release(); serialized_from_solutions[i]->init(from_sys.n_dofs(), false, SERIAL); // Need to pull down a full copy of this vector on every processor so we can get values in parallel from_sys.solution->localize(*serialized_from_solutions[i]); } // Swap back Moose::swapLibMeshComm(swapped); } */ // We've found the nearest nodes for this processor. We need to see which processor _actually_ found the nearest though _communicator.minloc(min_distances, min_procs); // Now loop through min_procs and see if _this_ processor had the actual minimum for any nodes. // If it did then we're going to go get the value from that nearest node and transfer its value processor_id_type proc_id = processor_id(); for (unsigned int j=0; j<min_procs.size(); j++) { if (min_procs[j] == proc_id) // This means that this processor really did find the minumum so we need to transfer the value { // The zero only works for LAGRANGE! dof_id_type to_dof = 0; if (is_nodal) { Node & to_node = to_mesh->node(j); to_dof = to_node.dof_number(to_sys_num, to_var_num, 0); } else { Elem & to_elem = *to_mesh->elem(j); to_dof = to_elem.dof_number(to_sys_num, to_var_num, 0); } // The app that has the nearest node in it unsigned int from_app_num = min_apps[j]; mooseAssert(_multi_app->hasLocalApp(from_app_num), "Something went very wrong!"); // Swap MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm()); FEProblem & from_problem = *_multi_app->appProblem(from_app_num); MooseVariable & from_var = from_problem.getVariable(0, _from_var_name); SystemBase & from_system_base = from_var.sys(); System & from_sys = from_system_base.system(); unsigned int from_sys_num = from_sys.number(); unsigned int from_var_num = from_sys.variable_number(from_var.name()); // EquationSystems & from_es = from_sys.get_equation_systems(); MeshBase * from_mesh = NULL; if (_displaced_source_mesh && from_problem.getDisplacedProblem()) from_mesh = &from_problem.getDisplacedProblem()->mesh().getMesh(); else from_mesh = &from_problem.mesh().getMesh(); Node & from_node = from_mesh->node(min_nodes[j]); // Assuming LAGRANGE! dof_id_type from_dof = from_node.dof_number(from_sys_num, from_var_num, 0); Real from_value = (*from_sys.solution)(from_dof); // Swap back Moose::swapLibMeshComm(swapped); to_solution.set(to_dof, from_value); } } to_solution.close(); to_sys.update(); break; } } _console << "Finished NearestNodeTransfer " << _name << std::endl; }