58{
59 TCLAP::CmdLine cmd(
60 "Structured mesh generator.\n"
61 "The documentation is available at "
62 "https://docs.opengeosys.org/docs/tools/meshing/"
63 "structured-mesh-generation.\n\n"
64 "OpenGeoSys-6 software, version " +
66 ".\n"
67 "Copyright (c) 2012-2024, OpenGeoSys Community "
68 "(http://www.opengeosys.org)",
70
71 auto tclapOutput = std::make_unique<BaseLib::TCLAPCustomOutput>();
72 cmd.setOutput(tclapOutput.get());
73
74 std::vector<std::string> allowed_ele_types;
75 allowed_ele_types.emplace_back("line");
76 allowed_ele_types.emplace_back("tri");
77 allowed_ele_types.emplace_back("quad");
78 allowed_ele_types.emplace_back("hex");
79 allowed_ele_types.emplace_back("prism");
80 allowed_ele_types.emplace_back("tet");
81 allowed_ele_types.emplace_back("pyramid");
82 TCLAP::ValuesConstraint<std::string> allowedVals(allowed_ele_types);
83 TCLAP::ValueArg<std::string> eleTypeArg(
84 "e", "element-type",
85 "element type to be created: line | tri | quad | hex | prism | tet | "
86 "pyramid",
87 true, "line", &allowedVals);
88 cmd.add(eleTypeArg);
89 TCLAP::ValueArg<std::string> mesh_out(
90 "o", "mesh-output-file",
91 "the name of the file the mesh will be written to", true, "",
92 "file name of output mesh");
93 cmd.add(mesh_out);
94 TCLAP::ValueArg<double> lengthXArg(
95 "", "lx", "length of a domain in x direction", false, 10.0, "real");
96 cmd.add(lengthXArg);
97 TCLAP::ValueArg<double> lengthYArg(
98 "", "ly", "length of a domain in y direction", false, 10.0, "real");
99 cmd.add(lengthYArg);
100 TCLAP::ValueArg<double> lengthZArg(
101 "", "lz", "length of a domain in z direction", false, 10.0, "real");
102 cmd.add(lengthZArg);
103 TCLAP::ValueArg<unsigned> nsubdivXArg(
104 "", "nx", "the number of subdivision in x direction", false, 10,
105 "integer");
106 cmd.add(nsubdivXArg);
107 TCLAP::ValueArg<unsigned> nsubdivYArg(
108 "", "ny", "the number of subdivision in y direction", false, 10,
109 "integer");
110 cmd.add(nsubdivYArg);
111 TCLAP::ValueArg<unsigned> nsubdivZArg(
112 "", "nz", "the number of subdivision in z direction", false, 10,
113 "integer");
114 cmd.add(nsubdivZArg);
115
116 TCLAP::ValueArg<double> d0XArg(
117 "", "dx0", "initial cell length in x direction", false, 1, "real");
118 cmd.add(d0XArg);
119 TCLAP::ValueArg<double> d0YArg(
120 "", "dy0", "initial cell length in y direction", false, 1, "real");
121 cmd.add(d0YArg);
122 TCLAP::ValueArg<double> d0ZArg(
123 "", "dz0", "initial cell length in z direction", false, 1, "real");
124 cmd.add(d0ZArg);
125 TCLAP::ValueArg<double> dmaxXArg(
126 "", "dx-max", "maximum cell length in x direction", false,
127 std::numeric_limits<double>::max(), "real");
128 cmd.add(dmaxXArg);
129 TCLAP::ValueArg<double> dmaxYArg(
130 "", "dy-max", "maximum cell length in y direction", false,
131 std::numeric_limits<double>::max(), "real");
132 cmd.add(dmaxYArg);
133 TCLAP::ValueArg<double> dmaxZArg(
134 "", "dz-max", "maximum cell length in z direction", false,
135 std::numeric_limits<double>::max(), "real");
136 cmd.add(dmaxZArg);
137 TCLAP::ValueArg<double> multiXArg("", "mx", "multiplier in x direction",
138 false, 1, "real");
139 cmd.add(multiXArg);
140 TCLAP::ValueArg<double> multiYArg("", "my", "multiplier in y direction",
141 false, 1, "real");
142 cmd.add(multiYArg);
143 TCLAP::ValueArg<double> multiZArg("", "mz", "multiplier in z direction",
144 false, 1, "real");
145 cmd.add(multiZArg);
146 TCLAP::ValueArg<double> originXArg(
147 "", "ox", "mesh origin (lower left corner) in x direction", false, 0,
148 "real");
149 cmd.add(originXArg);
150 TCLAP::ValueArg<double> originYArg(
151 "", "oy", "mesh origin (lower left corner) in y direction", false, 0,
152 "real");
153 cmd.add(originYArg);
154 TCLAP::ValueArg<double> originZArg(
155 "", "oz", "mesh origin (lower left corner) in z direction", false, 0,
156 "real");
157 cmd.add(originZArg);
158
159
160 cmd.parse(argc, argv);
162 const std::string eleTypeName(eleTypeArg.getValue());
166
167 bool dim_used[3] = {false};
168 for (unsigned i = 0; i < dim; i++)
169 {
170 dim_used[i] = true;
171 }
172
173 std::vector<TCLAP::ValueArg<double>*> vec_lengthArg = {
174 &lengthXArg, &lengthYArg, &lengthZArg};
175 std::vector<TCLAP::ValueArg<unsigned>*> vec_ndivArg = {
176 &nsubdivXArg, &nsubdivYArg, &nsubdivZArg};
177 std::vector<TCLAP::ValueArg<double>*> vec_d0Arg = {&d0XArg, &d0YArg,
178 &d0ZArg};
179 std::vector<TCLAP::ValueArg<double>*> vec_dMaxArg = {&dmaxXArg, &dmaxYArg,
180 &dmaxZArg};
181 std::vector<TCLAP::ValueArg<double>*> vec_multiArg = {
182 &multiXArg, &multiYArg, &multiZArg};
184 {originXArg.getValue(), originYArg.getValue(), originZArg.getValue()});
185
186 const bool isLengthSet =
187 std::any_of(vec_lengthArg.begin(), vec_lengthArg.end(),
188 [&](TCLAP::ValueArg<double>* arg) { return arg->isSet(); });
189 if (!isLengthSet)
190 {
191 ERR(
"Missing input: Length information is not provided at all.");
192 return EXIT_FAILURE;
193 }
194 for (unsigned i = 0; i < 3; i++)
195 {
196 if (dim_used[i] && !vec_lengthArg[i]->isSet())
197 {
198 ERR(
"Missing input: Length for dimension [{:d}] is required but "
199 "missing.",
200 i);
201 return EXIT_FAILURE;
202 }
203 }
204
205 std::vector<double> length(dim);
206 std::vector<unsigned> n_subdivision(dim);
207 std::vector<double> vec_dx(dim);
208 for (unsigned i = 0; i < dim; i++)
209 {
210 length[i] = vec_lengthArg[i]->getValue();
211 n_subdivision[i] = vec_ndivArg[i]->getValue();
212 vec_dx[i] = length[i] / n_subdivision[i];
213 }
214
215 std::vector<std::unique_ptr<BaseLib::ISubdivision>> vec_div;
216 vec_div.reserve(dim);
217 for (unsigned i = 0; i < dim; i++)
218 {
219 if (vec_multiArg[i]->isSet())
220 {
221 if (vec_ndivArg[i]->isSet())
222 {
223
224 if (vec_d0Arg[i]->isSet())
225 {
227 "Specifying all of --m?, --d?0 and --n? for coordinate "
228 "'?' is not supported.");
229 }
231 length[i], vec_ndivArg[i]->
getValue(),
233 }
234 else
235 {
237 length[i], vec_d0Arg[i]->
getValue(),
239 }
240 }
241 else
242 {
243 vec_div.emplace_back(
245 }
246 }
247
248
249 std::unique_ptr<MeshLib::Mesh> mesh;
250 switch (eleType)
251 {
254 *vec_div[0], origin));
255 break;
258 *vec_div[0], *vec_div[1], origin));
259 break;
262 *vec_div[0], *vec_div[1], origin));
263 break;
266 *vec_div[0], *vec_div[1], *vec_div[2], origin));
267 break;
270 length[0], length[1], length[2], n_subdivision[0],
271 n_subdivision[1], n_subdivision[2], origin));
272 break;
275 *vec_div[0], *vec_div[1], *vec_div[2], origin));
276 break;
279 *vec_div[0], *vec_div[1], *vec_div[2], origin));
280 break;
281 default:
282 ERR(
"Given element type is not supported.");
283 break;
284 }
285
286 if (mesh)
287 {
288 INFO(
"Mesh created: {:d} nodes, {:d} elements.",
289 mesh->getNumberOfNodes(), mesh->getNumberOfElements());
290
291
293 *(mesh.get()), std::filesystem::path(mesh_out.getValue()));
294 }
295
296 return EXIT_SUCCESS;
297}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
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)