PeriDEM 0.2.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
mesh.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2024 Prashant K. Jha
4 * -------------------------------------------
5 * PeriDEM https://github.com/prashjha/PeriDEM
6 *
7 * Distributed under the Boost Software License, Version 1.0. (See accompanying
8 * file LICENSE)
9 */
10
11#include "mesh.h"
12#include "inp/decks/meshDeck.h"
13#include "quadElem.h"
14#include "rw/reader.h"
15#include "tetElem.h"
16#include "triElem.h"
17#include "util/feElementDefs.h"
18#include "util/function.h"
19#include "util/geom.h"
20#include "util/parallelUtil.h"
21#include <cstdint>
22#include <iostream>
23#include <taskflow/taskflow/taskflow.hpp>
24#include <taskflow/taskflow/algorithm/for_each.hpp>
25
26fe::Mesh::Mesh(size_t dim)
27 : d_numNodes(0), d_numElems(0), d_eType(1), d_eNumVertex(0), d_numDofs(0),
28 d_h(0.), d_dim(dim), d_encDataPopulated(false), d_needEncData(false),
29 d_nPart(0){}
30
32 : d_numNodes(0), d_numElems(0), d_eType(1), d_eNumVertex(0), d_numDofs(0),
33 d_h(deck->d_h), d_dim(deck->d_dim),
34 d_spatialDiscretization(deck->d_spatialDiscretization),
35 d_filename(deck->d_filename), d_encDataPopulated(false),
36 d_needEncData(deck->d_populateElementNodeConnectivity),
37 d_nPart(0) {
38
39 // perform check on input data
40 if (d_spatialDiscretization != "finite_difference" and
41 d_spatialDiscretization != "weak_finite_element" and
42 d_spatialDiscretization != "nodal_finite_element" and
43 d_spatialDiscretization != "truss_finite_element") {
44 std::cerr << "Error: Spatial discretization type not known. Check input "
45 "data.\n";
46 std::cerr << deck->printStr() << "\n";
47 exit(1);
48 }
49
51 std::cerr << "Error: Check Dimension in input data.\n";
52 exit(1);
53 }
54
55 if (d_filename.empty()) {
56 std::cerr << "Error: Filename for mesh data not specified.\n";
57 exit(1);
58 }
59
60 // read mesh data from file
62}
63
64//
65// Utility functions
66//
67void fe::Mesh::createData(const std::string &filename, bool ref_config) {
68
69 util::io::log("Mesh: Reading element data.\n");
70
71 int file_type = -1;
72 // find the extension of file and call correct reader
73 if (util::io::getExtensionFromFile(filename) == "csv")
74 file_type = 0;
75 else if (util::io::getExtensionFromFile(filename) == "msh")
76 file_type = 1;
77 else if (util::io::getExtensionFromFile(filename) == "vtu")
78 file_type = 2;
79 else {
80 std::cerr << "Error: Currently only '.csv', '.msg', and '.vtu' "
81 "files are supported for reading mesh.\n";
82 exit(EXIT_FAILURE);
83 }
84
85 if (d_spatialDiscretization != "finite_difference" and file_type == 0) {
86
87 std::cerr << "Error: For discretization = " << d_spatialDiscretization
88 << " .vtu or .msh mesh file is required.\n";
89 exit(1);
90 }
91
92 //
93 bool is_fd = false;
94 if (d_spatialDiscretization == "finite_difference")
95 is_fd = true;
96
97 // read node and elements
98 if (file_type == 0)
99 rw::reader::readCsvFile(filename, d_dim, &d_nodes, &d_vol);
100 else if (file_type == 1) {
101 rw::reader::readMshFile(filename, d_dim, &d_nodes, d_eType, d_numElems,
102 &d_enc, &d_nec, &d_vol, false);
103 d_encDataPopulated = true;
104 }
105 else if (file_type == 2) {
106 //
107 // old reading of mesh
108 //
109 // rw::reader::readVtuFile(filename, d_dim, &d_nodes, d_eType, d_numElems,
110 // &d_enc, &d_nec, &d_vol, false);
111
112 //
113 // new reading of mesh
114 // We read the data from file one by one depending on what data we need
115 //
116
117 // read node
118 rw::reader::readVtuFileNodes(filename, d_dim, &d_nodes, ref_config);
119
120 // read volume if required
121 bool found_volume_data = false;
122 if (is_fd) {
123 found_volume_data =
124 rw::reader::readVtuFilePointData(filename, "Node_Volume", &d_vol);
125
126 // try another tag for nodal volume
127 if (!found_volume_data)
128 found_volume_data =
129 rw::reader::readVtuFilePointData(filename, "Volume", &d_vol);
130 }
131
132 // read element data (only if this is fe simulation or if we need
133 // element-node connectivity data for nodal volume calculation)
134 if (!is_fd || !found_volume_data) {
135 rw::reader::readVtuFileCells(filename, d_dim, d_eType, d_numElems, &d_enc,
136 &d_nec);
137 d_encDataPopulated = true;
138 }
139
140 // check if file has fixity data
141 rw::reader::readVtuFilePointData(filename, "Fixity", &d_fix);
142 }
143
144 // compute data from mesh data
145 d_numNodes = d_nodes.size();
146 d_eNumVertex = util::vtk_map_element_to_num_nodes[d_eType];
147 d_numDofs = d_numNodes * d_dim;
148
149 //
150 // assign default values to fixity
151 //
152 if (d_fix.size() != d_numNodes)
153 d_fix = std::vector<uint8_t>(d_nodes.size(), uint8_t(0));
154
155 //
156 // compute nodal volume if required
157 //
158 bool compute_vol = false;
159 if (is_fd and d_vol.empty()) compute_vol = true;
160
161 // if this is weak finite element simulation then check from policy if
162 // volume is to be computed
163 if (d_spatialDiscretization == "weak_finite_element")
164 compute_vol = false;
165
166 if (compute_vol) {
167 util::io::log("Mesh: Computing nodal volume.\n");
168 computeVol();
169 }
170
171 //
172 // compute bounding box
173 //
174 computeBBox();
175
176 // check if we need to compute mesh size
177 //if (deck->d_computeMeshSize)
178 computeMeshSize();
179
180 // check nodal volume
181 size_t counter = 0;
182 for (const auto &v : d_vol) {
183
184 if (v < 0.01 * std::pow(d_h, d_dim)) {
185
186 std::cerr << "Error: Check nodal volume " << v
187 << " is less than " << 0.01 * std::pow(d_h, d_dim)
188 << ", Node = " << counter
189 << " at position = " << d_nodes[counter].printStr() << "\n"
190 << "mesh filename = " << filename << "\n"
191 << printStr() << "\n";
192
193 exit(1);
194 }
195
196 counter++;
197 }
198
199 if (d_needEncData and (!d_encDataPopulated or d_enc.empty()))
200 readElementData(d_filename);
201}
202
203bool fe::Mesh::readElementData(const std::string &filename) {
204
205 if (d_encDataPopulated and !d_enc.empty()) {
206 util::io::log("Mesh: Element data is populated already.\n");
207 return false;
208 }
209
210 util::io::log("Mesh: Reading element-node connectivity data.\n");
211
212 int file_type = -1;
213 // find the extension of file and call correct reader
214 if (util::io::getExtensionFromFile(filename) == "csv")
215 file_type = 0;
216 else if (util::io::getExtensionFromFile(filename) == "msh")
217 file_type = 1;
218 else if (util::io::getExtensionFromFile(filename) == "vtu")
219 file_type = 2;
220 else {
221 std::cerr << "Error: Currently only '.csv', '.msg', and '.vtu' "
222 "files are supported for reading mesh.\n";
223 exit(EXIT_FAILURE);
224 }
225
226 if (file_type == 0) {
227 std::cerr << "Error: readElementData() requires file to be either "
228 ".vtu or .msh mesh file.\n";
229 exit(EXIT_FAILURE);
230 }
231
232 if (file_type == 1) {
233 rw::reader::readMshFileCells(filename, d_dim, d_eType, d_numElems,
234 &d_enc,
235 &d_nec);
236 d_encDataPopulated = true;
237 return true;
238 }
239 else if (file_type == 2) {
240 rw::reader::readVtuFileCells(filename, d_dim, d_eType, d_numElems,
241 &d_enc,
242 &d_nec);
243 d_encDataPopulated = true;
244 return true;
245 }
246
247 return false;
248}
249
251
252 // initialize quadrature data
253 fe::BaseElem *quads;
254 if (d_eType == util::vtk_type_triangle)
255 quads = new fe::TriElem(2);
256 else if (d_eType == util::vtk_type_quad)
257 quads = new fe::QuadElem(2);
258 else if (d_eType == util::vtk_type_tetra)
259 quads = new fe::TetElem(2);
260
261 // check if we have valid element-node connectivity data for nodal volume
262 // calculations
263 if (d_nec.size() != d_numNodes || d_enc.empty()) {
264 std::cerr << "Error: Can not compute nodal volume for given finite "
265 "element mesh as the element-node connectivity data is "
266 "invalid."
267 << std::endl;
268 exit(EXIT_FAILURE);
269 }
270
271 if (false) {
272 print(0, 0);
273 std::cout << "\n-------- Node data ----------\n";
274 std::cout << util::io::printStr(d_nodes, 0) << "\n";
275 std::cout << "\n-------- Element data ----------\n";
276 std::cout << util::io::printStr(d_enc, 0) << "\n";
277 }
278
279 //
280 // compute nodal volume
281 //
282 d_vol.resize(d_numNodes);
283
284 tf::Executor executor(util::parallel::getNThreads());
285 tf::Taskflow taskflow;
286
287 taskflow.for_each_index(
288 (std::size_t) 0, this->d_numNodes, (std::size_t) 1, [this, quads](std::size_t i) {
289 double v = 0.0;
290
291 for (auto e : this->d_nec[i]) {
292
293 std::vector<size_t> e_ns = this->getElementConnectivity(e);
294
295 // locate global node i in local list of element el
296 int loc_i = -1;
297 for (size_t l = 0; l < e_ns.size(); l++)
298 if (e_ns[l] == i)
299 loc_i = l;
300
301 if (loc_i == -1) {
302 std::cerr << "Error: Check node element connectivity.\n";
303 exit(1);
304 }
305
306 // get quad data
307 std::vector<util::Point> e_nodes;
308 for (auto k : e_ns)
309 e_nodes.emplace_back(this->d_nodes[k]);
310
311 // get volume of element
312 double vol = quads->elemSize(e_nodes);
313 double factor = 1.;
314 if (vol < 0.)
315 factor = -1.;
316
317 std::vector<fe::QuadData> qds = quads->getQuadDatas(e_nodes);
318
319 // compute V_e and add it to volume
320 for (auto qd : qds)
321 v += qd.d_shapes[loc_i] * factor * qd.d_w;
322 } // loop over elements
323
324 // update
325 this->d_vol[i] = v;
326 }
327 ); // for_each
328
329 executor.run(taskflow).get();
330}
331
333 std::vector<double> p1(3,0.);
334 std::vector<double> p2(3,0.);
335 for (const auto& x : d_nodes) {
336 if (util::isLess(x.d_x, p1[0]))
337 p1[0] = x.d_x;
338 if (util::isLess(x.d_y, p1[1]))
339 p1[1] = x.d_y;
340 if (util::isLess(x.d_z, p1[2]))
341 p1[2] = x.d_z;
342 if (util::isLess(p2[0], x.d_x))
343 p2[0] = x.d_x;
344 if (util::isLess(p2[1], x.d_y))
345 p2[1] = x.d_y;
346 if (util::isLess(p2[2], x.d_z))
347 p2[2] = x.d_z;
348 }
349
350 d_bbox = std::make_pair(p1, p2);
351}
352
354
355 double guess = 0.;
356 if (d_nodes.size() < 2) {
357 d_h = 0.;
358 return;
359 }
360
361 guess = (d_nodes[0] - d_nodes[1]).length();
362 for (size_t i = 0; i < d_nodes.size(); i++)
363 for (size_t j = 0; j < d_nodes.size(); j++)
364 if (i != j) {
365 double val = d_nodes[i].dist(d_nodes[j]);
366
367 if (util::isLess(val, 1.0E-12)) {
368
369 std::cout << "Check nodes are too close = "
370 << util::io::printStr<util::Point>({d_nodes[i],
371 d_nodes[j]})
372 << "\n";
373 std::cout << "Distance = " << val << ", guess = " << guess << "\n";
374 }
375 if (util::isLess(val, guess))
376 guess = val;
377 }
378
379 d_h = guess;
380}
381
382//
383// Setter functions
384//
385void fe::Mesh::setFixity(const size_t &i, const unsigned int &dof,
386 const bool &flag) {
387
388 // to set i^th bit as true of integer a,
389 // a |= 1UL << (i % 8)
390
391 // to set i^th bit as false of integer a,
392 // a &= ~(1UL << (i % 8))
393
394 flag ? (d_fix[i] |= 1UL << dof) : (d_fix[i] &= ~(1UL << dof));
395}
397 if (!d_enc.empty())
398 d_enc.shrink_to_fit();
399 d_numElems = 0;
400 if (!d_nec.empty())
401 d_nec.shrink_to_fit();
402}
403
404std::string fe::Mesh::printStr(int nt, int lvl) const {
405
406 auto tabS = util::io::getTabS(nt);
407 std::ostringstream oss;
408 oss << tabS << "------- Mesh --------" << std::endl << std::endl;
409 oss << tabS << "Dimension = " << d_dim << std::endl;
410 oss << tabS << "Spatial discretization type = " << d_spatialDiscretization << std::endl;
411 oss << tabS << "Mesh size = " << d_h << std::endl;
412 oss << tabS << "Num nodes = " << d_numNodes << std::endl;
413 oss << tabS << "Num elements = " << d_numElems << std::endl;
414 oss << tabS << "Element type = " << d_eType << std::endl;
415 oss << tabS << "Num nodes per element = " << d_eNumVertex << std::endl;
416 oss << tabS << "Num nodal vol = " << d_vol.size() << std::endl;
417 oss << tabS << "Bounding box: " << std::endl;
418 oss << util::io::printBoxStr(d_bbox, nt + 1);
419 oss << tabS << std::endl;
420
421 return oss.str();
422}
A base class which provides methods to map points to/from reference element and to compute quadrature...
Definition baseElem.h:84
virtual std::vector< fe::QuadData > getQuadDatas(const std::vector< util::Point > &nodes)=0
Get vector of quadrature data.
virtual double elemSize(const std::vector< util::Point > &nodes)=0
Returns the size of element (length in 1-d, area in 2-d, volume in 3-d element)
std::string d_spatialDiscretization
Tag for spatial discretization type.
Definition mesh.h:478
bool readElementData(const std::string &filename)
Reads element-node connectivity data from file. This function is meant for cases when mesh was create...
Definition mesh.cpp:203
size_t d_dim
Dimension of the mesh.
Definition mesh.h:468
void computeBBox()
Compute the bounding box
Definition mesh.cpp:332
void clearElementData()
Clear element-node connectivity data.
Definition mesh.cpp:396
void computeMeshSize()
Compute the mesh size.
Definition mesh.cpp:353
Mesh(size_t dim=0)
Constructor.
Definition mesh.cpp:26
std::string d_filename
Filename to read mesh data.
Definition mesh.h:481
void setFixity(const size_t &i, const unsigned int &dof, const bool &flag)
Set the fixity to free (0) or fixed (1)
Definition mesh.cpp:385
void computeVol()
Compute the nodal volume.
Definition mesh.cpp:250
void createData(const std::string &filename, bool ref_config=false)
Reads mesh data from the file and populates other data.
Definition mesh.cpp:67
std::string printStr(int nt=0, int lvl=0) const
Returns the string containing printable information about the object.
Definition mesh.cpp:404
A class for mapping and quadrature related operations for bi-linear quadrangle element.
Definition quadElem.h:64
A class for mapping and quadrature related operations for linear tetrahedron element.
Definition tetElem.h:141
A class for mapping and quadrature related operations for linear triangle element.
Definition triElem.h:91
static int vtk_map_element_to_num_nodes[16]
Map from element type to number of nodes (for vtk)
static const int vtk_type_triangle
Integer flag for triangle element.
static const int vtk_type_quad
Integer flag for quad element.
static const int vtk_type_tetra
Integer flag for tetrahedron element.
void readVtuFileCells(const std::string &filename, size_t dim, size_t &element_type, size_t &num_elem, std::vector< size_t > *enc, std::vector< std::vector< size_t > > *nec)
Reads cell data, i.e. element-node connectivity and node-element connectivity.
Definition reader.cpp:168
void readMshFileCells(const std::string &filename, size_t dim, size_t &element_type, size_t &num_elem, std::vector< size_t > *enc, std::vector< std::vector< size_t > > *nec)
Reads cell data, i.e. element-node connectivity and node-element connectivity.
Definition reader.cpp:401
bool readVtuFilePointData(const std::string &filename, const std::string &tag, std::vector< uint8_t > *data)
Reads data of specified tag from the vtu file.
Definition reader.cpp:208
void readVtuFileNodes(const std::string &filename, size_t dim, std::vector< util::Point > *nodes, bool ref_config=false)
Reads nodal coordinates.
Definition reader.cpp:137
void readCsvFile(const std::string &filename, size_t dim, std::vector< util::Point > *nodes, std::vector< double > *volumes)
Reads mesh data into node file and element file.
Definition reader.cpp:16
void readMshFile(const std::string &filename, size_t dim, std::vector< util::Point > *nodes, size_t &element_type, size_t &num_elem, std::vector< size_t > *enc, std::vector< std::vector< size_t > > *nec, std::vector< double > *volumes, bool is_fd=false)
Reads mesh data into node file and element file.
Definition reader.cpp:351
std::string printBoxStr(const std::pair< util::Point, util::Point > &box, int nt=print_default_tab)
Returns formatted string for output.
Definition io.h:168
std::string getTabS(int nt)
Returns tab spaces of given size.
Definition io.h:40
std::string printStr(const T &msg, int nt=print_default_tab)
Returns formatted string for output.
Definition io.h:54
std::string getExtensionFromFile(std::string const &filename)
Get extension from the filename.
Definition io.h:428
void log(std::ostringstream &oss, bool screen_out=false, int printMpiRank=print_default_mpi_rank)
Global method to log the message.
Definition io.cpp:38
unsigned int getNThreads()
Get number of threads to be used by taskflow.
bool isLess(const double &a, const double &b)
Returns true if a < b.
Definition function.cpp:20
Structure to read and store mesh related input data.
Definition meshDeck.h:26
std::string printStr(int nt=0, int lvl=0) const
Returns the string containing printable information about the object.
Definition meshDeck.h:95