PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
vtkParticleWriter.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2026 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 "vtkParticleWriter.h"
12#include <util/feElementDefs.h>
13#include <vtkCellArray.h>
14#include <vtkCellData.h>
15#include <vtkDoubleArray.h>
16#include <vtkIdList.h>
17#include <vtkIntArray.h>
18#include <vtkPointData.h>
19#include <vtkPoints.h>
20#include <vtkUnsignedCharArray.h>
21#include <vtkUnsignedIntArray.h>
22
23#include "mesh/mesh.h"
24#include <cstdint>
25#include "data/modelData.h"
28#include "util/parallelUtil.h"
29
30#include "util/vecMethods.h"
31#include <algorithm>
32#include <unordered_map>
33#include <unordered_set>
34#include <vector>
35
37 const std::string &compress_type)
38 : d_compressType(compress_type) {
39
40 std::string f = filename + ".vtu";
41
42 d_writer_p = vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
43 d_writer_p->SetFileName(const_cast<char *>(f.c_str()));
44}
45
47 const data::ModelData *model,
48 const std::vector<std::string> &tags) {
49
50 if (model->d_x.size() == 0)
51 return;
52
53 // write point data
54 auto points = vtkSmartPointer<vtkPoints>::New();
55
56 // get all the nodes first
57 for (const auto &x : model->d_x)
58 points->InsertNextPoint(x.d_x, x.d_y, x.d_z);
59
60 // write point data
61 d_grid_p = vtkSmartPointer<vtkUnstructuredGrid>::New();
62 d_grid_p->SetPoints(points);
63
64 // now write data associated to nodes in both particle and wall
65 double value[3];
66 value[0] = 0;
67 value[1] = 0;
68 value[2] = 0;
69 double p_tag[1];
70 p_tag[0] = 0;
71
72 // handle displacement
73 if (util::methods::isTagInList("Displacement", tags)) {
74
75 auto array = vtkSmartPointer<vtkDoubleArray>::New();
76 array->SetNumberOfComponents(3);
77 array->SetName("Displacement");
78
79 array->SetComponentName(0, "x");
80 array->SetComponentName(1, "y");
81 array->SetComponentName(2, "z");
82
83 for (const auto &ui : model->d_u) {
84 value[0] = ui.d_x;
85 value[1] = ui.d_y;
86 value[2] = ui.d_z;
87 array->InsertNextTuple(value);
88 }
89
90 // write
91 d_grid_p->GetPointData()->AddArray(array);
92 } // displacement
93
94 // handle velocity
95 if (util::methods::isTagInList("Velocity", tags)) {
96
97 auto array = vtkSmartPointer<vtkDoubleArray>::New();
98 array->SetNumberOfComponents(3);
99 array->SetName("Velocity");
100
101 array->SetComponentName(0, "x");
102 array->SetComponentName(1, "y");
103 array->SetComponentName(2, "z");
104
105 for (const auto &ui : model->d_v) {
106 value[0] = ui.d_x;
107 value[1] = ui.d_y;
108 value[2] = ui.d_z;
109 array->InsertNextTuple(value);
110 }
111
112 // write
113 d_grid_p->GetPointData()->AddArray(array);
114 } // velocity
115
116 // handle force
117 if (util::methods::isTagInList("Force_Density", tags)) {
118
119 auto array = vtkSmartPointer<vtkDoubleArray>::New();
120 array->SetNumberOfComponents(3);
121 array->SetName("Force_Density");
122
123 array->SetComponentName(0, "x");
124 array->SetComponentName(1, "y");
125 array->SetComponentName(2, "z");
126
127 for (const auto &ui : model->d_f) {
128 value[0] = ui.d_x;
129 value[1] = ui.d_y;
130 value[2] = ui.d_z;
131 array->InsertNextTuple(value);
132 }
133
134 // write
135 d_grid_p->GetPointData()->AddArray(array);
136 } // force
137
138 // handle force
139 if (util::methods::isTagInList("Force", tags)) {
140
141 auto array = vtkSmartPointer<vtkDoubleArray>::New();
142 array->SetNumberOfComponents(3);
143 array->SetName("Force");
144
145 array->SetComponentName(0, "x");
146 array->SetComponentName(1, "y");
147 array->SetComponentName(2, "z");
148
149 size_t i_count = 0;
150 for (const auto &ui : model->d_f) {
151 const auto &voli = model->d_vol[i_count];
152 value[0] = ui.d_x * voli;
153 value[1] = ui.d_y * voli;
154 value[2] = ui.d_z * voli;
155 array->InsertNextTuple(value);
156
157 i_count++;
158 }
159
160 // write
161 d_grid_p->GetPointData()->AddArray(array);
162 } // force
163
164 // handle fixity
165 if (util::methods::isTagInList("Fixity", tags)) {
166
167 auto array = vtkSmartPointer<vtkDoubleArray>::New();
168 array->SetNumberOfComponents(1);
169 array->SetName("Fixity");
170
171 for (const auto &n : model->d_fix) {
172 p_tag[0] = double(n);
173 array->InsertNextTuple(p_tag);
174 }
175
176 // write
177 d_grid_p->GetPointData()->AddArray(array);
178 } // fixity
179
180 // handle Particle ID
181 if (util::methods::isTagInList("Particle_ID", tags)) {
182
183 auto array = vtkSmartPointer<vtkDoubleArray>::New();
184 array->SetNumberOfComponents(1);
185 array->SetName("Particle_ID");
186
187 for (size_t i = 0; i<model->d_x.size(); i++) {
188 auto pi = model->getPtId(i);
189 p_tag[0] = double(model->getParticleFromAllList(pi)->getId());
190 array->InsertNextTuple(p_tag);
191 }
192
193 // write
194 d_grid_p->GetPointData()->AddArray(array);
195 } // Particle ID
196
197 // handle Zone ID
198 if (util::methods::isTagInList("Zone_ID", tags)) {
199
200 auto array = vtkSmartPointer<vtkDoubleArray>::New();
201 array->SetNumberOfComponents(1);
202 array->SetName("Zone_ID");
203
204 for (size_t i = 0; i<model->d_x.size(); i++) {
205 auto pi = model->getPtId(i);
206 p_tag[0] = double(model->getParticleFromAllList(pi)->d_groups.at("geom_id"));
207 array->InsertNextTuple(p_tag);
208 }
209
210 // write
211 d_grid_p->GetPointData()->AddArray(array);
212 } // Zone ID
213
214 // handle force fixity
215 if (util::methods::isTagInList("Force_Fixity", tags)) {
216
217 auto array = vtkSmartPointer<vtkDoubleArray>::New();
218 array->SetNumberOfComponents(1);
219 array->SetName("Force_Fixity");
220
221 for (const auto &n : model->d_forceFixity) {
222 p_tag[0] = double(n);
223 array->InsertNextTuple(p_tag);
224 }
225
226 // write
227 d_grid_p->GetPointData()->AddArray(array);
228 } // force fixity
229
230 // handle nodal volume
231 if (util::methods::isTagInList("Nodal_Volume", tags)) {
232
233 auto array = vtkSmartPointer<vtkDoubleArray>::New();
234 array->SetNumberOfComponents(1);
235 array->SetName("Nodal_Volume");
236
237 for (const auto &n : model->d_vol) {
238 p_tag[0] = double(n);
239 array->InsertNextTuple(p_tag);
240 }
241
242 // write
243 d_grid_p->GetPointData()->AddArray(array);
244 } // nodal volume
245
246 // handle damage_Z
247 if (util::methods::isTagInList("Damage_Z", tags)) {
248
249 auto array = vtkSmartPointer<vtkDoubleArray>::New();
250 array->SetNumberOfComponents(1);
251 array->SetName("Damage_Z");
252
253 for (const auto &n : model->d_Z) {
254 p_tag[0] = double(n);
255 array->InsertNextTuple(p_tag);
256 }
257
258 // write
259 d_grid_p->GetPointData()->AddArray(array);
260 } // damage_Z
261
262 // handle damage function phi = 1 - (intact bond volume)/(horizon volume)
263 // (Silling 2000/2003, Trask, Bhattacharya "fraction of broken bonds")
264 if (util::methods::isTagInList("Damage", tags) && !model->d_phi.empty()) {
265
266 auto array = vtkSmartPointer<vtkDoubleArray>::New();
267 array->SetNumberOfComponents(1);
268 array->SetName("Damage");
269
270 for (const auto &n : model->d_phi) {
271 p_tag[0] = double(n);
272 array->InsertNextTuple(p_tag);
273 }
274
275 // write
276 d_grid_p->GetPointData()->AddArray(array);
277 } // damage phi
278
279 // handle broken-bond count fraction (Bhattacharya & Lipton damage)
280 if (util::methods::isTagInList("Damage_Bond", tags) &&
281 !model->d_phiBond.empty()) {
282
283 auto array = vtkSmartPointer<vtkDoubleArray>::New();
284 array->SetNumberOfComponents(1);
285 array->SetName("Damage_Bond");
286
287 for (const auto &n : model->d_phiBond) {
288 p_tag[0] = double(n);
289 array->InsertNextTuple(p_tag);
290 }
291
292 // write
293 d_grid_p->GetPointData()->AddArray(array);
294 } // damage bond fraction
295
296 // handle theta
297 if (util::methods::isTagInList("Theta", tags)) {
298
299 if (model->getParticleFromAllList(0)->d_material_p->isStateActive()) {
300
301 auto array = vtkSmartPointer<vtkDoubleArray>::New();
302 array->SetNumberOfComponents(1);
303 array->SetName("Theta");
304
305 for (const auto &n : model->d_thetaX) {
306 p_tag[0] = double(n);
307 array->InsertNextTuple(p_tag);
308 }
309
310 // write
311 d_grid_p->GetPointData()->AddArray(array);
312 }
313 } // Theta
314}
315
317 const data::ModelData *model,
318 const std::vector<std::string> &tags) {
319
320 if (model->d_x.size() == 0)
321 return;
322
323 // write point data
324 appendNodes(model, tags);
325
326 //
327 // process elements data
328 //
329
330 // get total number of elements and maximum number of vertex in any element
331 size_t num_elems = 0;
332 size_t num_vertex = 0;
333
334 // count number of elements in all particles
335 for (const auto &p : model->d_particlesListTypeAll) {
336 //const auto &rp = p->d_rp_p;
337 num_elems += p->getMeshP()->getNumElements();
338 auto n =
339 util::vtk_map_element_to_num_nodes[p->getMeshP()->getElementType()];
340 if (num_vertex < n)
341 num_vertex = n;
342 }
343
344 if (num_elems == 0)
345 return;
346
347 // element node connectivity
348 auto cells = vtkSmartPointer<vtkCellArray>::New();
349 // VTK 9+: legacy Allocate(sz,ext) maps to AllocateExact(sz,sz); use AllocateEstimate.
350 cells->AllocateEstimate(static_cast<vtkIdType>(num_elems), static_cast<vtkIdType>(num_vertex));
351
352 // VTK 9+: prefer vtkUnsignedCharArray for cell types (XML writer path).
353 auto cellTypeArray = vtkSmartPointer<vtkUnsignedCharArray>::New();
354 cellTypeArray->SetNumberOfValues(static_cast<vtkIdType>(num_elems));
355
356 // loop over particles
357 size_t global_elem_counter = 0;
358 for (const auto &p : model->d_particlesListTypeAll) {
359 // get mesh of reference particle in this zone
360 const auto &mesh = p->getMeshP();
361
362 // get element type
363 size_t element_type = mesh->getElementType();
364
365 // loop over elements of this particle
366 size_t num_vertex_p = util::vtk_map_element_to_num_nodes[element_type];
367 vtkIdType ids[8];
368 for (size_t e = 0; e < mesh->getNumElements(); e++) {
369 auto elem = mesh->getElementConnectivity(e);
370
371 // assign global ids to the nodes
372 for (size_t n = 0; n < elem.size(); n++)
373 ids[n] = elem[n] + p->d_globStart;
374
375 cells->InsertNextCell(static_cast<int>(num_vertex_p), ids);
376 cellTypeArray->SetValue(static_cast<vtkIdType>(global_elem_counter),
377 static_cast<unsigned char>(element_type));
378
379 // increment global element counter
380 global_elem_counter++;
381 }
382 }
383
384 d_grid_p->SetCells(cellTypeArray, cells);
385}
386
387namespace {
388
389void appendPointArraysForNodes(vtkUnstructuredGrid *grid,
390 const data::ModelData *model,
391 const std::vector<size_t> &gids,
392 const std::vector<std::string> &tags) {
393 double value[3] = {0., 0., 0.};
394 auto add_vec3 = [&](const char *name, const std::vector<util::Point> &field) {
395 auto array = vtkSmartPointer<vtkDoubleArray>::New();
396 array->SetNumberOfComponents(3);
397 array->SetName(name);
398 array->SetComponentName(0, "x");
399 array->SetComponentName(1, "y");
400 array->SetComponentName(2, "z");
401 for (size_t g : gids) {
402 const auto &ui = field[g];
403 value[0] = ui.d_x;
404 value[1] = ui.d_y;
405 value[2] = ui.d_z;
406 array->InsertNextTuple(value);
407 }
408 grid->GetPointData()->AddArray(array);
409 };
410 auto add_scalar = [&](const char *name, auto getter) {
411 auto array = vtkSmartPointer<vtkDoubleArray>::New();
412 array->SetNumberOfComponents(1);
413 array->SetName(name);
414 for (size_t g : gids) {
415 value[0] = static_cast<double>(getter(g));
416 array->InsertNextTuple(value);
417 }
418 grid->GetPointData()->AddArray(array);
419 };
420
421 if (util::methods::isTagInList("Displacement", tags))
422 add_vec3("Displacement", model->d_u);
423 if (util::methods::isTagInList("Velocity", tags))
424 add_vec3("Velocity", model->d_v);
425 if (util::methods::isTagInList("Force_Density", tags))
426 add_vec3("Force_Density", model->d_f);
427 if (util::methods::isTagInList("Force", tags)) {
428 auto array = vtkSmartPointer<vtkDoubleArray>::New();
429 array->SetNumberOfComponents(3);
430 array->SetName("Force");
431 array->SetComponentName(0, "x");
432 array->SetComponentName(1, "y");
433 array->SetComponentName(2, "z");
434 for (size_t g : gids) {
435 const auto &fi = model->d_f[g];
436 const double vol = model->d_vol[g];
437 value[0] = fi.d_x * vol;
438 value[1] = fi.d_y * vol;
439 value[2] = fi.d_z * vol;
440 array->InsertNextTuple(value);
441 }
442 grid->GetPointData()->AddArray(array);
443 }
444 if (util::methods::isTagInList("Damage_Z", tags) && !model->d_Z.empty())
445 add_scalar("Damage_Z", [&](size_t g) { return model->d_Z[g]; });
446 if (util::methods::isTagInList("Damage", tags) && !model->d_phi.empty())
447 add_scalar("Damage", [&](size_t g) { return model->d_phi[g]; });
448 if (util::methods::isTagInList("Damage_Bond", tags) && !model->d_phiBond.empty())
449 add_scalar("Damage_Bond", [&](size_t g) { return model->d_phiBond[g]; });
450 if (util::methods::isTagInList("Particle_ID", tags))
451 add_scalar("Particle_ID", [&](size_t g) {
452 return static_cast<double>(
453 model->getParticleFromAllList(model->d_ptId[g])->getId());
454 });
455}
456
457} // namespace
458
460 const data::ModelData *model, const std::vector<std::string> &tags) {
461
462 if (model->d_x.empty())
463 return;
464
465 const int mpi_size = util::parallel::mpiSize();
466 const int mpi_rank = util::parallel::mpiRank();
467 if (mpi_size <= 1) {
468 appendMesh(model, tags);
469 return;
470 }
471
472 std::unordered_set<size_t> node_set;
473 struct LocalElem {
474 size_t type{};
475 std::vector<size_t> gids;
476 };
477 std::vector<LocalElem> elems;
478
479 if (model->d_pdDofMpi &&
480 model->d_pdNodePartition.size() == model->d_x.size()) {
481 // Cell owner = min node-owner among vertices; piece includes all nodes of
482 // those cells (may include halo nodes for connectivity).
483 for (const auto &p : model->d_particlesListTypeAll) {
484 const auto &mesh = p->getMeshP();
485 const size_t element_type = mesh->getElementType();
486 for (size_t e = 0; e < mesh->getNumElements(); ++e) {
487 auto conn = mesh->getElementConnectivity(e);
488 size_t cell_owner = model->d_pdNodePartition[conn[0] + p->d_globStart];
489 for (size_t n = 1; n < conn.size(); ++n)
490 cell_owner = std::min(
491 cell_owner,
492 model->d_pdNodePartition[conn[n] + p->d_globStart]);
493 if (static_cast<int>(cell_owner) != mpi_rank)
494 continue;
495 LocalElem le;
496 le.type = element_type;
497 le.gids.reserve(conn.size());
498 for (size_t n : conn) {
499 const size_t g = n + p->d_globStart;
500 le.gids.push_back(g);
501 node_set.insert(g);
502 }
503 elems.push_back(std::move(le));
504 }
505 }
506 } else {
507 // Particle-MPI: whole owned grains; walls only on rank 0.
508 for (const auto &p : model->d_particlesListTypeAll) {
509 if (p->isWall()) {
510 if (mpi_rank != 0)
511 continue;
512 } else if (!particle::isLocallyOwned(*p)) {
513 continue;
514 }
515 for (size_t i = 0; i < p->getNumNodes(); ++i)
516 node_set.insert(p->d_globStart + i);
517 const auto &mesh = p->getMeshP();
518 const size_t element_type = mesh->getElementType();
519 for (size_t e = 0; e < mesh->getNumElements(); ++e) {
520 auto conn = mesh->getElementConnectivity(e);
521 LocalElem le;
522 le.type = element_type;
523 for (size_t n : conn)
524 le.gids.push_back(n + p->d_globStart);
525 elems.push_back(std::move(le));
526 }
527 }
528 }
529
530 if (node_set.empty()) {
531 // Empty piece still valid for PVTU.
532 d_grid_p = vtkSmartPointer<vtkUnstructuredGrid>::New();
533 auto points = vtkSmartPointer<vtkPoints>::New();
534 d_grid_p->SetPoints(points);
535 return;
536 }
537
538 std::vector<size_t> gids(node_set.begin(), node_set.end());
539 std::sort(gids.begin(), gids.end());
540 std::unordered_map<size_t, vtkIdType> g2l;
541 g2l.reserve(gids.size());
542 auto points = vtkSmartPointer<vtkPoints>::New();
543 for (size_t i = 0; i < gids.size(); ++i) {
544 const auto &x = model->d_x[gids[i]];
545 points->InsertNextPoint(x.d_x, x.d_y, x.d_z);
546 g2l[gids[i]] = static_cast<vtkIdType>(i);
547 }
548
549 d_grid_p = vtkSmartPointer<vtkUnstructuredGrid>::New();
550 d_grid_p->SetPoints(points);
551 appendPointArraysForNodes(d_grid_p, model, gids, tags);
552
553 if (elems.empty())
554 return;
555
556 size_t num_vertex = 0;
557 for (const auto &le : elems)
558 num_vertex = std::max(num_vertex, le.gids.size());
559
560 auto cells = vtkSmartPointer<vtkCellArray>::New();
561 cells->AllocateEstimate(static_cast<vtkIdType>(elems.size()),
562 static_cast<vtkIdType>(num_vertex));
563 auto cellTypeArray = vtkSmartPointer<vtkUnsignedCharArray>::New();
564 cellTypeArray->SetNumberOfValues(static_cast<vtkIdType>(elems.size()));
565
566 vtkIdType ids[8];
567 for (size_t ei = 0; ei < elems.size(); ++ei) {
568 const auto &le = elems[ei];
569 for (size_t n = 0; n < le.gids.size(); ++n)
570 ids[n] = g2l.at(le.gids[n]);
571 cells->InsertNextCell(static_cast<int>(le.gids.size()), ids);
572 cellTypeArray->SetValue(static_cast<vtkIdType>(ei),
573 static_cast<unsigned char>(le.type));
574 }
575 d_grid_p->SetCells(cellTypeArray, cells);
576}
577
578void rw::writer::VtkParticleWriter::addTimeStep(const double &timestep) {
579
580 auto t = vtkDoubleArray::New();
581 t->SetName("TIME");
582 t->SetNumberOfTuples(1);
583 t->SetTuple1(0, timestep);
584 d_grid_p->GetFieldData()->AddArray(t);
585}
586
588 d_writer_p->SetInputData(d_grid_p);
589 // VTK 9.1 (linked by PeriDEM) cannot parse AppendedData VTUs from this
590 // writer as Restart.File (base64 → "junk after document element"; raw →
591 // "invalid token"). Ascii is read back by Restart.File without error.
592 d_writer_p->SetDataModeToAscii();
593 d_writer_p->SetCompressor(0);
594 d_writer_p->Write();
595}
596
598 const data::ModelData *model,
599 const std::vector<size_t> *processed_nodes,
600 const std::vector <
601 std::pair<size_t, size_t>> *processed_elems) {
602
603 if (processed_nodes->size() == 0)
604 return;
605
606 // write point data
607 auto points = vtkSmartPointer<vtkPoints>::New();
608
609
610 const size_t num_nodes = processed_nodes->size();
611 const size_t num_elems = processed_elems->size();
612
613 if (num_elems == 0)
614 return;
615
616 // get all the nodes first
617 for (const auto &i : *processed_nodes) {
618 const auto &x = model->d_x[i];
619 points->InsertNextPoint(x.d_x, x.d_y, x.d_z);
620 }
621
622 // write point data
623 d_grid_p = vtkSmartPointer<vtkUnstructuredGrid>::New();
624 d_grid_p->SetPoints(points);
625
626 // now wrtie element data
627 const size_t vtk_element_type = 3; // line element
628 const size_t num_vertex = 2;
629 // element node connectivity
630 auto cells = vtkSmartPointer<vtkCellArray>::New();
631 cells->AllocateEstimate(static_cast<vtkIdType>(num_elems), static_cast<vtkIdType>(num_vertex));
632
633 auto cellTypeArray = vtkSmartPointer<vtkUnsignedCharArray>::New();
634 cellTypeArray->SetNumberOfValues(static_cast<vtkIdType>(num_elems));
635
636 vtkIdType ids[num_vertex];
637 for (size_t i = 0; i < num_elems; i++) {
638
639 ids[0] = (*processed_elems)[i].first;
640 ids[1] = (*processed_elems)[i].second;
641
642 cells->InsertNextCell(static_cast<int>(num_vertex), ids);
643 cellTypeArray->SetValue(static_cast<vtkIdType>(i), static_cast<unsigned char>(vtk_element_type));
644 }
645
646 d_grid_p->SetCells(cellTypeArray, cells);
647
648 // write cell data (normal direction)
649 {
650 auto array = vtkSmartPointer < vtkDoubleArray > ::New();
651 array->SetNumberOfComponents(3);
652 array->SetName("Normal");
653 array->SetComponentName(0, "x");
654 array->SetComponentName(1, "y");
655 array->SetComponentName(2, "z");
656
657 double value[3];
658 for (size_t i = 0; i < num_elems; i++) {
659
660 ids[0] = (*processed_elems)[i].first;
661 ids[1] = (*processed_elems)[i].second;
662
663 auto glob_id1 = (*processed_nodes)[ids[0]];
664 auto glob_id2 = (*processed_nodes)[ids[1]];
665
666 const auto &x1 = model->d_x[glob_id1];
667 const auto &x2 = model->d_x[glob_id2];
668
669 auto xd = (x1 - x2)/((x2 - x1).length());
670
671 value[0] = xd[0];
672 value[1] = xd[1];
673 value[2] = xd[2];
674 array->InsertNextTuple(value);
675 }
676
677 d_grid_p->GetCellData()->AddArray(array);
678 }
679}
680
681
683 const data::ModelData *model) {
684
685 if (model->d_xQuadCur.size() == 0) {
686 std::cout << "VtkParticleWriter::appendStrainStress: Nothing to write.\n";
687 return;
688 }
689
690 // write point data
691 auto points = vtkSmartPointer<vtkPoints>::New();
692
693 // get all the quadrature points first
694 for (const auto &x : model->d_xQuadCur)
695 points->InsertNextPoint(x.d_x, x.d_y, x.d_z);
696
697 // write point data
698 d_grid_p = vtkSmartPointer<vtkUnstructuredGrid>::New();
699 d_grid_p->SetPoints(points);
700
701 // now write data associated to nodes (in this case, quad points are nodes)
702 double value[3] = {0., 0., 0.};
703 double value_s[6] = {0., 0., 0., 0., 0., 0.};
704 double p_tag[1] = {0.};
705
706 auto array_strain = vtkSmartPointer<vtkDoubleArray>::New();
707 array_strain->SetNumberOfComponents(6);
708 array_strain->SetName("Strain");
709
710 auto array_stress = vtkSmartPointer<vtkDoubleArray>::New();
711 array_stress->SetNumberOfComponents(6);
712 array_stress->SetName("Stress");
713
714 std::vector<std::string> coord_strings = {"xx", "yy", "zz", "yz", "xz", "xy"};
715 for (size_t i =0; i<6; i++) {
716 array_strain->SetComponentName(i, coord_strings[i].c_str());
717 array_stress->SetComponentName(i, coord_strings[i].c_str());
718 }
719
720 for (size_t i=0; i<model->d_strain.size(); i++) {
721
722 model->d_strain[i].copy(value_s);
723 array_strain->InsertNextTuple(value_s);
724
725 model->d_stress[i].copy(value_s);
726 array_stress->InsertNextTuple(value_s);
727 }
728
729
730 // write
731 d_grid_p->GetPointData()->AddArray(array_strain);
732 d_grid_p->GetPointData()->AddArray(array_stress);
733}
A class to store model data.
Definition modelData.h:50
std::vector< util::Point > d_x
Current positions of the nodes.
Definition modelData.h:745
std::vector< float > d_Z
Damage at nodes.
Definition modelData.h:818
std::vector< util::Point > d_u
Displacement of the nodes.
Definition modelData.h:748
std::vector< uint8_t > d_fix
Vector of fixity mask of each node.
Definition modelData.h:792
std::vector< util::Point > d_f
Total force on the nodes.
Definition modelData.h:757
size_t & getPtId(size_t i)
Get particle id given the location in particle list.
Definition modelData.h:187
bool d_pdDofMpi
Nodal DOF-MPI active.
Definition modelData.h:680
std::vector< size_t > d_pdNodePartition
Owner rank for each node when d_pdDofMpi is true.
Definition modelData.h:692
std::vector< double > d_thetaX
Dilation.
Definition modelData.h:802
std::vector< size_t > d_ptId
Global node to particle id (walls are assigned id after last particle id)
Definition modelData.h:764
std::vector< float > d_phi
Damage function at the nodes (volume-weighted, Silling 2000)
Definition modelData.h:834
std::vector< particle::BaseParticle * > d_particlesListTypeAll
List of particles + walls.
Definition modelData.h:704
std::vector< double > d_vol
Nodal volumes.
Definition modelData.h:760
std::vector< util::SymMatrix3 > d_stress
Stress in elements (values at quadrature points)
Definition modelData.h:852
std::vector< util::Point > d_v
Velocity of the nodes.
Definition modelData.h:751
std::vector< float > d_phiBond
Damage as broken-bond count fraction (Bhattacharya & Lipton 2023)
Definition modelData.h:837
std::vector< util::SymMatrix3 > d_strain
Strain in elements (values at quadrature points)
Definition modelData.h:849
std::vector< uint8_t > d_forceFixity
Vector of fixity mask of each node for force.
Definition modelData.h:795
const particle::BaseParticle * getParticleFromAllList(size_t i) const
Get pointer to base particle.
Definition modelData.h:86
std::vector< util::Point > d_xQuadCur
Current position of quadrature points.
Definition modelData.h:846
size_t getId() const
Get id.
std::map< std::string, size_t > d_groups
Map that provides different groups of this particle.
std::unique_ptr< material::Material > d_material_p
Pointer to peridynamic material object.
void appendContactData(const data::ModelData *model, const std::vector< size_t > *processed_nodes, const std::vector< std::pair< size_t, size_t > > *processed_elems)
Prepares contact data that is set of nodes in contact and line-element connecting two contacting node...
void appendStrainStress(const data::ModelData *model)
Writes strain/stress.
VtkParticleWriter(const std::string &filename, const std::string &compress_type="")
Constructor.
void appendNodes(const data::ModelData *model, const std::vector< std::string > &tags)
Writes the nodes to the file.
vtkSmartPointer< vtkXMLUnstructuredGridWriter > d_writer_p
XML unstructured grid writer.
void appendMesh(const data::ModelData *model, const std::vector< std::string > &tags)
Writes the nodes to the file.
void addTimeStep(const double &timestep)
Writes the time step to the file.
void appendMeshParallelPiece(const data::ModelData *model, const std::vector< std::string > &tags)
Write only this rank's mesh piece for parallel VTU output.
void close()
Closes the file and store it to the hard disk.
static int vtk_map_element_to_num_nodes[16]
Map from element type to number of nodes (for vtk)
void appendPointArraysForNodes(vtkUnstructuredGrid *grid, const data::ModelData *model, const std::vector< size_t > &gids, const std::vector< std::string > &tags)
Collection of methods and data related to finite element and mesh.
Definition mesh.cpp:29
bool isLocallyOwned(const BaseParticle &p)
True if this rank updates / assembles forces for the particle. Walls are replicated on every rank....
bool isTagInList(const std::string &tag, const std::vector< std::string > &tags)
Returns true if tag is found in the list of tags.
Definition vecMethods.h:284
int mpiSize()
Get size (number) of processors.
int mpiRank()
get rank (id) of this processor