ViennaLS
Loading...
Searching...
No Matches
lsLocalLaxFriedrichsAnalytical.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <hrleSparseBoxIterator.hpp>
4#include <hrleVectorType.hpp>
5
6#include <lsDomain.hpp>
7#include <lsExpand.hpp>
8#include <lsVelocityField.hpp>
9
10#include <vcVectorUtil.hpp>
11
12namespace lsInternal {
13
14using namespace viennacore;
15
21template <class T, int D, int order> class LocalLaxFriedrichsAnalytical {
22 SmartPointer<viennals::Domain<T, D>> levelSet;
23 SmartPointer<viennals::VelocityField<T>> velocities;
24 hrleSparseBoxIterator<hrleDomain<T, D>> neighborIterator;
25 hrleVectorType<T, 3> finalAlphas;
26
27 static T pow2(const T &value) { return value * value; }
28
29 T calculateNormalComponent(T neg, T center, T pos, T delta) {
30 auto diffPos = (pos - center) / delta;
31 auto diffNeg = (center - neg) / delta;
32 return (diffPos + diffNeg) * 0.5;
33 }
34
35 void incrementIndices(hrleVectorType<hrleIndexType, D> &index,
36 hrleIndexType minIndex, hrleIndexType maxIndex) {
37 unsigned dir = 0;
38 for (; dir < D - 1; ++dir) {
39 if (index[dir] < maxIndex)
40 break;
41 index[dir] = minIndex;
42 }
43 ++index[dir];
44 }
45
46public:
47 static void prepareLS(SmartPointer<viennals::Domain<T, D>> passedlsDomain) {
48 assert(order == 1 || order == 2);
49 // at least order+1 layers since we need neighbor neighbors for
50 // dissipation alpha calculation
51 viennals::Expand<T, D>(passedlsDomain, 2 * (order + 2) + 1).apply();
52 }
53
54 // neighboriterator always needs order 2 for alpha calculation
56 SmartPointer<viennals::Domain<T, D>> passedlsDomain,
57 SmartPointer<viennals::VelocityField<T>> vel)
58 : levelSet(passedlsDomain), velocities(vel),
59 neighborIterator(levelSet->getDomain(), 2) {
60 for (int i = 0; i < 3; ++i) {
61 finalAlphas[i] = 0;
62 }
63 }
64
65 std::pair<T, T> operator()(const hrleVectorType<hrleIndexType, D> &indices,
66 int material) {
67
68 auto &grid = levelSet->getGrid();
69 double gridDelta = grid.getGridDelta();
70
71 hrleVectorType<T, 3> coordinate(0., 0., 0.);
72 for (unsigned i = 0; i < D; ++i) {
73 coordinate[i] = indices[i] * gridDelta;
74 }
75
76 // move neighborIterator to current position
77 neighborIterator.goToIndicesSequential(indices);
78
79 // convert coordinate to std array for interface
80 Vec3D<T> coordArray = {coordinate[0], coordinate[1], coordinate[2]};
81
82 T gradPos[D];
83 T gradNeg[D];
84
85 T grad = 0.;
86 T dissipation = 0.;
87
88 Vec3D<T> normalVector = {};
89 T normalModulus = 0;
90
91 for (int i = 0; i < D; i++) { // iterate over dimensions
92 hrleVectorType<hrleIndexType, D> posUnit(0);
93 hrleVectorType<hrleIndexType, D> negUnit(0);
94 posUnit[i] = 1;
95 negUnit[i] = -1;
96
97 const T deltaPos = gridDelta;
98 const T deltaNeg = -gridDelta;
99
100 const T phi0 = neighborIterator.getCenter().getValue();
101 const T phiPos = neighborIterator.getNeighbor(posUnit).getValue();
102 const T phiNeg = neighborIterator.getNeighbor(negUnit).getValue();
103
104 T diffPos = (phiPos - phi0) / deltaPos;
105 T diffNeg = (phiNeg - phi0) / deltaNeg;
106
107 if (order == 2) { // if second order time integration scheme is used
108 posUnit[i] = 2;
109 negUnit[i] = -2;
110
111 const T deltaPosPos = 2 * gridDelta;
112 const T deltaNegNeg = -2 * gridDelta;
113
114 const T diff00 =
115 (((deltaNeg * phiPos - deltaPos * phiNeg) / (deltaPos - deltaNeg) +
116 phi0)) /
117 (deltaPos * deltaNeg);
118 const T phiPosPos = neighborIterator.getNeighbor(posUnit).getValue();
119 const T phiNegNeg = neighborIterator.getNeighbor(negUnit).getValue();
120
121 const T diffNegNeg = (((deltaNeg * phiNegNeg - deltaNegNeg * phiNeg) /
122 (deltaNegNeg - deltaNeg) +
123 phi0)) /
124 (deltaNegNeg * deltaNeg);
125 const T diffPosPos = (((deltaPos * phiPosPos - deltaPosPos * phiPos) /
126 (deltaPosPos - deltaPos) +
127 phi0)) /
128 (deltaPosPos * deltaPos);
129
130 if (std::signbit(diff00) == std::signbit(diffPosPos)) {
131 if (std::abs(diffPosPos * deltaPos) < std::abs(diff00 * deltaNeg)) {
132 diffPos -= deltaPos * diffPosPos;
133 } else {
134 diffPos += deltaNeg * diff00;
135 }
136 }
137
138 if (std::signbit(diff00) == std::signbit(diffNegNeg)) {
139 if (std::abs(diffNegNeg * deltaNeg) < std::abs(diff00 * deltaPos)) {
140 diffNeg -= deltaNeg * diffNegNeg;
141 } else {
142 diffNeg += deltaPos * diff00;
143 }
144 }
145 }
146
147 gradPos[i] = diffNeg;
148 gradNeg[i] = diffPos;
149
150 normalVector[i] = (diffNeg + diffPos) * 0.5;
151 normalModulus += normalVector[i] * normalVector[i];
152
153 grad += pow2((diffNeg + diffPos) * 0.5);
154 }
155
156 // normalise normal vector
157 normalModulus = std::sqrt(normalModulus);
158 for (unsigned i = 0; i < D; ++i) {
159 normalVector[i] /= normalModulus;
160 }
161
162 // Get velocities
163 double scalarVelocity = velocities->getScalarVelocity(
164 coordArray, material, normalVector,
165 neighborIterator.getCenter().getPointId());
166 Vec3D<T> vectorVelocity = velocities->getVectorVelocity(
167 coordArray, material, normalVector,
168 neighborIterator.getCenter().getPointId());
169
170 // calculate hamiltonian
171 T totalGrad = 0.;
172 if (scalarVelocity != 0.) {
173 totalGrad = scalarVelocity * std::sqrt(grad);
174 }
175
176 for (int w = 0; w < D; w++) {
177 if (vectorVelocity[w] > 0.) {
178 totalGrad += vectorVelocity[w] * gradPos[w];
179 } else {
180 totalGrad += vectorVelocity[w] * gradNeg[w];
181 }
182 }
183
184 // calculate alphas
185 T alpha[D] = {};
186 {
187 // alpha calculation is always on order 1 stencil
188 const hrleIndexType minIndex = -1;
189 const hrleIndexType maxIndex = 1;
190 const unsigned numNeighbors = std::pow((maxIndex - minIndex) + 1, D);
191
192 hrleVectorType<hrleIndexType, D> neighborIndex(minIndex);
193 for (unsigned i = 0; i < numNeighbors; ++i) {
194
195 Vec3D<T> normal = {};
196 auto center = neighborIterator.getNeighbor(neighborIndex).getValue();
197 for (unsigned dir = 0; dir < D; ++dir) {
198 hrleVectorType<hrleIndexType, D> unity(0);
199 unity[dir] = 1;
200 auto neg =
201 neighborIterator.getNeighbor(neighborIndex - unity).getValue();
202 auto pos =
203 neighborIterator.getNeighbor(neighborIndex + unity).getValue();
204 normal[dir] = calculateNormalComponent(neg, center, pos, gridDelta);
205 }
206
207 for (unsigned dir = 0; dir < D; ++dir) {
208 T tempAlpha = velocities->getDissipationAlpha(dir, material, normal);
209 alpha[dir] = std::max(alpha[dir], tempAlpha);
210 finalAlphas[dir] = std::max(finalAlphas[dir], tempAlpha);
211 }
212
213 // advance to next index
214 incrementIndices(neighborIndex, minIndex, maxIndex);
215 }
216 }
217
218 // calculate local dissipation alphas for each direction
219 // and add to dissipation term
220 for (unsigned i = 0; i < D; ++i) {
221 dissipation += alpha[i] * (gradNeg[i] - gradPos[i]) * 0.5;
222 }
223
224 return {totalGrad, ((totalGrad != 0.) ? dissipation : 0)};
225 }
226
227 void reduceTimeStepHamiltonJacobi(double &MaxTimeStep,
228 hrleCoordType gridDelta) {
229 const double alpha_maxCFL = 1.0;
230 // second time step test, based on alphas
231
232 double timeStep = 0;
233 for (int i = 0; i < D; ++i) {
234 timeStep += finalAlphas[i] / gridDelta;
235 }
236
237 timeStep = alpha_maxCFL / timeStep;
238 MaxTimeStep = std::min(timeStep, MaxTimeStep);
239 }
240};
241} // namespace lsInternal
LocalLaxFriedrichsAnalytical(SmartPointer< viennals::Domain< T, D > > passedlsDomain, SmartPointer< viennals::VelocityField< T > > vel)
Definition lsLocalLaxFriedrichsAnalytical.hpp:55
void reduceTimeStepHamiltonJacobi(double &MaxTimeStep, hrleCoordType gridDelta)
Definition lsLocalLaxFriedrichsAnalytical.hpp:227
static void prepareLS(SmartPointer< viennals::Domain< T, D > > passedlsDomain)
Definition lsLocalLaxFriedrichsAnalytical.hpp:47
std::pair< T, T > operator()(const hrleVectorType< hrleIndexType, D > &indices, int material)
Definition lsLocalLaxFriedrichsAnalytical.hpp:65
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:27
Expands the leveleSet to the specified number of layers. The largest value in the levelset is thus wi...
Definition lsExpand.hpp:16
void apply()
Apply the expansion to the specified width.
Definition lsExpand.hpp:44
Abstract class defining the interface for the velocity field used during advection using lsAdvect.
Definition lsVelocityField.hpp:13
Definition lsCurvatureFormulas.hpp:9
constexpr int D
Definition pyWrap.cpp:66
double T
Definition pyWrap.cpp:64