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