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