59{
60 TCLAP::CmdLine cmd(
61 "Structured mesh generator.\n"
62 "The documentation is available at "
63 "https://docs.opengeosys.org/docs/tools/meshing/"
64 "structured-mesh-generation.\n\n"
65 "OpenGeoSys-6 software, version " +
67 ".\n"
68 "Copyright (c) 2012-2025, OpenGeoSys Community "
69 "(http://www.opengeosys.org)",
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("e", "element-type",
82 "element type to be created", true,
83 "line", &allowedVals);
84 cmd.add(eleTypeArg);
85 TCLAP::ValueArg<std::string> mesh_out(
86 "o", "mesh-output-file",
87 "Output (.vtu). The name of the file the mesh will be written to", true,
88 "", "OUTPUT_FILE");
89 cmd.add(mesh_out);
90 TCLAP::ValueArg<double> lengthXArg("", "lx",
91 "length of a domain in x direction, "
92 "(min = 0)",
93 false, 10.0, "LENGTH_X");
94 cmd.add(lengthXArg);
95 TCLAP::ValueArg<double> lengthYArg("", "ly",
96 "length of a domain in y direction, "
97 "(min = 0)",
98 false, 10.0, "LENGTH_Y");
99 cmd.add(lengthYArg);
100 TCLAP::ValueArg<double> lengthZArg("", "lz",
101 "length of a domain in z direction, "
102 "(min = 0)",
103 false, 10.0, "LENGTH_Z");
104 cmd.add(lengthZArg);
105 TCLAP::ValueArg<unsigned> nsubdivXArg(
106 "", "nx",
107 "the number of subdivision in x direction, "
108 "(min = 0)",
109 false, 10, "SUBDIVISIONS_X");
110 cmd.add(nsubdivXArg);
111 TCLAP::ValueArg<unsigned> nsubdivYArg(
112 "", "ny",
113 "the number of subdivision in y direction, "
114 "(min = 0)",
115 false, 10, "SUBDIVISIONS_Y");
116 cmd.add(nsubdivYArg);
117 TCLAP::ValueArg<unsigned> nsubdivZArg(
118 "", "nz",
119 "the number of subdivision in z direction, "
120 "(min = 0)",
121 false, 10, "SUBDIVISIONS_Z");
122 cmd.add(nsubdivZArg);
123
124 TCLAP::ValueArg<double> d0XArg("", "dx0",
125 "initial cell length in x direction, "
126 "(min = 0)",
127 false, 1, "INITIAL_X");
128 cmd.add(d0XArg);
129 TCLAP::ValueArg<double> d0YArg("", "dy0",
130 "initial cell length in y direction, "
131 "(min = 0)",
132 false, 1, "INITIAL_Y");
133 cmd.add(d0YArg);
134 TCLAP::ValueArg<double> d0ZArg("", "dz0",
135 "initial cell length in z direction, "
136 "(min = 0)",
137 false, 1, "INITIAL_Z");
138 cmd.add(d0ZArg);
139 TCLAP::ValueArg<double> dmaxXArg("", "dx-max",
140 "maximum cell length in x direction, "
141 "(min = 0)",
142 false, std::numeric_limits<double>::max(),
143 "MAX_X");
144 cmd.add(dmaxXArg);
145 TCLAP::ValueArg<double> dmaxYArg("", "dy-max",
146 "maximum cell length in y direction, "
147 "(min = 0)",
148 false, std::numeric_limits<double>::max(),
149 "MAX_Y");
150 cmd.add(dmaxYArg);
151 TCLAP::ValueArg<double> dmaxZArg("", "dz-max",
152 "maximum cell length in z direction, "
153 "(min = 0)",
154 false, std::numeric_limits<double>::max(),
155 "MAX_Z");
156 cmd.add(dmaxZArg);
157 TCLAP::ValueArg<double> multiXArg("", "mx", "multiplier in x direction",
158 false, 1, "MULTIPLIER_X");
159 cmd.add(multiXArg);
160 TCLAP::ValueArg<double> multiYArg("", "my", "multiplier in y direction",
161 false, 1, "MULTIPLIER_Y");
162 cmd.add(multiYArg);
163 TCLAP::ValueArg<double> multiZArg("", "mz", "multiplier in z direction",
164 false, 1, "MULTIPLIER_Z");
165 cmd.add(multiZArg);
166 TCLAP::ValueArg<double> originXArg(
167 "", "ox", "mesh origin (lower left corner) in x direction", false, 0,
168 "ORIGIN_X");
169 cmd.add(originXArg);
170 TCLAP::ValueArg<double> originYArg(
171 "", "oy", "mesh origin (lower left corner) in y direction", false, 0,
172 "ORIGIN_Y");
173 cmd.add(originYArg);
174 TCLAP::ValueArg<double> originZArg(
175 "", "oz", "mesh origin (lower left corner) in z direction", false, 0,
176 "ORIGIN_Z");
177 cmd.add(originZArg);
178
179
181 cmd.add(log_level_arg);
182 cmd.parse(argc, argv);
185
186 const std::string eleTypeName(eleTypeArg.getValue());
190
191 bool dim_used[3] = {false};
192 for (unsigned i = 0; i < dim; i++)
193 {
194 dim_used[i] = true;
195 }
196
197 std::vector<TCLAP::ValueArg<double>*> vec_lengthArg = {
198 &lengthXArg, &lengthYArg, &lengthZArg};
199 std::vector<TCLAP::ValueArg<unsigned>*> vec_ndivArg = {
200 &nsubdivXArg, &nsubdivYArg, &nsubdivZArg};
201 std::vector<TCLAP::ValueArg<double>*> vec_d0Arg = {&d0XArg, &d0YArg,
202 &d0ZArg};
203 std::vector<TCLAP::ValueArg<double>*> vec_dMaxArg = {&dmaxXArg, &dmaxYArg,
204 &dmaxZArg};
205 std::vector<TCLAP::ValueArg<double>*> vec_multiArg = {
206 &multiXArg, &multiYArg, &multiZArg};
208 {originXArg.getValue(), originYArg.getValue(), originZArg.getValue()});
209
210 const bool isLengthSet =
211 std::any_of(vec_lengthArg.begin(), vec_lengthArg.end(),
212 [&](TCLAP::ValueArg<double>* arg) { return arg->isSet(); });
213 if (!isLengthSet)
214 {
215 ERR(
"Missing input: Length information is not provided at all.");
216 return EXIT_FAILURE;
217 }
218 for (unsigned i = 0; i < 3; i++)
219 {
220 if (dim_used[i] && !vec_lengthArg[i]->isSet())
221 {
222 ERR(
"Missing input: Length for dimension [{:d}] is required but "
223 "missing.",
224 i);
225 return EXIT_FAILURE;
226 }
227 }
228
229 std::vector<double> length(dim);
230 std::vector<unsigned> n_subdivision(dim);
231 std::vector<double> vec_dx(dim);
232 for (unsigned i = 0; i < dim; i++)
233 {
234 length[i] = vec_lengthArg[i]->getValue();
235 n_subdivision[i] = vec_ndivArg[i]->getValue();
236 vec_dx[i] = length[i] / n_subdivision[i];
237 }
238
239 std::vector<std::unique_ptr<BaseLib::ISubdivision>> vec_div;
240 vec_div.reserve(dim);
241 for (unsigned i = 0; i < dim; i++)
242 {
243 if (vec_multiArg[i]->isSet())
244 {
245 if (vec_ndivArg[i]->isSet())
246 {
247
248 if (vec_d0Arg[i]->isSet())
249 {
251 "Specifying all of --m?, --d?0 and --n? for coordinate "
252 "'?' is not supported.");
253 }
255 length[i], vec_ndivArg[i]->
getValue(),
257 }
258 else
259 {
261 length[i], vec_d0Arg[i]->
getValue(),
263 }
264 }
265 else
266 {
267 vec_div.emplace_back(
269 }
270 }
271
272
273 std::unique_ptr<MeshLib::Mesh> mesh;
274 switch (eleType)
275 {
278 *vec_div[0], origin));
279 break;
282 *vec_div[0], *vec_div[1], origin));
283 break;
286 *vec_div[0], *vec_div[1], origin));
287 break;
290 *vec_div[0], *vec_div[1], *vec_div[2], origin));
291 break;
294 length[0], length[1], length[2], n_subdivision[0],
295 n_subdivision[1], n_subdivision[2], origin));
296 break;
299 *vec_div[0], *vec_div[1], *vec_div[2], origin));
300 break;
303 *vec_div[0], *vec_div[1], *vec_div[2], origin));
304 break;
305 default:
306 ERR(
"Given element type is not supported.");
307 break;
308 }
309
310 if (mesh)
311 {
312 INFO(
"Mesh created: {:d} nodes, {:d} elements.",
313 mesh->getNumberOfNodes(), mesh->getNumberOfElements());
314
315
317 *(mesh.get()), std::filesystem::path(mesh_out.getValue()));
318 }
319
320 return EXIT_SUCCESS;
321}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
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...
MeshElemType
Types of mesh elements supported by OpenGeoSys. Values are from VTKCellType enum.
unsigned getDimension(MeshLib::MeshElemType eleType)