https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
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
39 params.addParam<processor_id_type>(
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
55std::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
110void
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
190std::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}
registerMooseObject("PhaseFieldApp", EBSDMeshGenerator)
unsigned int dim
void ErrorVector unsigned int
Mesh generated from parameters read from a DREAM3D EBSD file.
const bool _distributed
are we working on a distributed mesh?
Geometry _geometry
EBSD data file mesh information.
std::unique_ptr< MeshBase > generate() override
const FileName & _filename
Name of the file containing the EBSD data.
static InputParameters validParams()
std::unique_ptr< MeshBase > & buildMeshSubgenerator()
EBSDMeshGenerator(const InputParameters &parameters)
void readEBSDHeader()
Read the EBSD data file header.
std::unique_ptr< MeshBase > & _base
const unsigned int _pre_refine
InputParameters getValidParams(const std::string &name) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void addMeshSubgenerator(const std::string &type, const std::string &name, Ts... extra_input_parameters)
std::unique_ptr< MeshBase > & getMeshByName(const MeshGeneratorName &mesh_generator_name)
static InputParameters validParams()
Factory & getFactory()
const std::string & name() const
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
MooseApp & _app
void uniformly_refine(unsigned int n=1)
T pow(T x, int e)
std::array< Real, 3 > min
std::array< unsigned int, 3 > n