ViennaLS
Loading...
Searching...
No Matches
lsSlice.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <lsDomain.hpp>
4#include <lsMesh.hpp>
6#include <lsToSurfaceMesh.hpp>
7#include <lsVTKWriter.hpp>
8#include <lsWriter.hpp>
9
10namespace viennals {
11
12using namespace viennacore;
13
19template <class T> class Slice {
20 SmartPointer<Domain<T, 3>> sourceLevelSet = nullptr;
21 SmartPointer<Domain<T, 2>> sliceLevelSet = nullptr;
22
23 int sliceDimension = 0; // (0=x, 1=y, 2=z)
24 T slicePosition = 0; // Position of the slice
25
26 bool writeSliceLevelSet = false;
27 bool writeSurfaceMesh = false;
28 std::string writePath;
29
30 bool reflectX = false;
31
32public:
33 Slice() = default;
34
35 Slice(SmartPointer<Domain<T, 3>> passedDomain,
36 SmartPointer<Domain<T, 2>> passedSliceDomain,
37 int passedSliceDimension = 0, T passedSlicePosition = 0)
38 : sourceLevelSet(passedDomain), sliceLevelSet(passedSliceDomain),
39 sliceDimension(passedSliceDimension),
40 slicePosition(passedSlicePosition) {}
41
42 Slice(SmartPointer<Domain<T, 3>> passedDomain, int passedSliceDimension = 0,
43 T passedSlicePosition = 0)
44 : sourceLevelSet(passedDomain), sliceDimension(passedSliceDimension),
45 slicePosition(passedSlicePosition) {}
46
47 void setSourceLevelSet(SmartPointer<Domain<T, 3>> passedDomain) {
48 sourceLevelSet = passedDomain;
49 }
50
51 void setSliceLevelSet(SmartPointer<Domain<T, 2>> passedDomain) {
52 sliceLevelSet = passedDomain;
53 }
54
55 void setWritePath(const std::string &path,
56 bool writeSliceSurfaceMesh = false) {
57 writeSliceLevelSet = true;
58 writeSurfaceMesh = writeSliceSurfaceMesh;
59 writePath = path;
60 }
61
62 // Getter needed if used without passed slice level-set
63 SmartPointer<Domain<T, 2>> getSliceLevelSet() { return sliceLevelSet; }
64
65 void setSliceDimension(const int dimension) {
66 if (dimension >= 0 && dimension < 3) {
67 sliceDimension = dimension;
68 } else {
69 Logger::getInstance()
70 .addError("Invalid slice dimension. Must be 0 (x), 1 (y), or 2 (z)")
71 .print();
72 }
73 }
74
75 void setSlicePosition(T position) { slicePosition = position; }
76
77 void setReflectX(bool reflect) { reflectX = reflect; }
78
79 void apply() {
80 if (sourceLevelSet == nullptr) {
81 Logger::getInstance()
82 .addError("No source level-set passed to Slice")
83 .print();
84 return;
85 }
86
87 // If no slice domain is set, create one automatically with bounds and BCs
88 // derived from the source domain
89 bool autoCreateSlice = false;
90 if (sliceLevelSet == nullptr) {
91 autoCreateSlice = true;
92 Logger::getInstance()
93 .addInfo("No slice level-set passed to Slice. Auto-created slice "
94 "level-set with bounds derived from "
95 "source domain")
96 .print();
97 }
98
99 const auto &sourceGrid = sourceLevelSet->getGrid();
100 auto const gridDelta = sourceGrid.getGridDelta();
101
102 // Container for the extracted points
103 std::vector<std::pair<viennahrle::Index<2>, T>> pointData;
104
105 // Check if slice position is divisible by grid delta without remainder
106 if (std::fmod(slicePosition, gridDelta) != 0) {
107 // If not, change slice position to the nearest grid point
108 slicePosition = std::round(slicePosition / gridDelta) * gridDelta;
109 Logger::getInstance()
110 .addWarning("Slice position is not divisible by grid delta in "
111 "Slice. Adjusting slice position to the nearest "
112 "multiple of grid delta: " +
113 std::to_string(slicePosition))
114 .print();
115 }
116
117 // slice index
118 const int sliceIndex = static_cast<int>(slicePosition / gridDelta);
119
120 // Iterate through the source domain
121 viennahrle::ConstSparseIterator<typename Domain<T, 3>::DomainType> it(
122 sourceLevelSet->getDomain());
123
124 while (!it.isFinished()) {
125 if (!it.isDefined()) {
126 it.next();
127 continue;
128 }
129
130 auto indices = it.getStartIndices();
131 if (indices[sliceDimension] == sliceIndex) {
132 // Extract the value
133 T value = it.getValue();
134
135 // Create a new 2D index
136 viennahrle::Index<2> sliceIndices;
137 for (int d = 0, j = 0; d < 3; d++) {
138 if (d != sliceDimension) {
139 sliceIndices[j++] = indices[d];
140 }
141 }
142
143 if (reflectX) {
144 sliceIndices[0] = -sliceIndices[0];
145 }
146
147 // Add to our collection
148 pointData.emplace_back(sliceIndices, value);
149 }
150
151 it.next();
152 }
153
154 // Insert the extracted points into the slice domain, issue a warning if
155 // there are no points to insert
156 if (pointData.empty()) {
157 Logger::getInstance().addWarning("No points extracted in Slice").print();
158 } else {
159 if (autoCreateSlice) {
160 // Create slice domain with bounds and BCs derived from source domain
161 double sliceBounds[4];
162 BoundaryConditionEnum sliceBoundaryConds[2];
163
164 for (int i = 0, d = 0; d < 3; d++) {
165 if (d != sliceDimension) {
166 sliceBounds[2 * i] = sourceGrid.getMinGridPoint(d) * gridDelta;
167 sliceBounds[2 * i + 1] = sourceGrid.getMaxGridPoint(d) * gridDelta;
168 sliceBoundaryConds[i] = sourceGrid.getBoundaryConditions(d);
169 i++;
170 }
171 }
172
173 if (reflectX) {
174 // Swap and negate the X bounds
175 double temp = sliceBounds[0];
176 sliceBounds[0] = -sliceBounds[1];
177 sliceBounds[1] = -temp;
178 }
179
180 sliceLevelSet = SmartPointer<Domain<T, 2>>::New(
181 pointData, sliceBounds, sliceBoundaryConds, gridDelta);
182 } else {
183 // Use passed slice domain
184 sliceLevelSet->insertPoints(pointData);
185 }
186
187 if (writeSliceLevelSet) {
188 Writer<T, 2> writer(sliceLevelSet, writePath);
189 writer.apply();
190 if (writeSurfaceMesh) {
191 auto mesh = SmartPointer<Mesh<>>::New();
192 ToSurfaceMesh<T, 2> surfaceMesh(sliceLevelSet, mesh);
193 surfaceMesh.apply();
194 VTKWriter<T>(mesh, writePath + ".vtp").apply();
195 }
196 }
197 }
198 };
199};
200
201// Add template specializations for this class
203
204} // namespace viennals
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:27
Slice(SmartPointer< Domain< T, 3 > > passedDomain, SmartPointer< Domain< T, 2 > > passedSliceDomain, int passedSliceDimension=0, T passedSlicePosition=0)
Definition lsSlice.hpp:35
Slice()=default
Slice(SmartPointer< Domain< T, 3 > > passedDomain, int passedSliceDimension=0, T passedSlicePosition=0)
Definition lsSlice.hpp:42
void setSourceLevelSet(SmartPointer< Domain< T, 3 > > passedDomain)
Definition lsSlice.hpp:47
void setReflectX(bool reflect)
Definition lsSlice.hpp:77
void setSliceDimension(const int dimension)
Definition lsSlice.hpp:65
void setWritePath(const std::string &path, bool writeSliceSurfaceMesh=false)
Definition lsSlice.hpp:55
SmartPointer< Domain< T, 2 > > getSliceLevelSet()
Definition lsSlice.hpp:63
void setSlicePosition(T position)
Definition lsSlice.hpp:75
void setSliceLevelSet(SmartPointer< Domain< T, 2 > > passedDomain)
Definition lsSlice.hpp:51
void apply()
Definition lsSlice.hpp:79
Extract an explicit Mesh<> instance from an lsDomain. The interface is then described by explicit sur...
Definition lsToSurfaceMesh.hpp:20
void apply()
Definition lsToSurfaceMesh.hpp:44
Class handling the output of an Mesh<> to VTK file types.
Definition lsVTKWriter.hpp:32
void apply()
Definition lsVTKWriter.hpp:92
Definition lsWriter.hpp:13
void apply()
Definition lsWriter.hpp:35
#define PRECOMPILE_PRECISION(className)
Definition lsPreCompileMacros.hpp:30
Definition lsAdvect.hpp:36
viennahrle::BoundaryType BoundaryConditionEnum
Definition lsDomain.hpp:23
double T
Definition pyWrap.cpp:69