OGS
generateStructuredMesh.cpp File Reference
#include <tclap/CmdLine.h>
#include <algorithm>
#include <filesystem>
#include <memory>
#include <range/v3/algorithm/all_of.hpp>
#include <range/v3/algorithm/find_if.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/filter.hpp>
#include <string>
#include <vector>
#include "BaseLib/Error.h"
#include "BaseLib/Logging.h"
#include "BaseLib/MPI.h"
#include "BaseLib/Subdivision.h"
#include "BaseLib/TCLAPArguments.h"
#include "InfoLib/GitInfo.h"
#include "MathLib/Point3d.h"
#include "MeshLib/Elements/Element.h"
#include "MeshLib/Elements/Point.h"
#include "MeshLib/IO/writeMeshToFile.h"
#include "MeshLib/Mesh.h"
#include "MeshLib/MeshEnums.h"
#include "MeshLib/Node.h"
#include "MeshLib/Utils/addPropertyToMesh.h"
#include "MeshToolsLib/MeshEditing/RemoveMeshComponents.h"
#include "MeshToolsLib/MeshGenerators/MeshGenerator.h"
#include "MeshToolsLib/MeshSurfaceExtraction.h"
Include dependency graph for generateStructuredMesh.cpp:

Go to the source code of this file.

Classes

struct  anonymous_namespace{generateStructuredMesh.cpp}::BoundarySide

Namespaces

namespace  anonymous_namespace{generateStructuredMesh.cpp}

Functions

void anonymous_namespace{generateStructuredMesh.cpp}::extract1DBoundaryMeshes (MeshLib::Mesh const &mesh, MathLib::Point3d const &origin, std::vector< double > const &length, std::string const &base)
void anonymous_namespace{generateStructuredMesh.cpp}::extract2D3DBoundaryMeshes (MeshLib::Mesh const &mesh, unsigned dim, MathLib::Point3d const &origin, std::vector< double > const &length, std::string const &base)
int main (int argc, char *argv[])

Function Documentation

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 166 of file generateStructuredMesh.cpp.

167{
168 TCLAP::CmdLine cmd(
169 "Structured mesh generator.\n"
170 "The documentation is available at "
171 "https://docs.opengeosys.org/docs/tools/meshing/"
172 "structured-mesh-generation.\n\n"
173 "OpenGeoSys-6 software, version " +
175 ".\n"
176 "Copyright (c) 2012-2026, OpenGeoSys Community "
177 "(http://www.opengeosys.org)",
179
180 std::vector<std::string> allowed_ele_types;
181 allowed_ele_types.emplace_back("line");
182 allowed_ele_types.emplace_back("tri");
183 allowed_ele_types.emplace_back("quad");
184 allowed_ele_types.emplace_back("hex");
185 allowed_ele_types.emplace_back("prism");
186 allowed_ele_types.emplace_back("tet");
187 allowed_ele_types.emplace_back("pyramid");
188 TCLAP::ValuesConstraint<std::string> allowedVals(allowed_ele_types);
189 TCLAP::ValueArg<std::string> eleTypeArg("e", "element-type",
190 "element type to be created", true,
191 "line", &allowedVals);
192 cmd.add(eleTypeArg);
193 TCLAP::ValueArg<std::string> mesh_out(
194 "o", "mesh-output-file",
195 "Output (.vtu). The name of the file the mesh will be written to", true,
196 "", "OUTPUT_FILE");
197 cmd.add(mesh_out);
198 TCLAP::ValueArg<double> lengthXArg("", "lx",
199 "length of a domain in x direction, "
200 "(min = 0)",
201 false, 10.0, "LENGTH_X");
202 cmd.add(lengthXArg);
203 TCLAP::ValueArg<double> lengthYArg("", "ly",
204 "length of a domain in y direction, "
205 "(min = 0)",
206 false, 10.0, "LENGTH_Y");
207 cmd.add(lengthYArg);
208 TCLAP::ValueArg<double> lengthZArg("", "lz",
209 "length of a domain in z direction, "
210 "(min = 0)",
211 false, 10.0, "LENGTH_Z");
212 cmd.add(lengthZArg);
213 TCLAP::ValueArg<unsigned> nsubdivXArg(
214 "", "nx",
215 "the number of subdivision in x direction, "
216 "(min = 0)",
217 false, 10, "SUBDIVISIONS_X");
218 cmd.add(nsubdivXArg);
219 TCLAP::ValueArg<unsigned> nsubdivYArg(
220 "", "ny",
221 "the number of subdivision in y direction, "
222 "(min = 0)",
223 false, 10, "SUBDIVISIONS_Y");
224 cmd.add(nsubdivYArg);
225 TCLAP::ValueArg<unsigned> nsubdivZArg(
226 "", "nz",
227 "the number of subdivision in z direction, "
228 "(min = 0)",
229 false, 10, "SUBDIVISIONS_Z");
230 cmd.add(nsubdivZArg);
231 // in case of gradual refinement
232 TCLAP::ValueArg<double> d0XArg("", "dx0",
233 "initial cell length in x direction, "
234 "(min = 0)",
235 false, 1, "INITIAL_X");
236 cmd.add(d0XArg);
237 TCLAP::ValueArg<double> d0YArg("", "dy0",
238 "initial cell length in y direction, "
239 "(min = 0)",
240 false, 1, "INITIAL_Y");
241 cmd.add(d0YArg);
242 TCLAP::ValueArg<double> d0ZArg("", "dz0",
243 "initial cell length in z direction, "
244 "(min = 0)",
245 false, 1, "INITIAL_Z");
246 cmd.add(d0ZArg);
247 TCLAP::ValueArg<double> dmaxXArg("", "dx-max",
248 "maximum cell length in x direction, "
249 "(min = 0)",
250 false, std::numeric_limits<double>::max(),
251 "MAX_X");
252 cmd.add(dmaxXArg);
253 TCLAP::ValueArg<double> dmaxYArg("", "dy-max",
254 "maximum cell length in y direction, "
255 "(min = 0)",
256 false, std::numeric_limits<double>::max(),
257 "MAX_Y");
258 cmd.add(dmaxYArg);
259 TCLAP::ValueArg<double> dmaxZArg("", "dz-max",
260 "maximum cell length in z direction, "
261 "(min = 0)",
262 false, std::numeric_limits<double>::max(),
263 "MAX_Z");
264 cmd.add(dmaxZArg);
265 TCLAP::ValueArg<double> multiXArg("", "mx", "multiplier in x direction",
266 false, 1, "MULTIPLIER_X");
267 cmd.add(multiXArg);
268 TCLAP::ValueArg<double> multiYArg("", "my", "multiplier in y direction",
269 false, 1, "MULTIPLIER_Y");
270 cmd.add(multiYArg);
271 TCLAP::ValueArg<double> multiZArg("", "mz", "multiplier in z direction",
272 false, 1, "MULTIPLIER_Z");
273 cmd.add(multiZArg);
274 TCLAP::ValueArg<double> originXArg(
275 "", "ox", "mesh origin (lower left corner) in x direction", false, 0,
276 "ORIGIN_X");
277 cmd.add(originXArg);
278 TCLAP::ValueArg<double> originYArg(
279 "", "oy", "mesh origin (lower left corner) in y direction", false, 0,
280 "ORIGIN_Y");
281 cmd.add(originYArg);
282 TCLAP::ValueArg<double> originZArg(
283 "", "oz", "mesh origin (lower left corner) in z direction", false, 0,
284 "ORIGIN_Z");
285 cmd.add(originZArg);
286 // parse arguments
287 auto log_level_arg = BaseLib::makeLogLevelArg();
288 cmd.add(log_level_arg);
289 cmd.parse(argc, argv);
290 BaseLib::MPI::Setup mpi_setup(argc, argv);
291 BaseLib::initOGSLogger(log_level_arg.getValue());
292
293 const std::string eleTypeName(eleTypeArg.getValue());
294 const MeshLib::MeshElemType eleType =
295 MeshLib::String2MeshElemType(eleTypeName);
296 const unsigned dim = MeshLib::getDimension(eleType);
297
298 bool dim_used[3] = {false};
299 for (unsigned i = 0; i < dim; i++)
300 {
301 dim_used[i] = true;
302 }
303
304 std::vector<TCLAP::ValueArg<double>*> vec_lengthArg = {
305 &lengthXArg, &lengthYArg, &lengthZArg};
306 std::vector<TCLAP::ValueArg<unsigned>*> vec_ndivArg = {
307 &nsubdivXArg, &nsubdivYArg, &nsubdivZArg};
308 std::vector<TCLAP::ValueArg<double>*> vec_d0Arg = {&d0XArg, &d0YArg,
309 &d0ZArg};
310 std::vector<TCLAP::ValueArg<double>*> vec_dMaxArg = {&dmaxXArg, &dmaxYArg,
311 &dmaxZArg};
312 std::vector<TCLAP::ValueArg<double>*> vec_multiArg = {
313 &multiXArg, &multiYArg, &multiZArg};
314 MathLib::Point3d const origin(
315 {originXArg.getValue(), originYArg.getValue(), originZArg.getValue()});
316
317 const bool isLengthSet =
318 std::any_of(vec_lengthArg.begin(), vec_lengthArg.end(),
319 [&](TCLAP::ValueArg<double>* arg) { return arg->isSet(); });
320 if (!isLengthSet)
321 {
322 ERR("Missing input: Length information is not provided at all.");
323 return EXIT_FAILURE;
324 }
325 for (unsigned i = 0; i < 3; i++)
326 {
327 if (dim_used[i] && !vec_lengthArg[i]->isSet())
328 {
329 ERR("Missing input: Length for dimension [{:d}] is required but "
330 "missing.",
331 i);
332 return EXIT_FAILURE;
333 }
334 }
335
336 std::vector<double> length(dim);
337 std::vector<unsigned> n_subdivision(dim);
338 std::vector<double> vec_dx(dim);
339 for (unsigned i = 0; i < dim; i++)
340 {
341 length[i] = vec_lengthArg[i]->getValue();
342 n_subdivision[i] = vec_ndivArg[i]->getValue();
343 vec_dx[i] = length[i] / n_subdivision[i];
344 }
345
346 std::vector<std::unique_ptr<BaseLib::ISubdivision>> vec_div;
347 vec_div.reserve(dim);
348 for (unsigned i = 0; i < dim; i++)
349 {
350 if (vec_multiArg[i]->isSet())
351 {
352 if (vec_ndivArg[i]->isSet())
353 {
354 // number of partitions in direction is specified
355 if (vec_d0Arg[i]->isSet())
356 {
357 OGS_FATAL(
358 "Specifying all of --m?, --d?0 and --n? for coordinate "
359 "'?' is not supported.");
360 }
361 vec_div.emplace_back(new BaseLib::GradualSubdivisionFixedNum(
362 length[i], vec_ndivArg[i]->getValue(),
363 vec_multiArg[i]->getValue()));
364 }
365 else
366 {
367 vec_div.emplace_back(new BaseLib::GradualSubdivision(
368 length[i], vec_d0Arg[i]->getValue(),
369 vec_dMaxArg[i]->getValue(), vec_multiArg[i]->getValue()));
370 }
371 }
372 else
373 {
374 vec_div.emplace_back(
375 new BaseLib::UniformSubdivision(length[i], n_subdivision[i]));
376 }
377 }
378
379 // generate a mesh
380 std::unique_ptr<MeshLib::Mesh> mesh;
381 switch (eleType)
382 {
385 *vec_div[0], origin));
386 break;
389 *vec_div[0], *vec_div[1], origin));
390 break;
393 *vec_div[0], *vec_div[1], origin));
394 break;
397 *vec_div[0], *vec_div[1], *vec_div[2], origin));
398 break;
401 length[0], length[1], length[2], n_subdivision[0],
402 n_subdivision[1], n_subdivision[2], origin));
403 break;
406 *vec_div[0], *vec_div[1], *vec_div[2], origin));
407 break;
410 *vec_div[0], *vec_div[1], *vec_div[2], origin));
411 break;
412 default:
413 ERR("Given element type is not supported.");
414 break;
415 }
416
417 if (!mesh)
418 {
419 return EXIT_FAILURE;
420 }
421
422 INFO("Mesh created: {:d} nodes, {:d} elements.", mesh->getNumberOfNodes(),
423 mesh->getNumberOfElements());
424
425 auto const out_path = std::filesystem::path(mesh_out.getValue());
426 if (MeshLib::IO::writeMeshToFile(*mesh, out_path) != 0)
427 {
428 return EXIT_FAILURE;
429 }
430
431 auto const base = (out_path.parent_path() / out_path.stem()).string();
432
433 if (dim == 1)
434 {
435 extract1DBoundaryMeshes(*mesh, origin, length, base);
436 }
437 else if (dim >= 2)
438 {
439 extract2D3DBoundaryMeshes(*mesh, dim, origin, length, base);
440 }
441
442 return EXIT_SUCCESS;
443}
#define OGS_FATAL(...)
Definition Error.h:19
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
std::string getValue(std::string const &line, std::string const &val_name, bool is_string)
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
Definition Logging.cpp:56
GITINFOLIB_EXPORT const std::string ogs_version
int writeMeshToFile(const MeshLib::Mesh &mesh, std::filesystem::path const &file_path, std::set< std::string > output_variable_names, bool const use_compression, int const data_mode)
MeshElemType String2MeshElemType(const std::string &s)
Definition MeshEnums.cpp:84
constexpr unsigned getDimension(MeshElemType t)
Returns the dimension of the given MeshElemType.
Definition MeshEnums.h:118
MeshElemType
Types of mesh elements supported by OpenGeoSys. Values are from VTKCellType enum.
Definition MeshEnums.h:38
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")
void extract2D3DBoundaryMeshes(MeshLib::Mesh const &mesh, unsigned dim, MathLib::Point3d const &origin, std::vector< double > const &length, std::string const &base)
void extract1DBoundaryMeshes(MeshLib::Mesh const &mesh, MathLib::Point3d const &origin, std::vector< double > const &length, std::string const &base)

References ERR(), anonymous_namespace{generateStructuredMesh.cpp}::extract1DBoundaryMeshes(), anonymous_namespace{generateStructuredMesh.cpp}::extract2D3DBoundaryMeshes(), MeshToolsLib::MeshGenerator::generateLineMesh(), MeshToolsLib::MeshGenerator::generateRegularHexMesh(), MeshToolsLib::MeshGenerator::generateRegularPrismMesh(), MeshToolsLib::MeshGenerator::generateRegularPyramidMesh(), MeshToolsLib::MeshGenerator::generateRegularQuadMesh(), MeshToolsLib::MeshGenerator::generateRegularTetMesh(), MeshToolsLib::MeshGenerator::generateRegularTriMesh(), MeshLib::getDimension(), getValue(), MeshLib::HEXAHEDRON, INFO(), BaseLib::initOGSLogger(), MeshLib::LINE, BaseLib::makeLogLevelArg(), OGS_FATAL, GitInfoLib::GitInfo::ogs_version, MeshLib::PRISM, MeshLib::PYRAMID, MeshLib::QUAD, MeshLib::String2MeshElemType(), MeshLib::TETRAHEDRON, MeshLib::TRIANGLE, and MeshLib::IO::writeMeshToFile().