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