Loading...
Searching...
No Matches
volcartesian.cpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
25#include <cmath>
26#include <bitset>
27#if BITPIT_ENABLE_MPI==1
28# include <mpi.h>
29#endif
30
31#include "bitpit_common.hpp"
32
33#include "volcartesian.hpp"
34
35namespace bitpit {
36
67#if BITPIT_ENABLE_MPI==1
68 : VolumeKernel(MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
69#else
70 : VolumeKernel(ADAPTION_DISABLED)
71#endif
72{
73 initialize();
74}
75
85 const std::array<double, 3> &origin,
86 const std::array<double, 3> &lengths,
87 const std::array<int, 3> &nCells)
88 : VolCartesian(PatchManager::AUTOMATIC_ID, dimension, origin, lengths, nCells)
89{
90}
91
101VolCartesian::VolCartesian(int id, int dimension,
102 const std::array<double, 3> &origin,
103 const std::array<double, 3> &lengths,
104 const std::array<int, 3> &nCells)
105#if BITPIT_ENABLE_MPI==1
106 : VolumeKernel(id, dimension, MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
107#else
108 : VolumeKernel(id, dimension, ADAPTION_DISABLED)
109#endif
110{
111 initialize();
112
113 setOrigin(origin);
114 setLengths(lengths);
115
116 setDiscretization(nCells);
117}
118
128 const std::array<double, 3> &origin,
129 double length, int nCells)
130 : VolCartesian(PatchManager::AUTOMATIC_ID, dimension, origin, length, nCells)
131{
132}
133
143VolCartesian::VolCartesian(int id, int dimension,
144 const std::array<double, 3> &origin,
145 double length, int nCells)
146#if BITPIT_ENABLE_MPI==1
147 : VolumeKernel(id, dimension, MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
148#else
149 : VolumeKernel(id, dimension, ADAPTION_DISABLED)
150#endif
151{
152 initialize();
153
154 setOrigin(origin);
155 setLengths({{length, length, length}});
156
157 setDiscretization({{nCells, nCells, nCells}});
158}
159
169 const std::array<double, 3> &origin,
170 double length, double dh)
171 : VolCartesian(PatchManager::AUTOMATIC_ID, dimension, origin, length, dh)
172{
173}
174
184VolCartesian::VolCartesian(int id, int dimension,
185 const std::array<double, 3> &origin,
186 double length, double dh)
187#if BITPIT_ENABLE_MPI==1
188 : VolumeKernel(id, dimension, MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
189#else
190 : VolumeKernel(id, dimension, ADAPTION_DISABLED)
191#endif
192{
193 initialize();
194
195 setOrigin(origin);
196 setLengths({{length, length, length}});
197
198 int nCells = (int) std::ceil(length / dh);
199 setDiscretization({{nCells, nCells, nCells}});
200}
201
207VolCartesian::VolCartesian(std::istream &stream)
208#if BITPIT_ENABLE_MPI==1
209 : VolumeKernel(MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
210#else
211 : VolumeKernel(ADAPTION_DISABLED)
212#endif
213{
214 initialize();
215 restore(stream);
216}
217
223std::unique_ptr<PatchKernel> VolCartesian::clone() const
224{
225 return std::unique_ptr<VolCartesian>(new VolCartesian(*this));
226}
227
232{
233 // Switch to light memeory mode
234 switchMemoryMode(MEMORY_LIGHT);
235
236 // Reset geometry and discretization
237 m_minCoords = {{0., 0., 0.}};
238 m_maxCoords = {{1., 1., 1.}};
239
240 m_nCells1D = {{0, 0, 0}};
241 m_nVertices1D = {{0, 0, 0}};
242 m_cellSpacings = {{0., 0., 0.}};
243
244 for (int n = 0; n < 3; ++n) {
245 std::vector<double>().swap(m_vertexCoords[n]);
246 std::vector<double>().swap(m_cellCenters[n]);
247 }
248
249 m_nVertices = 0;
250 m_nCells = 0;
251 m_nInterfaces = 0;
252}
253
261
262
269{
270 // Partial updates are not supported
273
274 bool partialUpdate = false;
275 for (CellConstIterator cellIterator = beginItr; cellIterator != endItr; ++cellIterator) {
276 long cellId = cellIterator.getId();
277 if (!testCellAlterationFlags(cellId, FLAG_ADJACENCIES_DIRTY)) {
278 partialUpdate = true;
279 break;
280 }
281 }
282
283 if (partialUpdate) {
284 log::cout() << " It is not possible to partially update the adjacencies.";
285 log::cout() << " All adjacencies will be updated.";
286 }
287
288 // Update adjacencies
289 int nCellFaces = 2 * getDimension();
290 for (Cell &cell : getCells()) {
291 // Reset cell adjacencies
292 if (cell.getAdjacencyCount() != 0) {
293 cell.resetAdjacencies();
294 }
295
296 // Evaluate adjacencies
297 long cellId = cell.getId();
298 for (int face = 0; face < nCellFaces; ++face) {
299 // Identify face neighbour
300 long neighId = getCellFaceNeighsLinearId(cellId, face);
301 if (neighId < 0) {
302 continue;
303 }
304
305 // Add adjacency
306 cell.pushAdjacency(face, neighId);
307 }
308 }
309}
310
318{
319 // Partial updates are not supported
322
323 bool partialUpdate = false;
324 for (CellConstIterator cellIterator = beginItr; cellIterator != endItr; ++cellIterator) {
325 long cellId = cellIterator.getId();
326 if (!testCellAlterationFlags(cellId, FLAG_INTERFACES_DIRTY)) {
327 partialUpdate = true;
328 break;
329 }
330 }
331
332 if (partialUpdate) {
333 log::cout() << " It is not possible to partially update the interfaces.";
334 log::cout() << " All interfaces will be updated.";
335 }
336
337 // Build interfaces
338 if (getMemoryMode() == MemoryMode::MEMORY_NORMAL) {
339 int nCellFaces = 2 * getDimension();
340
341 // Info on the interfaces
342 ElementType interfaceType = getInterfaceType();
343
344 const ReferenceElementInfo &interfaceTypeInfo = ReferenceElementInfo::getInfo(interfaceType);
345 const int nInterfaceVertices = interfaceTypeInfo.nVertices;
346
347 // Enable manual adaption
348 AdaptionMode previousAdaptionMode = getAdaptionMode();
350
351 // Initialize interfaces
352 for (Cell &cell : getCells()) {
353 cell.setInterfaces(FlatVector2D<long>(nCellFaces, 1, Interface::NULL_ID));
354 }
355
356 // Build interfaces
357 for (Cell &cell : getCells()) {
358 long cellId = cell.getId();
359 for (int face = 0; face < nCellFaces; ++face) {
360 // Get neighbour information
361 //
362 // The interface between two cells needs to be processed only
363 // once. In order to ensure this, we build an interface if the
364 // faces is a border, or if the id of this cell is lower than
365 // the id of its neighbour.
366 long neighId;
367 if (cell.getAdjacencyCount(face) > 0) {
368 neighId = cell.getAdjacencies(face)[0];
369 if (neighId < cellId) {
370 continue;
371 }
372 } else {
373 neighId = Cell::NULL_ID;
374 }
375
376 // Create the interface
377 InterfaceIterator interfaceIterator = VolumeKernel::addInterface(interfaceType);
378 Interface &interface = *interfaceIterator;
379 long interfaceId = interface.getId();
380
381 // Set connectivity
382 ConstProxyVector<long> faceConnect = cell.getFaceConnect(face);
383 int connectSize = faceConnect.size();
384
385 std::unique_ptr<long[]> connect = std::unique_ptr<long[]>(new long[nInterfaceVertices]);
386 for (int k = 0; k < connectSize; ++k) {
387 connect[k] = faceConnect[k];
388 }
389 interface.setConnect(std::move(connect));
390
391 // Set owner data
392 interface.setOwner(cellId, face);
393 cell.setInterface(face, 0, interfaceId);
394
395 // Neighbour data
396 if (neighId >= 0) {
397 Cell &neigh = getCell(neighId);
398 int neighFace = 2 * static_cast<int>(std::floor(face / 2.)) + (1 - face % 2);
399
400 interface.setNeigh(neighId, neighFace);
401 neigh.setInterface(neighFace, 0, interfaceId);
402 } else {
403 interface.unsetNeigh();
404 }
405 }
406 }
407
408 // Restore previous adaption mode
409 setAdaptionMode(previousAdaptionMode);
410 }
411}
412
416void VolCartesian::initialize()
417{
418 // Normals
419 int i = 0;
420 for (int n = 0; n < 3; n++) {
421 for (int k = -1; k <= 1; k += 2) {
422 std::array<double, 3> normal = {{0.0, 0.0, 0.0}};
423 normal[n] = k;
424
425 m_normals[i++] = normal;
426 }
427 }
428
429 // Deltas for the evaluation of the vertex neighbours
430 m_vertexNeighDeltas = std::vector<std::array<int, 3>>(8);
431 m_vertexNeighDeltas[0] = {{ 0, 0, 0}};
432 m_vertexNeighDeltas[1] = {{-1, 0, 0}};
433 m_vertexNeighDeltas[2] = {{ 0, -1, 0}};
434 m_vertexNeighDeltas[3] = {{-1, -1, 0}};
435 m_vertexNeighDeltas[4] = {{ 0, 0, -1}};
436 m_vertexNeighDeltas[5] = {{-1, 0, -1}};
437 m_vertexNeighDeltas[6] = {{ 0, -1, -1}};
438 m_vertexNeighDeltas[7] = {{-1, -1, -1}};
439
440 // Deltas for the evaluation of the edge neighbours
441 m_edgeNeighDeltas = std::vector<std::array<int, 3>>(12);
442 m_edgeNeighDeltas[ 0] = {{-1, 0, -1}};
443 m_edgeNeighDeltas[ 1] = {{ 1, 0, -1}};
444 m_edgeNeighDeltas[ 2] = {{ 0, -1, -1}};
445 m_edgeNeighDeltas[ 3] = {{ 0, 1, -1}};
446 m_edgeNeighDeltas[ 4] = {{-1, -1, 0}};
447 m_edgeNeighDeltas[ 5] = {{ 1, -1, 0}};
448 m_edgeNeighDeltas[ 6] = {{-1, 1, 0}};
449 m_edgeNeighDeltas[ 7] = {{ 1, 1, 0}};
450 m_edgeNeighDeltas[ 8] = {{-1, 0, 1}};
451 m_edgeNeighDeltas[ 9] = {{ 1, 0, 1}};
452 m_edgeNeighDeltas[10] = {{ 0, -1, 1}};
453 m_edgeNeighDeltas[11] = {{ 0, 1, 1}};
454
455 // Faces associated to the edges
456 m_edgeFaces = std::vector<std::array<int, 2>>(12);
457 m_edgeFaces[ 0] = {{ 0, 4}};
458 m_edgeFaces[ 1] = {{ 1, 4}};
459 m_edgeFaces[ 2] = {{ 2, 4}};
460 m_edgeFaces[ 3] = {{ 3, 4}};
461 m_edgeFaces[ 4] = {{ 0, 2}};
462 m_edgeFaces[ 5] = {{ 1, 2}};
463 m_edgeFaces[ 6] = {{ 0, 3}};
464 m_edgeFaces[ 7] = {{ 1, 3}};
465 m_edgeFaces[ 8] = {{ 0, 5}};
466 m_edgeFaces[ 9] = {{ 1, 5}};
467 m_edgeFaces[10] = {{ 2, 5}};
468 m_edgeFaces[11] = {{ 3, 5}};
469
470 // Set the bounding box as frozen
472
473 // Set the light memory mode
474 setMemoryMode(MemoryMode::MEMORY_LIGHT);
475
476 // Reset the patch
477 reset();
478}
479
483void VolCartesian::initializeCellVolume()
484{
485 m_cellVolume = 1;
486 for (int d = 0; d < getDimension(); ++d) {
487 if (m_directionOrdering[d] >= 0) {
488 m_cellVolume *= m_cellSpacings[d];
489 }
490 }
491}
492
496void VolCartesian::initializeCellSize()
497{
498 m_cellSize = std::pow(m_cellVolume, 1. / getDimension());
499}
500
504void VolCartesian::initializeInterfaceArea()
505{
506 for (int d = 0; d < getDimension(); ++d) {
507 if (m_directionOrdering[d] >= 0) {
508 m_interfaceArea[d] = m_cellVolume / m_cellSpacings[d];
509 } else {
510 m_interfaceArea[d] = 0.;
511 }
512 }
513}
514
520void VolCartesian::setDiscretization(const std::array<int, 3> &nCells)
521{
522 // Spacing
523 for (int d = 0; d < getDimension(); ++d) {
524 // Initialize cells
525 if (nCells[d] > 0) {
526 m_nCells1D[d] = nCells[d];
527 m_cellSpacings[d] = (m_maxCoords[d] - m_minCoords[d]) / m_nCells1D[d];
528
529 m_cellCenters[d].resize(m_nCells1D[d]);
530 for (int i = 0; i < m_nCells1D[d]; i++) {
531 m_cellCenters[d][i] = m_minCoords[d] + (0.5 + i) * m_cellSpacings[d];
532 }
533 } else {
534 m_nCells1D[d] = 0;
535 m_cellSpacings[d] = 0.;
536 }
537
538 log::cout() << " - Cell count along direction " << d << " : " << m_nCells1D[d] << "\n";
539
540 // Initialize vertices
541 m_nVertices1D[d] = m_nCells1D[d] + 1;
542
543 m_vertexCoords[d].resize(m_nVertices1D[d]);
544 for (int i = 0; i < m_nVertices1D[d]; i++) {
545 m_vertexCoords[d][i] = m_minCoords[d] + i * m_cellSpacings[d];
546 }
547 }
548
549 for (int d = getDimension(); d < 3; ++d) {
550 m_nCells1D[d] = 0;
551 m_cellSpacings[d] = 0.;
552
553 m_nVertices1D[d] = 1;
554 }
555
556 log::cout() << std::endl;
557
558 // Define direction ordering
559 //
560 // It is the ordering in which the different directions will be considered
561 // when numbering cell, vertices, ... For each direction, it will contain
562 // the order in which the direction should be considered or -1 if there
563 // are no cells along the direction.
564 for (int d = 0; d < 3; ++d) {
565 if (d == 0) {
566 m_directionOrdering[d] = 0;
567 } else {
568 int previousDirection = m_directionOrdering[d - 1];
569 if (previousDirection < 0 || previousDirection >= 2) {
570 m_directionOrdering[d] = -1;
571 continue;
572 }
573
574 m_directionOrdering[d] = previousDirection + 1;
575 }
576
577 while (m_nCells1D[m_directionOrdering[d]] == 0) {
578 if (m_directionOrdering[d] == 2) {
579 m_directionOrdering[d] = -1;
580 break;
581 }
582
583 ++m_directionOrdering[d];
584 }
585 }
586
587 // Count the total number of vertices
588 m_nVertices = 1;
589 for (int n = 0; n < getDimension(); ++n) {
590 m_nVertices *= m_nVertices1D[n];
591 }
592 log::cout() << " - Total vertex count: " << m_nVertices << "\n";
593
594 // Count the total number of cells
595 m_nCells = 1;
596 for (int d = 0; d < getDimension(); ++d) {
597 if (m_directionOrdering[d] >= 0) {
598 m_nCells *= m_nCells1D[d];
599 }
600 }
601
602 log::cout() << " - Total cell count: " << m_nCells << "\n";
603
604 // Count the total number of interfaces
605 m_nInterfaces = 0;
606 for (int d = 0; d < getDimension(); ++d) {
607 int nDirectionInterfaces = 1;
608 for (int n = 0; n < getDimension(); n++) {
609 int nDirectionInterfaces1D = m_nCells1D[n];
610 if (n == d) {
611 ++nDirectionInterfaces1D;
612 }
613
614 nDirectionInterfaces *= nDirectionInterfaces1D;
615 }
616 m_nInterfaces += nDirectionInterfaces;
617 }
618
619 log::cout() << " - Total interface count: " << m_nInterfaces << "\n";
620
621 // Cell volume
622 initializeCellVolume();
623
624 // Cell size
625 initializeCellSize();
626
627 // Interface area
628 initializeInterfaceArea();
629
630 // Update patch data structures
631 if (getMemoryMode() == MemoryMode::MEMORY_NORMAL) {
632 // Switch to light mode to reset patchdata structures
633 switchMemoryMode(MemoryMode::MEMORY_LIGHT);
634
635 // Swich back to normal mode to rebuild patchdata structures
636 switchMemoryMode(MemoryMode::MEMORY_NORMAL);
637 }
638}
639
646{
647 return m_nVertices;
648}
649
656int VolCartesian::getVertexCount(int direction) const
657{
658 return m_nVertices1D[direction];
659}
660
667{
668 return m_nCells;
669}
670
677int VolCartesian::getCellCount(int direction) const
678{
679 return m_nCells1D[direction];
680}
681
689{
690 BITPIT_UNUSED(id);
691
692 return getCellType();
693}
694
701{
702 if (isThreeDimensional()) {
703 return ElementType::VOXEL;
704 } else {
705 return ElementType::PIXEL;
706 }
707}
708
715{
716 return m_nInterfaces;
717}
718
726{
727 BITPIT_UNUSED(id);
728
729 return getInterfaceType();
730}
731
738{
739 if (isThreeDimensional()) {
740 return ElementType::PIXEL;
741 } else {
742 return ElementType::LINE;
743 }
744}
745
752std::array<double, 3> VolCartesian::evalVertexCoords(long id) const
753{
754 std::array<int, 3> ijk = getVertexCartesianId(id);
755
756 return evalVertexCoords(ijk);
757}
758
765std::array<double, 3> VolCartesian::evalVertexCoords(const std::array<int, 3> &ijk) const
766{
767 std::array<double, 3> coords;
768 for (int d = 0; d < 3; ++d) {
769 if (ijk[d] >= 0) {
770 coords[d] = m_vertexCoords[d][ijk[d]];
771 } else {
772 coords[d] = m_minCoords[d];
773 }
774 }
775
776 return coords;
777}
778
787const std::vector<double> & VolCartesian::getVertexCoords(int direction) const
788{
789 return m_vertexCoords[direction];
790}
791
798double VolCartesian::evalCellVolume(long id) const
799{
800 BITPIT_UNUSED(id);
801
802 return evalCellVolume();
803}
804
811double VolCartesian::evalCellVolume(const std::array<int, 3> &ijk) const
812{
813 BITPIT_UNUSED(ijk);
814
815 return evalCellVolume();
816}
817
825double VolCartesian::evalCellVolume() const
826{
827 return m_cellVolume;
828}
829
836double VolCartesian::evalCellSize(long id) const
837{
838 BITPIT_UNUSED(id);
839
840 return evalCellSize();
841}
842
849double VolCartesian::evalCellSize(const std::array<int, 3> &ijk) const
850{
851 BITPIT_UNUSED(ijk);
852
853 return evalCellSize();
854}
855
863double VolCartesian::evalCellSize() const
864{
865 return m_cellSize;
866}
867
875void VolCartesian::evalCellBoundingBox(long id, std::array<double,3> *minPoint, std::array<double,3> *maxPoint) const
876{
877 std::array<double,3> cellCentroid = evalCellCentroid(id);
878 for (int d = 0; d < 3; ++d) {
879 (*minPoint)[d] = cellCentroid[d] - 0.5 * m_cellSpacings[d];
880 (*maxPoint)[d] = cellCentroid[d] + 0.5 * m_cellSpacings[d];
881 }
882}
883
891{
892 const Interface &interface = getInterface(id);
893 int ownerFace = interface.getOwnerFace();
894 int direction = static_cast<int>(std::floor(ownerFace / 2.));
895
896 return m_interfaceArea[direction];
897}
898
905std::array<double, 3> VolCartesian::evalInterfaceNormal(long id) const
906{
907 const Interface &interface = getInterface(id);
908 int ownerFace = interface.getOwnerFace();
909
910 return m_normals[ownerFace];
911}
912
918std::array<double, 3> VolCartesian::getSpacing() const
919{
920 return m_cellSpacings;
921}
922
929{
930 // Early return if the current memory mode matches the requested one
931 if (mode == getMemoryMode()) {
932 return;
933 }
934
935 // Update patch data structures
936 switch (mode) {
937
938 case MemoryMode::MEMORY_NORMAL:
939 {
940 // Enable manual adaption
941 AdaptionMode previousAdaptionMode = getAdaptionMode();
943
944 // Create the mesh
945 addVertices();
946 addCells();
947
948 // Restore previous adaption mode
949 setAdaptionMode(previousAdaptionMode);
950
951 break;
952 }
953
954 case MemoryMode::MEMORY_LIGHT:
955 {
956 // To put the patch in memory mode we need to reset the generic data
957 // of the patch, therefore we can call the 'reset' implementation of
958 // the kernel.
960
961 break;
962 }
963
964 }
965
966 // Set the requested memory mode
967 setMemoryMode(mode);
968}
969
977void VolCartesian::setMemoryMode(MemoryMode mode)
978{
979 m_memoryMode = mode;
980}
981
987VolCartesian::MemoryMode VolCartesian::getMemoryMode() const
988{
989 return m_memoryMode;
990}
991
999double VolCartesian::getSpacing(int direction) const
1000{
1001 return m_cellSpacings[direction];
1002}
1003
1007void VolCartesian::addVertices()
1008{
1009 log::cout() << " >> Creating vertices\n";
1010
1011 log::cout() << " - Vertex count: " << m_nVertices << "\n";
1012
1013 m_vertices.reserve(m_nVertices);
1014 for (int k = 0; (isThreeDimensional()) ? (k < m_nVertices1D[Vertex::COORD_Z]) : (k <= 0); k++) {
1015 for (int j = 0; j < m_nVertices1D[Vertex::COORD_Y]; j++) {
1016 for (int i = 0; i < m_nVertices1D[Vertex::COORD_X]; i++) {
1017 // Linear index of the vertex
1018 long id_vertex = getVertexLinearId(i, j, k);
1019
1020 // Vertex coordinates
1021 std::array<double, 3> coords = evalVertexCoords(id_vertex);
1022
1023 // Add vertex
1024 VolumeKernel::addVertex(std::move(coords), id_vertex);
1025 }
1026 }
1027 }
1028}
1029
1033void VolCartesian::addCells()
1034{
1035 log::cout() << " >> Creating cells\n";
1036
1037 // Info on the cells
1038 ElementType cellType = getCellType();
1039
1040 // Create the cells
1041 log::cout() << " - Cell count: " << m_nCells << "\n";
1042
1043 m_cells.reserve(m_nCells);
1044 for (int k = 0; (isThreeDimensional()) ? (k < m_nCells1D[Vertex::COORD_Z]) : (k <= 0); k++) {
1045 for (int j = 0; j < m_nCells1D[Vertex::COORD_Y]; j++) {
1046 for (int i = 0; i < m_nCells1D[Vertex::COORD_X]; i++) {
1047 long id_cell = getCellLinearId(i, j, k);
1048 CellIterator cellIterator = VolumeKernel::addCell(cellType, id_cell);
1049 Cell &cell = *cellIterator;
1050
1051 // Connettività
1052 long *cellConnect = cell.getConnect();
1053
1054 cellConnect[0] = getVertexLinearId(i, j, k);
1055 cellConnect[1] = getVertexLinearId(i + 1, j, k);
1056 cellConnect[2] = getVertexLinearId(i, j + 1, k);
1057 cellConnect[3] = getVertexLinearId(i + 1, j + 1, k);
1058 if (cellType == ElementType::VOXEL) {
1059 cellConnect[4] = getVertexLinearId(i, j, k + 1);
1060 cellConnect[5] = getVertexLinearId(i + 1, j, k + 1);
1061 cellConnect[6] = getVertexLinearId(i, j + 1, k + 1);
1062 cellConnect[7] = getVertexLinearId(i + 1, j + 1, k + 1);
1063 }
1064 }
1065 }
1066 }
1067}
1068
1075{
1076 const int DUMP_VERSION = 2;
1077
1078 return DUMP_VERSION;
1079}
1080
1086void VolCartesian::_dump(std::ostream &stream) const
1087{
1088 utils::binary::write(stream, m_minCoords[0]);
1089 utils::binary::write(stream, m_minCoords[1]);
1090 utils::binary::write(stream, m_minCoords[2]);
1091
1092 utils::binary::write(stream, m_maxCoords[0] - m_minCoords[0]);
1093 utils::binary::write(stream, m_maxCoords[1] - m_minCoords[1]);
1094 utils::binary::write(stream, m_maxCoords[2] - m_minCoords[2]);
1095
1096 utils::binary::write(stream, m_nCells1D[0]);
1097 utils::binary::write(stream, m_nCells1D[1]);
1098 utils::binary::write(stream, m_nCells1D[2]);
1099
1100 utils::binary::write(stream, m_memoryMode);
1101
1102 if (m_memoryMode == MEMORY_NORMAL) {
1103 for (const Cell &cell : getCells()) {
1104 utils::binary::write(stream, cell.getPID());
1105 }
1106 }
1107
1108 if (m_memoryMode == MEMORY_NORMAL) {
1109 for (const Interface &interface : getInterfaces()) {
1110 utils::binary::write(stream, interface.getPID());
1111 }
1112 }
1113}
1114
1120void VolCartesian::_restore(std::istream &stream)
1121{
1122 // Origin
1123 std::array<double, 3> origin;
1124 utils::binary::read(stream, origin[0]);
1125 utils::binary::read(stream, origin[1]);
1126 utils::binary::read(stream, origin[2]);
1127
1128 setOrigin(origin);
1129
1130 // Lengths
1131 std::array<double, 3> lengths;
1132 utils::binary::read(stream, lengths[0]);
1133 utils::binary::read(stream, lengths[1]);
1134 utils::binary::read(stream, lengths[2]);
1135
1136 setLengths(lengths);
1137
1138 // Discretization
1139 std::array<int, 3> nCells;
1140 utils::binary::read(stream, nCells[0]);
1141 utils::binary::read(stream, nCells[1]);
1142 utils::binary::read(stream, nCells[2]);
1143
1144 setDiscretization(nCells);
1145
1146 // Memory mode
1147 MemoryMode memoryMode;
1148 utils::binary::read(stream, memoryMode);
1149 switchMemoryMode(memoryMode);
1150
1151 // Cell data
1152 if (m_memoryMode == MEMORY_NORMAL) {
1153 for (Cell &cell : getCells()) {
1154 int PID;
1155 utils::binary::read(stream, PID);
1156 cell.setPID(PID);
1157 }
1158 }
1159
1160 // Interface data
1161 if (m_memoryMode == MEMORY_NORMAL) {
1162 for (Interface &interface : getInterfaces()) {
1163 int PID;
1164 utils::binary::read(stream, PID);
1165 interface.setPID(PID);
1166 }
1167 }
1168}
1169
1177bool VolCartesian::isPointInside(long id, const std::array<double, 3> &point) const
1178{
1179 std::array<int, 3> cellIjk = getCellCartesianId(id);
1180
1181 const double EPS = getTol();
1182 for (int d = 0; d < 3; ++d){
1183 long index = cellIjk[d];
1184
1185 double spacing = m_cellSpacings[d];
1186 double cellMin = m_cellCenters[d][index] - 0.5 * spacing;
1187 double cellMax = m_cellCenters[d][index] + 0.5 * spacing;
1188
1189 if (point[d]< cellMin - EPS || point[d] > cellMax + EPS) {
1190 return false;
1191 }
1192 }
1193
1194 return true;
1195}
1196
1203bool VolCartesian::isPointInside(const std::array<double, 3> &point) const
1204{
1205 const double EPS = getTol();
1206
1207 for (int n = 0; n < getDimension(); n++) {
1208 if (point[n] < m_minCoords[n] - EPS || point[n] > m_maxCoords[n] + EPS) {
1209 return false;
1210 }
1211 }
1212
1213 return true;
1214}
1215
1227long VolCartesian::locatePoint(const std::array<double, 3> &point) const
1228{
1229 std::array<int, 3> pointIjk = locatePointCartesian(point);
1230 if (isCellCartesianIdValid(pointIjk)) {
1231 return getCellLinearId(pointIjk);
1232 } else {
1233 return Element::NULL_ID;
1234 }
1235}
1236
1247std::array<int, 3> VolCartesian::locatePointCartesian(const std::array<double, 3> &point) const
1248{
1249 std::array<int, 3> ijk;
1250 if (!isPointInside(point)) {
1251 ijk[0] = -1;
1252 ijk[1] = -1;
1253 ijk[2] = -1;
1254
1255 return ijk;
1256 }
1257
1258 ijk[0] = static_cast<int>(std::floor((point[Vertex::COORD_X] - m_minCoords[Vertex::COORD_X]) / m_cellSpacings[Vertex::COORD_X]));
1259 ijk[1] = static_cast<int>(std::floor((point[Vertex::COORD_Y] - m_minCoords[Vertex::COORD_Y]) / m_cellSpacings[Vertex::COORD_Y]));
1260 if (isThreeDimensional()) {
1261 ijk[2] = static_cast<int>(std::floor((point[Vertex::COORD_Z] - m_minCoords[Vertex::COORD_Z]) / m_cellSpacings[Vertex::COORD_Z]));
1262 } else {
1263 ijk[2] = -1;
1264 }
1265
1266 return ijk;
1267}
1268
1275long VolCartesian::locateClosestVertex(std::array<double,3> const &point) const
1276{
1278}
1279
1287std::array<int, 3> VolCartesian::locateClosestVertexCartesian(std::array<double,3> const &point) const
1288{
1289 std::array<int, 3> ijk;
1290 for (int n = 0; n < getDimension(); ++n) {
1291 ijk[n] = std::min(m_nVertices1D[n] - 1, std::max(0, (int) round((point[n] - m_minCoords[n]) / m_cellSpacings[n])));
1292 }
1293
1294 if (!isThreeDimensional()) {
1295 ijk[Vertex::COORD_Z] = -1;
1296 }
1297
1298 return ijk;
1299}
1300
1310long VolCartesian::locateClosestCell(const std::array<double, 3> &point) const
1311{
1312 std::array<int, 3> pointIjk = locateClosestCellCartesian(point);
1313 return getCellLinearId(pointIjk);
1314}
1315
1325std::array<int, 3> VolCartesian::locateClosestCellCartesian(const std::array<double, 3> &point) const
1326{
1327 std::array<int,3> ijk({{0,0,0}});
1328
1329 for( int i=0; i<getDimension(); ++i){
1330 ijk[i] = static_cast<int>(std::floor((point[i] - m_minCoords[i]) / m_cellSpacings[i]));
1331 ijk[i] = std::max( ijk[i], 0 );
1332 ijk[i] = std::min( ijk[i], m_nCells1D[i]-1 );
1333 }
1334
1335 return ijk;
1336}
1337
1352long VolCartesian::getCellLinearId(int i, int j, int k) const
1353{
1354 return getCellLinearId(std::array<int, 3>{{i, j, k}});
1355}
1356
1369long VolCartesian::getCellLinearId(const std::array<int, 3> &ijk) const
1370{
1371 int l = m_directionOrdering[0];
1372 int m = m_directionOrdering[1];
1373 int n = m_directionOrdering[2];
1374
1375 if (l == -1) {
1376 return Cell::NULL_ID;
1377 }
1378
1379 long id = ijk[l];
1380 if (m >= 0) {
1381 id += m_nCells1D[l] * ijk[m];
1382 if (n >= 0) {
1383 id += m_nCells1D[l] * m_nCells1D[m] * ijk[n];
1384 }
1385 }
1386
1387 return id;
1388}
1389
1403std::array<int, 3> VolCartesian::getCellCartesianId(long id) const
1404{
1405 int l = m_directionOrdering[0];
1406 int m = m_directionOrdering[1];
1407 int n = m_directionOrdering[2];
1408
1409 std::array<int, 3> ijk = {{-1, -1, -1}};
1410 if (m == -1) {
1411 ijk[l] = id;
1412 } else if (l >= 0) {
1413 int offset_lm = m_nCells1D[l] * m_nCells1D[m];
1414 int index_n = id / offset_lm;
1415
1416 ijk[m] = (id - index_n * offset_lm) / m_nCells1D[l];
1417 ijk[l] = id - (id / m_nCells1D[l]) * m_nCells1D[l];
1418 if (n != -1) {
1419 ijk[n] = index_n;
1420 }
1421 }
1422
1423 return ijk;
1424}
1425
1432bool VolCartesian::isCellCartesianIdValid(const std::array<int, 3> &ijk) const
1433{
1434 for (int k = 0; k < getDimension(); ++k) {
1435 if (ijk[k] < 0 || ijk[k] >= m_nCells1D[k]) {
1436 return false;
1437 }
1438 }
1439
1440 return true;
1441}
1442
1457long VolCartesian::getVertexLinearId(int i, int j, int k) const
1458{
1459 return getVertexLinearId(std::array<int, 3>{{i, j, k}});
1460}
1461
1474long VolCartesian::getVertexLinearId(const std::array<int, 3> &ijk) const
1475{
1476 int l = m_directionOrdering[0];
1477 int m = m_directionOrdering[1];
1478 int n = m_directionOrdering[2];
1479
1480 if (l == -1) {
1481 return Vertex::NULL_ID;
1482 }
1483
1484 long id = ijk[l];
1485 if (m >= 0) {
1486 id += m_nVertices1D[l] * ijk[m];
1487 if (n >= 0) {
1488 id += m_nVertices1D[l] * m_nVertices1D[m] * ijk[n];
1489 }
1490 }
1491
1492 return id;
1493}
1494
1508std::array<int, 3> VolCartesian::getVertexCartesianId(long id) const
1509{
1510 int l = m_directionOrdering[0];
1511 int m = m_directionOrdering[1];
1512 int n = m_directionOrdering[2];
1513
1514 std::array<int, 3> ijk = {{-1, -1, -1}};
1515 if (m == -1) {
1516 ijk[l] = id;
1517 } else if (l >= 0) {
1518 int offset_lm = m_nVertices1D[l] * m_nVertices1D[m];
1519 int index_n = id / offset_lm;
1520
1521 ijk[m] = (id - index_n * offset_lm) / m_nVertices1D[l];
1522 ijk[l] = id - (id / m_nVertices1D[l]) * m_nVertices1D[l];
1523 if (n != -1) {
1524 ijk[n] = index_n;
1525 }
1526 }
1527
1528 return ijk;
1529}
1530
1545std::array<int, 3> VolCartesian::getVertexCartesianId(long cellId, int vertex) const
1546{
1547 return getVertexCartesianId(getCellCartesianId(cellId), vertex);
1548}
1549
1564std::array<int, 3> VolCartesian::getVertexCartesianId(const std::array<int, 3> &cellIjk, int vertex) const
1565{
1566 std::bitset<3> vertexBitset(vertex);
1567 std::array<int, 3> vertexIjk(cellIjk);
1568 for (int k = 0; k < 3; ++k) {
1569 vertexIjk[k] += vertexBitset[k];
1570 }
1571
1572 return vertexIjk;
1573}
1574
1581bool VolCartesian::isVertexCartesianIdValid(const std::array<int, 3> &ijk) const
1582{
1583 for (int k = 0; k < getDimension(); ++k) {
1584 if (ijk[k] < 0 || ijk[k] >= m_nVertices1D[k]) {
1585 return false;
1586 }
1587 }
1588
1589 return true;
1590}
1591
1604void VolCartesian::_findCellFaceNeighs(long id, int face, const std::vector<long> *blackList, std::vector<long> *neighs) const
1605{
1606 long neighId = getCellFaceNeighsLinearId(id, face);
1607 if (neighId < 0) {
1608 return;
1609 } else if (blackList && utils::findInOrderedVector<long>(neighId, *blackList) != blackList->end()) {
1610 return;
1611 }
1612
1613 neighs->push_back(neighId);
1614}
1615
1631void VolCartesian::_findCellEdgeNeighs(long id, int edge, const std::vector<long> *blackList, std::vector<long> *neighs) const
1632{
1633 assert(isThreeDimensional());
1634 if (!isThreeDimensional()) {
1635 return;
1636 }
1637
1638 // Diagonal neighbour
1639 std::array<int, 3> diagNeighIjk(getCellCartesianId(id) + m_edgeNeighDeltas[edge]);
1640 if (isCellCartesianIdValid(diagNeighIjk)) {
1641 long diagNeighId = getCellLinearId(diagNeighIjk);
1642 if (!blackList || utils::findInOrderedVector<long>(diagNeighId, *blackList) == blackList->end()) {
1643 utils::addToOrderedVector<long>(diagNeighId, *neighs);
1644 }
1645 }
1646
1647 // Faces incident to the edge
1648 for (int face : m_edgeFaces[edge]) {
1649 _findCellFaceNeighs(id, face, blackList, neighs);
1650 }
1651}
1652
1666void VolCartesian::_findCellVertexNeighs(long id, int vertex, const std::vector<long> *blackList, std::vector<long> *neighs) const
1667{
1668 std::array<int, 3> cellIjk = getCellCartesianId(id);
1669 std::array<int, 3> vertexIjk = getVertexCartesianId(cellIjk, vertex);
1670
1671 for (const auto &delta : m_vertexNeighDeltas) {
1672 // Get the Cartesian index
1673 std::array<int, 3> neighIjk(vertexIjk + delta);
1674 if (neighIjk == cellIjk) {
1675 continue;
1676 } else if (!isCellCartesianIdValid(neighIjk)) {
1677 continue;
1678 }
1679
1680 // Get the linear neighbour index and, if it's not on the blacklist,
1681 // add it to the list of neighbours
1682 long neighId = getCellLinearId(neighIjk);
1683 if (!blackList || utils::findInOrderedVector<long>(neighId, *blackList) == blackList->end()) {
1684 utils::addToOrderedVector<long>(neighId, *neighs);
1685 }
1686 }
1687}
1688
1696std::vector<long> VolCartesian::extractCellSubSet(std::array<int, 3> const &ijkMin, std::array<int, 3> const &ijkMax) const
1697{
1698 int nSubsetCells_x = ijkMax[0] - ijkMin[0] + 1;
1699 int nSubsetCells_y = ijkMax[1] - ijkMin[1] + 1;
1700 int nSubsetCells_z = ijkMax[2] - ijkMin[2] + 1;
1701
1702 std::vector<long> ids;
1703 ids.resize(nSubsetCells_x * nSubsetCells_y * nSubsetCells_z);
1704
1705 std::vector<long>::iterator it = ids.begin();
1706 for (int k = ijkMin[2]; k <= ijkMax[2]; ++k) {
1707 for (int j = ijkMin[1]; j <= ijkMax[1]; ++j) {
1708 for (int i = ijkMin[0]; i <= ijkMax[0]; ++i) {
1709 *it = getCellLinearId(i, j, k);
1710 ++it;
1711 }
1712 }
1713 }
1714
1715 return ids;
1716}
1717
1725std::vector<long> VolCartesian::extractCellSubSet(int idMin, int idMax) const
1726{
1728}
1729
1737std::vector<long> VolCartesian::extractCellSubSet(std::array<double, 3> const &pointMin, std::array<double, 3> const &pointMax) const
1738{
1739 return extractCellSubSet(locatePointCartesian(pointMin), locatePointCartesian(pointMax));
1740}
1741
1749std::vector<long> VolCartesian::extractVertexSubSet(std::array<int, 3> const &ijkMin, std::array<int, 3> const &ijkMax) const
1750{
1751 int nSubsetVertices_x = ijkMax[0] - ijkMin[0] + 1;
1752 int nSubsetVertices_y = ijkMax[1] - ijkMin[1] + 1;
1753 int nSubsetVertices_z = ijkMax[2] - ijkMin[2] + 1;
1754
1755 std::vector<long> ids;
1756 ids.resize(nSubsetVertices_x * nSubsetVertices_y * nSubsetVertices_z);
1757
1758 std::vector<long>::iterator it = ids.begin();
1759 for (int k = ijkMin[2]; k <= ijkMax[2]; ++k) {
1760 for (int j = ijkMin[1]; j <= ijkMax[1]; ++j) {
1761 for (int i = ijkMin[0]; i <= ijkMax[0]; ++i) {
1762 *it = getVertexLinearId(i, j, k);
1763 ++it;
1764 }
1765 }
1766 }
1767
1768 return ids;
1769}
1770
1778std::vector<long> VolCartesian::extractVertexSubSet(int idMin, int idMax) const
1779{
1781}
1782
1790std::vector<long> VolCartesian::extractVertexSubSet(std::array<double, 3> const &pointMin, std::array<double, 3> const &pointMax) const
1791{
1793}
1794
1803std::array<double, 3> VolCartesian::getOrigin() const
1804{
1805 return m_minCoords;
1806}
1807
1815void VolCartesian::setOrigin(const std::array<double, 3> &origin)
1816{
1817 std::array<double, 3> translation = origin - getOrigin();
1818 translate(translation);
1819}
1820
1826void VolCartesian::translate(const std::array<double, 3> &translation)
1827{
1828 for (int n = 0; n < 3; ++n) {
1829 m_minCoords[n] += translation[n];
1830 m_maxCoords[n] += translation[n];
1831
1832 for (int i = 1; i < m_nVertices1D[n]; ++i) {
1833 m_vertexCoords[n][i] += translation[n];
1834 }
1835
1836 for (int i = 1; i < m_nCells1D[n]; ++i) {
1837 m_cellCenters[n][i] += translation[n];
1838 }
1839 }
1840
1841 setBoundingBox(m_minCoords, m_maxCoords);
1842
1843 VolumeKernel::translate(translation);
1844}
1845
1854void VolCartesian::rotate(const std::array<double, 3> &n0, const std::array<double, 3> &n1, double angle)
1855{
1856 BITPIT_UNUSED(n0);
1857 BITPIT_UNUSED(n1);
1858 BITPIT_UNUSED(angle);
1859
1860 throw std::runtime_error("It is not possible to rotate a Cartesian patch.");
1861}
1862
1868std::array<double, 3> VolCartesian::getLengths() const
1869{
1870 return (m_maxCoords - m_minCoords);
1871}
1872
1879void VolCartesian::setLengths(const std::array<double, 3> &lengths)
1880{
1881 // Set the maximum coordinate
1882 m_maxCoords = m_minCoords + lengths;
1883
1884 // Reset the bounding box
1885 setBoundingBox(m_minCoords, m_maxCoords);
1886
1887 // If needed update the discretization
1888 if (m_nVertices > 0) {
1889 // Rebuild the discretization
1890 setDiscretization(m_nCells1D);
1891
1892 // Rebuild vertex coordinates
1893 for (Vertex vertex : m_vertices) {
1894 long id = vertex.getId();
1895 vertex.setCoords(evalVertexCoords(id));
1896 }
1897 }
1898}
1899
1906void VolCartesian::scale(const std::array<double, 3> &scaling, const std::array<double, 3> &center)
1907{
1908 for (int n = 0; n < 3; ++n) {
1909 m_minCoords[n] = center[n] + scaling[n] * (m_minCoords[n] - center[n]);
1910 m_maxCoords[n] = center[n] + scaling[n] * (m_maxCoords[n] - center[n]);
1911
1912 for (int i = 1; i < m_nVertices1D[n]; ++i) {
1913 m_vertexCoords[n][i] = center[n] + scaling[n] * (m_vertexCoords[n][i] - center[n]);
1914 }
1915
1916 for (int i = 1; i < m_nCells1D[n]; ++i) {
1917 m_cellCenters[n][i] = center[n] + scaling[n] * (m_cellCenters[n][i] - center[n]);
1918 }
1919
1920 m_cellSpacings[n] *= scaling[n];
1921 }
1922
1923 initializeCellVolume();
1924
1925 initializeCellSize();
1926
1927 initializeInterfaceArea();
1928
1929 setBoundingBox(m_minCoords, m_maxCoords);
1930
1931 VolumeKernel::scale(scaling, center);
1932}
1933
1941std::vector<double> VolCartesian::convertToVertexData(const std::vector<double> &cellData) const
1942{
1943 int dimension = getDimension();
1944
1945 int nContribs_x = 2;
1946 int nContribs_y = 2;
1947 int nContribs_z = dimension - 1;
1948
1949 std::vector<int> nodeCounter(getVertexCount());
1950 std::vector<double> vertexData(getVertexCount());
1951 std::fill (vertexData.begin(), vertexData.end(), 0.);
1952
1953 for (int k = 0; (isThreeDimensional()) ? (k < m_nCells1D[Vertex::COORD_Z]) : (k < 1); k++) {
1954 for (int j = 0; j < m_nCells1D[Vertex::COORD_Y]; ++j) {
1955 for (int i = 0; i < m_nCells1D[Vertex::COORD_X]; ++i) {
1956 // Get cell contribution
1957 long cellId = getCellLinearId(i, j, k);
1958 double cellContrib = cellData[cellId];
1959
1960 // Eval vertex data
1961 for (int n = 0; n < nContribs_z; n++) {
1962 int k_v = k + n;
1963 for (int m = 0; m < nContribs_y; ++m) {
1964 int j_v = j + m;
1965 for (int l = 0; l < nContribs_x; ++l) {
1966 int i_v = i + l;
1967
1968 // Get vertex index
1969 long vertexId = getVertexLinearId(i_v, j_v, k_v);
1970
1971 // Sum cell contribution
1972 vertexData[vertexId] += cellContrib;
1973 nodeCounter[vertexId]++;
1974 }
1975 }
1976 }
1977 }
1978 }
1979 }
1980
1981 // Average values
1982 for (int i = 0; i < getVertexCount(); ++i) {
1983 vertexData[i] /= nodeCounter[i];
1984 }
1985
1986 return vertexData;
1987}
1988
1996std::vector<double> VolCartesian::convertToCellData(const std::vector<double> &vertexData) const
1997{
1998 int dimension = getDimension();
1999
2000 int nContribs_x = 2;
2001 int nContribs_y = 2;
2002 int nContribs_z = dimension - 1;
2003
2004 std::vector<double> cellData(getCellCount());
2005 std::fill (cellData.begin(), cellData.end(), 0.);
2006
2007 for (int k = 0; (isThreeDimensional()) ? (k < m_nCells1D[Vertex::COORD_Z]) : (k < 1); k++) {
2008 for (int j = 0; j < m_nCells1D[Vertex::COORD_Y]; ++j) {
2009 for (int i = 0; i < m_nCells1D[Vertex::COORD_X]; ++i) {
2010 // Eval cell data
2011 long cellId = getCellLinearId(i, j, k);
2012 for (int n = 0; n < nContribs_z; ++n) {
2013 int k_v = k + n;
2014 for (int m = 0; m < nContribs_y; ++m) {
2015 int j_v = j + m;
2016 for (int l = 0; l < nContribs_x; ++l) {
2017 int i_v = i + l;
2018
2019 // Get vertex contribution
2020 long vertexId = getVertexLinearId(i_v, j_v, k_v);
2021 double vertexContrib = vertexData[vertexId];
2022
2023 // Sum vertex contribution
2024 cellData[cellId] += vertexContrib;
2025 }
2026 }
2027 }
2028 }
2029 }
2030 }
2031
2032 double weight = pow(0.5, dimension);
2033 for (int i = 0; i < getCellCount(); ++i) {
2034 cellData[i] *= weight;
2035 }
2036
2037 return cellData;
2038}
2039
2040
2054int VolCartesian::linearCellInterpolation(const std::array<double,3> &point,
2055 std::vector<int> *stencil, std::vector<double> *weights) const
2056{
2057 std::array<int, 3> ijk_point = locatePointCartesian(point);
2058 if (ijk_point[0] < 0) {
2059 stencil->clear();
2060 weights->clear();
2061 return 0;
2062 }
2063
2064 int dimension = getDimension();
2065
2066 int nContribs_x = 1;
2067 int nContribs_y = 1;
2068 int nContribs_z = 1;
2069
2070 std::array< std::array<int,2>, 3> cStencil;
2071 std::array< std::array<double,2>, 3> cWeights;
2072 for (int d = 0; d < dimension; ++d) {
2073 // Find cell index
2074 int index_point = ijk_point[d];
2075 if (point[d] < m_cellCenters[d][index_point]) {
2076 index_point = index_point - 1;
2077 }
2078
2079 int index_next = index_point + 1;
2080
2081 if (index_point < 0) {
2082 cStencil[d][0] = 0;
2083 cWeights[d][0] = 1.;
2084 } else if (index_next > m_nCells1D[d] - 1) {
2085 cStencil[d][0] = m_nCells1D[d] - 1;
2086 cWeights[d][0] = 1.;
2087 } else {
2088 if (d == 0) {
2089 nContribs_x = 2;
2090 } else if (d == 1) {
2091 nContribs_y = 2;
2092 } else {
2093 nContribs_z = 2;
2094 }
2095
2096 cStencil[d][0] = index_point;
2097 cStencil[d][1] = index_next;
2098
2099 cWeights[d][1] = (point[d] - m_cellCenters[d][index_point]) / m_cellSpacings[d] ;
2100 cWeights[d][0] = 1.0 - cWeights[d][1];
2101 }
2102 }
2103
2104 for (int d = dimension; d < 3; ++d) {
2105 cStencil[d][0] = 0;
2106 cWeights[d][0] = 1.;
2107 }
2108
2109 int stencilSize = nContribs_x * nContribs_y * nContribs_z;
2110 stencil->resize(stencilSize);
2111 weights->resize(stencilSize);
2112
2113 std::vector<int>::iterator itrStencil = stencil->begin();
2114 std::vector<double>::iterator itrWeights = weights->begin();
2115 for (int k = 0; k < nContribs_z; ++k) {
2116 for (int j = 0; j < nContribs_y; ++j) {
2117 for (int i = 0; i < nContribs_x; ++i) {
2118 int &is = cStencil[0][i];
2119 int &js = cStencil[1][j];
2120 int &ks = cStencil[2][k];
2121
2122 double &iw = cWeights[0][i];
2123 double &jw = cWeights[1][j];
2124 double &kw = cWeights[2][k];
2125
2126 *itrStencil = getCellLinearId(is, js, ks);
2127 *itrWeights = iw *jw * kw;
2128
2129 ++itrStencil;
2130 ++itrWeights;
2131 }
2132 }
2133 }
2134
2135 return stencilSize;
2136}
2137
2151int VolCartesian::linearVertexInterpolation(const std::array<double,3> &point,
2152 std::vector<int> *stencil, std::vector<double> *weights) const
2153{
2154 std::array<int, 3> ijk_point = locatePointCartesian(point);
2155 if (ijk_point[0] < 0) {
2156 stencil->clear();
2157 weights->clear();
2158 return 0;
2159 }
2160
2161 int dimension = getDimension();
2162
2163 int nContribs_x = 2;
2164 int nContribs_y = 2;
2165 int nContribs_z = dimension - 1;
2166
2167 std::array< std::array<int,2>, 3> cStencil;
2168 std::array< std::array<double,2>, 3> cWeights;
2169 for (int d = 0; d < dimension; ++d) {
2170 int index_point = ijk_point[d];
2171 int index_next = index_point +1;
2172
2173 cStencil[d][0] = index_point;
2174 cStencil[d][1] = index_next;
2175
2176 cWeights[d][1] = (point[d] - m_vertexCoords[d][index_point]) / m_cellSpacings[d];
2177 cWeights[d][0] = 1.0 - cWeights[d][1];
2178 }
2179
2180 for (int d = dimension; d < 3; ++d) {
2181 cStencil[d][0] = 0;
2182 cWeights[d][0] = 1.;
2183 }
2184
2185 int stencilSize = uipow(2, dimension);
2186 stencil->resize(stencilSize);
2187 weights->resize(stencilSize);
2188
2189 std::vector<int>::iterator itrStencil = stencil->begin();
2190 std::vector<double>::iterator itrWeights = weights->begin();
2191 for (int k = 0; k < nContribs_z; ++k) {
2192 for (int j = 0; j < nContribs_y; ++j) {
2193 for (int i = 0; i < nContribs_x; ++i) {
2194 int &is = cStencil[0][i];
2195 int &js = cStencil[1][j];
2196 int &ks = cStencil[2][k];
2197
2198 double &iw = cWeights[0][i];
2199 double &jw = cWeights[1][j];
2200 double &kw = cWeights[2][k];
2201
2202 *itrStencil = getVertexLinearId(is, js, ks);
2203 *itrWeights = iw * jw * kw;
2204
2205 ++itrStencil;
2206 ++itrWeights;
2207 }
2208 }
2209 }
2210
2211 return stencilSize;
2212}
2213
2220std::array<double, 3> VolCartesian::evalCellCentroid(long id) const
2221{
2222 std::array<int, 3> ijk = getCellCartesianId(id);
2223
2224 return evalCellCentroid(ijk);
2225}
2226
2233std::array<double, 3> VolCartesian::evalCellCentroid(const std::array<int, 3> &ijk) const
2234{
2235 std::array<double, 3> centroid;
2236 for (int d = 0; d < 3; ++d) {
2237 if (ijk[d] >= 0) {
2238 centroid[d] = m_cellCenters[d][ijk[d]];
2239 } else {
2240 centroid[d] = m_minCoords[d];
2241 }
2242 }
2243
2244 return centroid;
2245}
2246
2253const std::vector<double> & VolCartesian::getCellCentroids(int direction) const
2254{
2255 return m_cellCenters[direction];
2256}
2257
2265std::array<int, 3> VolCartesian::getCellFaceNeighsCartesianId(long id, int face) const
2266{
2267 int neighSide = face % 2;
2268 int neighDirection = static_cast<int>(std::floor(face / 2));
2269
2270 std::array<int, 3> neighIjk(getCellCartesianId(id));
2271 if (neighSide == 0) {
2272 neighIjk[neighDirection]--;
2273 } else {
2274 neighIjk[neighDirection]++;
2275 }
2276
2277 return neighIjk;
2278}
2279
2287long VolCartesian::getCellFaceNeighsLinearId(long id, int face) const
2288{
2289 std::array<int, 3> neighIjk = getCellFaceNeighsCartesianId(id, face);
2290
2291 long neighId;
2292 if (isCellCartesianIdValid(neighIjk)) {
2293 neighId = getCellLinearId(neighIjk);
2294 } else {
2295 neighId = Cell::NULL_ID;
2296 }
2297
2298 return neighId;
2299}
2300
2301}
The Cell class defines the cells.
Definition cell.hpp:42
void setInterface(int face, int index, long interface)
Definition cell.cpp:484
Metafunction for generation of a flattened vector of vectors.
The Interface class defines the interfaces among cells.
Definition interface.hpp:37
int getOwnerFace() const
CellConstIterator cellConstBegin() const
PiercedVector< Cell > & getCells()
AdaptionMode getAdaptionMode() const
InterfaceIterator addInterface(const Interface &source, long id=Element::NULL_ID)
VertexIterator addVertex(const Vertex &source, long id=Vertex::NULL_ID)
void setBoundingBoxFrozen(bool frozen)
Cell & getCell(long id)
CellIterator addCell(const Cell &source, long id=Element::NULL_ID)
CellConstIterator cellConstEnd() const
void scale(const std::array< double, 3 > &scaling)
virtual void translate(const std::array< double, 3 > &translation)
virtual void resetInterfaces()
virtual void reset()
void setAdaptionMode(AdaptionMode mode)
PiercedVector< Interface > & getInterfaces()
bool testCellAlterationFlags(long id, AlterationFlags flags) const
double getTol() const
void setBoundingBox(const std::array< double, 3 > &minPoint, const std::array< double, 3 > &maxPoint)
bool isThreeDimensional() const
The PatchManager oversee the handling of the patches.
id_t getId(const id_t &fallback=-1) const noexcept
Iterator for the class PiercedStorage.
Metafunction for generating a list of elements that can be either stored in an external vectror or,...
std::size_t size() const
The ReferenceElementInfo class allows to define information about reference elements.
static BITPIT_PUBLIC_API const ReferenceElementInfo & getInfo(ElementType type)
The Vertex class defines the vertexs.
Definition vertex.hpp:42
The VolCartesian defines a Cartesian patch.
void _findCellVertexNeighs(long id, int vertex, const std::vector< long > *blackList, std::vector< long > *neighs) const override
std::array< double, 3 > getLengths() const
std::array< int, 3 > getCellFaceNeighsCartesianId(long id, int face) const
long getCellLinearId(int i, int j, int k) const
double evalCellSize(long id) const override
std::array< double, 3 > evalInterfaceNormal(long id) const override
void reset() override
long getCellFaceNeighsLinearId(long id, int face) const
long getInterfaceCount() const override
void setLengths(const std::array< double, 3 > &lengths)
void resetInterfaces() override
void setOrigin(const std::array< double, 3 > &origin)
bool isPointInside(const std::array< double, 3 > &point) const override
void evalCellBoundingBox(long id, std::array< double, 3 > *minPoint, std::array< double, 3 > *maxPoint) const override
std::vector< long > extractVertexSubSet(std::array< int, 3 > const &ijkMin, std::array< int, 3 > const &ijkMax) const
long locateClosestCell(std::array< double, 3 > const &point) const
std::vector< long > extractCellSubSet(std::array< int, 3 > const &ijkMin, std::array< int, 3 > const &ijkMax) const
std::array< int, 3 > locatePointCartesian(const std::array< double, 3 > &point) const
std::array< int, 3 > locateClosestVertexCartesian(std::array< double, 3 > const &point) const
long locateClosestVertex(std::array< double, 3 > const &point) const
long getCellCount() const override
std::unique_ptr< PatchKernel > clone() const override
std::array< double, 3 > getOrigin() const
void rotate(const std::array< double, 3 > &n0, const std::array< double, 3 > &n1, double angle) override
double evalCellVolume(long id) const override
void _updateAdjacencies() override
std::array< int, 3 > locateClosestCellCartesian(std::array< double, 3 > const &point) const
ElementType getCellType() const
std::array< double, 3 > evalCellCentroid(long id) const override
int _getDumpVersion() const override
bool isVertexCartesianIdValid(const std::array< int, 3 > &ijk) const
std::array< int, 3 > getVertexCartesianId(long id) const
ElementType getInterfaceType() const
long locatePoint(const std::array< double, 3 > &point) const override
const std::vector< double > & getVertexCoords(int direction) const
long getVertexCount() const override
std::vector< double > convertToCellData(const std::vector< double > &vertexData) const
double evalInterfaceArea(long id) const override
void _findCellFaceNeighs(long id, int face, const std::vector< long > *blackList, std::vector< long > *neighs) const override
std::array< int, 3 > getCellCartesianId(long id) const
std::vector< double > convertToVertexData(const std::vector< double > &cellData) const
bool isCellCartesianIdValid(const std::array< int, 3 > &ijk) const
void switchMemoryMode(MemoryMode mode)
int linearCellInterpolation(const std::array< double, 3 > &point, std::vector< int > *stencil, std::vector< double > *weights) const
void _updateInterfaces() override
void _findCellEdgeNeighs(long id, int edge, const std::vector< long > *blackList, std::vector< long > *neighs) const override
int linearVertexInterpolation(const std::array< double, 3 > &point, std::vector< int > *stencil, std::vector< double > *weights) const
long getVertexLinearId(int i, int j, int k) const
void translate(const std::array< double, 3 > &translation) override
const std::vector< double > & getCellCentroids(int direction) const
std::array< double, 3 > evalVertexCoords(long id) const
std::array< double, 3 > getSpacing() const
void _dump(std::ostream &stream) const override
void _restore(std::istream &stream) override
void scale(const std::array< double, 3 > &scaling, const std::array< double, 3 > &center) override
MemoryMode getMemoryMode() const
The VolumeKernel class provides an interface for defining volume patches.
std::array< T, d > pow(std::array< T, d > &x, double p)
T uipow(const T &, unsigned int)
Definition Operators.tpp:55
void write(std::ostream &stream, const std::vector< bool > &container)
void read(std::istream &stream, std::vector< bool > &container)
#define BITPIT_UNUSED(variable)
Definition compiler.hpp:63
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)
Definition logger.cpp:1705
--- layout: doxygen_footer ---