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 bool calculateNormalVectors = true;
24 const double alpha = 1.0;
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 LaxFriedrichs(SmartPointer<viennals::Domain<T, D>> passedlsDomain,
35 SmartPointer<viennals::VelocityField<T>> vel,
36 bool calcNormal = true, double a = 1.0)
37 : levelSet(passedlsDomain), velocities(vel),
38 neighborIterator(hrleSparseStarIterator<hrleDomain<T, D>, order>(
39 levelSet->getDomain())),
40 calculateNormalVectors(calcNormal), alpha(a) {}
41
42 T operator()(const hrleVectorType<hrleIndexType, D> &indices, int material) {
43
44 auto &grid = levelSet->getGrid();
45 double gridDelta = grid.getGridDelta();
46
47 hrleVectorType<T, 3> coordinate(0., 0., 0.);
48 for (unsigned i = 0; i < D; ++i) {
49 coordinate[i] = indices[i] * gridDelta;
50 }
51
52 // move neighborIterator to current position
53 neighborIterator.goToIndicesSequential(indices);
54
55 T gradPos[D];
56 T gradNeg[D];
57
58 T grad = 0.;
59 T dissipation = 0.;
60
61 Vec3D<T> normalVector = {};
62 T normalModulus = 0;
63 const bool calcNormals = calculateNormalVectors;
64
65 for (int i = 0; i < D; i++) { // iterate over dimensions
66
67 const T deltaPos = gridDelta;
68 const T deltaNeg = -gridDelta;
69
70 const T phi0 = neighborIterator.getCenter().getValue();
71 const T phiPos = neighborIterator.getNeighbor(i).getValue();
72 const T phiNeg = neighborIterator.getNeighbor(i + D).getValue();
73
74 T diffPos = (phiPos - phi0) / deltaPos;
75 T diffNeg = (phiNeg - phi0) / deltaNeg;
76
77 if (order == 2) { // if second order time integration scheme is used
78 const T deltaPosPos = 2 * gridDelta;
79 const T deltaNegNeg = -2 * gridDelta;
80
81 const T diff00 =
82 (((deltaNeg * phiPos - deltaPos * phiNeg) / (deltaPos - deltaNeg) +
83 phi0)) /
84 (deltaPos * deltaNeg);
85 const T phiPosPos =
86 neighborIterator.getNeighbor((D * order) + i).getValue();
87 const T phiNegNeg =
88 neighborIterator.getNeighbor((D * order) + D + i).getValue();
89
90 const T diffNegNeg = (((deltaNeg * phiNegNeg - deltaNegNeg * phiNeg) /
91 (deltaNegNeg - deltaNeg) +
92 phi0)) /
93 (deltaNegNeg * deltaNeg);
94 const T diffPosPos = (((deltaPos * phiPosPos - deltaPosPos * phiPos) /
95 (deltaPosPos - deltaPos) +
96 phi0)) /
97 (deltaPosPos * deltaPos);
98
99 if (std::signbit(diff00) == std::signbit(diffPosPos)) {
100 if (std::abs(diffPosPos * deltaPos) < std::abs(diff00 * deltaNeg)) {
101 diffPos -= deltaPos * diffPosPos;
102 } else {
103 diffPos += deltaNeg * diff00;
104 }
105 }
106
107 if (std::signbit(diff00) == std::signbit(diffNegNeg)) {
108 if (std::abs(diffNegNeg * deltaNeg) < std::abs(diff00 * deltaPos)) {
109 diffNeg -= deltaNeg * diffNegNeg;
110 } else {
111 diffNeg += deltaPos * diff00;
112 }
113 }
114 }
115
116 gradPos[i] = diffNeg;
117 gradNeg[i] = diffPos;
118
119 if (calcNormals) {
120 normalVector[i] = (diffNeg + diffPos) * 0.5;
121 normalModulus += normalVector[i] * normalVector[i];
122 }
123
124 grad += pow2((diffNeg + diffPos) * 0.5);
125 dissipation += (diffPos - diffNeg) * 0.5;
126 }
127
128 if (calcNormals) {
129 normalModulus = std::sqrt(normalModulus);
130 for (unsigned i = 0; i < D; ++i) {
131 normalVector[i] /= normalModulus;
132 }
133 }
134
135 // convert coordinate to std array for interface
136 Vec3D<T> coordArray = {coordinate[0], coordinate[1], coordinate[2]};
137
138 double scalarVelocity = velocities->getScalarVelocity(
139 coordArray, material, normalVector,
140 neighborIterator.getCenter().getPointId());
141 Vec3D<T> vectorVelocity = velocities->getVectorVelocity(
142 coordArray, material, normalVector,
143 neighborIterator.getCenter().getPointId());
144
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 return totalGrad - ((totalGrad != 0.) ? alpha * dissipation : 0);
159 }
160};
161} // namespace lsInternal
Lax Friedrichs integration scheme with constant alpha value for dissipation. This alpha value should ...
Definition lsLaxFriedrichs.hpp:19
static void prepareLS(SmartPointer< viennals::Domain< T, D > > passedlsDomain)
Definition lsLaxFriedrichs.hpp:29
T operator()(const hrleVectorType< hrleIndexType, D > &indices, int material)
Definition lsLaxFriedrichs.hpp:42
LaxFriedrichs(SmartPointer< viennals::Domain< T, D > > passedlsDomain, SmartPointer< viennals::VelocityField< T > > vel, bool calcNormal=true, double a=1.0)
Definition lsLaxFriedrichs.hpp:34
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