34 using LevelSetType = SmartPointer<viennals::Domain<T, D>>;
36 LevelSetType levelSet;
37 SmartPointer<viennals::VelocityField<T>> velocities;
38 viennahrle::ConstSparseBoxIterator<viennahrle::Domain<T, D>,
39 static_cast<int>(finiteDifferenceScheme) +
42 const double gridDelta;
43 const double alphaFactor;
44 const double baseNormalEpsilon =
45 std::cbrt(std::numeric_limits<double>::epsilon());
48 VectorType<T, D> finalAlphas{};
49 static constexpr unsigned numStencilPoints = hrleUtil::pow(2 * order + 1,
D);
50 static double maxDissipation;
53 static constexpr T velocityScaleFactor =
55 static constexpr T smoothnessThreshold =
57 static constexpr T epsilonMinScale = 0.1;
58 static constexpr T epsilonMaxScale = 100.0;
60#if ADAPTIVE_EPSILON_STRATEGY == 1
62 T calculateSimpleAdaptiveEpsilon(
T velocityMagnitude)
const {
63 T absVel = std::abs(velocityMagnitude);
64 T baseEps = baseNormalEpsilon * gridDelta;
69 T scale = std::max(
T(0.1), std::min(
T(10.0), absVel));
70 return baseEps * scale;
77#if ADAPTIVE_EPSILON_STRATEGY == 2
80 T calculateAdaptiveEpsilon(
T velocityMagnitude,
81 const Vec3D<T> &localCoordArray,
int material,
82 const Vec3D<T> &normal)
const {
84 T adaptiveEpsilon = baseNormalEpsilon * gridDelta;
89 T absVelocity = std::abs(velocityMagnitude);
90 if (absVelocity > 1e-12) {
91 T velocityScale = 1.0 + velocityScaleFactor * std::log(1.0 + absVelocity);
92 adaptiveEpsilon *= velocityScale;
97 if (absVelocity > 1e-10) {
98 T maxRelativeVariation = 0.0;
101 for (
int dir = 0; dir <
D; ++dir) {
102 Vec3D<T> perturbedNormal = normal;
103 perturbedNormal[dir] += smoothnessThreshold;
107 for (
int i = 0; i <
D; ++i) {
108 normSq += perturbedNormal[i] * perturbedNormal[i];
110 if (normSq > 1e-12) {
111 T invNorm =
T(1) / std::sqrt(normSq);
112 for (
int i = 0; i <
D; ++i) {
113 perturbedNormal[i] *= invNorm;
116 T perturbedVel = velocities->getScalarVelocity(
117 localCoordArray, material, perturbedNormal,
118 neighborIterator.getCenter().getPointId());
120 T relativeVariation =
121 std::abs(perturbedVel - velocityMagnitude) / absVelocity;
122 maxRelativeVariation =
123 std::max(maxRelativeVariation, relativeVariation);
128 if (maxRelativeVariation > smoothnessThreshold) {
129 T smoothnessFactor = 1.0 + maxRelativeVariation;
130 adaptiveEpsilon *= smoothnessFactor;
135 T minEpsilon = baseNormalEpsilon * gridDelta * epsilonMinScale;
136 T maxEpsilon = baseNormalEpsilon * gridDelta * epsilonMaxScale;
138 return std::max(minEpsilon, std::min(maxEpsilon, adaptiveEpsilon));
142 Vec3D<T> calculateNormal(
const viennahrle::Index<D> &offset)
const {
144 constexpr int startIndex = -1;
147 for (
unsigned i = 0; i <
D; ++i) {
148 viennahrle::Index<D> index(offset);
149 std::array<T, 3> values;
150 for (
unsigned j = 0; j < 3; ++j) {
151 index[i] = startIndex + j;
152 values[j] = neighborIterator.getNeighbor(index).getValue();
156 modulus += normal[i] * normal[i];
158 modulus =
T(1) / std::sqrt(modulus);
159 for (
unsigned i = 0; i <
D; ++i) {
160 normal[i] *= modulus;
165 VectorType<T, D> calculateGradient(
const viennahrle::Index<D> &offset)
const {
166 VectorType<T, D> gradient;
168 constexpr unsigned numValues =
170 const int startIndex = -std::floor(numValues / 2);
172 for (
unsigned i = 0; i <
D; ++i) {
173 viennahrle::Index<D> index(offset);
174 std::array<T, numValues> values;
175 for (
unsigned j = 0; j < numValues; ++j) {
176 index[i] = startIndex + j;
177 values[j] = neighborIterator.getNeighbor(index).getValue();
182 values.data(), gridDelta);
188 VectorType<T, D> calculateGradientDiff()
const {
189 VectorType<T, D> gradient;
191 constexpr unsigned numValues =
193 const int startIndex =
194 -std::floor(numValues / 2);
196 for (
unsigned i = 0; i <
D; ++i) {
197 viennahrle::Index<D> index(0);
198 std::array<T, numValues> values;
199 for (
unsigned j = 0; j < numValues; ++j) {
200 index[i] = startIndex + j;
201 values[j] = neighborIterator.getNeighbor(index).getValue();
206 values.data(), gridDelta);
212 static void incrementIndex(viennahrle::Index<D> &index) {
214 for (; dim <
D - 1; ++dim) {
215 if (index[dim] < order)
232 : levelSet(passedlsDomain), velocities(vel),
233 neighborIterator(levelSet->getDomain()),
234 gridDelta(levelSet->getGrid().getGridDelta()), alphaFactor(a) {}
238 std::pair<T, T>
operator()(
const viennahrle::Index<D> &indices,
241 Vec3D<T> coordinate{};
242 for (
unsigned i = 0; i <
D; ++i) {
243 coordinate[i] = indices[i] * gridDelta;
245 const auto pointId = neighborIterator.getCenter().getPointId();
248 neighborIterator.goToIndicesSequential(indices);
252 Vec3D<T> normalVector = calculateNormal(viennahrle::Index<D>(0));
254 double scalarVelocity = velocities->getScalarVelocity(
255 coordinate, material, normalVector, pointId);
256 auto vectorVelocity = velocities->getVectorVelocity(coordinate, material,
257 normalVector, pointId);
260 for (
unsigned i = 0; i <
D; ++i) {
261 scalarVelocity += vectorVelocity[i] * normalVector[i];
264 if (scalarVelocity ==
T(0)) {
269 Norm(calculateGradient(viennahrle::Index<D>(0))) * scalarVelocity;
274 std::array<VectorType<T, D>, numStencilPoints> alphas{};
276 viennahrle::Index<D> currentIndex(-order);
278 for (
auto &alpha : alphas) {
279 Vec3D<T> localNormal = calculateNormal(currentIndex);
282 if ((std::abs(localNormal[0]) < 1e-6) &&
283 (std::abs(localNormal[1]) < 1e-6) &&
284 (std::abs(localNormal[2]) < 1e-6)) {
290 Vec3D<T> localCoordArray = coordinate;
291 for (
unsigned dir = 0; dir <
D; ++dir)
292 localCoordArray[dir] += currentIndex[dir] * gridDelta;
294 T localScalarVelocity = velocities->getScalarVelocity(
295 localCoordArray, material, localNormal, pointId);
296 Vec3D<T> localVectorVelocity = velocities->getVectorVelocity(
297 localCoordArray, material, localNormal, pointId);
299 for (
unsigned dir = 0; dir <
D; ++dir) {
300 localScalarVelocity += localVectorVelocity[dir] * localNormal[dir];
305#if ADAPTIVE_EPSILON_STRATEGY == 0
307 DN = std::abs(baseNormalEpsilon * localScalarVelocity);
308#elif ADAPTIVE_EPSILON_STRATEGY == 1
310 DN = calculateSimpleAdaptiveEpsilon(localScalarVelocity);
311#elif ADAPTIVE_EPSILON_STRATEGY == 2
313 DN = calculateAdaptiveEpsilon(localScalarVelocity, localCoordArray,
314 material, localNormal);
317 DN = std::abs(baseNormalEpsilon * localScalarVelocity);
320 Vec3D<T> normal_p = localNormal;
321 Vec3D<T> normal_n = localNormal;
323 VectorType<T, D> velocityDelta;
324 for (
int k = 0; k <
D; ++k) {
329 T vp = velocities->getScalarVelocity(localCoordArray, material,
331 T vn = velocities->getScalarVelocity(localCoordArray, material,
334 velocityDelta[k] = (vn - vp) / (2.0 * DN);
341 for (
int k = 0; k <
D; ++k) {
348 VectorType<T, D> gradient = calculateGradient(currentIndex);
350 for (
int j = 0; j <
D - 1; ++j) {
351 int idx = (k + 1 + j) %
D;
352 monti += gradient[idx] * gradient[idx];
353 toifl += gradient[idx] * velocityDelta[idx];
356 T denom = DotProduct(gradient, gradient);
357 monti *= velocityDelta[k] / denom;
358 toifl *= -gradient[k] / denom;
361 T osher = localScalarVelocity * localNormal[k];
363 alpha[k] = std::fabs(monti + toifl + osher);
366 incrementIndex(currentIndex);
370 VectorType<T, D> gradientDiff = calculateGradientDiff();
371 for (
int d = 0; d <
D; ++d) {
374 for (
size_t i = 0; i < numStencilPoints; ++i) {
375 maxAlpha = std::max(maxAlpha, alphas[i][d]);
378 finalAlphas[d] = std::min(maxAlpha,
static_cast<T>(maxDissipation));
379 dissipation += finalAlphas[d] * gradientDiff[d];
382 return {hamiltonian, dissipation};
386 double gridDelta)
const {
387 constexpr double alpha_maxCFL = 1.0;
391 for (
int i = 0; i <
D; ++i) {
392 timeStep += finalAlphas[i] / gridDelta;
395 timeStep = alpha_maxCFL / timeStep;
396 MaxTimeStep = std::min(timeStep, MaxTimeStep);
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:28