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