https://mooseframework.inl.gov
PropertyReadFile.C
Go to the documentation of this file.
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 "PropertyReadFile.h"
11 #include "MooseRandom.h"
12 #include "MooseMesh.h"
13 
14 #include <fstream>
15 
19  "06/30/2021 24:00",
21 
24 {
26  params.addClassDescription("User Object to read property data from an external file and assign "
27  "it to elements / nodes / subdomains etc.");
28 
29  // Data source file(s)
30  params.addParam<std::vector<FileName>>(
31  "prop_file_name",
32  "Name(s) of the property file name. If specifying multiple files, the next file will be read "
33  "at initialization right before every execution");
34  params.addParam<FileName>("prop_file_names_csv",
35  "Name(s) of a CSV file containing the list of the property file names "
36  "as its first column, with no header.");
37 
38  // Data organization
39  params.addRequiredParam<unsigned int>("nprop", "Number of tabulated property values");
40  params.addParam<unsigned int>(
41  "nvoronoi", 0, "Number of voronoi tesselations/grains/nearest neighbor regions");
42  params.addDeprecatedParam<unsigned int>(
43  "ngrain", "Number of grains.", "ngrain is deprecated, use nvoronoi instead");
44  params.addParam<unsigned int>("nblock", 0, "Number of blocks");
45  params.addRequiredParam<MooseEnum>("read_type",
46  MooseEnum("element voronoi block node grain"),
47  "Type of property distribution: "
48  "element:by element "
49  "node: by node "
50  "voronoi:nearest neighbor / voronoi grain structure "
51  "block:by mesh block "
52  "grain: deprecated, use voronoi");
53  params.addParam<bool>("use_random_voronoi",
54  false,
55  "Wether to generate random positions for the Voronoi tesselation");
56  params.addParam<unsigned int>("rand_seed", 2000, "random seed");
57  params.addParam<MooseEnum>(
58  "rve_type",
59  MooseEnum("periodic none", "none"),
60  "Periodic or non-periodic grain distribution: Default is non-periodic");
61  params.addParam<bool>(
62  "use_zero_based_block_indexing", true, "Are the blocks numbered starting at zero?");
63 
64  // Data reading schedule
65  params.addParam<bool>(
66  "load_first_file_on_construction",
67  true,
68  "Whether to read the first CSV file on construction or on the first execution");
69 
70  // Set an execution schedule to what makes sense currently
71  // We do not allow INITIAL because we read the file at construction
72  ExecFlagEnum & exec_enum = params.set<ExecFlagEnum>("execute_on", true);
74  params.setDocString("execute_on", exec_enum.getDocString());
75  // we must read the files as early as possible
76  params.set<bool>("force_preaux") = true;
77 
78  return params;
79 }
80 
82  : GeneralUserObject(parameters),
83  _prop_file_names(getFileNames()),
84  _current_file_index(declareRestartableData<unsigned int>("file_index", 0)),
85  // index of files must be capped if restarting after having read all files
86  _reader(
87  _prop_file_names[std::min(_current_file_index, (unsigned int)_prop_file_names.size() - 1)]),
88  _read_type(getParam<MooseEnum>("read_type").getEnum<ReadTypeEnum>()),
89  _use_random_tesselation(getParam<bool>("use_random_voronoi")),
90  _rand_seed(getParam<unsigned int>("rand_seed")),
91  _rve_type(getParam<MooseEnum>("rve_type")),
92  _block_zero(getParam<bool>("use_zero_based_block_indexing")),
93  _ngrain(isParamValid("ngrain") ? getParam<unsigned int>("ngrain")
94  : getParam<unsigned int>("nvoronoi")),
95  _mesh(_fe_problem.mesh()),
96  _nprop(getParam<unsigned int>("nprop")),
97  _nvoronoi(isParamValid("ngrain") ? getParam<unsigned int>("ngrain")
98  : getParam<unsigned int>("nvoronoi")),
99  _nblock(getParam<unsigned int>("nblock")),
100  _initialize_called_once(declareRestartableData<bool>("initialize_called", false)),
101  _load_on_construction(getParam<bool>("load_first_file_on_construction"))
102 {
104  paramError("rand_seed",
105  "Random seeds should only be provided if random tesselation is desired");
106 
107  Point mesh_min, mesh_max;
108  for (unsigned int i : make_range(Moose::dim))
109  {
110  mesh_min(i) = _mesh.getMinInDimension(i);
111  mesh_max(i) = _mesh.getMaxInDimension(i);
112  }
113  _bounding_box = MooseUtils::buildBoundingBox(mesh_min, mesh_max);
114 
116  readData();
117 }
118 
119 std::vector<FileName>
121 {
122  std::vector<FileName> prop_file_names;
123  // Retrieve the property file names
124  if (isParamValid("prop_file_name") && !isParamValid("prop_file_names_csv"))
125  prop_file_names = getParam<std::vector<FileName>>("prop_file_name");
126  else if (isParamValid("prop_file_names_csv") && !isParamValid("prop_file_name"))
127  {
129  getParam<FileName>("prop_file_names_csv"));
131  file_name_reader.read();
132  if (file_name_reader.getData().size())
133  {
134  const auto fdata = file_name_reader.getData(0);
135  for (const auto & fname : fdata)
136  prop_file_names.push_back(fname);
137  }
138  }
139  else
140  paramError("prop_file_name",
141  "The names of the property files must be provided with either 'prop_file_name' "
142  "or 'prop_file_names_csv'. Providing both or none is not supported.");
143  if (prop_file_names.empty())
144  paramError("prop_file_name", "A property file should have been specified.");
145  return prop_file_names;
146 }
147 
148 void
150 {
151  // Since we read at construction, no need to re-read the file on first initialize
153  {
155  return;
156  }
157 
158  // Set then read new file, only if we have not reached the last file
160  {
162  readData();
163  }
164  else if (_prop_file_names.size() > 1 && _current_file_index == _prop_file_names.size())
165  mooseInfo("Last file specified has been read. The file will no longer be updated.");
166 }
167 
168 void
170 {
171  if (_read_type == ReadTypeEnum::ELEMENT && _mesh.getMesh().allow_renumbering())
172  mooseWarning("CSV data is sorted by element, but mesh element renumbering is on, be careful!");
173  if (_read_type == ReadTypeEnum::NODE && _mesh.getMesh().allow_renumbering())
174  mooseWarning("CSV data is sorted by node, but mesh node renumbering is on, be careful!");
175 
177  _reader.read();
178 
179  unsigned int nobjects = 0;
180 
181  switch (_read_type)
182  {
184  nobjects = _mesh.nElem();
185  break;
186 
187  case ReadTypeEnum::NODE:
188  nobjects = _mesh.nNodes();
189  break;
190 
192  if (_nvoronoi <= 0)
193  paramError("nvoronoi", "Provide non-zero number of voronoi tesselations/grains.");
194  nobjects = _nvoronoi;
195  break;
196 
197  // TODO Delete after Grizzly update see idaholab/Grizzly#182
198  case ReadTypeEnum::GRAIN:
199  if (_nvoronoi <= 0)
200  paramError("ngrain", "Provide non-zero number of voronoi tesselations/grains.");
201  nobjects = _nvoronoi;
202  break;
203 
204  case ReadTypeEnum::BLOCK:
205  if (_nblock <= 0)
206  paramError("nblock", "Provide non-zero number of blocks.");
207  nobjects = _nblock;
208  break;
209  }
210 
211  // make sure the data from file has enough rows and columns
212  if (_reader.getData().size() < nobjects)
213  mooseError("Data in ",
215  " does not have enough rows for ",
216  nobjects,
217  " objects.");
218  if (_reader.getData().size() > nobjects)
219  mooseWarning("Data size in ",
221  " is larger than ",
222  nobjects,
223  " objects, some data will not be used.");
224  for (unsigned int i = 0; i < nobjects; i++)
225  if (_reader.getData(i).size() < _nprop)
226  mooseError("Row ",
227  i,
228  " in ",
230  " has number of data less than ",
231  _nprop);
232 
235 
237 }
238 
239 void
241 {
242  _center.resize(_nvoronoi);
243 
244  // Generate a random tesselation
246  {
248  for (const auto i : make_range(_nvoronoi))
249  for (const auto j : make_range(Moose::dim))
250  _center[i](j) = _bounding_box.min()(j) +
251  MooseRandom::rand() * (_bounding_box.max() - _bounding_box.min())(j);
252  }
253  // Read tesselation from file
254  else
255  {
256  for (const auto i : make_range(_nvoronoi))
257  for (const auto j : make_range(Moose::dim))
258  _center[i](j) = _reader.getData(i)[j];
259  }
260 }
261 
262 Real
263 PropertyReadFile::getData(const Elem * const elem, const unsigned int prop_num) const
264 {
265  if (prop_num > _nprop)
266  paramError(
267  "nprop", "Property number ", prop_num, " greater than total number of properties ", _nprop);
268 
269  Real data = 0.0;
270  switch (_read_type)
271  {
273  data = getElementData(elem, prop_num);
274  break;
275 
277  data = getVoronoiData(elem->vertex_average(), prop_num);
278  break;
279 
280  // TODO: Delete after Grizzly update
281  case ReadTypeEnum::GRAIN:
282  data = getVoronoiData(elem->vertex_average(), prop_num);
283  break;
284 
285  case ReadTypeEnum::BLOCK:
286  data = getBlockData(elem, prop_num);
287  break;
288 
289  case ReadTypeEnum::NODE:
290  mooseError(
291  "PropertyReadFile has data sorted by node, it should note be retrieved by element");
292  break;
293  }
294  return data;
295 }
296 
297 Real
298 PropertyReadFile::getElementData(const Elem * elem, unsigned int prop_num) const
299 {
300  unsigned int jelem = elem->id();
301  if (jelem >= _mesh.nElem())
302  mooseError("Element ID ",
303  jelem,
304  " greater than than total number of element in mesh: ",
305  _mesh.nElem(),
306  ". Elements should be numbered consecutively, and ids should start from 0.");
307  return _reader.getData(jelem)[prop_num];
308 }
309 
310 Real
311 PropertyReadFile::getNodeData(const Node * const node, const unsigned int prop_num) const
312 {
313  unsigned int jnode = node->id();
314  if (jnode >= _mesh.nNodes())
315  mooseError("Node ID ",
316  jnode,
317  " greater than than total number of nodes in mesh: ",
318  _mesh.nNodes(),
319  ". Nodes should be numbered consecutively, with ids starting from 0.");
320  return _reader.getData(jnode)[prop_num];
321 }
322 
323 Real
324 PropertyReadFile::getBlockData(const Elem * elem, unsigned int prop_num) const
325 {
326  unsigned int offset = 0;
327  if (!_block_zero)
328  offset = 1;
329 
330  unsigned int elem_subdomain_id = elem->subdomain_id();
331  if (elem_subdomain_id >= _nblock + offset)
332  paramError("nblock",
333  "Element block id ",
334  elem_subdomain_id,
335  " greater than than total number of blocks in mesh: ",
336  _nblock,
337  ". Blocks should be numbered consecutively, starting from 0.");
338  return _reader.getData(elem_subdomain_id - offset)[prop_num];
339 }
340 
341 Real
342 PropertyReadFile::getVoronoiData(const Point & point, const unsigned int prop_num) const
343 {
345  unsigned int ivoronoi = 0;
346 
347  for (const auto i : make_range(_nvoronoi))
348  {
349  Real dist = 0.0;
350  switch (_rve_type)
351  {
352  case 0:
353  // Calculates minimum periodic distance when "periodic" is specified
354  // for rve_type
355  dist = minPeriodicDistance(_center[i], point);
356  break;
357 
358  default:
359  // Calculates minimum distance when nothing is specified
360  // for rve_type
361  Point dist_vec = _center[i] - point;
362  dist = dist_vec.norm();
363  }
364 
365  if (dist < min_dist)
366  {
367  min_dist = dist;
368  ivoronoi = i;
369  }
370  }
371  return _reader.getData(ivoronoi)[prop_num];
372 }
373 
374 // TODO: this should probably use the built-in min periodic distance!
375 Real
376 PropertyReadFile::minPeriodicDistance(const Point & c, const Point & p) const
377 {
378  Point dist_vec = c - p;
379  Real min_dist = dist_vec.norm();
380 
381  Real fac[3] = {-1.0, 0.0, 1.0};
382  for (unsigned int i = 0; i < 3; i++)
383  for (unsigned int j = 0; j < 3; j++)
384  for (unsigned int k = 0; k < 3; k++)
385  {
386  Point p1;
387  p1(0) = p(0) + fac[i] * (_bounding_box.max() - _bounding_box.min())(0);
388  p1(1) = p(1) + fac[j] * (_bounding_box.max() - _bounding_box.min())(1);
389  p1(2) = p(2) + fac[k] * (_bounding_box.max() - _bounding_box.min())(2);
390 
391  dist_vec = c - p1;
392  Real dist = dist_vec.norm();
393 
394  if (dist < min_dist)
395  min_dist = dist;
396  }
397 
398  return min_dist;
399 }
void readData()
This function reads the data from file.
virtual Real getMaxInDimension(unsigned int component) const
Definition: MooseMesh.C:2203
BoundingBox _bounding_box
Bounding box for the mesh.
virtual Real getMinInDimension(unsigned int component) const
Returns the min or max of the requested dimension respectively.
Definition: MooseMesh.C:2194
Real getVoronoiData(const Point &point, const unsigned int prop_num) const
This function retrieves properties for elements from a file with nearest neighbor / grain based prope...
A MultiMooseEnum object to hold "execute_on" flags.
Definition: ExecFlagEnum.h:21
bool & _initialize_called_once
To keep track of initialization to avoid reading the files twice.
Real getBlockData(const Elem *const elem, const unsigned int prop_num) const
This function retrieves properties for elements, from a file that has block-based data...
std::vector< FileName > _prop_file_names
Name of file containing property values.
std::vector< Point > _center
unsigned int & _current_file_index
Index of the file we last read.
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
const ReadTypeEnum _read_type
Type of read - element, grain, or block.
static InputParameters validParams()
void setDocString(const std::string &name, const std::string &doc)
Set the doc string of a parameter.
PropertyReadFile(const InputParameters &parameters)
void mooseInfo(Args &&... args) const
registerMooseObjectRenamed("MooseApp", ElementPropertyReadFile, "06/30/2021 24:00", PropertyReadFile)
Read properties from file - grain, element, node or block Input file syntax: prop1 prop2 etc...
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
const MooseEnum _rve_type
Type of voronoi tesselation/grain structure - non-periodic default.
MeshBase & mesh
MooseUtils::DelimitedFileReader _reader
Use DelimitedFileReader to read and store data from file.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
Real getNodeData(const Node *const node, const unsigned int prop_num) const
This function retrieves properties for nodes, from a file that has node-based data.
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:154
static InputParameters validParams()
Real getData(const Elem *const elem, const unsigned int prop_num) const
This function retrieves property data for elements.
Real minPeriodicDistance(const Point &, const Point &) const
This function calculates minimum distance between 2 points considering periodicity of the simulation ...
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
auto max(const L &left, const R &right)
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
const unsigned int _rand_seed
Random seed - used for generating grain centers.
const unsigned int _nvoronoi
Number of grains (for reading a CSV file with properties ordered by grains)
void setFileName(const std::string &new_file)
Set the file name, used to change the file to read from We also reset the column/row names as a secon...
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3443
ReadTypeEnum
How data is organized in the CSV file.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
void read()
Perform the actual data reading.
const ExecFlagType EXEC_LINEAR
Definition: Moose.C:29
const std::vector< std::vector< T > > & getData() const
Return the rows/columns of data.
virtual dof_id_type nNodes() const
Calls n_nodes/elem() on the underlying libMesh mesh object.
Definition: MooseMesh.C:3070
const bool _load_on_construction
Whether to read the first CSV file in the constructor or on the first initialization before execution...
const ExecFlagType EXEC_NONLINEAR
Definition: Moose.C:31
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was set by the user.
const unsigned int _nblock
Number of blocks (for reading a CSV file with properties ordered by blocks)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Utility class for reading delimited data (e.g., CSV data).
static void seed(unsigned int seed)
The method seeds the random number generator.
Definition: MooseRandom.h:44
const bool _use_random_tesselation
Parameters for the nearest neighbor / grain interpolation Whether to use a random tesselation for the...
IntRange< T > make_range(T beg, T end)
static Real rand()
This method returns the next random number (Real format) from the generator.
Definition: MooseRandom.h:50
void removeAvailableFlags(const ExecFlagType &flag, Args... flags)
Remove flags from being available.
Definition: ExecFlagEnum.h:90
libMesh::BoundingBox buildBoundingBox(const Point &p1, const Point &p2)
Construct a valid bounding box from 2 arbitrary points.
Definition: MooseUtils.C:1237
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
const InputParameters & parameters() const
Get the parameters of the object.
const unsigned int _nprop
Class attributes useful for range-checking Number of properties in a row.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
virtual void initVoronoiCenterPoints()
This function generates voronoi tesselation center points Presently random generated.
bool _block_zero
Do the block numbers start with zero or one?
registerMooseObject("MooseApp", PropertyReadFile)
auto min(const L &left, const R &right)
std::vector< FileName > getFileNames()
Retrieve the property file names from the parameters.
const ExecFlagType EXEC_FINAL
Definition: Moose.C:44
void ErrorVector unsigned int
virtual void initialize()
Called before execute() is ever called so that data can be cleared.
virtual dof_id_type nElem() const
Definition: MooseMesh.C:3076
Real getElementData(const Elem *const elem, const unsigned int prop_num) const
This function retrieves properties for elements, from a file that has element-based data...
const ExecFlagType EXEC_INITIAL
Definition: Moose.C:28