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 VIENNACORE_LOG_DEBUG("No slice level-set passed to Slice. Auto-creating "
93 "slice level-set with bounds derived from source "
94 "domain.");
95 }
96
97 const auto &sourceGrid = sourceLevelSet->getGrid();
98 auto const gridDelta = sourceGrid.getGridDelta();
99
100 // Container for the extracted points
101 std::vector<std::pair<viennahrle::Index<2>, T>> pointData;
102
103 // Check if slice position is divisible by grid delta without remainder
104 if (std::fmod(slicePosition, gridDelta) != 0) {
105 // If not, change slice position to the nearest grid point
106 slicePosition = std::round(slicePosition / gridDelta) * gridDelta;
107 VIENNACORE_LOG_WARNING("Slice position is not divisible by grid delta in "
108 "Slice. Adjusting slice position to the nearest "
109 "multiple of grid delta: " +
110 std::to_string(slicePosition));
111 }
112
113 // slice index
114 const int sliceIndex = static_cast<int>(slicePosition / gridDelta);
115
116 // Iterate through the source domain
117 viennahrle::ConstSparseIterator<typename Domain<T, 3>::DomainType> it(
118 sourceLevelSet->getDomain());
119
120 while (!it.isFinished()) {
121 if (!it.isDefined()) {
122 it.next();
123 continue;
124 }
125
126 auto indices = it.getStartIndices();
127 if (indices[sliceDimension] == sliceIndex) {
128 // Extract the value
129 T value = it.getValue();
130
131 // Create a new 2D index
132 viennahrle::Index<2> sliceIndices;
133 for (int d = 0, j = 0; d < 3; d++) {
134 if (d != sliceDimension) {
135 sliceIndices[j++] = indices[d];
136 }
137 }
138
139 if (reflectX) {
140 sliceIndices[0] = -sliceIndices[0];
141 }
142
143 // Add to our collection
144 pointData.emplace_back(sliceIndices, value);
145 }
146
147 it.next();
148 }
149
150 // Insert the extracted points into the slice domain, issue a warning if
151 // there are no points to insert
152 if (pointData.empty()) {
153 VIENNACORE_LOG_WARNING("No points extracted in Slice");
154 } else {
155 if (autoCreateSlice) {
156 // Create slice domain with bounds and BCs derived from source domain
157 double sliceBounds[4];
158 BoundaryConditionEnum sliceBoundaryConds[2];
159
160 for (int i = 0, d = 0; d < 3; d++) {
161 if (d != sliceDimension) {
162 sliceBounds[2 * i] = sourceGrid.getMinGridPoint(d) * gridDelta;
163 sliceBounds[2 * i + 1] = sourceGrid.getMaxGridPoint(d) * gridDelta;
164 sliceBoundaryConds[i] = sourceGrid.getBoundaryConditions(d);
165 i++;
166 }
167 }
168
169 if (reflectX) {
170 // Swap and negate the X bounds
171 double temp = sliceBounds[0];
172 sliceBounds[0] = -sliceBounds[1];
173 sliceBounds[1] = -temp;
174 }
175
176 sliceLevelSet = Domain<T, 2>::New(pointData, sliceBounds,
177 sliceBoundaryConds, gridDelta);
178 } else {
179 // Use passed slice domain
180 sliceLevelSet->insertPoints(pointData);
181 }
182
183 if (writeSliceLevelSet) {
184 Writer<T, 2> writer(sliceLevelSet, writePath);
185 writer.apply();
186 if (writeSurfaceMesh) {
187 auto mesh = Mesh<T>::New();
188 ToSurfaceMesh<T, 2> surfaceMesh(sliceLevelSet, mesh);
189 surfaceMesh.apply();
190 VTKWriter<T>(mesh, writePath + ".vtp").apply();
191 }
192 }
193 }
194 };
195};
196
197// Add template specializations for this class
199
200} // namespace viennals
double T
Definition Epitaxy.cpp:12
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:27
static auto New(Args &&...args)
Definition lsDomain.hpp:111
static auto New()
Definition lsMesh.hpp:63
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:21
void apply()
Definition lsToSurfaceMesh.hpp:45
Class handling the output of an Mesh<> to VTK file types.
Definition lsVTKWriter.hpp:33
void apply()
Definition lsVTKWriter.hpp:136
Definition lsWriter.hpp:13
#define PRECOMPILE_PRECISION(className)
Definition lsPreCompileMacros.hpp:30
Definition lsAdvect.hpp:37
viennahrle::BoundaryType BoundaryConditionEnum
Definition lsDomain.hpp:23