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:2208
void mooseInfo(Args &&... args) const
Definition: MooseBase.h:317
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:2199
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.
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 ...
Definition: MooseBase.h:435
static InputParameters validParams()
void setDocString(const std::string &name, const std::string &doc)
Set the doc string of a parameter.
PropertyReadFile(const InputParameters &parameters)
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:127
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:159
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 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)
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:3448
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 read()
Perform the actual data reading.
const ExecFlagType EXEC_LINEAR
Definition: Moose.C:31
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:3075
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:33
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...
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
Definition: MooseBase.h:295
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:267
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 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 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 isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:195
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:46
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:3081
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:30