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