https://mooseframework.inl.gov
EBSDMeshGenerator.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 "EBSDMeshGenerator.h"
11 #include "MooseApp.h"
12 #include "MathUtils.h"
13 
14 #include "libmesh/int_range.h"
15 #include "libmesh/mesh_refinement.h"
16 
17 #include <fstream>
18 
19 registerMooseObject("PhaseFieldApp", EBSDMeshGenerator);
20 
23 {
25  params.addClassDescription("Mesh generated from a specified DREAM.3D EBSD data file.");
26  params.addRequiredParam<FileName>("filename", "The name of the file containing the EBSD data");
27 
28  params.addDeprecatedParam<unsigned int>("uniform_refine",
29  "Deprecated. Use `pre_refine` instead.",
30  "Deprecated. Use `pre_refine` instead.");
31  params.addParam<unsigned int>(
32  "pre_refine",
33  0,
34  "Number of coarsening levels available in adaptive mesh refinement. The resulting mesh will "
35  "have one mesh element per EBSD data cell, but will be based on a refined coarser mesh with "
36  "'pre_refine' levels of refinement. This requires all dimension of the EBSD data to be "
37  "divisible by 2^pre_refine.(this parameter was formerly called 'uniform_refine')");
38 
40  "num_cores_for_partition",
41  "Number of cores for partitioning the graph (dafaults to the number of MPI ranks)");
42  return params;
43 }
44 
46  : MeshGenerator(parameters),
47  _distributed(_mesh->isDistributedMesh()),
48  _filename(getParam<FileName>("filename")),
49  _pre_refine(isParamValid("pre_refine") ? getParam<unsigned int>("pre_refine")
50  : getParam<unsigned int>("uniform_refine")),
51  _base(buildMeshSubgenerator())
52 {
53 }
54 
55 std::unique_ptr<MeshBase> &
57 {
59 
60  const auto generator_type =
61  _distributed ? "DistributedRectilinearMeshGenerator" : "GeneratedMeshGenerator";
62  auto params = _app.getFactory().getValidParams(generator_type);
63 
64  params.set<MooseEnum>("dim") = (_geometry.dim == 1 ? "1" : (_geometry.dim == 2 ? "2" : "3"));
65 
66  std::array<unsigned int, 3> nr;
67  nr[0] = _geometry.n[0];
68  nr[1] = _geometry.n[1];
69  nr[2] = _geometry.n[2];
70 
71  // set min/max box length
72  params.set<Real>("xmin") = _geometry.min[0];
73  params.set<Real>("xmax") = nr[0] * _geometry.d[0] + _geometry.min[0];
74  params.set<Real>("ymin") = _geometry.min[1];
75  params.set<Real>("ymax") = nr[1] * _geometry.d[1] + _geometry.min[1];
76  params.set<Real>("zmin") = _geometry.min[2];
77  params.set<Real>("zmax") = nr[2] * _geometry.d[2] + _geometry.min[2];
78 
79  // check if the requested uniform refine level is possible and determine initial grid size
80  for (auto i : make_range(_geometry.dim))
81  {
82  auto factor = MathUtils::pow(2, _pre_refine);
83  if (nr[i] % factor != 0)
84  paramError("pre_refine",
85  "EBSDMeshGenerator error. Requested levels of pre refinement not possible.");
86  nr[i] /= factor;
87  }
88 
89  if (_distributed)
90  {
91  params.set<dof_id_type>("nx") = nr[0];
92  params.set<dof_id_type>("ny") = nr[1];
93  params.set<dof_id_type>("nz") = nr[2];
94  params.set<processor_id_type>("num_cores_for_partition") =
95  isParamValid("num_cores_for_partition")
96  ? getParam<processor_id_type>("num_cores_for_partition")
97  : 0;
98  }
99  else
100  {
101  params.set<unsigned int>("nx") = nr[0];
102  params.set<unsigned int>("ny") = nr[1];
103  params.set<unsigned int>("nz") = nr[2];
104  }
105 
106  addMeshSubgenerator(generator_type, name() + "_base_mesh", params);
107  return getMeshByName(name() + "_base_mesh");
108 }
109 
110 void
112 {
113  std::ifstream stream_in(_filename.c_str());
114 
115  if (!stream_in)
116  paramError("filename", "Can't open EBSD file: ", _filename);
117 
118  // Labels to look for in the header
119  const std::vector<std::string> labels = {
120  "x_step", "x_dim", "y_step", "y_dim", "z_step", "z_dim", "x_min", "y_min", "z_min"};
121 
122  // Dimension variables to store once they are found in the header
123  // X_step, X_Dim, Y_step, Y_Dim, Z_step, Z_Dim
124  // We use Reals even though the Dim values should all be integers...
125  std::vector<Real> label_vals(labels.size(), 0.0);
126 
127  std::string line;
128  while (std::getline(stream_in, line))
129  {
130  // We need to process the comment lines that have:
131  // X_step, X_Dim
132  // Y_step, Y_Dim
133  // Z_step, Z_Dim
134  // in them. The labels are case insensitive.
135  if (line.find("#") == 0)
136  {
137  // Process lines that start with a comment character (comments and meta data)
138  std::transform(line.begin(), line.end(), line.begin(), ::tolower);
139 
140  for (unsigned i = 0; i < labels.size(); ++i)
141  if (line.find(labels[i]) != std::string::npos)
142  {
143  std::string dummy;
144  std::istringstream iss(line);
145  iss >> dummy >> dummy >> label_vals[i];
146 
147  // One label per line, break out of for loop over labels
148  break;
149  }
150  }
151  else
152  // first non comment line marks the end of the header
153  break;
154  }
155 
156  // Copy stuff out of the label_vars array into class variables
157  _geometry.d[0] = label_vals[0];
158  _geometry.n[0] = label_vals[1];
159  _geometry.min[0] = label_vals[6];
160 
161  _geometry.d[1] = label_vals[2];
162  _geometry.n[1] = label_vals[3];
163  _geometry.min[1] = label_vals[7];
164 
165  _geometry.d[2] = label_vals[4];
166  _geometry.n[2] = label_vals[5];
167  _geometry.min[2] = label_vals[8];
168 
169  unsigned int dim;
170 
171  // determine mesh dimension
172  for (dim = 3; dim > 0 && _geometry.n[dim - 1] == 0; --dim)
173  ;
174 
175  // check if the data has nonzero stepsizes
176  for (unsigned i = 0; i < dim; ++i)
177  {
178  if (_geometry.n[i] == 0)
179  mooseError("Error reading header, EBSD grid size is zero.");
180  if (_geometry.d[i] == 0.0)
181  mooseError("Error reading header, EBSD data step size is zero.");
182  }
183 
184  if (dim == 0)
185  mooseError("Error reading header, EBSD data is zero dimensional.");
186 
187  _geometry.dim = dim;
188 }
189 
190 std::unique_ptr<MeshBase>
192 {
193  if (_pre_refine)
194  {
195  libMesh::MeshRefinement mesh_refinement(*_base);
196  mesh_refinement.uniformly_refine(_pre_refine);
197  }
198  return std::move(_base);
199 }
std::unique_ptr< MeshBase > & getMeshByName(const MeshGeneratorName &mesh_generator_name)
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
static InputParameters validParams()
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
unsigned int dim
T & set(const std::string &name, bool quiet_mode=false)
EBSDMeshGenerator(const InputParameters &parameters)
InputParameters getValidParams(const std::string &name) const
registerMooseObject("PhaseFieldApp", EBSDMeshGenerator)
virtual const std::string & name() const
const bool _distributed
are we working on a distributed mesh?
void addRequiredParam(const std::string &name, const std::string &doc_string)
Mesh generated from parameters read from a DREAM3D EBSD file.
Factory & getFactory()
void readEBSDHeader()
Read the EBSD data file header.
const unsigned int _pre_refine
bool isParamValid(const std::string &name) const
uint8_t processor_id_type
void addMeshSubgenerator(const std::string &type, const std::string &name, Ts... extra_input_parameters)
std::array< Real, 3 > min
std::unique_ptr< MeshBase > generate() override
void paramError(const std::string &param, Args... args) const
static InputParameters validParams()
std::array< Real, 3 > d
Geometry _geometry
EBSD data file mesh information.
const FileName & _filename
Name of the file containing the EBSD data.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
MooseApp & _app
std::unique_ptr< MeshBase > & _base
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
std::array< unsigned int, 3 > n
T pow(T x, int e)
std::unique_ptr< MeshBase > & buildMeshSubgenerator()
void ErrorVector unsigned int
uint8_t dof_id_type
void uniformly_refine(unsigned int n=1)