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 "PolycrystalCircles.h" 11 : #include "MooseMesh.h" 12 : #include "MooseVariable.h" 13 : 14 : #include "libmesh/utility.h" 15 : #include <fstream> 16 : 17 : registerMooseObject("PhaseFieldApp", PolycrystalCircles); 18 : 19 : InputParameters 20 24 : PolycrystalCircles::validParams() 21 : { 22 24 : InputParameters params = PolycrystalUserObjectBase::validParams(); 23 24 : params.addClassDescription( 24 : "Polycrystal circles generated from a vector input or read from a file"); 25 48 : params.addParam<bool>("read_from_file", 26 48 : false, 27 : "Set to true to read the position and radius " 28 : "vectors from a file rather than inputing them " 29 : "manually"); 30 48 : params.addParam<bool>( 31 48 : "columnar_3D", false, "3D microstructure will be columnar in the z-direction?"); 32 48 : params.addParam<std::vector<Real>>("x_positions", "x coordinate for each circle center"); 33 48 : params.addParam<std::vector<Real>>("y_positions", "y coordinate for each circle center"); 34 48 : params.addParam<std::vector<Real>>("z_positions", "z coordinate for each circle center"); 35 48 : params.addParam<std::vector<Real>>("radii", "The radius for each circle"); 36 48 : params.addParam<FileName>("file_name", "File containing circle centers and radii"); 37 48 : params.addParam<Real>("int_width", 0.0, "Width of diffuse interface"); 38 : 39 24 : return params; 40 0 : } 41 : 42 12 : PolycrystalCircles::PolycrystalCircles(const InputParameters & parameters) 43 : : PolycrystalUserObjectBase(parameters), 44 12 : _columnar_3D(getParam<bool>("columnar_3D")), 45 24 : _int_width(getParam<Real>("int_width")), 46 24 : _grain_num(0) 47 : { 48 12 : } 49 : 50 : void 51 1274834 : PolycrystalCircles::getGrainsBasedOnPoint(const Point & point, 52 : std::vector<unsigned int> & grains) const 53 : { 54 1274834 : unsigned int n_grains = _centerpoints.size(); 55 1274834 : grains.resize(0); 56 : 57 11473506 : for (unsigned int i = 0; i < n_grains; ++i) 58 : { 59 : Real distance = 0; 60 : 61 10198672 : if (_columnar_3D) 62 : { 63 0 : Real d_x = (point(0) - _centerpoints[i](0)) * (point(0) - _centerpoints[i](0)); 64 0 : Real d_y = (point(1) - _centerpoints[i](1)) * (point(1) - _centerpoints[i](1)); 65 0 : distance = std::sqrt(d_x + d_y); 66 : } 67 : else 68 10198672 : distance = _mesh.minPeriodicDistance(_vars[0]->number(), _centerpoints[i], point); 69 : 70 10198672 : if (distance < _radii[i] + _int_width) 71 1233781 : grains.push_back(i); 72 : } 73 1274834 : } 74 : 75 : Real 76 1224056 : PolycrystalCircles::getVariableValue(unsigned int op_index, const Point & p) const 77 : { 78 : std::vector<unsigned int> grain_ids; 79 1224056 : getGrainsBasedOnPoint(p, grain_ids); 80 : 81 1224056 : unsigned int active_grain_on_op = invalid_id; 82 2159693 : for (auto grain_id : grain_ids) 83 1143179 : if (op_index == _grain_to_op.at(grain_id)) 84 : { 85 207542 : active_grain_on_op = grain_id; 86 207542 : break; 87 : } 88 : 89 2448112 : return active_grain_on_op != invalid_id ? computeDiffuseInterface(p, active_grain_on_op) : 0.0; 90 1224056 : } 91 : 92 : void 93 12 : PolycrystalCircles::precomputeGrainStructure() 94 : { 95 24 : bool readfromfile = getParam<bool>("read_from_file"); 96 12 : if (readfromfile) 97 : { 98 : // Read file 99 8 : const FileName file_name = getParam<FileName>("file_name"); 100 8 : MooseUtils::DelimitedFileReader txt_reader(file_name, &_communicator); 101 : 102 8 : txt_reader.read(); 103 8 : std::vector<std::string> col_names = txt_reader.getNames(); 104 8 : std::vector<std::vector<Real>> data = txt_reader.getData(); 105 8 : _grain_num = data[0].size(); 106 8 : _centerpoints.resize(_grain_num); 107 : 108 : std::array<int, 4> col_map = {{-1, -1, -1, -1}}; 109 : 110 40 : for (unsigned int i = 0; i < col_names.size(); ++i) 111 : { 112 : // Check vector lengths 113 32 : if (data[i].size() != _grain_num) 114 0 : mooseError("Columns in ", file_name, " do not have uniform lengths."); 115 : 116 : // Map columns to variables 117 32 : if (col_names[i] == "x") 118 8 : col_map[X] = i; 119 24 : else if (col_names[i] == "y") 120 8 : col_map[Y] = i; 121 16 : else if (col_names[i] == "z") 122 8 : col_map[Z] = i; 123 8 : else if (col_names[i] == "r") 124 8 : col_map[R] = i; 125 : } 126 : 127 : // Check all columns are included 128 8 : if (col_map[X] == -1) 129 0 : mooseError("No column 'x' in ", file_name, "."); 130 8 : if (col_map[Y] == -1) 131 0 : mooseError("No column 'y' in ", file_name, "."); 132 8 : if (col_map[Z] == -1) 133 0 : mooseError("No column 'z' in ", file_name, "."); 134 8 : if (col_map[R] == -1) 135 0 : mooseError("No column 'r' in ", file_name, "."); 136 : 137 : // Write data to variables 138 8 : _radii.assign(data[col_map[R]].begin(), data[col_map[R]].end()); 139 72 : for (unsigned int i = 0; i < _grain_num; ++i) 140 : { 141 64 : _centerpoints[i](0) = data[col_map[X]][i]; 142 64 : _centerpoints[i](1) = data[col_map[Y]][i]; 143 64 : _centerpoints[i](2) = data[col_map[Z]][i]; 144 : } 145 8 : } 146 : else // if (readfromfile) 147 : { 148 : // Read vectors 149 8 : std::vector<Real> x_c = getParam<std::vector<Real>>("x_positions"); 150 8 : std::vector<Real> y_c = getParam<std::vector<Real>>("y_positions"); 151 8 : std::vector<Real> z_c = getParam<std::vector<Real>>("z_positions"); 152 12 : std::vector<Real> r_c = getParam<std::vector<Real>>("radii"); 153 : 154 4 : _grain_num = r_c.size(); 155 4 : _centerpoints.resize(_grain_num); 156 : 157 : // Check vector lengths 158 4 : if (_grain_num != x_c.size()) 159 0 : mooseError("The vector length of x_positions does not match the length of radii"); 160 4 : else if (_grain_num != y_c.size()) 161 0 : mooseError("The vector length of y_positions does not match the length of radii"); 162 4 : else if (_grain_num != z_c.size()) 163 0 : mooseError("The vector length of z_positions does not match the length of radii"); 164 : 165 : // Assign values 166 4 : _radii.assign(r_c.begin(), r_c.end()); 167 36 : for (unsigned int i = 0; i < _grain_num; ++i) 168 : { 169 32 : _centerpoints[i](0) = x_c[i]; 170 32 : _centerpoints[i](1) = y_c[i]; 171 32 : _centerpoints[i](2) = z_c[i]; 172 : } 173 4 : } 174 12 : } 175 : 176 : Real 177 207542 : PolycrystalCircles::computeDiffuseInterface(const Point & p, const unsigned int & i) const 178 : { 179 207542 : if (_int_width == 0) 180 : return 1.0; 181 : 182 : Real d = 0; 183 : 184 207542 : if (_columnar_3D) 185 : { 186 0 : Real d_x = (p(0) - _centerpoints[i](0)) * (p(0) - _centerpoints[i](0)); 187 0 : Real d_y = (p(1) - _centerpoints[i](1)) * (p(1) - _centerpoints[i](1)); 188 0 : d = std::sqrt(d_x + d_y); 189 : } 190 : else 191 207542 : d = _mesh.minPeriodicDistance(_vars[0]->number(), _centerpoints[i], p); 192 : 193 207542 : return 0.5 * (1 - std::tanh(2.0 * (d - _radii[i]) / _int_width)); 194 : }