Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "DiscreteNucleationMap.h" 11 : #include "MooseMesh.h" 12 : #include "Executioner.h" 13 : 14 : #include "libmesh/quadrature.h" 15 : 16 : registerMooseObject("PhaseFieldApp", DiscreteNucleationMap); 17 : 18 : InputParameters 19 310 : DiscreteNucleationMap::validParams() 20 : { 21 310 : InputParameters params = ElementUserObject::validParams(); 22 310 : params.addClassDescription("Generates a spatial smoothed map of all nucleation sites with the " 23 : "data of the DiscreteNucleationInserter for use by the " 24 : "DiscreteNucleation material."); 25 620 : params.addParam<Real>("int_width", 0.0, "Nucleus interface width for smooth nuclei"); 26 620 : params.addRequiredParam<UserObjectName>("inserter", "DiscreteNucleationInserter user object"); 27 620 : params.addCoupledVar("periodic", 28 : "Use the periodicity settings of this variable to populate the grain map"); 29 : // the mapping needs to run at timestep begin, which is after the adaptivity 30 : // run of the previous timestep. 31 310 : params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_BEGIN; 32 310 : return params; 33 0 : } 34 : 35 164 : DiscreteNucleationMap::DiscreteNucleationMap(const InputParameters & parameters) 36 : : ElementUserObject(parameters), 37 164 : _mesh_changed(false), 38 164 : _inserter(getUserObject<DiscreteNucleationInserterBase>("inserter")), 39 298 : _periodic(isCoupled("periodic") ? coupled("periodic") : -1), 40 328 : _int_width(getParam<Real>("int_width")), 41 328 : _nucleus_list(_inserter.getNucleusList()) 42 : { 43 164 : _zero_map.assign(_fe_problem.getMaxQps(), 0.0); 44 164 : } 45 : 46 : void 47 1123 : DiscreteNucleationMap::initialize() 48 : { 49 1123 : if (_inserter.isMapUpdateRequired() || _mesh_changed || _force_rebuild_map) 50 : { 51 : // If the last solve didn't converge, postpone the rebuild until the next timestep 52 511 : if (_app.getExecutioner()->lastSolveConverged()) 53 : { 54 502 : _rebuild_map = true; 55 : _nucleus_map.clear(); 56 502 : _force_rebuild_map = false; 57 : } 58 : else 59 : { 60 9 : _rebuild_map = false; 61 9 : _force_rebuild_map = true; 62 : } 63 : } 64 : else 65 612 : _rebuild_map = false; 66 : 67 1123 : _mesh_changed = false; 68 1123 : } 69 : 70 : void 71 1586128 : DiscreteNucleationMap::execute() 72 : { 73 1586128 : if (_rebuild_map) 74 : { 75 : // reserve space for each quadrature point in the element 76 833074 : _elem_map.assign(_qrule->n_points(), 0); 77 : 78 : // store a random number for each quadrature point 79 : unsigned int active_nuclei = 0; 80 4119770 : for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp) 81 : { 82 : Real r = std::numeric_limits<Real>::max(); 83 : 84 : // find the distance to the closest nucleus 85 : Real local_radius = 0.0; 86 12783568 : for (unsigned i = 0; i < _nucleus_list.size(); ++i) 87 : { 88 : // use a non-periodic or periodic distance 89 9496872 : r = _periodic < 0 90 9496872 : ? (_q_point[qp] - _nucleus_list[i].center).norm() 91 7779272 : : _mesh.minPeriodicDistance(_periodic, _q_point[qp], _nucleus_list[i].center); 92 : 93 : // grab the radius of the nucleus that this qp is closest to 94 9496872 : local_radius = _nucleus_list[i].radius; 95 : 96 : // compute intensity value with smooth interface 97 : Real value = 0.0; 98 9496872 : if (r <= local_radius - _int_width / 2.0) // Inside circle 99 : { 100 1055880 : active_nuclei++; 101 : value = 1.0; 102 : } 103 8440992 : else if (r < local_radius + _int_width / 2.0) // Smooth interface 104 : { 105 52444 : Real int_pos = (r - local_radius + _int_width / 2.0) / _int_width; 106 52444 : active_nuclei++; 107 52444 : value = (1.0 + std::cos(int_pos * libMesh::pi)) / 2.0; 108 : } 109 9496872 : if (value > _elem_map[qp]) 110 883053 : _elem_map[qp] = value; 111 : } 112 : } 113 : 114 : // if the map is not empty insert it 115 833074 : if (active_nuclei > 0) 116 : _nucleus_map.insert( 117 458058 : std::pair<dof_id_type, std::vector<Real>>(_current_elem->id(), _elem_map)); 118 : } 119 1586128 : } 120 : 121 : void 122 142 : DiscreteNucleationMap::threadJoin(const UserObject & y) 123 : { 124 : // if the map needs to be updated we merge the maps from all threads 125 142 : if (_rebuild_map) 126 : { 127 : const auto & uo = static_cast<const DiscreteNucleationMap &>(y); 128 64 : _nucleus_map.insert(uo._nucleus_map.begin(), uo._nucleus_map.end()); 129 : } 130 142 : } 131 : 132 : void 133 27 : DiscreteNucleationMap::meshChanged() 134 : { 135 27 : _mesh_changed = true; 136 27 : } 137 : 138 : const std::vector<Real> & 139 2228668 : DiscreteNucleationMap::nuclei(const Elem * elem) const 140 : { 141 2228668 : NucleusMap::const_iterator i = _nucleus_map.find(elem->id()); 142 : 143 : // if no entry in the map was found the element contains no nucleus 144 2228668 : if (i == _nucleus_map.end()) 145 1787694 : return _zero_map; 146 : 147 440974 : return i->second; 148 : }