ViennaLS
Loading...
Searching...
No Matches
lsLocalLaxFriedrichs.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 LocalLaxFriedrichs {
22 SmartPointer<viennals::Domain<T, D>> levelSet;
23 SmartPointer<viennals::VelocityField<T>> velocities;
24 hrleSparseBoxIterator<hrleDomain<T, D>> neighborIterator;
25 const double alphaFactor;
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
55 LocalLaxFriedrichs(SmartPointer<viennals::Domain<T, D>> passedlsDomain,
56 SmartPointer<viennals::VelocityField<T>> vel,
57 double a = 1.0)
58 : levelSet(passedlsDomain), velocities(vel),
59 neighborIterator(levelSet->getDomain(), 2), alphaFactor(a) {}
60
61 T operator()(const hrleVectorType<hrleIndexType, D> &indices, int material) {
62
63 auto &grid = levelSet->getGrid();
64 double gridDelta = grid.getGridDelta();
65
66 hrleVectorType<T, 3> coordinate(0., 0., 0.);
67 for (unsigned i = 0; i < D; ++i) {
68 coordinate[i] = indices[i] * gridDelta;
69 }
70
71 // move neighborIterator to current position
72 neighborIterator.goToIndicesSequential(indices);
73
74 // convert coordinate to std array for interface
75 Vec3D<T> coordArray = {coordinate[0], coordinate[1], coordinate[2]};
76
77 T gradPos[D];
78 T gradNeg[D];
79
80 T grad = 0.;
81 T dissipation = 0.;
82
83 Vec3D<T> normalVector = {};
84 T normalModulus = 0;
85
86 for (int i = 0; i < D; i++) { // iterate over dimensions
87 hrleVectorType<hrleIndexType, D> posUnit(0);
88 hrleVectorType<hrleIndexType, D> negUnit(0);
89 posUnit[i] = 1;
90 negUnit[i] = -1;
91
92 const T deltaPos = gridDelta;
93 const T deltaNeg = -gridDelta;
94
95 const T phi0 = neighborIterator.getCenter().getValue();
96 const T phiPos = neighborIterator.getNeighbor(posUnit).getValue();
97 const T phiNeg = neighborIterator.getNeighbor(negUnit).getValue();
98
99 T diffPos = (phiPos - phi0) / deltaPos;
100 T diffNeg = (phiNeg - phi0) / deltaNeg;
101
102 if (order == 2) { // if second order time integration 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 // normalise normal vector
152 normalModulus = std::sqrt(normalModulus);
153 for (unsigned i = 0; i < D; ++i) {
154 normalVector[i] /= normalModulus;
155 }
156
157 // Get velocities
158 double scalarVelocity = velocities->getScalarVelocity(
159 coordArray, material, normalVector,
160 neighborIterator.getCenter().getPointId());
161 Vec3D<T> vectorVelocity = velocities->getVectorVelocity(
162 coordArray, 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 // calculate alphas
180 T alpha[D] = {};
181 {
182 // alpha calculation is always on order 1 stencil
183 const hrleIndexType minIndex = -1;
184 const hrleIndexType maxIndex = 1;
185 const unsigned numNeighbors = std::pow((maxIndex - minIndex) - 1, D);
186
187 hrleVectorType<hrleIndexType, D> neighborIndex(minIndex);
188 for (unsigned i = 0; i < numNeighbors; ++i) {
189 Vec3D<T> coords;
190 for (unsigned dir = 0; dir < D; ++dir) {
191 coords[dir] = coordinate[dir] + neighborIndex[dir] * gridDelta;
192 }
193 Vec3D<T> normal = {};
194 double normalModulus = 0.;
195 auto center = neighborIterator.getNeighbor(neighborIndex).getValue();
196 for (unsigned dir = 0; dir < D; ++dir) {
197 hrleVectorType<hrleIndexType, D> unity(0);
198 unity[dir] = 1;
199 auto neg =
200 neighborIterator.getNeighbor(neighborIndex - unity).getValue();
201 auto pos =
202 neighborIterator.getNeighbor(neighborIndex + unity).getValue();
203 normal[dir] = calculateNormalComponent(neg, center, pos, gridDelta);
204 normalModulus += normal[dir] * normal[dir];
205 }
206 normalModulus = std::sqrt(normalModulus);
207
208 T scaVel = velocities->getScalarVelocity(
209 coords, material, normal,
210 neighborIterator.getCenter().getPointId());
211 auto vecVel = velocities->getVectorVelocity(
212 coords, material, normal,
213 neighborIterator.getCenter().getPointId());
214
215 for (unsigned dir = 0; dir < D; ++dir) {
216 // normalise normal vector
217 normal[i] /= normalModulus;
218 T tempAlpha = std::abs((scaVel + vecVel[i]) * normal[i]);
219 alpha[dir] = std::max(alpha[dir], tempAlpha);
220 }
221
222 // advance to next index
223 incrementIndices(neighborIndex, minIndex, maxIndex);
224 }
225 }
226
227 // calculate local dissipation alphas for each direction
228 // and add to dissipation term
229 for (unsigned i = 0; i < D; ++i) {
230 dissipation += alphaFactor * alpha[i] * (gradNeg[i] - gradPos[i]) * 0.5;
231 }
232
233 // std::cout << neighborIterator.getCenter().getPointId() << " dissipation:
234 // " << dissipation << std::endl;
235 return totalGrad - ((totalGrad != 0.) ? dissipation : 0);
236 }
237};
238} // namespace lsInternal
Lax Friedrichs integration scheme, which uses a first neighbour stencil to calculate the alpha values...
Definition lsLocalLaxFriedrichs.hpp:21
static void prepareLS(SmartPointer< viennals::Domain< T, D > > passedlsDomain)
Definition lsLocalLaxFriedrichs.hpp:47
LocalLaxFriedrichs(SmartPointer< viennals::Domain< T, D > > passedlsDomain, SmartPointer< viennals::VelocityField< T > > vel, double a=1.0)
Definition lsLocalLaxFriedrichs.hpp:55
T operator()(const hrleVectorType< hrleIndexType, D > &indices, int material)
Definition lsLocalLaxFriedrichs.hpp:61
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:28
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 lsAdvect.hpp:37
constexpr int D
Definition pyWrap.cpp:65
double T
Definition pyWrap.cpp:63