OGS
generateStructuredMesh.cpp
Go to the documentation of this file.
1 
10 #include <tclap/CmdLine.h>
11 
12 #include <algorithm>
13 #include <memory>
14 #include <string>
15 #include <vector>
16 
17 #include "BaseLib/Error.h"
18 #include "BaseLib/Subdivision.h"
20 #include "InfoLib/GitInfo.h"
23 #include "MeshLib/Mesh.h"
24 #include "MeshLib/MeshEnums.h"
26 #include "MeshLib/Node.h"
27 
28 namespace
29 {
33 {
34  switch (eleType)
35  {
37  return 1;
40  return 2;
45  return 3;
48  return 0;
49  }
50  return 0;
51 }
52 
53 } // end namespace
54 
55 int main(int argc, char* argv[])
56 {
57  TCLAP::CmdLine cmd(
58  "Structured mesh generator.\n"
59  "The documentation is available at "
60  "https://docs.opengeosys.org/docs/tools/meshing/"
61  "structured-mesh-generation.\n\n"
62  "OpenGeoSys-6 software, version " +
64  ".\n"
65  "Copyright (c) 2012-2021, OpenGeoSys Community "
66  "(http://www.opengeosys.org)",
68 
69  auto tclapOutput = std::make_unique<BaseLib::TCLAPCustomOutput>();
70  cmd.setOutput(tclapOutput.get());
71 
72  std::vector<std::string> allowed_ele_types;
73  allowed_ele_types.emplace_back("line");
74  allowed_ele_types.emplace_back("tri");
75  allowed_ele_types.emplace_back("quad");
76  allowed_ele_types.emplace_back("hex");
77  allowed_ele_types.emplace_back("prism");
78  allowed_ele_types.emplace_back("tet");
79  allowed_ele_types.emplace_back("pyramid");
80  TCLAP::ValuesConstraint<std::string> allowedVals(allowed_ele_types);
81  TCLAP::ValueArg<std::string> eleTypeArg(
82  "e", "element-type",
83  "element type to be created: line | tri | quad | hex | prism | tet | "
84  "pyramid",
85  true, "line", &allowedVals);
86  cmd.add(eleTypeArg);
87  TCLAP::ValueArg<std::string> mesh_out(
88  "o", "mesh-output-file",
89  "the name of the file the mesh will be written to", true, "",
90  "file name of output mesh");
91  cmd.add(mesh_out);
92  TCLAP::ValueArg<double> lengthXArg(
93  "", "lx", "length of a domain in x direction", false, 10.0, "real");
94  cmd.add(lengthXArg);
95  TCLAP::ValueArg<double> lengthYArg(
96  "", "ly", "length of a domain in y direction", false, 10.0, "real");
97  cmd.add(lengthYArg);
98  TCLAP::ValueArg<double> lengthZArg(
99  "", "lz", "length of a domain in z direction", false, 10.0, "real");
100  cmd.add(lengthZArg);
101  TCLAP::ValueArg<unsigned> nsubdivXArg(
102  "", "nx", "the number of subdivision in x direction", false, 10,
103  "integer");
104  cmd.add(nsubdivXArg);
105  TCLAP::ValueArg<unsigned> nsubdivYArg(
106  "", "ny", "the number of subdivision in y direction", false, 10,
107  "integer");
108  cmd.add(nsubdivYArg);
109  TCLAP::ValueArg<unsigned> nsubdivZArg(
110  "", "nz", "the number of subdivision in z direction", false, 10,
111  "integer");
112  cmd.add(nsubdivZArg);
113  // in case of gradual refinement
114  TCLAP::ValueArg<double> d0XArg(
115  "", "dx0", "initial cell length in x direction", false, 1, "real");
116  cmd.add(d0XArg);
117  TCLAP::ValueArg<double> d0YArg(
118  "", "dy0", "initial cell length in y direction", false, 1, "real");
119  cmd.add(d0YArg);
120  TCLAP::ValueArg<double> d0ZArg(
121  "", "dz0", "initial cell length in z direction", false, 1, "real");
122  cmd.add(d0ZArg);
123  TCLAP::ValueArg<double> dmaxXArg(
124  "", "dx-max", "maximum cell length in x direction", false,
125  std::numeric_limits<double>::max(), "real");
126  cmd.add(dmaxXArg);
127  TCLAP::ValueArg<double> dmaxYArg(
128  "", "dy-max", "maximum cell length in y direction", false,
129  std::numeric_limits<double>::max(), "real");
130  cmd.add(dmaxYArg);
131  TCLAP::ValueArg<double> dmaxZArg(
132  "", "dz-max", "maximum cell length in z direction", false,
133  std::numeric_limits<double>::max(), "real");
134  cmd.add(dmaxZArg);
135  TCLAP::ValueArg<double> multiXArg("", "mx", "multiplier in x direction",
136  false, 1, "real");
137  cmd.add(multiXArg);
138  TCLAP::ValueArg<double> multiYArg("", "my", "multiplier in y direction",
139  false, 1, "real");
140  cmd.add(multiYArg);
141  TCLAP::ValueArg<double> multiZArg("", "mz", "multiplier in z direction",
142  false, 1, "real");
143  cmd.add(multiZArg);
144 
145  // parse arguments
146  cmd.parse(argc, argv);
147  const std::string eleTypeName(eleTypeArg.getValue());
148  const MeshLib::MeshElemType eleType =
149  MeshLib::String2MeshElemType(eleTypeName);
150  const unsigned dim = getDimension(eleType);
151 
152  bool dim_used[3] = {false};
153  for (unsigned i = 0; i < dim; i++)
154  {
155  dim_used[i] = true;
156  }
157 
158  std::vector<TCLAP::ValueArg<double>*> vec_lengthArg = {
159  &lengthXArg, &lengthYArg, &lengthZArg};
160  std::vector<TCLAP::ValueArg<unsigned>*> vec_ndivArg = {
161  &nsubdivXArg, &nsubdivYArg, &nsubdivZArg};
162  std::vector<TCLAP::ValueArg<double>*> vec_d0Arg = {&d0XArg, &d0YArg,
163  &d0ZArg};
164  std::vector<TCLAP::ValueArg<double>*> vec_dMaxArg = {&dmaxXArg, &dmaxYArg,
165  &dmaxZArg};
166  std::vector<TCLAP::ValueArg<double>*> vec_multiArg = {
167  &multiXArg, &multiYArg, &multiZArg};
168 
169  const bool isLengthSet =
170  std::any_of(vec_lengthArg.begin(), vec_lengthArg.end(),
171  [&](TCLAP::ValueArg<double>* arg) { return arg->isSet(); });
172  if (!isLengthSet)
173  {
174  ERR("Missing input: Length information is not provided at all.");
175  return EXIT_FAILURE;
176  }
177  for (unsigned i = 0; i < 3; i++)
178  {
179  if (dim_used[i] && !vec_lengthArg[i]->isSet())
180  {
181  ERR("Missing input: Length for dimension [{:d}] is required but "
182  "missing.",
183  i);
184  return EXIT_FAILURE;
185  }
186  }
187 
188  std::vector<double> length(dim);
189  std::vector<unsigned> n_subdivision(dim);
190  std::vector<double> vec_dx(dim);
191  for (unsigned i = 0; i < dim; i++)
192  {
193  length[i] = vec_lengthArg[i]->getValue();
194  n_subdivision[i] = vec_ndivArg[i]->getValue();
195  vec_dx[i] = length[i] / n_subdivision[i];
196  }
197 
198  std::vector<std::unique_ptr<BaseLib::ISubdivision>> vec_div;
199  vec_div.reserve(dim);
200  for (unsigned i = 0; i < dim; i++)
201  {
202  if (vec_multiArg[i]->isSet())
203  {
204  if (vec_ndivArg[i]->isSet())
205  {
206  // number of partitions in direction is specified
207  if (vec_d0Arg[i]->isSet())
208  {
209  OGS_FATAL(
210  "Specifying all of --m?, --d?0 and --n? for coordinate "
211  "'?' is not supported.");
212  }
213  vec_div.emplace_back(new BaseLib::GradualSubdivisionFixedNum(
214  length[i], vec_ndivArg[i]->getValue(),
215  vec_multiArg[i]->getValue()));
216  }
217  else
218  {
219  vec_div.emplace_back(new BaseLib::GradualSubdivision(
220  length[i], vec_d0Arg[i]->getValue(),
221  vec_dMaxArg[i]->getValue(), vec_multiArg[i]->getValue()));
222  }
223  }
224  else
225  {
226  vec_div.emplace_back(
227  new BaseLib::UniformSubdivision(length[i], n_subdivision[i]));
228  }
229  }
230 
231  // generate a mesh
232  std::unique_ptr<MeshLib::Mesh> mesh;
233  switch (eleType)
234  {
236  mesh.reset(MeshLib::MeshGenerator::generateLineMesh(*vec_div[0]));
237  break;
240  *vec_div[0], *vec_div[1]));
241  break;
244  *vec_div[0], *vec_div[1]));
245  break;
248  *vec_div[0], *vec_div[1], *vec_div[2]));
249  break;
252  length[0], length[1], length[2], n_subdivision[0],
253  n_subdivision[1], n_subdivision[2]));
254  break;
257  *vec_div[0], *vec_div[1], *vec_div[2]));
258  break;
261  *vec_div[0], *vec_div[1], *vec_div[2]));
262  break;
263  default:
264  ERR("Given element type is not supported.");
265  break;
266  }
267 
268  if (mesh)
269  {
270  INFO("Mesh created: {:d} nodes, {:d} elements.",
271  mesh->getNumberOfNodes(), mesh->getNumberOfElements());
272 
273  // write into a file
275  *(mesh.get()), std::filesystem::path(mesh_out.getValue()));
276  }
277 
278  return EXIT_SUCCESS;
279 }
Definition of the Element class.
#define OGS_FATAL(...)
Definition: Error.h:26
Git information.
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
Definition of mesh-related Enumerations.
Definition of the Mesh class.
Definition of the Node class.
std::string getValue(std::string const &line, std::string const &val_name, bool is_string)
int main(int argc, char *argv[])
GITINFOLIB_EXPORT const std::string ogs_version
int writeMeshToFile(const MeshLib::Mesh &mesh, std::filesystem::path const &file_path, [[maybe_unused]] std::set< std::string > variable_output_names)
Mesh * generateRegularPrismMesh(const double x_length, const double y_length, const double z_length, const std::size_t x_subdivision, const std::size_t y_subdivision, const std::size_t z_subdivision, MathLib::Point3d const &origin=MathLib::ORIGIN, std::string const &mesh_name="mesh")
Mesh * generateLineMesh(const BaseLib::ISubdivision &div, MathLib::Point3d const &origin=MathLib::ORIGIN, std::string const &mesh_name="mesh")
Mesh * generateRegularTriMesh(const BaseLib::ISubdivision &div_x, const BaseLib::ISubdivision &div_y, MathLib::Point3d const &origin=MathLib::ORIGIN, std::string const &mesh_name="mesh")
Mesh * generateRegularQuadMesh(const BaseLib::ISubdivision &div_x, const BaseLib::ISubdivision &div_y, MathLib::Point3d const &origin=MathLib::ORIGIN, std::string const &mesh_name="mesh")
Mesh * generateRegularPyramidMesh(const BaseLib::ISubdivision &div_x, const BaseLib::ISubdivision &div_y, const BaseLib::ISubdivision &div_z, MathLib::Point3d const &origin=MathLib::ORIGIN, std::string const &mesh_name="mesh")
Mesh * generateRegularTetMesh(const BaseLib::ISubdivision &div_x, const BaseLib::ISubdivision &div_y, const BaseLib::ISubdivision &div_z, MathLib::Point3d const &origin=MathLib::ORIGIN, std::string const &mesh_name="mesh")
Mesh * generateRegularHexMesh(const BaseLib::ISubdivision &div_x, const BaseLib::ISubdivision &div_y, const BaseLib::ISubdivision &div_z, MathLib::Point3d const &origin=MathLib::ORIGIN, std::string const &mesh_name="mesh")
MeshElemType String2MeshElemType(const std::string &s)
Given a string of the shortened name of the element type, this returns the corresponding MeshElemType...
Definition: MeshEnums.cpp:95
MeshElemType
Types of mesh elements supported by OpenGeoSys. Values are from VTKCellType enum.
Definition: MeshEnums.h:27
unsigned getDimension(MeshLib::MeshElemType eleType)