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
63
68#if BITPIT_ENABLE_MPI==1
69 : VolumeKernel(MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
70#else
71 : VolumeKernel(ADAPTION_DISABLED)
72#endif
73{
74 initialize();
75}
76
86 const std::array<double, 3> &origin,
87 const std::array<double, 3> &lengths,
88 const std::array<int, 3> &nCells)
89 : VolCartesian(PatchManager::AUTOMATIC_ID, dimension, origin, lengths, nCells)
90{
91}
92
102VolCartesian::VolCartesian(int id, int dimension,
103 const std::array<double, 3> &origin,
104 const std::array<double, 3> &lengths,
105 const std::array<int, 3> &nCells)
106#if BITPIT_ENABLE_MPI==1
107 : VolumeKernel(id, dimension, MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
108#else
109 : VolumeKernel(id, dimension, ADAPTION_DISABLED)
110#endif
111{
112 initialize();
113
114 setOrigin(origin);
115 setLengths(lengths);
116
117 setDiscretization(nCells);
118}
119
129 const std::array<double, 3> &origin,
130 double length, int nCells)
131 : VolCartesian(PatchManager::AUTOMATIC_ID, dimension, origin, length, nCells)
132{
133}
134
144VolCartesian::VolCartesian(int id, int dimension,
145 const std::array<double, 3> &origin,
146 double length, int nCells)
147#if BITPIT_ENABLE_MPI==1
148 : VolumeKernel(id, dimension, MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
149#else
150 : VolumeKernel(id, dimension, ADAPTION_DISABLED)
151#endif
152{
153 initialize();
154
155 setOrigin(origin);
156 setLengths({{length, length, length}});
157
158 setDiscretization({{nCells, nCells, nCells}});
159}
160
170 const std::array<double, 3> &origin,
171 double length, double dh)
172 : VolCartesian(PatchManager::AUTOMATIC_ID, dimension, origin, length, dh)
173{
174}
175
185VolCartesian::VolCartesian(int id, int dimension,
186 const std::array<double, 3> &origin,
187 double length, double dh)
188#if BITPIT_ENABLE_MPI==1
189 : VolumeKernel(id, dimension, MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
190#else
191 : VolumeKernel(id, dimension, ADAPTION_DISABLED)
192#endif
193{
194 initialize();
195
196 setOrigin(origin);
197 setLengths({{length, length, length}});
198
199 int nCells = (int) std::ceil(length / dh);
200 setDiscretization({{nCells, nCells, nCells}});
201}
202
208VolCartesian::VolCartesian(std::istream &stream)
209#if BITPIT_ENABLE_MPI==1
210 : VolumeKernel(MPI_COMM_NULL, 0, ADAPTION_DISABLED, PARTITIONING_DISABLED)
211#else
212 : VolumeKernel(ADAPTION_DISABLED)
213#endif
214{
215 initialize();
216 restore(stream);
217}
218
224std::unique_ptr<PatchKernel> VolCartesian::clone() const
225{
226 return std::unique_ptr<VolCartesian>(new VolCartesian(*this));
227}
228
233{
234 // Switch to light memeory mode
235 switchMemoryMode(MEMORY_LIGHT);
236
237 // Reset geometry and discretization
238 m_minCoords = {{0., 0., 0.}};
239 m_maxCoords = {{1., 1., 1.}};
240
241 m_nCells1D = {{0, 0, 0}};
242 m_nVertices1D = {{0, 0, 0}};
243 m_cellSpacings = {{0., 0., 0.}};
244
245 for (int n = 0; n < 3; ++n) {
246 std::vector<double>().swap(m_vertexCoords[n]);
247 std::vector<double>().swap(m_cellCenters[n]);
248 }
249
250 m_nVertices = 0;
251 m_nCells = 0;
252 m_nInterfaces = 0;
253}
254
261{
262 // Partial updates are not supported
263 CellConstIterator beginItr = cellConstBegin();
264 CellConstIterator endItr = cellConstEnd();
265
266 bool partialUpdate = false;
267 for (CellConstIterator cellIterator = beginItr; cellIterator != endItr; ++cellIterator) {
268 long cellId = cellIterator.getId();
269 if (!testCellAlterationFlags(cellId, FLAG_ADJACENCIES_DIRTY)) {
270 partialUpdate = true;
271 break;
272 }
273 }
274
275 if (partialUpdate) {
276 log::cout() << " It is not possible to partially update the adjacencies.";
277 log::cout() << " All adjacencies will be updated.";
278 }
279
280 // Update adjacencies
281 int nCellFaces = 2 * getDimension();
282 for (Cell &cell : getCells()) {
283 // Reset cell adjacencies
284 if (cell.getAdjacencyCount() != 0) {
285 cell.resetAdjacencies();
286 }
287
288 // Evaluate adjacencies
289 long cellId = cell.getId();
290 for (int face = 0; face < nCellFaces; ++face) {
291 // Identify face neighbour
292 long neighId = getCellFaceNeighsLinearId(cellId, face);
293 if (neighId < 0) {
294 continue;
295 }
296
297 // Add adjacency
298 cell.pushAdjacency(face, neighId);
299 }
300 }
301}
302
310{
311 // Partial updates are not supported
312 CellConstIterator beginItr = cellConstBegin();
313 CellConstIterator endItr = cellConstEnd();
314
315 bool partialUpdate = false;
316 for (CellConstIterator cellIterator = beginItr; cellIterator != endItr; ++cellIterator) {
317 long cellId = cellIterator.getId();
318 if (!testCellAlterationFlags(cellId, FLAG_INTERFACES_DIRTY)) {
319 partialUpdate = true;
320 break;
321 }
322 }
323
324 if (partialUpdate) {
325 log::cout() << " It is not possible to partially update the interfaces.";
326 log::cout() << " All interfaces will be updated.";
327 }
328
329 // Build interfaces
330 if (getMemoryMode() == MemoryMode::MEMORY_NORMAL) {
331 int nCellFaces = 2 * getDimension();
332
333 // Info on the interfaces
334 ElementType interfaceType = getInterfaceType();
335
336 const ReferenceElementInfo &interfaceTypeInfo = ReferenceElementInfo::getInfo(interfaceType);
337 const int nInterfaceVertices = interfaceTypeInfo.nVertices;
338
339 // Enable manual adaption
340 AdaptionMode previousAdaptionMode = getAdaptionMode();
342
343 // Initialize interfaces
344 for (Cell &cell : getCells()) {
345 cell.setInterfaces(FlatVector2D<long>(nCellFaces, 1, Interface::NULL_ID));
346 }
347
348 // Build interfaces
349 for (Cell &cell : getCells()) {
350 long cellId = cell.getId();
351 for (int face = 0; face < nCellFaces; ++face) {
352 // Get neighbour information
353 //
354 // The interface between two cells needs to be processed only
355 // once. In order to ensure this, we build an interface if the
356 // faces is a border, or if the id of this cell is lower than
357 // the id of its neighbour.
358 long neighId;
359 if (cell.getAdjacencyCount(face) > 0) {
360 neighId = cell.getAdjacencies(face)[0];
361 if (neighId < cellId) {
362 continue;
363 }
364 } else {
365 neighId = Cell::NULL_ID;
366 }
367
368 // Create the interface
369 InterfaceIterator interfaceIterator = VolumeKernel::addInterface(interfaceType);
370 Interface &interface = *interfaceIterator;
371 long interfaceId = interface.getId();
372
373 // Set connectivity
374 ConstProxyVector<long> faceConnect = cell.getFaceConnect(face);
375 int connectSize = faceConnect.size();
376
377 std::unique_ptr<long[]> connect = std::unique_ptr<long[]>(new long[nInterfaceVertices]);
378 for (int k = 0; k < connectSize; ++k) {
379 connect[k] = faceConnect[k];
380 }
381 interface.setConnect(std::move(connect));
382
383 // Set owner data
384 interface.setOwner(cellId, face);
385 cell.setInterface(face, 0, interfaceId);
386
387 // Neighbour data
388 if (neighId >= 0) {
389 Cell &neigh = getCell(neighId);
390 int neighFace = 2 * static_cast<int>(std::floor(face / 2.)) + (1 - face % 2);
391
392 interface.setNeigh(neighId, neighFace);
393 neigh.setInterface(neighFace, 0, interfaceId);
394 } else {
395 interface.unsetNeigh();
396 }
397 }
398 }
399
400 // Restore previous adaption mode
401 setAdaptionMode(previousAdaptionMode);
402 }
403}
404
408void VolCartesian::initialize()
409{
410 // Normals
411 int i = 0;
412 for (int n = 0; n < 3; n++) {
413 for (int k = -1; k <= 1; k += 2) {
414 std::array<double, 3> normal = {{0.0, 0.0, 0.0}};
415 normal[n] = k;
416
417 m_normals[i++] = normal;
418 }
419 }
420
421 // Deltas for the evaluation of the vertex neighbours
422 m_vertexNeighDeltas = std::vector<std::array<int, 3>>(8);
423 m_vertexNeighDeltas[0] = {{ 0, 0, 0}};
424 m_vertexNeighDeltas[1] = {{-1, 0, 0}};
425 m_vertexNeighDeltas[2] = {{ 0, -1, 0}};
426 m_vertexNeighDeltas[3] = {{-1, -1, 0}};
427 m_vertexNeighDeltas[4] = {{ 0, 0, -1}};
428 m_vertexNeighDeltas[5] = {{-1, 0, -1}};
429 m_vertexNeighDeltas[6] = {{ 0, -1, -1}};
430 m_vertexNeighDeltas[7] = {{-1, -1, -1}};
431
432 // Deltas for the evaluation of the edge neighbours
433 m_edgeNeighDeltas = std::vector<std::array<int, 3>>(12);
434 m_edgeNeighDeltas[ 0] = {{-1, 0, -1}};
435 m_edgeNeighDeltas[ 1] = {{ 1, 0, -1}};
436 m_edgeNeighDeltas[ 2] = {{ 0, -1, -1}};
437 m_edgeNeighDeltas[ 3] = {{ 0, 1, -1}};
438 m_edgeNeighDeltas[ 4] = {{-1, -1, 0}};
439 m_edgeNeighDeltas[ 5] = {{ 1, -1, 0}};
440 m_edgeNeighDeltas[ 6] = {{-1, 1, 0}};
441 m_edgeNeighDeltas[ 7] = {{ 1, 1, 0}};
442 m_edgeNeighDeltas[ 8] = {{-1, 0, 1}};
443 m_edgeNeighDeltas[ 9] = {{ 1, 0, 1}};
444 m_edgeNeighDeltas[10] = {{ 0, -1, 1}};
445 m_edgeNeighDeltas[11] = {{ 0, 1, 1}};
446
447 // Faces associated to the edges
448 m_edgeFaces = std::vector<std::array<int, 2>>(12);
449 m_edgeFaces[ 0] = {{ 0, 4}};
450 m_edgeFaces[ 1] = {{ 1, 4}};
451 m_edgeFaces[ 2] = {{ 2, 4}};
452 m_edgeFaces[ 3] = {{ 3, 4}};
453 m_edgeFaces[ 4] = {{ 0, 2}};
454 m_edgeFaces[ 5] = {{ 1, 2}};
455 m_edgeFaces[ 6] = {{ 0, 3}};
456 m_edgeFaces[ 7] = {{ 1, 3}};
457 m_edgeFaces[ 8] = {{ 0, 5}};
458 m_edgeFaces[ 9] = {{ 1, 5}};
459 m_edgeFaces[10] = {{ 2, 5}};
460 m_edgeFaces[11] = {{ 3, 5}};
461
462 // Set the bounding box as frozen
464
465 // Set the light memory mode
466 setMemoryMode(MemoryMode::MEMORY_LIGHT);
467
468 // Reset the patch
469 reset();
470}
471
475void VolCartesian::initializeCellVolume()
476{
477 m_cellVolume = 1;
478 for (int d = 0; d < getDimension(); ++d) {
479 if (m_directionOrdering[d] >= 0) {
480 m_cellVolume *= m_cellSpacings[d];
481 }
482 }
483}
484
488void VolCartesian::initializeCellSize()
489{
490 m_cellSize = std::pow(m_cellVolume, 1. / getDimension());
491}
492
496void VolCartesian::initializeInterfaceArea()
497{
498 for (int d = 0; d < getDimension(); ++d) {
499 if (m_directionOrdering[d] >= 0) {
500 m_interfaceArea[d] = m_cellVolume / m_cellSpacings[d];
501 } else {
502 m_interfaceArea[d] = 0.;
503 }
504 }
505}
506
512void VolCartesian::setDiscretization(const std::array<int, 3> &nCells)
513{
514 // Spacing
515 for (int d = 0; d < getDimension(); ++d) {
516 // Initialize cells
517 if (nCells[d] > 0) {
518 m_nCells1D[d] = nCells[d];
519 m_cellSpacings[d] = (m_maxCoords[d] - m_minCoords[d]) / m_nCells1D[d];
520
521 m_cellCenters[d].resize(m_nCells1D[d]);
522 for (int i = 0; i < m_nCells1D[d]; i++) {
523 m_cellCenters[d][i] = m_minCoords[d] + (0.5 + i) * m_cellSpacings[d];
524 }
525 } else {
526 m_nCells1D[d] = 0;
527 m_cellSpacings[d] = 0.;
528 }
529
530 log::cout() << " - Cell count along direction " << d << " : " << m_nCells1D[d] << "\n";
531
532 // Initialize vertices
533 m_nVertices1D[d] = m_nCells1D[d] + 1;
534
535 m_vertexCoords[d].resize(m_nVertices1D[d]);
536 for (int i = 0; i < m_nVertices1D[d]; i++) {
537 m_vertexCoords[d][i] = m_minCoords[d] + i * m_cellSpacings[d];
538 }
539 }
540
541 for (int d = getDimension(); d < 3; ++d) {
542 m_nCells1D[d] = 0;
543 m_cellSpacings[d] = 0.;
544
545 m_nVertices1D[d] = 1;
546 }
547
548 log::cout() << std::endl;
549
550 // Define direction ordering
551 //
552 // It is the ordering in which the different directions will be considered
553 // when numbering cell, vertices, ... For each direction, it will contain
554 // the order in which the direction should be considered or -1 if there
555 // are no cells along the direction.
556 for (int d = 0; d < 3; ++d) {
557 if (d == 0) {
558 m_directionOrdering[d] = 0;
559 } else {
560 int previousDirection = m_directionOrdering[d - 1];
561 if (previousDirection < 0 || previousDirection >= 2) {
562 m_directionOrdering[d] = -1;
563 continue;
564 }
565
566 m_directionOrdering[d] = previousDirection + 1;
567 }
568
569 while (m_nCells1D[m_directionOrdering[d]] == 0) {
570 if (m_directionOrdering[d] == 2) {
571 m_directionOrdering[d] = -1;
572 break;
573 }
574
575 ++m_directionOrdering[d];
576 }
577 }
578
579 // Count the total number of vertices
580 m_nVertices = 1;
581 for (int n = 0; n < getDimension(); ++n) {
582 m_nVertices *= m_nVertices1D[n];
583 }
584 log::cout() << " - Total vertex count: " << m_nVertices << "\n";
585
586 // Count the total number of cells
587 m_nCells = 1;
588 for (int d = 0; d < getDimension(); ++d) {
589 if (m_directionOrdering[d] >= 0) {
590 m_nCells *= m_nCells1D[d];
591 }
592 }
593
594 log::cout() << " - Total cell count: " << m_nCells << "\n";
595
596 // Count the total number of interfaces
597 m_nInterfaces = 0;
598 for (int d = 0; d < getDimension(); ++d) {
599 int nDirectionInterfaces = 1;
600 for (int n = 0; n < getDimension(); n++) {
601 int nDirectionInterfaces1D = m_nCells1D[n];
602 if (n == d) {
603 ++nDirectionInterfaces1D;
604 }
605
606 nDirectionInterfaces *= nDirectionInterfaces1D;
607 }
608 m_nInterfaces += nDirectionInterfaces;
609 }
610
611 log::cout() << " - Total interface count: " << m_nInterfaces << "\n";
612
613 // Cell volume
614 initializeCellVolume();
615
616 // Cell size
617 initializeCellSize();
618
619 // Interface area
620 initializeInterfaceArea();
621
622 // Update patch data structures
623 if (getMemoryMode() == MemoryMode::MEMORY_NORMAL) {
624 // Switch to light mode to reset patchdata structures
625 switchMemoryMode(MemoryMode::MEMORY_LIGHT);
626
627 // Swich back to normal mode to rebuild patchdata structures
628 switchMemoryMode(MemoryMode::MEMORY_NORMAL);
629 }
630}
631
638{
639 return m_nVertices;
640}
641
648int VolCartesian::getVertexCount(int direction) const
649{
650 return m_nVertices1D[direction];
651}
652
659{
660 return m_nCells;
661}
662
669int VolCartesian::getCellCount(int direction) const
670{
671 return m_nCells1D[direction];
672}
673
681{
682 BITPIT_UNUSED(id);
683
684 return getCellType();
685}
686
693{
694 if (isThreeDimensional()) {
695 return ElementType::VOXEL;
696 } else {
697 return ElementType::PIXEL;
698 }
699}
700
707{
708 return m_nInterfaces;
709}
710
718{
719 BITPIT_UNUSED(id);
720
721 return getInterfaceType();
722}
723
730{
731 if (isThreeDimensional()) {
732 return ElementType::PIXEL;
733 } else {
734 return ElementType::LINE;
735 }
736}
737
744std::array<double, 3> VolCartesian::evalVertexCoords(long id) const
745{
746 std::array<int, 3> ijk = getVertexCartesianId(id);
747
748 return evalVertexCoords(ijk);
749}
750
757std::array<double, 3> VolCartesian::evalVertexCoords(const std::array<int, 3> &ijk) const
758{
759 std::array<double, 3> coords;
760 for (int d = 0; d < 3; ++d) {
761 if (ijk[d] >= 0) {
762 coords[d] = m_vertexCoords[d][ijk[d]];
763 } else {
764 coords[d] = m_minCoords[d];
765 }
766 }
767
768 return coords;
769}
770
779const std::vector<double> & VolCartesian::getVertexCoords(int direction) const
780{
781 return m_vertexCoords[direction];
782}
783
790double VolCartesian::evalCellVolume(long id) const
791{
792 BITPIT_UNUSED(id);
793
794 return evalCellVolume();
795}
796
803double VolCartesian::evalCellVolume(const std::array<int, 3> &ijk) const
804{
805 BITPIT_UNUSED(ijk);
806
807 return evalCellVolume();
808}
809
817double VolCartesian::evalCellVolume() const
818{
819 return m_cellVolume;
820}
821
828double VolCartesian::evalCellSize(long id) const
829{
830 BITPIT_UNUSED(id);
831
832 return evalCellSize();
833}
834
841double VolCartesian::evalCellSize(const std::array<int, 3> &ijk) const
842{
843 BITPIT_UNUSED(ijk);
844
845 return evalCellSize();
846}
847
855double VolCartesian::evalCellSize() const
856{
857 return m_cellSize;
858}
859
867void VolCartesian::evalCellBoundingBox(long id, std::array<double,3> *minPoint, std::array<double,3> *maxPoint) const
868{
869 std::array<double,3> cellCentroid = evalCellCentroid(id);
870 for (int d = 0; d < 3; ++d) {
871 (*minPoint)[d] = cellCentroid[d] - 0.5 * m_cellSpacings[d];
872 (*maxPoint)[d] = cellCentroid[d] + 0.5 * m_cellSpacings[d];
873 }
874}
875
883{
884 const Interface &interface = getInterface(id);
885 int ownerFace = interface.getOwnerFace();
886 int direction = static_cast<int>(std::floor(ownerFace / 2.));
887
888 return m_interfaceArea[direction];
889}
890
897std::array<double, 3> VolCartesian::evalInterfaceNormal(long id) const
898{
899 const Interface &interface = getInterface(id);
900 int ownerFace = interface.getOwnerFace();
901
902 return m_normals[ownerFace];
903}
904
910std::array<double, 3> VolCartesian::getSpacing() const
911{
912 return m_cellSpacings;
913}
914
921{
922 // Early return if the current memory mode matches the requested one
923 if (mode == getMemoryMode()) {
924 return;
925 }
926
927 // Update patch data structures
928 switch (mode) {
929
930 case MemoryMode::MEMORY_NORMAL:
931 {
932 // Enable manual adaption
933 AdaptionMode previousAdaptionMode = getAdaptionMode();
935
936 // Create the mesh
937 addVertices();
938 addCells();
939
940 // Restore previous adaption mode
941 setAdaptionMode(previousAdaptionMode);
942
943 break;
944 }
945
946 case MemoryMode::MEMORY_LIGHT:
947 {
948 // To put the patch in memory mode we need to reset the generic data
949 // of the patch, therefore we can call the 'reset' implementation of
950 // the kernel.
952
953 break;
954 }
955
956 }
957
958 // Set the requested memory mode
959 setMemoryMode(mode);
960
961 // Update the patch
962 //
963 // This will update all data structures (e.g., the interface) associated with the patch.
964 if (mode == MemoryMode::MEMORY_NORMAL) {
965 update();
966 }
967}
968
976void VolCartesian::setMemoryMode(MemoryMode mode)
977{
978 m_memoryMode = mode;
979}
980
986VolCartesian::MemoryMode VolCartesian::getMemoryMode() const
987{
988 return m_memoryMode;
989}
990
998double VolCartesian::getSpacing(int direction) const
999{
1000 return m_cellSpacings[direction];
1001}
1002
1006void VolCartesian::addVertices()
1007{
1008 log::cout() << " >> Creating vertices\n";
1009
1010 log::cout() << " - Vertex count: " << m_nVertices << "\n";
1011
1012 m_vertices.reserve(m_nVertices);
1013 for (int k = 0; (isThreeDimensional()) ? (k < m_nVertices1D[Vertex::COORD_Z]) : (k <= 0); k++) {
1014 for (int j = 0; j < m_nVertices1D[Vertex::COORD_Y]; j++) {
1015 for (int i = 0; i < m_nVertices1D[Vertex::COORD_X]; i++) {
1016 // Linear index of the vertex
1017 long id_vertex = getVertexLinearId(i, j, k);
1018
1019 // Vertex coordinates
1020 std::array<double, 3> coords = evalVertexCoords(id_vertex);
1021
1022 // Add vertex
1023 VolumeKernel::addVertex(std::move(coords), id_vertex);
1024 }
1025 }
1026 }
1027}
1028
1032void VolCartesian::addCells()
1033{
1034 log::cout() << " >> Creating cells\n";
1035
1036 // Info on the cells
1037 ElementType cellType = getCellType();
1038
1039 // Create the cells
1040 log::cout() << " - Cell count: " << m_nCells << "\n";
1041
1042 m_cells.reserve(m_nCells);
1043 for (int k = 0; (isThreeDimensional()) ? (k < m_nCells1D[Vertex::COORD_Z]) : (k <= 0); k++) {
1044 for (int j = 0; j < m_nCells1D[Vertex::COORD_Y]; j++) {
1045 for (int i = 0; i < m_nCells1D[Vertex::COORD_X]; i++) {
1046 long id_cell = getCellLinearId(i, j, k);
1047 CellIterator cellIterator = VolumeKernel::addCell(cellType, id_cell);
1048 Cell &cell = *cellIterator;
1049
1050 // Connettività
1051 long *cellConnect = cell.getConnect();
1052
1053 cellConnect[0] = getVertexLinearId(i, j, k);
1054 cellConnect[1] = getVertexLinearId(i + 1, j, k);
1055 cellConnect[2] = getVertexLinearId(i, j + 1, k);
1056 cellConnect[3] = getVertexLinearId(i + 1, j + 1, k);
1057 if (cellType == ElementType::VOXEL) {
1058 cellConnect[4] = getVertexLinearId(i, j, k + 1);
1059 cellConnect[5] = getVertexLinearId(i + 1, j, k + 1);
1060 cellConnect[6] = getVertexLinearId(i, j + 1, k + 1);
1061 cellConnect[7] = getVertexLinearId(i + 1, j + 1, k + 1);
1062 }
1063 }
1064 }
1065 }
1066}
1067
1074{
1075 const int DUMP_VERSION = 2;
1076
1077 return DUMP_VERSION;
1078}
1079
1085void VolCartesian::_dump(std::ostream &stream) const
1086{
1087 utils::binary::write(stream, m_minCoords[0]);
1088 utils::binary::write(stream, m_minCoords[1]);
1089 utils::binary::write(stream, m_minCoords[2]);
1090
1091 utils::binary::write(stream, m_maxCoords[0] - m_minCoords[0]);
1092 utils::binary::write(stream, m_maxCoords[1] - m_minCoords[1]);
1093 utils::binary::write(stream, m_maxCoords[2] - m_minCoords[2]);
1094
1095 utils::binary::write(stream, m_nCells1D[0]);
1096 utils::binary::write(stream, m_nCells1D[1]);
1097 utils::binary::write(stream, m_nCells1D[2]);
1098
1099 utils::binary::write(stream, m_memoryMode);
1100
1101 if (m_memoryMode == MEMORY_NORMAL) {
1102 for (const Cell &cell : getCells()) {
1103 utils::binary::write(stream, cell.getPID());
1104 }
1105 }
1106
1107 if (m_memoryMode == MEMORY_NORMAL) {
1108 for (const Interface &interface : getInterfaces()) {
1109 utils::binary::write(stream, interface.getPID());
1110 }
1111 }
1112}
1113
1119void VolCartesian::_restore(std::istream &stream)
1120{
1121 // Origin
1122 std::array<double, 3> origin;
1123 utils::binary::read(stream, origin[0]);
1124 utils::binary::read(stream, origin[1]);
1125 utils::binary::read(stream, origin[2]);
1126
1127 setOrigin(origin);
1128
1129 // Lengths
1130 std::array<double, 3> lengths;
1131 utils::binary::read(stream, lengths[0]);
1132 utils::binary::read(stream, lengths[1]);
1133 utils::binary::read(stream, lengths[2]);
1134
1135 setLengths(lengths);
1136
1137 // Discretization
1138 std::array<int, 3> nCells;
1139 utils::binary::read(stream, nCells[0]);
1140 utils::binary::read(stream, nCells[1]);
1141 utils::binary::read(stream, nCells[2]);
1142
1143 setDiscretization(nCells);
1144
1145 // Memory mode
1146 MemoryMode memoryMode;
1147 utils::binary::read(stream, memoryMode);
1148 switchMemoryMode(memoryMode);
1149
1150 // Cell data
1151 if (m_memoryMode == MEMORY_NORMAL) {
1152 for (Cell &cell : getCells()) {
1153 int PID;
1154 utils::binary::read(stream, PID);
1155 cell.setPID(PID);
1156 }
1157 }
1158
1159 // Interface data
1160 if (m_memoryMode == MEMORY_NORMAL) {
1161 for (Interface &interface : getInterfaces()) {
1162 int PID;
1163 utils::binary::read(stream, PID);
1164 interface.setPID(PID);
1165 }
1166 }
1167}
1168
1176bool VolCartesian::isPointInside(long id, const std::array<double, 3> &point) const
1177{
1178 std::array<int, 3> cellIjk = getCellCartesianId(id);
1179
1180 const double EPS = getTol();
1181 for (int d = 0; d < 3; ++d){
1182 long index = cellIjk[d];
1183
1184 double spacing = m_cellSpacings[d];
1185 double cellMin = m_cellCenters[d][index] - 0.5 * spacing;
1186 double cellMax = m_cellCenters[d][index] + 0.5 * spacing;
1187
1188 if (point[d]< cellMin - EPS || point[d] > cellMax + EPS) {
1189 return false;
1190 }
1191 }
1192
1193 return true;
1194}
1195
1202bool VolCartesian::isPointInside(const std::array<double, 3> &point) const
1203{
1204 const double EPS = getTol();
1205
1206 for (int n = 0; n < getDimension(); n++) {
1207 if (point[n] < m_minCoords[n] - EPS || point[n] > m_maxCoords[n] + EPS) {
1208 return false;
1209 }
1210 }
1211
1212 return true;
1213}
1214
1226long VolCartesian::locatePoint(const std::array<double, 3> &point) const
1227{
1228 std::array<int, 3> pointIjk = locatePointCartesian(point);
1229 if (isCellCartesianIdValid(pointIjk)) {
1230 return getCellLinearId(pointIjk);
1231 } else {
1232 return Element::NULL_ID;
1233 }
1234}
1235
1246std::array<int, 3> VolCartesian::locatePointCartesian(const std::array<double, 3> &point) const
1247{
1248 std::array<int, 3> ijk;
1249 if (!isPointInside(point)) {
1250 ijk[0] = -1;
1251 ijk[1] = -1;
1252 ijk[2] = -1;
1253
1254 return ijk;
1255 }
1256
1257 ijk[0] = static_cast<int>(std::floor((point[Vertex::COORD_X] - m_minCoords[Vertex::COORD_X]) / m_cellSpacings[Vertex::COORD_X]));
1258 ijk[1] = static_cast<int>(std::floor((point[Vertex::COORD_Y] - m_minCoords[Vertex::COORD_Y]) / m_cellSpacings[Vertex::COORD_Y]));
1259 if (isThreeDimensional()) {
1260 ijk[2] = static_cast<int>(std::floor((point[Vertex::COORD_Z] - m_minCoords[Vertex::COORD_Z]) / m_cellSpacings[Vertex::COORD_Z]));
1261 } else {
1262 ijk[2] = -1;
1263 }
1264
1265 return ijk;
1266}
1267
1274long VolCartesian::locateClosestVertex(std::array<double,3> const &point) const
1275{
1277}
1278
1286std::array<int, 3> VolCartesian::locateClosestVertexCartesian(std::array<double,3> const &point) const
1287{
1288 std::array<int, 3> ijk;
1289 for (int n = 0; n < getDimension(); ++n) {
1290 ijk[n] = std::min(m_nVertices1D[n] - 1, std::max(0, (int) round((point[n] - m_minCoords[n]) / m_cellSpacings[n])));
1291 }
1292
1293 if (!isThreeDimensional()) {
1294 ijk[Vertex::COORD_Z] = -1;
1295 }
1296
1297 return ijk;
1298}
1299
1309long VolCartesian::locateClosestCell(const std::array<double, 3> &point) const
1310{
1311 std::array<int, 3> pointIjk = locateClosestCellCartesian(point);
1312 return getCellLinearId(pointIjk);
1313}
1314
1324std::array<int, 3> VolCartesian::locateClosestCellCartesian(const std::array<double, 3> &point) const
1325{
1326 std::array<int,3> ijk({{0,0,0}});
1327
1328 for( int i=0; i<getDimension(); ++i){
1329 ijk[i] = static_cast<int>(std::floor((point[i] - m_minCoords[i]) / m_cellSpacings[i]));
1330 ijk[i] = std::max( ijk[i], 0 );
1331 ijk[i] = std::min( ijk[i], m_nCells1D[i]-1 );
1332 }
1333
1334 return ijk;
1335}
1336
1351long VolCartesian::getCellLinearId(int i, int j, int k) const
1352{
1353 return getCellLinearId(std::array<int, 3>{{i, j, k}});
1354}
1355
1368long VolCartesian::getCellLinearId(const std::array<int, 3> &ijk) const
1369{
1370 int l = m_directionOrdering[0];
1371 int m = m_directionOrdering[1];
1372 int n = m_directionOrdering[2];
1373
1374 if (l == -1) {
1375 return Cell::NULL_ID;
1376 }
1377
1378 long id = ijk[l];
1379 if (m >= 0) {
1380 id += m_nCells1D[l] * ijk[m];
1381 if (n >= 0) {
1382 id += m_nCells1D[l] * m_nCells1D[m] * ijk[n];
1383 }
1384 }
1385
1386 return id;
1387}
1388
1402std::array<int, 3> VolCartesian::getCellCartesianId(long id) const
1403{
1404 int l = m_directionOrdering[0];
1405 int m = m_directionOrdering[1];
1406 int n = m_directionOrdering[2];
1407
1408 std::array<int, 3> ijk = {{-1, -1, -1}};
1409 if (m == -1) {
1410 ijk[l] = id;
1411 } else if (l >= 0) {
1412 int offset_lm = m_nCells1D[l] * m_nCells1D[m];
1413 int index_n = id / offset_lm;
1414
1415 ijk[m] = (id - index_n * offset_lm) / m_nCells1D[l];
1416 ijk[l] = id - (id / m_nCells1D[l]) * m_nCells1D[l];
1417 if (n != -1) {
1418 ijk[n] = index_n;
1419 }
1420 }
1421
1422 return ijk;
1423}
1424
1431bool VolCartesian::isCellCartesianIdValid(const std::array<int, 3> &ijk) const
1432{
1433 for (int k = 0; k < getDimension(); ++k) {
1434 if (ijk[k] < 0 || ijk[k] >= m_nCells1D[k]) {
1435 return false;
1436 }
1437 }
1438
1439 return true;
1440}
1441
1456long VolCartesian::getVertexLinearId(int i, int j, int k) const
1457{
1458 return getVertexLinearId(std::array<int, 3>{{i, j, k}});
1459}
1460
1473long VolCartesian::getVertexLinearId(const std::array<int, 3> &ijk) const
1474{
1475 int l = m_directionOrdering[0];
1476 int m = m_directionOrdering[1];
1477 int n = m_directionOrdering[2];
1478
1479 if (l == -1) {
1480 return Vertex::NULL_ID;
1481 }
1482
1483 long id = ijk[l];
1484 if (m >= 0) {
1485 id += m_nVertices1D[l] * ijk[m];
1486 if (n >= 0) {
1487 id += m_nVertices1D[l] * m_nVertices1D[m] * ijk[n];
1488 }
1489 }
1490
1491 return id;
1492}
1493
1507std::array<int, 3> VolCartesian::getVertexCartesianId(long id) const
1508{
1509 int l = m_directionOrdering[0];
1510 int m = m_directionOrdering[1];
1511 int n = m_directionOrdering[2];
1512
1513 std::array<int, 3> ijk = {{-1, -1, -1}};
1514 if (m == -1) {
1515 ijk[l] = id;
1516 } else if (l >= 0) {
1517 int offset_lm = m_nVertices1D[l] * m_nVertices1D[m];
1518 int index_n = id / offset_lm;
1519
1520 ijk[m] = (id - index_n * offset_lm) / m_nVertices1D[l];
1521 ijk[l] = id - (id / m_nVertices1D[l]) * m_nVertices1D[l];
1522 if (n != -1) {
1523 ijk[n] = index_n;
1524 }
1525 }
1526
1527 return ijk;
1528}
1529
1544std::array<int, 3> VolCartesian::getVertexCartesianId(long cellId, int vertex) const
1545{
1546 return getVertexCartesianId(getCellCartesianId(cellId), vertex);
1547}
1548
1563std::array<int, 3> VolCartesian::getVertexCartesianId(const std::array<int, 3> &cellIjk, int vertex) const
1564{
1565 std::bitset<3> vertexBitset(vertex);
1566 std::array<int, 3> vertexIjk(cellIjk);
1567 for (int k = 0; k < 3; ++k) {
1568 vertexIjk[k] += vertexBitset[k];
1569 }
1570
1571 return vertexIjk;
1572}
1573
1580bool VolCartesian::isVertexCartesianIdValid(const std::array<int, 3> &ijk) const
1581{
1582 for (int k = 0; k < getDimension(); ++k) {
1583 if (ijk[k] < 0 || ijk[k] >= m_nVertices1D[k]) {
1584 return false;
1585 }
1586 }
1587
1588 return true;
1589}
1590
1603void VolCartesian::_findCellFaceNeighs(long id, int face, const std::vector<long> *blackList, std::vector<long> *neighs) const
1604{
1605 long neighId = getCellFaceNeighsLinearId(id, face);
1606 if (neighId < 0) {
1607 return;
1608 } else if (blackList && utils::findInOrderedVector<long>(neighId, *blackList) != blackList->end()) {
1609 return;
1610 }
1611
1612 neighs->push_back(neighId);
1613}
1614
1630void VolCartesian::_findCellEdgeNeighs(long id, int edge, const std::vector<long> *blackList, std::vector<long> *neighs) const
1631{
1632 assert(isThreeDimensional());
1633 if (!isThreeDimensional()) {
1634 return;
1635 }
1636
1637 // Diagonal neighbour
1638 std::array<int, 3> diagNeighIjk(getCellCartesianId(id) + m_edgeNeighDeltas[edge]);
1639 if (isCellCartesianIdValid(diagNeighIjk)) {
1640 long diagNeighId = getCellLinearId(diagNeighIjk);
1641 if (!blackList || utils::findInOrderedVector<long>(diagNeighId, *blackList) == blackList->end()) {
1642 utils::addToOrderedVector<long>(diagNeighId, *neighs);
1643 }
1644 }
1645
1646 // Faces incident to the edge
1647 for (int face : m_edgeFaces[edge]) {
1648 _findCellFaceNeighs(id, face, blackList, neighs);
1649 }
1650}
1651
1665void VolCartesian::_findCellVertexNeighs(long id, int vertex, const std::vector<long> *blackList, std::vector<long> *neighs) const
1666{
1667 std::array<int, 3> cellIjk = getCellCartesianId(id);
1668 std::array<int, 3> vertexIjk = getVertexCartesianId(cellIjk, vertex);
1669
1670 for (const auto &delta : m_vertexNeighDeltas) {
1671 // Get the Cartesian index
1672 std::array<int, 3> neighIjk(vertexIjk + delta);
1673 if (neighIjk == cellIjk) {
1674 continue;
1675 } else if (!isCellCartesianIdValid(neighIjk)) {
1676 continue;
1677 }
1678
1679 // Get the linear neighbour index and, if it's not on the blacklist,
1680 // add it to the list of neighbours
1681 long neighId = getCellLinearId(neighIjk);
1682 if (!blackList || utils::findInOrderedVector<long>(neighId, *blackList) == blackList->end()) {
1683 utils::addToOrderedVector<long>(neighId, *neighs);
1684 }
1685 }
1686}
1687
1695std::vector<long> VolCartesian::extractCellSubSet(std::array<int, 3> const &ijkMin, std::array<int, 3> const &ijkMax) const
1696{
1697 int nSubsetCells_x = ijkMax[0] - ijkMin[0] + 1;
1698 int nSubsetCells_y = ijkMax[1] - ijkMin[1] + 1;
1699 int nSubsetCells_z = ijkMax[2] - ijkMin[2] + 1;
1700
1701 std::vector<long> ids;
1702 ids.resize(nSubsetCells_x * nSubsetCells_y * nSubsetCells_z);
1703
1704 std::vector<long>::iterator it = ids.begin();
1705 for (int k = ijkMin[2]; k <= ijkMax[2]; ++k) {
1706 for (int j = ijkMin[1]; j <= ijkMax[1]; ++j) {
1707 for (int i = ijkMin[0]; i <= ijkMax[0]; ++i) {
1708 *it = getCellLinearId(i, j, k);
1709 ++it;
1710 }
1711 }
1712 }
1713
1714 return ids;
1715}
1716
1724std::vector<long> VolCartesian::extractCellSubSet(int idMin, int idMax) const
1725{
1727}
1728
1736std::vector<long> VolCartesian::extractCellSubSet(std::array<double, 3> const &pointMin, std::array<double, 3> const &pointMax) const
1737{
1738 return extractCellSubSet(locatePointCartesian(pointMin), locatePointCartesian(pointMax));
1739}
1740
1748std::vector<long> VolCartesian::extractVertexSubSet(std::array<int, 3> const &ijkMin, std::array<int, 3> const &ijkMax) const
1749{
1750 int nSubsetVertices_x = ijkMax[0] - ijkMin[0] + 1;
1751 int nSubsetVertices_y = ijkMax[1] - ijkMin[1] + 1;
1752 int nSubsetVertices_z = ijkMax[2] - ijkMin[2] + 1;
1753
1754 std::vector<long> ids;
1755 ids.resize(nSubsetVertices_x * nSubsetVertices_y * nSubsetVertices_z);
1756
1757 std::vector<long>::iterator it = ids.begin();
1758 for (int k = ijkMin[2]; k <= ijkMax[2]; ++k) {
1759 for (int j = ijkMin[1]; j <= ijkMax[1]; ++j) {
1760 for (int i = ijkMin[0]; i <= ijkMax[0]; ++i) {
1761 *it = getVertexLinearId(i, j, k);
1762 ++it;
1763 }
1764 }
1765 }
1766
1767 return ids;
1768}
1769
1777std::vector<long> VolCartesian::extractVertexSubSet(int idMin, int idMax) const
1778{
1780}
1781
1789std::vector<long> VolCartesian::extractVertexSubSet(std::array<double, 3> const &pointMin, std::array<double, 3> const &pointMax) const
1790{
1792}
1793
1802std::array<double, 3> VolCartesian::getOrigin() const
1803{
1804 return m_minCoords;
1805}
1806
1814void VolCartesian::setOrigin(const std::array<double, 3> &origin)
1815{
1816 std::array<double, 3> translation = origin - getOrigin();
1817 translate(translation);
1818}
1819
1825void VolCartesian::translate(const std::array<double, 3> &translation)
1826{
1827 for (int n = 0; n < 3; ++n) {
1828 m_minCoords[n] += translation[n];
1829 m_maxCoords[n] += translation[n];
1830
1831 for (int i = 1; i < m_nVertices1D[n]; ++i) {
1832 m_vertexCoords[n][i] += translation[n];
1833 }
1834
1835 for (int i = 1; i < m_nCells1D[n]; ++i) {
1836 m_cellCenters[n][i] += translation[n];
1837 }
1838 }
1839
1840 setBoundingBox(m_minCoords, m_maxCoords);
1841
1842 VolumeKernel::translate(translation);
1843}
1844
1853void VolCartesian::rotate(const std::array<double, 3> &n0, const std::array<double, 3> &n1, double angle)
1854{
1855 BITPIT_UNUSED(n0);
1856 BITPIT_UNUSED(n1);
1857 BITPIT_UNUSED(angle);
1858
1859 throw std::runtime_error("It is not possible to rotate a Cartesian patch.");
1860}
1861
1867std::array<double, 3> VolCartesian::getLengths() const
1868{
1869 return (m_maxCoords - m_minCoords);
1870}
1871
1878void VolCartesian::setLengths(const std::array<double, 3> &lengths)
1879{
1880 // Set the maximum coordinate
1881 m_maxCoords = m_minCoords + lengths;
1882
1883 // Reset the bounding box
1884 setBoundingBox(m_minCoords, m_maxCoords);
1885
1886 // If needed update the discretization
1887 if (m_nVertices > 0) {
1888 // Rebuild the discretization
1889 setDiscretization(m_nCells1D);
1890
1891 // Rebuild vertex coordinates
1892 for (Vertex vertex : m_vertices) {
1893 long id = vertex.getId();
1894 vertex.setCoords(evalVertexCoords(id));
1895 }
1896 }
1897}
1898
1905void VolCartesian::scale(const std::array<double, 3> &scaling, const std::array<double, 3> &center)
1906{
1907 for (int n = 0; n < 3; ++n) {
1908 m_minCoords[n] = center[n] + scaling[n] * (m_minCoords[n] - center[n]);
1909 m_maxCoords[n] = center[n] + scaling[n] * (m_maxCoords[n] - center[n]);
1910
1911 for (int i = 1; i < m_nVertices1D[n]; ++i) {
1912 m_vertexCoords[n][i] = center[n] + scaling[n] * (m_vertexCoords[n][i] - center[n]);
1913 }
1914
1915 for (int i = 1; i < m_nCells1D[n]; ++i) {
1916 m_cellCenters[n][i] = center[n] + scaling[n] * (m_cellCenters[n][i] - center[n]);
1917 }
1918
1919 m_cellSpacings[n] *= scaling[n];
1920 }
1921
1922 initializeCellVolume();
1923
1924 initializeCellSize();
1925
1926 initializeInterfaceArea();
1927
1928 setBoundingBox(m_minCoords, m_maxCoords);
1929
1930 VolumeKernel::scale(scaling, center);
1931}
1932
1940std::vector<double> VolCartesian::convertToVertexData(const std::vector<double> &cellData) const
1941{
1942 int dimension = getDimension();
1943
1944 int nContribs_x = 2;
1945 int nContribs_y = 2;
1946 int nContribs_z = dimension - 1;
1947
1948 std::vector<int> nodeCounter(getVertexCount());
1949 std::vector<double> vertexData(getVertexCount());
1950 std::fill (vertexData.begin(), vertexData.end(), 0.);
1951
1952 for (int k = 0; (isThreeDimensional()) ? (k < m_nCells1D[Vertex::COORD_Z]) : (k < 1); k++) {
1953 for (int j = 0; j < m_nCells1D[Vertex::COORD_Y]; ++j) {
1954 for (int i = 0; i < m_nCells1D[Vertex::COORD_X]; ++i) {
1955 // Get cell contribution
1956 long cellId = getCellLinearId(i, j, k);
1957 double cellContrib = cellData[cellId];
1958
1959 // Eval vertex data
1960 for (int n = 0; n < nContribs_z; n++) {
1961 int k_v = k + n;
1962 for (int m = 0; m < nContribs_y; ++m) {
1963 int j_v = j + m;
1964 for (int l = 0; l < nContribs_x; ++l) {
1965 int i_v = i + l;
1966
1967 // Get vertex index
1968 long vertexId = getVertexLinearId(i_v, j_v, k_v);
1969
1970 // Sum cell contribution
1971 vertexData[vertexId] += cellContrib;
1972 nodeCounter[vertexId]++;
1973 }
1974 }
1975 }
1976 }
1977 }
1978 }
1979
1980 // Average values
1981 for (int i = 0; i < getVertexCount(); ++i) {
1982 vertexData[i] /= nodeCounter[i];
1983 }
1984
1985 return vertexData;
1986}
1987
1995std::vector<double> VolCartesian::convertToCellData(const std::vector<double> &vertexData) const
1996{
1997 int dimension = getDimension();
1998
1999 int nContribs_x = 2;
2000 int nContribs_y = 2;
2001 int nContribs_z = dimension - 1;
2002
2003 std::vector<double> cellData(getCellCount());
2004 std::fill (cellData.begin(), cellData.end(), 0.);
2005
2006 for (int k = 0; (isThreeDimensional()) ? (k < m_nCells1D[Vertex::COORD_Z]) : (k < 1); k++) {
2007 for (int j = 0; j < m_nCells1D[Vertex::COORD_Y]; ++j) {
2008 for (int i = 0; i < m_nCells1D[Vertex::COORD_X]; ++i) {
2009 // Eval cell data
2010 long cellId = getCellLinearId(i, j, k);
2011 for (int n = 0; n < nContribs_z; ++n) {
2012 int k_v = k + n;
2013 for (int m = 0; m < nContribs_y; ++m) {
2014 int j_v = j + m;
2015 for (int l = 0; l < nContribs_x; ++l) {
2016 int i_v = i + l;
2017
2018 // Get vertex contribution
2019 long vertexId = getVertexLinearId(i_v, j_v, k_v);
2020 double vertexContrib = vertexData[vertexId];
2021
2022 // Sum vertex contribution
2023 cellData[cellId] += vertexContrib;
2024 }
2025 }
2026 }
2027 }
2028 }
2029 }
2030
2031 double weight = pow(0.5, dimension);
2032 for (int i = 0; i < getCellCount(); ++i) {
2033 cellData[i] *= weight;
2034 }
2035
2036 return cellData;
2037}
2038
2039
2053int VolCartesian::linearCellInterpolation(const std::array<double,3> &point,
2054 std::vector<int> *stencil, std::vector<double> *weights) const
2055{
2056 std::array<int, 3> ijk_point = locatePointCartesian(point);
2057 if (ijk_point[0] < 0) {
2058 stencil->clear();
2059 weights->clear();
2060 return 0;
2061 }
2062
2063 int dimension = getDimension();
2064
2065 int nContribs_x = 1;
2066 int nContribs_y = 1;
2067 int nContribs_z = 1;
2068
2069 std::array< std::array<int,2>, 3> cStencil;
2070 std::array< std::array<double,2>, 3> cWeights;
2071 for (int d = 0; d < dimension; ++d) {
2072 // Find cell index
2073 int index_point = ijk_point[d];
2074 if (point[d] < m_cellCenters[d][index_point]) {
2075 index_point = index_point - 1;
2076 }
2077
2078 int index_next = index_point + 1;
2079
2080 if (index_point < 0) {
2081 cStencil[d][0] = 0;
2082 cWeights[d][0] = 1.;
2083 } else if (index_next > m_nCells1D[d] - 1) {
2084 cStencil[d][0] = m_nCells1D[d] - 1;
2085 cWeights[d][0] = 1.;
2086 } else {
2087 if (d == 0) {
2088 nContribs_x = 2;
2089 } else if (d == 1) {
2090 nContribs_y = 2;
2091 } else {
2092 nContribs_z = 2;
2093 }
2094
2095 cStencil[d][0] = index_point;
2096 cStencil[d][1] = index_next;
2097
2098 cWeights[d][1] = (point[d] - m_cellCenters[d][index_point]) / m_cellSpacings[d] ;
2099 cWeights[d][0] = 1.0 - cWeights[d][1];
2100 }
2101 }
2102
2103 for (int d = dimension; d < 3; ++d) {
2104 cStencil[d][0] = 0;
2105 cWeights[d][0] = 1.;
2106 }
2107
2108 int stencilSize = nContribs_x * nContribs_y * nContribs_z;
2109 stencil->resize(stencilSize);
2110 weights->resize(stencilSize);
2111
2112 std::vector<int>::iterator itrStencil = stencil->begin();
2113 std::vector<double>::iterator itrWeights = weights->begin();
2114 for (int k = 0; k < nContribs_z; ++k) {
2115 for (int j = 0; j < nContribs_y; ++j) {
2116 for (int i = 0; i < nContribs_x; ++i) {
2117 int &is = cStencil[0][i];
2118 int &js = cStencil[1][j];
2119 int &ks = cStencil[2][k];
2120
2121 double &iw = cWeights[0][i];
2122 double &jw = cWeights[1][j];
2123 double &kw = cWeights[2][k];
2124
2125 *itrStencil = getCellLinearId(is, js, ks);
2126 *itrWeights = iw *jw * kw;
2127
2128 ++itrStencil;
2129 ++itrWeights;
2130 }
2131 }
2132 }
2133
2134 return stencilSize;
2135}
2136
2150int VolCartesian::linearVertexInterpolation(const std::array<double,3> &point,
2151 std::vector<int> *stencil, std::vector<double> *weights) const
2152{
2153 std::array<int, 3> ijk_point = locatePointCartesian(point);
2154 if (ijk_point[0] < 0) {
2155 stencil->clear();
2156 weights->clear();
2157 return 0;
2158 }
2159
2160 int dimension = getDimension();
2161
2162 int nContribs_x = 2;
2163 int nContribs_y = 2;
2164 int nContribs_z = dimension - 1;
2165
2166 std::array< std::array<int,2>, 3> cStencil;
2167 std::array< std::array<double,2>, 3> cWeights;
2168 for (int d = 0; d < dimension; ++d) {
2169 int index_point = ijk_point[d];
2170 int index_next = index_point +1;
2171
2172 cStencil[d][0] = index_point;
2173 cStencil[d][1] = index_next;
2174
2175 cWeights[d][1] = (point[d] - m_vertexCoords[d][index_point]) / m_cellSpacings[d];
2176 cWeights[d][0] = 1.0 - cWeights[d][1];
2177 }
2178
2179 for (int d = dimension; d < 3; ++d) {
2180 cStencil[d][0] = 0;
2181 cWeights[d][0] = 1.;
2182 }
2183
2184 int stencilSize = uipow(2, dimension);
2185 stencil->resize(stencilSize);
2186 weights->resize(stencilSize);
2187
2188 std::vector<int>::iterator itrStencil = stencil->begin();
2189 std::vector<double>::iterator itrWeights = weights->begin();
2190 for (int k = 0; k < nContribs_z; ++k) {
2191 for (int j = 0; j < nContribs_y; ++j) {
2192 for (int i = 0; i < nContribs_x; ++i) {
2193 int &is = cStencil[0][i];
2194 int &js = cStencil[1][j];
2195 int &ks = cStencil[2][k];
2196
2197 double &iw = cWeights[0][i];
2198 double &jw = cWeights[1][j];
2199 double &kw = cWeights[2][k];
2200
2201 *itrStencil = getVertexLinearId(is, js, ks);
2202 *itrWeights = iw * jw * kw;
2203
2204 ++itrStencil;
2205 ++itrWeights;
2206 }
2207 }
2208 }
2209
2210 return stencilSize;
2211}
2212
2219std::array<double, 3> VolCartesian::evalCellCentroid(long id) const
2220{
2221 std::array<int, 3> ijk = getCellCartesianId(id);
2222
2223 return evalCellCentroid(ijk);
2224}
2225
2232std::array<double, 3> VolCartesian::evalCellCentroid(const std::array<int, 3> &ijk) const
2233{
2234 std::array<double, 3> centroid;
2235 for (int d = 0; d < 3; ++d) {
2236 if (ijk[d] >= 0) {
2237 centroid[d] = m_cellCenters[d][ijk[d]];
2238 } else {
2239 centroid[d] = m_minCoords[d];
2240 }
2241 }
2242
2243 return centroid;
2244}
2245
2252const std::vector<double> & VolCartesian::getCellCentroids(int direction) const
2253{
2254 return m_cellCenters[direction];
2255}
2256
2264std::array<int, 3> VolCartesian::getCellFaceNeighsCartesianId(long id, int face) const
2265{
2266 int neighSide = face % 2;
2267 int neighDirection = static_cast<int>(std::floor(face / 2));
2268
2269 std::array<int, 3> neighIjk(getCellCartesianId(id));
2270 if (neighSide == 0) {
2271 neighIjk[neighDirection]--;
2272 } else {
2273 neighIjk[neighDirection]++;
2274 }
2275
2276 return neighIjk;
2277}
2278
2286long VolCartesian::getCellFaceNeighsLinearId(long id, int face) const
2287{
2288 std::array<int, 3> neighIjk = getCellFaceNeighsCartesianId(id, face);
2289
2290 long neighId;
2291 if (isCellCartesianIdValid(neighIjk)) {
2292 neighId = getCellLinearId(neighIjk);
2293 } else {
2294 neighId = Cell::NULL_ID;
2295 }
2296
2297 return neighId;
2298}
2299
2300}
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
std::vector< adaption::Info > update(bool trackAdaption=true, bool squeezeStorage=false)
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)
void restore(std::istream &stream, bool reregister=false)
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
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
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 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
VolumeKernel(MPI_Comm communicator, std::size_t haloSize, AdaptionMode adaptionMode, PartitioningMode partitioningMode)
std::array< T, d > pow(std::array< T, d > &x, double p)
T uipow(const T &, unsigned int)
Definition Operators.tpp:56
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:1714