ViennaLS
Loading...
Searching...
No Matches
lsLocalLocalLaxFriedrichs.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <hrleSparseStarIterator.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
18template <class T, int D, int order> class LocalLocalLaxFriedrichs {
19 SmartPointer<viennals::Domain<T, D>> levelSet;
20 SmartPointer<viennals::VelocityField<T>> velocities;
21 viennahrle::SparseStarIterator<viennahrle::Domain<T, D>, order>
22 neighborIterator;
23 const double alphaFactor;
24 VectorType<T, 3> finalAlphas;
25
26 static T pow2(const T &value) { return value * value; }
27
28public:
29 static void prepareLS(SmartPointer<viennals::Domain<T, D>> passedlsDomain) {
30 assert(order == 1 || order == 2);
31 viennals::Expand<T, D>(passedlsDomain, 2 * order + 1).apply();
32 }
33
34 LocalLocalLaxFriedrichs(SmartPointer<viennals::Domain<T, D>> passedlsDomain,
35 SmartPointer<viennals::VelocityField<T>> vel,
36 double a = 1.0)
37 : levelSet(passedlsDomain), velocities(vel),
38 neighborIterator(levelSet->getDomain()), alphaFactor(a) {
39 for (int i = 0; i < 3; ++i) {
40 finalAlphas[i] = 0;
41 }
42 }
43
44 std::pair<T, T> operator()(const viennahrle::Index<D> &indices,
45 int material) {
46
47 auto &grid = levelSet->getGrid();
48 double gridDelta = grid.getGridDelta();
49
50 VectorType<T, 3> coordinate{0., 0., 0.};
51 for (unsigned i = 0; i < D; ++i) {
52 coordinate[i] = indices[i] * gridDelta;
53 }
54
55 // move neighborIterator to current position
56 neighborIterator.goToIndicesSequential(indices);
57
58 // convert coordinate to std array for interface
59 Vec3D<T> coordArray{coordinate[0], coordinate[1], coordinate[2]};
60
61 T gradPos[D];
62 T gradNeg[D];
63
64 T grad = 0.;
65 T dissipation = 0.;
66
67 Vec3D<T> normalVector = {};
68 T normalModulus = 0;
69
70 for (int i = 0; i < D; i++) { // iterate over dimensions
71
72 const T deltaPos = gridDelta;
73 const T deltaNeg = -gridDelta;
74
75 const T phi0 = neighborIterator.getCenter().getValue();
76 const T phiPos = neighborIterator.getNeighbor(i).getValue();
77 const T phiNeg = neighborIterator.getNeighbor(i + D).getValue();
78
79 T diffPos = (phiPos - phi0) / deltaPos;
80 T diffNeg = (phiNeg - phi0) / deltaNeg;
81
82 if (order == 2) { // if second order time integration scheme is used
83 const T deltaPosPos = 2 * gridDelta;
84 const T deltaNegNeg = -2 * gridDelta;
85
86 const T diff00 =
87 (((deltaNeg * phiPos - deltaPos * phiNeg) / (deltaPos - deltaNeg) +
88 phi0)) /
89 (deltaPos * deltaNeg);
90 const T phiPosPos =
91 neighborIterator.getNeighbor((D * order) + i).getValue();
92 const T phiNegNeg =
93 neighborIterator.getNeighbor((D * order) + D + i).getValue();
94
95 const T diffNegNeg = (((deltaNeg * phiNegNeg - deltaNegNeg * phiNeg) /
96 (deltaNegNeg - deltaNeg) +
97 phi0)) /
98 (deltaNegNeg * deltaNeg);
99 const T diffPosPos = (((deltaPos * phiPosPos - deltaPosPos * phiPos) /
100 (deltaPosPos - deltaPos) +
101 phi0)) /
102 (deltaPosPos * deltaPos);
103
104 if (std::signbit(diff00) == std::signbit(diffPosPos)) {
105 if (std::abs(diffPosPos * deltaPos) < std::abs(diff00 * deltaNeg)) {
106 diffPos -= deltaPos * diffPosPos;
107 } else {
108 diffPos += deltaNeg * diff00;
109 }
110 }
111
112 if (std::signbit(diff00) == std::signbit(diffNegNeg)) {
113 if (std::abs(diffNegNeg * deltaNeg) < std::abs(diff00 * deltaPos)) {
114 diffNeg -= deltaNeg * diffNegNeg;
115 } else {
116 diffNeg += deltaPos * diff00;
117 }
118 }
119 }
120
121 gradPos[i] = diffNeg;
122 gradNeg[i] = diffPos;
123
124 normalVector[i] = (diffNeg + diffPos) * 0.5;
125 normalModulus += normalVector[i] * normalVector[i];
126
127 grad += pow2((diffNeg + diffPos) * 0.5);
128 }
129
130 // normalise normal vector
131 normalModulus = std::sqrt(normalModulus);
132 for (unsigned i = 0; i < D; ++i) {
133 normalVector[i] /= normalModulus;
134 }
135
136 // Get velocities
137 double scalarVelocity = velocities->getScalarVelocity(
138 coordArray, material, normalVector,
139 neighborIterator.getCenter().getPointId());
140 Vec3D<T> vectorVelocity = velocities->getVectorVelocity(
141 coordArray, material, normalVector,
142 neighborIterator.getCenter().getPointId());
143
144 // calculate hamiltonian
145 T totalGrad = 0.;
146 if (scalarVelocity != 0.) {
147 totalGrad = scalarVelocity * std::sqrt(grad);
148 }
149
150 for (int w = 0; w < D; w++) {
151 if (vectorVelocity[w] > 0.) {
152 totalGrad += vectorVelocity[w] * gradPos[w];
153 } else {
154 totalGrad += vectorVelocity[w] * gradNeg[w];
155 }
156 }
157
158 // calculate local dissipation alphas for each direction
159 // and add to dissipation term
160 for (unsigned i = 0; i < D; ++i) {
161 T alpha =
162 std::abs((scalarVelocity + vectorVelocity[i]) * normalVector[i]);
163 finalAlphas[i] = std::max(finalAlphas[i], alpha);
164 dissipation += alphaFactor * alpha * (gradNeg[i] - gradPos[i]) * 0.5;
165 }
166
167 return {totalGrad, ((totalGrad != 0.) ? dissipation : 0)};
168 }
169
170 void reduceTimeStepHamiltonJacobi(double &MaxTimeStep, double gridDelta) {
171 constexpr double alpha_maxCFL = 1.0;
172 // second time step test, based on alphas
173
174 double timeStep = 0;
175 for (int i = 0; i < D; ++i) {
176 timeStep += finalAlphas[i] / gridDelta;
177 }
178
179 timeStep = alpha_maxCFL / timeStep;
180 MaxTimeStep = std::min(timeStep, MaxTimeStep);
181 }
182};
183} // namespace lsInternal
void reduceTimeStepHamiltonJacobi(double &MaxTimeStep, double gridDelta)
Definition lsLocalLocalLaxFriedrichs.hpp:170
std::pair< T, T > operator()(const viennahrle::Index< D > &indices, int material)
Definition lsLocalLocalLaxFriedrichs.hpp:44
static void prepareLS(SmartPointer< viennals::Domain< T, D > > passedlsDomain)
Definition lsLocalLocalLaxFriedrichs.hpp:29
LocalLocalLaxFriedrichs(SmartPointer< viennals::Domain< T, D > > passedlsDomain, SmartPointer< viennals::VelocityField< T > > vel, double a=1.0)
Definition lsLocalLocalLaxFriedrichs.hpp:34
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 lsCurvatureFormulas.hpp:9
constexpr int D
Definition pyWrap.cpp:70
double T
Definition pyWrap.cpp:68