1 // Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and
2 // other Axom Project Developers. See the top-level LICENSE file for details.
3 //
4 // SPDX-License-Identifier: (BSD-3-Clause)
5
6 #include "axom/core.hpp" // for axom macros
7 #include "axom/mint.hpp" // for Mint classes & functions
8
9 // Sidre includes
10 #ifdef AXOM_MINT_USE_SIDRE
11 #include "axom/sidre/core/sidre.hpp"
12 namespace sidre = axom::sidre;
13 #endif
14
15 // C/C++ includes
16 #include <cmath> // for definition of M_PI, exp()
17
18 // namespace aliases
19 namespace mint = axom::mint;
20 namespace numerics = axom::numerics;
21
22 /*!
23 * \file
24 *
25 * \brief Various code snippets/examples used for the Mint tutorial section.
26 *
27 * \note These examples are designed to illustrate specific Mint
28 * concepts and capabilities. Consult the Tutorial section of Mint's
29 * User Guide for more details.
30 *
31 */
32
33 //------------------------------------------------------------------------------
34 // TUTORIAL FUNCTIONS
35 //------------------------------------------------------------------------------
vtk_output(mint::Mesh * mesh,const std::string fileName)36 void vtk_output(mint::Mesh* mesh, const std::string fileName)
37 {
38 // sphinx_tutorial_vtk_output_start
39
40 mint::write_vtk(mesh, fileName);
41
42 // sphinx_tutorial_vtk_output_end
43 }
44
45 //------------------------------------------------------------------------------
node_traversals()46 void node_traversals()
47 {
48 using exec_policy = axom::SEQ_EXEC;
49 using IndexType = axom::IndexType;
50
51 const double lo[] = {-5.0, -5.0};
52 const double hi[] = {5.0, 5.0};
53 mint::UniformMesh mesh(lo, hi, 50, 50);
54
55 mesh.createField<double>("xold", mint::NODE_CENTERED);
56 mesh.createField<double>("yold", mint::NODE_CENTERED);
57 mesh.createField<double>("vx", mint::NODE_CENTERED);
58 mesh.createField<double>("vy", mint::NODE_CENTERED);
59 mesh.createField<double>("vmag", mint::NODE_CENTERED);
60 mesh.createField<IndexType>("ID", mint::NODE_CENTERED);
61
62 // Index example
63 {
64 // sphinx_tutorial_for_all_nodes_index_start
65
66 const double* vx = mesh.getFieldPtr<double>("vx", mint::NODE_CENTERED);
67 const double* vy = mesh.getFieldPtr<double>("vy", mint::NODE_CENTERED);
68
69 double* vmag = mesh.getFieldPtr<double>("vmag", mint::NODE_CENTERED);
70
71 mint::for_all_nodes<exec_policy>(
72 &mesh,
73 AXOM_LAMBDA(IndexType nodeIdx) {
74 const double vx2 = vx[nodeIdx] * vx[nodeIdx];
75 const double vy2 = vy[nodeIdx] * vy[nodeIdx];
76 vmag[nodeIdx] = sqrt(vx2 + vy2);
77 });
78
79 // sphinx_tutorial_for_all_nodes_index_end
80 }
81
82 // IJ examples
83 {
84 // sphinx_tutorial_for_all_nodes_ij_start
85
86 const IndexType jp = mesh.nodeJp();
87
88 IndexType* ID = mesh.getFieldPtr<IndexType>("ID", mint::NODE_CENTERED);
89 mint::for_all_nodes<exec_policy, mint::xargs::ij>(
90 &mesh,
91 AXOM_LAMBDA(IndexType nodeIdx, IndexType i, IndexType j) {
92 ID[nodeIdx] = i + j * jp;
93 });
94
95 // sphinx_tutorial_for_all_nodes_ij_end
96 }
97
98 // XY example
99 {
100 // sphinx_tutorial_for_all_nodes_xy_start
101
102 double invdt = 0.5;
103
104 const double* xold = mesh.getFieldPtr<double>("xold", mint::NODE_CENTERED);
105 const double* yold = mesh.getFieldPtr<double>("yold", mint::NODE_CENTERED);
106
107 double* vx = mesh.getFieldPtr<double>("vx", mint::NODE_CENTERED);
108 double* vy = mesh.getFieldPtr<double>("vy", mint::NODE_CENTERED);
109
110 mint::for_all_nodes<exec_policy, mint::xargs::xy>(
111 &mesh,
112 AXOM_LAMBDA(IndexType nodeIdx, double x, double y) {
113 vx[nodeIdx] = (x - xold[nodeIdx]) * invdt;
114 vy[nodeIdx] = (y - yold[nodeIdx]) * invdt;
115 });
116
117 // sphinx_tutorial_for_all_nodes_xy_end
118 }
119 }
120
121 //------------------------------------------------------------------------------
cell_traversals()122 void cell_traversals()
123 {
124 using exec_policy = axom::SEQ_EXEC;
125 using IndexType = axom::IndexType;
126
127 const double lo[] = {-5.0, -5.0};
128 const double hi[] = {5.0, 5.0};
129 mint::UniformMesh mesh(lo, hi, 50, 50);
130
131 mesh.createField<double>("vx", mint::NODE_CENTERED);
132 mesh.createField<double>("vy", mint::NODE_CENTERED);
133
134 mesh.createField<double>("cell_vx", mint::CELL_CENTERED);
135 mesh.createField<double>("cell_vy", mint::CELL_CENTERED);
136 mesh.createField<double>("den", mint::CELL_CENTERED);
137 mesh.createField<double>("mass", mint::CELL_CENTERED);
138 mesh.createField<double>("vol", mint::CELL_CENTERED);
139 mesh.createField<double>("xc", mint::CELL_CENTERED);
140 mesh.createField<double>("yc", mint::CELL_CENTERED);
141 mesh.createField<double>("perimeter", mint::CELL_CENTERED);
142 mesh.createField<IndexType>("ID", mint::CELL_CENTERED);
143
144 mesh.createField<double>("area", mint::FACE_CENTERED);
145 // Index example
146 {
147 // sphinx_tutorial_for_all_cells_index_start
148
149 const double* mass = mesh.getFieldPtr<double>("mass", mint::CELL_CENTERED);
150 const double* vol = mesh.getFieldPtr<double>("vol", mint::CELL_CENTERED);
151
152 double* den = mesh.getFieldPtr<double>("den", mint::CELL_CENTERED);
153
154 mint::for_all_cells<exec_policy>(
155 &mesh,
156 AXOM_LAMBDA(IndexType cellIdx) {
157 den[cellIdx] = mass[cellIdx] / vol[cellIdx];
158 });
159
160 // sphinx_tutorial_for_all_cells_index_end
161 }
162
163 // IJ example
164 {
165 // sphinx_tutorial_for_all_cells_ij_start
166
167 const IndexType jp = mesh.cellJp();
168
169 IndexType* ID = mesh.getFieldPtr<IndexType>("ID", mint::CELL_CENTERED);
170 mint::for_all_cells<exec_policy, mint::xargs::ij>(
171 &mesh,
172 AXOM_LAMBDA(IndexType cellIdx, IndexType i, IndexType j) {
173 ID[cellIdx] = i + j * jp;
174 });
175
176 // sphinx_tutorial_for_all_cells_ij_end
177 }
178
179 // nodeIds example
180 {
181 // sphinx_tutorial_for_all_cells_nodeids_start
182
183 const double* vx = mesh.getFieldPtr<double>("vx", mint::NODE_CENTERED);
184 const double* vy = mesh.getFieldPtr<double>("vy", mint::NODE_CENTERED);
185
186 double* cell_vx = mesh.getFieldPtr<double>("cell_vx", mint::CELL_CENTERED);
187 double* cell_vy = mesh.getFieldPtr<double>("cell_vy", mint::CELL_CENTERED);
188
189 mint::for_all_cells<exec_policy, mint::xargs::nodeids>(
190 &mesh,
191 AXOM_LAMBDA(IndexType cellIdx, const IndexType* nodeIDs, IndexType N) {
192 // sum nodal contributions
193 cell_vx[cellIdx] = 0.0;
194 cell_vy[cellIdx] = 0.0;
195 for(IndexType inode = 0; inode < N; ++inode)
196 {
197 cell_vx[cellIdx] += vx[nodeIDs[inode]];
198 cell_vy[cellIdx] += vy[nodeIDs[inode]];
199 } // END for all cell nodes
200
201 // average at the cell center
202 const double invf = 1.0 / static_cast<double>(N);
203 cell_vx[cellIdx] *= invf;
204 cell_vy[cellIdx] *= invf;
205 });
206
207 // sphinx_tutorial_for_all_cells_nodeids_end
208 }
209
210 // coords example
211 {
212 // sphinx_tutorial_for_all_cells_coords_start
213
214 double* xc = mesh.getFieldPtr<double>("xc", mint::CELL_CENTERED);
215 double* yc = mesh.getFieldPtr<double>("yc", mint::CELL_CENTERED);
216
217 mint::for_all_cells<exec_policy, mint::xargs::coords>(
218 &mesh,
219 AXOM_LAMBDA(IndexType cellIdx,
220 const numerics::Matrix<double>& coords,
221 const IndexType* AXOM_UNUSED_PARAM(nodeIdx)) {
222 // sum nodal coordinates
223 double xsum = 0.0;
224 double ysum = 0.0;
225 const int numNodes = coords.getNumColumns();
226 for(int inode = 0; inode < numNodes; ++inode)
227 {
228 const double* node = coords.getColumn(inode);
229 xsum += node[mint::X_COORDINATE];
230 ysum += node[mint::Y_COORDINATE];
231 } // end for all cell nodes
232
233 // compute centroid by averaging nodal coordinates
234 const double invf = 1.0 / static_cast<double>(numNodes);
235 xc[cellIdx] = xsum * invf;
236 yc[cellIdx] = ysum * invf;
237 });
238
239 // sphinx_tutorial_for_all_cells_coords_end
240 }
241
242 // faceids example
243 {
244 // sphinx_tutorial_for_all_cells_faceids_start
245
246 const double* area = mesh.getFieldPtr<double>("area", mint::FACE_CENTERED);
247 double* perimeter =
248 mesh.getFieldPtr<double>("perimeter", mint::CELL_CENTERED);
249
250 mint::for_all_cells<exec_policy, mint::xargs::faceids>(
251 &mesh,
252 AXOM_LAMBDA(IndexType cellIdx, const IndexType* faceIDs, IndexType N) {
253 perimeter[cellIdx] = 0.0;
254 for(IndexType iface = 0; iface < N; ++iface)
255 {
256 perimeter[cellIdx] += area[faceIDs[iface]];
257 }
258 });
259
260 // sphinx_tutorial_for_all_cells_faceids_end
261 }
262 }
263
264 //------------------------------------------------------------------------------
face_traversals()265 void face_traversals()
266 {
267 using exec_policy = axom::SEQ_EXEC;
268 using IndexType = axom::IndexType;
269
270 const double lo[] = {-5.0, -5.0};
271 const double hi[] = {5.0, 5.0};
272 mint::UniformMesh mesh(lo, hi, 50, 50);
273
274 mesh.createField<double>("vx", mint::NODE_CENTERED);
275 mesh.createField<double>("vy", mint::NODE_CENTERED);
276
277 mesh.createField<double>("t1", mint::FACE_CENTERED);
278 mesh.createField<double>("t2", mint::FACE_CENTERED);
279 mesh.createField<double>("w", mint::FACE_CENTERED);
280 ;
281 mesh.createField<double>("temp", mint::FACE_CENTERED);
282 mesh.createField<double>("face_vx", mint::FACE_CENTERED);
283 mesh.createField<double>("face_vy", mint::FACE_CENTERED);
284 mesh.createField<double>("fx", mint::FACE_CENTERED);
285 mesh.createField<double>("fy", mint::FACE_CENTERED);
286 mesh.createField<IndexType>("boundary", mint::FACE_CENTERED);
287
288 // Index example
289 {
290 // sphinx_tutorial_for_all_faces_index_start
291
292 const double* t1 = mesh.getFieldPtr<double>("t1", mint::FACE_CENTERED);
293 const double* t2 = mesh.getFieldPtr<double>("t2", mint::FACE_CENTERED);
294 const double* w = mesh.getFieldPtr<double>("w", mint::FACE_CENTERED);
295
296 double* temp = mesh.getFieldPtr<double>("temp", mint::FACE_CENTERED);
297 mint::for_all_faces<exec_policy>(
298 &mesh,
299 AXOM_LAMBDA(IndexType faceIdx) {
300 const double wf = w[faceIdx];
301 const double a = t1[faceIdx];
302 const double b = t2[faceIdx];
303
304 temp[faceIdx] = wf * a + (1. - wf) * b;
305 });
306
307 // sphinx_tutorial_for_all_faces_index_end
308 }
309
310 // nodeids example
311 {
312 // sphinx_tutorial_for_all_faces_nodeids_start
313
314 const double* vx = mesh.getFieldPtr<double>("vx", mint::NODE_CENTERED);
315 const double* vy = mesh.getFieldPtr<double>("vy", mint::NODE_CENTERED);
316
317 double* face_vx = mesh.getFieldPtr<double>("face_vx", mint::FACE_CENTERED);
318 double* face_vy = mesh.getFieldPtr<double>("face_vy", mint::FACE_CENTERED);
319
320 mint::for_all_faces<exec_policy, mint::xargs::nodeids>(
321 &mesh,
322 AXOM_LAMBDA(IndexType faceIdx, const IndexType* nodeIDs, IndexType N) {
323 // sum constituent face node contributions
324 face_vx[faceIdx] = 0.0;
325 face_vy[faceIdx] = 0.0;
326 for(int inode = 0; inode < N; ++inode)
327 {
328 face_vx[faceIdx] += vx[nodeIDs[inode]];
329 face_vy[faceIdx] += vy[nodeIDs[inode]];
330 } // END for all face nodes
331
332 // average
333 const double invf = 1.0 / static_cast<double>(N);
334 face_vx[faceIdx] *= invf;
335 face_vy[faceIdx] *= invf;
336 });
337
338 // sphinx_tutorial_for_all_faces_nodeids_end
339 }
340
341 // coords example
342 {
343 // sphinx_tutorial_for_all_faces_coords_start
344
345 double* fx = mesh.getFieldPtr<double>("fx", mint::FACE_CENTERED);
346 double* fy = mesh.getFieldPtr<double>("fy", mint::FACE_CENTERED);
347
348 mint::for_all_faces<exec_policy, mint::xargs::coords>(
349 &mesh,
350 AXOM_LAMBDA(IndexType faceIdx,
351 const numerics::Matrix<double>& coords,
352 const IndexType* AXOM_UNUSED_PARAM(nodeIdx)) {
353 // sum nodal coordinates
354 double xsum = 0.0;
355 double ysum = 0.0;
356 const int numNodes = coords.getNumColumns();
357 for(int inode = 0; inode < numNodes; ++inode)
358 {
359 const double* node = coords.getColumn(inode);
360 xsum += node[mint::X_COORDINATE];
361 ysum += node[mint::Y_COORDINATE];
362 } // end for all face nodes
363
364 // compute centroid by averaging nodal coordinates
365 const double invf = 1.0 / static_cast<double>(numNodes);
366 fx[faceIdx] = xsum * invf;
367 fy[faceIdx] = ysum * invf;
368 });
369
370 // sphinx_tutorial_for_all_faces_coords_end
371 }
372
373 // cellids example
374 {
375 // sphinx_tutorial_for_all_faces_cellids_start
376
377 constexpr IndexType ON_BOUNDARY = 1;
378 constexpr IndexType INTERIOR = 0;
379
380 IndexType* boundary =
381 mesh.getFieldPtr<IndexType>("boundary", mint::FACE_CENTERED);
382
383 mint::for_all_faces<exec_policy, mint::xargs::cellids>(
384 &mesh,
385 AXOM_LAMBDA(IndexType faceIdx, IndexType AXOM_UNUSED_PARAM(c1), IndexType c2) {
386 boundary[faceIdx] = (c2 == -1) ? ON_BOUNDARY : INTERIOR;
387 });
388
389 // sphinx_tutorial_for_all_faces_cellids_end
390 }
391 }
392
393 //------------------------------------------------------------------------------
fem_tutorial()394 void fem_tutorial()
395 {
396 // sphinx_tutorial_create_fe_start
397
398 constexpr bool ZERO_COPY = true;
399
400 double coords[] = {
401 0.0,
402 0.0, // x1, y1
403 5.0,
404 0.0, // x2, y2
405 5.0,
406 5.0, // x3, y3,
407 0.0,
408 5.0 // x4, y4
409 };
410
411 numerics::Matrix<double> nodes_matrix(2, 4, coords, ZERO_COPY);
412 mint::FiniteElement fe(nodes_matrix, mint::QUAD);
413
414 // bind to FE basis, wires the shape function pointers
415 mint::bind_basis<MINT_LAGRANGE_BASIS, mint::QUAD>(fe);
416
417 // sphinx_tutorial_create_fe_end
418
419 // sphinx_tutorial_evaluate_shape_functions_start
420
421 // isoparametric center
422 double xi[] = {0.5, 0.5};
423 double N[4];
424 fe.evaluateShapeFunctions(xi, N);
425
426 // sphinx_tutorial_evaluate_shape_functions_end
427
428 // sphinx_tutorial_jacobian_start
429
430 numerics::Matrix<double> J(2, 2);
431 fe.jacobian(xi, J);
432
433 const double jdet = numerics::determinant(J);
434 std::cout << "jacobian determinant: " << jdet << std::endl;
435
436 // sphinx_tutorial_jacobian_end
437
438 // sphinx_tutorial_forward_map_start
439
440 double xc[2];
441 fe.computePhysicalCoords(xi, xc);
442 std::cout << "xc: ( ";
443 std::cout << xc[0] << ", " << xc[1];
444 std::cout << " )\n";
445
446 // sphinx_tutorial_forward_map_end
447
448 // sphinx_tutorial_inverse_map_start
449
450 double xr[2];
451 int status = fe.computeReferenceCoords(xc, xr);
452
453 switch(status)
454 {
455 case mint::INVERSE_MAP_FAILED:
456 std::cout << "Newton-Raphson failed!";
457 break;
458 case mint::OUTSIDE_ELEMENT:
459 std::cout << "point is outside!\n";
460 break;
461 default:
462 // found the reference coordinates!
463 std::cout << "xr: ( ";
464 std::cout << xr[0] << ", " << xr[1];
465 std::cout << " )\n";
466 }
467
468 // sphinx_tutorial_inverse_map_end
469 }
470
471 //------------------------------------------------------------------------------
working_with_fields(mint::Mesh * mesh)472 void working_with_fields(mint::Mesh* mesh)
473 {
474 constexpr int FIELD_ASSOCIATION = mint::NODE_CENTERED;
475
476 { // START unnamed namespace
477
478 // sphinx_tutorial_add_fields_start
479
480 double* den = mesh->createField<double>("den", mint::CELL_CENTERED);
481 double* vel = mesh->createField<double>("vel", mint::NODE_CENTERED, 3);
482
483 // sphinx_tutorial_add_fields_end
484
485 AXOM_UNUSED_VAR(den);
486 AXOM_UNUSED_VAR(vel);
487
488 } // END unnamed namespace
489
490 // sphinx_tutorial_get_field_by_name_start
491
492 double* den = mesh->getFieldPtr<double>("den", mint::CELL_CENTERED);
493
494 axom::IndexType nc = -1; // number of components
495 double* vel = mesh->getFieldPtr<double>("vel", mint::NODE_CENTERED, nc);
496
497 // sphinx_tutorial_get_field_by_name_end
498
499 // sphinx_tutorial_check_fields_start
500
501 const bool hasDen = mesh->hasField("den", mint::CELL_CENTERED);
502 const bool hasVel = mesh->hasField("vel", mint::NODE_CENTERED);
503
504 // sphinx_tutorial_check_fields_end
505
506 // sphinx_tutorial_remove_fields_start
507
508 bool isRemoved = mesh->removeField("den", mint::CELL_CENTERED);
509
510 // sphinx_tutorial_remove_fields_end
511
512 // sphinx_tutorial_query_fields_start
513
514 const mint::FieldData* fieldData = mesh->getFieldData(FIELD_ASSOCIATION);
515
516 const int numFields = fieldData->getNumFields();
517 for(int ifield = 0; ifield < numFields; ++ifield)
518 {
519 const mint::Field* field = fieldData->getField(ifield);
520
521 const std::string& fieldName = field->getName();
522 axom::IndexType numTuples = field->getNumTuples();
523 axom::IndexType numComponents = field->getNumComponents();
524
525 std::cout << "field name: " << fieldName << std::endl;
526 std::cout << "numTuples: " << numTuples << std::endl;
527 std::cout << "numComponents: " << numComponents << std::endl;
528
529 if(field->getType() == mint::DOUBLE_FIELD_TYPE)
530 {
531 double* data = mesh->getFieldPtr<double>(fieldName, FIELD_ASSOCIATION);
532 data[0] = 42.0;
533 // process double precision floating point data
534 // ...
535 }
536 else if(field->getType() == mint::INT32_FIELD_TYPE)
537 {
538 int* data = mesh->getFieldPtr<int>(fieldName, FIELD_ASSOCIATION);
539 data[0] = 42;
540 // process integral data
541 // ...
542 }
543 // ...
544
545 } // END for all fields
546
547 // sphinx_tutorial_query_fields_end
548
549 AXOM_UNUSED_VAR(hasDen);
550 AXOM_UNUSED_VAR(hasVel);
551 AXOM_UNUSED_VAR(den);
552 AXOM_UNUSED_VAR(vel);
553 AXOM_UNUSED_VAR(isRemoved);
554 }
555
556 //------------------------------------------------------------------------------
construct_uniform()557 void construct_uniform()
558 {
559 // sphinx_tutorial_construct_uniform_start
560
561 const double lo[] = {-5.0, -5.0};
562 const double hi[] = {5.0, 5.0};
563 mint::UniformMesh mesh(lo, hi, 50, 50);
564
565 // sphinx_tutorial_construct_uniform_end
566
567 mint::write_vtk(&mesh, "tutorial_uniform_mesh.vtk");
568 }
569
570 //------------------------------------------------------------------------------
construct_rectilinear()571 void construct_rectilinear()
572 {
573 // sphinx_tutorial_construct_rectilinear_start
574
575 constexpr double beta = 0.1;
576 const double expbeta = exp(beta);
577 const double invf = 1 / (expbeta - 1.0);
578
579 // construct a N x N rectilinear mesh
580 constexpr axom::IndexType N = 25;
581 mint::RectilinearMesh mesh(N, N);
582 double* x = mesh.getCoordinateArray(mint::X_COORDINATE);
583 double* y = mesh.getCoordinateArray(mint::Y_COORDINATE);
584
585 // fill the coordinates along each axis
586 x[0] = y[0] = 0.0;
587 for(int i = 1; i < N; ++i)
588 {
589 const double delta = (exp(i * beta) - 1.0) * invf;
590 x[i] = x[i - 1] + delta;
591 y[i] = y[i - 1] + delta;
592 }
593
594 // sphinx_tutorial_construct_rectilinear_end
595
596 mint::write_vtk(&mesh, "tutorial_rectilinear_mesh.vtk");
597 }
598
599 //------------------------------------------------------------------------------
construct_curvilinear()600 void construct_curvilinear()
601 {
602 // sphinx_tutorial_construct_curvilinear_start
603
604 constexpr double R = 2.5;
605 constexpr double M = (2 * M_PI) / 50.0;
606 constexpr double h = 0.5;
607 constexpr axom::IndexType N = 25;
608
609 // construct the curvilinear mesh object
610 mint::CurvilinearMesh mesh(N, N);
611
612 // get a handle on the coordinate arrays
613 double* x = mesh.getCoordinateArray(mint::X_COORDINATE);
614 double* y = mesh.getCoordinateArray(mint::Y_COORDINATE);
615
616 // fill the coordinates of the curvilinear mesh
617 const axom::IndexType jp = mesh.nodeJp();
618 for(axom::IndexType j = 0; j < N; ++j)
619 {
620 const axom::IndexType j_offset = j * jp;
621
622 for(axom::IndexType i = 0; i < N; ++i)
623 {
624 const axom::IndexType nodeIdx = i + j_offset;
625
626 const double xx = h * i;
627 const double yy = h * j;
628 const double alpha = yy + R;
629 const double beta = xx * M;
630
631 x[nodeIdx] = alpha * cos(beta);
632 y[nodeIdx] = alpha * sin(beta);
633 } // END for all i
634
635 } // END for all j
636
637 // sphinx_tutorial_construct_curvilinear_end
638
639 mint::write_vtk(&mesh, "tutorial_curvilinear_mesh.vtk");
640 }
641
642 //------------------------------------------------------------------------------
construct_single_cell_type_unstructured()643 void construct_single_cell_type_unstructured()
644 {
645 // sphinx_tutorial_construct_unstructured_start
646
647 constexpr int DIMENSION = 2;
648 constexpr mint::CellType CELL_TYPE = mint::TRIANGLE;
649
650 // Construct the mesh object
651 mint::UnstructuredMesh<mint::SINGLE_SHAPE> mesh(DIMENSION, CELL_TYPE);
652
653 // Append the mesh nodes
654 const axom::IndexType n0 = mesh.appendNode(0.0, 0.0);
655 const axom::IndexType n1 = mesh.appendNode(2.0, 0.0);
656 const axom::IndexType n2 = mesh.appendNode(1.0, 1.0);
657 const axom::IndexType n3 = mesh.appendNode(3.5, 1.0);
658 const axom::IndexType n4 = mesh.appendNode(2.5, 2.0);
659 const axom::IndexType n5 = mesh.appendNode(5.0, 0.0);
660
661 // Append mesh cells
662 const axom::IndexType c0[] = {n1, n3, n2};
663 const axom::IndexType c1[] = {n2, n0, n1};
664 const axom::IndexType c2[] = {n3, n4, n2};
665 const axom::IndexType c3[] = {n1, n5, n3};
666
667 mesh.appendCell(c0);
668 mesh.appendCell(c1);
669 mesh.appendCell(c2);
670 mesh.appendCell(c3);
671
672 // sphinx_tutorial_construct_unstructured_end
673
674 // STEP 3: write output mesh
675 mint::write_vtk(&mesh, "tutorial_triangle_mesh.vtk");
676 }
677
678 //------------------------------------------------------------------------------
construct_mixed_cell_type_unstructured()679 void construct_mixed_cell_type_unstructured()
680 {
681 // sphinx_tutorial_construct_unstructured_mixed_start
682
683 constexpr int DIMENSION = 2;
684
685 // Construct the mesh object
686 mint::UnstructuredMesh<mint::MIXED_SHAPE> mesh(DIMENSION);
687
688 // Append the mesh nodes
689 const axom::IndexType n0 = mesh.appendNode(0.0, 0.0);
690 const axom::IndexType n1 = mesh.appendNode(2.0, 0.0);
691 const axom::IndexType n2 = mesh.appendNode(1.0, 1.0);
692 const axom::IndexType n3 = mesh.appendNode(3.5, 1.0);
693 const axom::IndexType n4 = mesh.appendNode(2.5, 2.0);
694 const axom::IndexType n5 = mesh.appendNode(5.0, 0.0);
695
696 // Append mesh cells
697 const axom::IndexType c0[] = {n0, n1, n2};
698 const axom::IndexType c1[] = {n1, n5, n3, n2};
699 const axom::IndexType c2[] = {n3, n4, n2};
700
701 mesh.appendCell(c0, mint::TRIANGLE);
702 mesh.appendCell(c1, mint::QUAD);
703 mesh.appendCell(c2, mint::TRIANGLE);
704
705 // sphinx_tutorial_construct_unstructured_mixed_end
706
707 // STEP 3: write output mesh
708 mint::write_vtk(&mesh, "tutorial_mixed_unstructured_mesh.vtk");
709 }
710
711 //------------------------------------------------------------------------------
using_external_storage()712 void using_external_storage()
713 {
714 // sphinx_tutorial_using_external_storage_start
715
716 constexpr axom::IndexType NUM_NODES = 6;
717 constexpr axom::IndexType NUM_CELLS = 4;
718
719 // application buffers
720 double x[] = {0.0, 2.0, 1.0, 3.5, 2.5, 5.0};
721 double y[] = {0.0, 0.0, 1.0, 1.0, 2.0, 0.0};
722
723 axom::IndexType cell_connectivity[] = {
724 1,
725 3,
726 2, // c0
727 2,
728 0,
729 1, // c1
730 3,
731 4,
732 2, // c2
733 1,
734 5,
735 3 // c3
736 };
737
738 // cell-centered density field values
739 double den[] = {0.5, 1.2, 2.5, 0.9};
740
741 // construct mesh object with external buffers
742 using MeshType = mint::UnstructuredMesh<mint::SINGLE_SHAPE>;
743 MeshType* mesh =
744 new MeshType(mint::TRIANGLE, NUM_CELLS, cell_connectivity, NUM_NODES, x, y);
745
746 // register external field
747 mesh->createField<double>("den", mint::CELL_CENTERED, den);
748
749 // output external mesh to vtk
750 mint::write_vtk(mesh, "tutorial_external_mesh.vtk");
751
752 // delete the mesh, doesn't touch application buffers
753 delete mesh;
754 mesh = nullptr;
755
756 // sphinx_tutorial_using_external_storage_end
757 }
758
759 //------------------------------------------------------------------------------
using_sidre()760 void using_sidre()
761 {
762 #ifdef AXOM_MINT_USE_SIDRE
763
764 // sphinx_tutorial_using_sidre_create_mesh_start
765 // create a Sidre Datastore to store the mesh
766 sidre::DataStore ds;
767 sidre::Group* group = ds.getRoot();
768
769 // Construct the mesh object and populate the supplied Sidre Group
770 mint::UnstructuredMesh<mint::SINGLE_SHAPE> mesh(2, mint::TRIANGLE, group);
771
772 // Append the mesh nodes
773 const axom::IndexType n0 = mesh.appendNode(0.0, 0.0);
774 const axom::IndexType n1 = mesh.appendNode(2.0, 0.0);
775 const axom::IndexType n2 = mesh.appendNode(1.0, 1.0);
776 const axom::IndexType n3 = mesh.appendNode(3.5, 1.0);
777 const axom::IndexType n4 = mesh.appendNode(2.5, 2.0);
778 const axom::IndexType n5 = mesh.appendNode(5.0, 0.0);
779
780 // Append mesh cells
781 const axom::IndexType c0[] = {n1, n3, n2};
782 const axom::IndexType c1[] = {n2, n0, n1};
783 const axom::IndexType c2[] = {n3, n4, n2};
784 const axom::IndexType c3[] = {n1, n5, n3};
785
786 mesh.appendCell(c0);
787 mesh.appendCell(c1);
788 mesh.appendCell(c2);
789 mesh.appendCell(c3);
790
791 // create a cell-centered field
792 double* den = mesh.createField<double>("den", mint::CELL_CENTERED);
793
794 // set density values at each cell
795 den[0] = 0.5; // c0
796 den[1] = 1.2; // c1
797 den[2] = 2.5; // c2
798 den[3] = 0.9; // c3
799
800 // sphinx_tutorial_using_sidre_create_mesh_end
801
802 std::ofstream ofs;
803 ofs.open("sphinx_tutorial_sidre_tree.txt");
804 group->print(ofs);
805 ofs.close();
806
807 // sphinx_tutorial_sidre_import_start
808
809 mint::Mesh* imported_mesh = mint::getMesh(group);
810 std::cout << "Mesh Type: " << imported_mesh->getMeshType() << std::endl;
811 std::cout << "hasSidre: " << imported_mesh->hasSidreGroup() << std::endl;
812
813 mint::write_vtk(imported_mesh, "tutorial_imported_mesh.vtk");
814
815 delete imported_mesh;
816 imported_mesh = nullptr;
817
818 // sphinx_tutorial_sidre_import_end
819
820 #endif /* AXOM_MINT_USE_SIDRE */
821 }
822
823 /*!
824 * \brief Tutorial main
825 */
main(int AXOM_UNUSED_PARAM (argc),char ** AXOM_UNUSED_PARAM (argv))826 int main(int AXOM_UNUSED_PARAM(argc), char** AXOM_UNUSED_PARAM(argv))
827 {
828 // Native construction of various mesh types
829 construct_uniform();
830 construct_rectilinear();
831 construct_curvilinear();
832 construct_single_cell_type_unstructured();
833 construct_mixed_cell_type_unstructured();
834
835 fem_tutorial();
836 using_sidre();
837 using_external_storage();
838
839 node_traversals();
840 cell_traversals();
841 face_traversals();
842
843 const double lo[] = {-5.0, -5.0};
844 const double hi[] = {5.0, 5.0};
845 mint::UniformMesh mesh(lo, hi, 50, 50);
846
847 working_with_fields(&mesh);
848 vtk_output(&mesh, "tutorial_mesh.vtk");
849
850 return 0;
851 }
852