5#include <hrleSparseIterator.hpp>
18using namespace viennacore;
25 for (
unsigned i = 0; i < static_cast<unsigned>(
D); ++i) {
26 seed ^= std::hash<long long>{}(
static_cast<long long>(index[i])) +
27 std::size_t(0x9e3779b97f4a7c15ULL) + (seed << 6) + (seed >> 2);
35 std::size_t
operator()(
const viennahrle::Index<D> &idx)
const {
40template <
class T>
inline Vec3D<T>
vecScaled(
const Vec3D<T> &source,
T factor) {
41 Vec3D<T> result{0., 0., 0.};
42 for (
unsigned i = 0; i < 3; ++i)
43 result[i] = source[i] * factor;
48inline Vec3D<T>
vecAdd(
const Vec3D<T> &a,
const Vec3D<T> &b) {
49 Vec3D<T> result{0., 0., 0.};
50 for (
unsigned i = 0; i < 3; ++i)
51 result[i] = a[i] + b[i];
56inline Vec3D<T>
vecSubtract(
const Vec3D<T> &a,
const Vec3D<T> &b) {
57 Vec3D<T> result{0., 0., 0.};
58 for (
unsigned i = 0; i < 3; ++i)
59 result[i] = a[i] - b[i];
64inline void vecAddTo(Vec3D<T> &target,
const Vec3D<T> &source) {
65 for (
unsigned i = 0; i < 3; ++i)
66 target[i] += source[i];
72 return v >
T(1) ?
T(1) : (v <
T(-1) ?
T(-1) : v);
77 T minBoundaryFraction,
T gridDelta) {
78 const T denom = std::abs(insidePhi) + std::abs(outsidePhi);
79 if (denom <= std::numeric_limits<T>::epsilon())
81 return std::max(minBoundaryFraction * gridDelta,
82 gridDelta * std::abs(insidePhi) / denom);
94 viennahrle::ConstSparseIterator<typename Domain<T, D>::DomainType>;
96 static constexpr std::size_t
noNode = std::numeric_limits<std::size_t>::max();
114 constexpr T eps =
T(1e-9);
115 return (a <= eps && b >= -eps) || (a >= -eps && b <= eps);
119 it.goToIndices(index);
120 return it.getValue();
124 for (
unsigned i = 0; i <
D; ++i)
131 std::size_t total = 1;
132 for (
unsigned i = 0; i <
D; ++i)
145 return std::numeric_limits<std::size_t>::max();
146 std::size_t result = 0;
147 for (
unsigned i = 0; i <
D; ++i)
148 result +=
static_cast<std::size_t
>(index[i] -
minIndex[i]) *
strides[i];
153 for (
unsigned i = 0; i <
D; ++i) {
167 for (
int radius = 1; radius <= 4; ++radius) {
168 T bestDistance2 = std::numeric_limits<T>::max();
169 std::size_t bestNode = std::numeric_limits<std::size_t>::max();
172 offset.fill(-radius);
176 for (
unsigned i = 0; i <
D; ++i) {
177 candidate[i] += offset[i];
178 distance2 +=
static_cast<T>(offset[i] * offset[i]);
181 if (distance2 > 0 &&
inBounds(candidate)) {
183 if (foundId !=
noNode && distance2 < bestDistance2) {
184 bestDistance2 = distance2;
190 for (; dim <
D; ++dim) {
191 if (offset[dim] < radius) {
195 offset[dim] = -radius;
201 if (bestNode != std::numeric_limits<std::size_t>::max())
204 return std::numeric_limits<std::size_t>::max();
210 SmartPointer<
Domain<T, D>> maskInterface,
bool useRequestedBounds,
212 std::size_t maxGridPoints,
const std::string &solverName) {
213 auto &reactionGrid = reactionInterface->getGrid();
214 auto &ambientGrid = ambientInterface->getGrid();
217 if (std::abs(
gridDelta - ambientGrid.getGridDelta()) >
218 std::numeric_limits<T>::epsilon() ||
219 (maskInterface !=
nullptr &&
220 std::abs(
gridDelta - maskInterface->getGrid().getGridDelta()) >
221 std::numeric_limits<T>::epsilon())) {
222 Logger::getInstance()
223 .addError(solverName +
": Interface grid deltas must match.")
228 IndexType gridMin = reactionGrid.getMinGridPoint();
229 IndexType gridMax = reactionGrid.getMaxGridPoint();
230 for (
unsigned i = 0; i <
D; ++i) {
231 gridMin[i] = std::max(gridMin[i], ambientGrid.getMinGridPoint(i));
232 gridMax[i] = std::min(gridMax[i], ambientGrid.getMaxGridPoint(i));
233 if (maskInterface !=
nullptr) {
235 std::max(gridMin[i], maskInterface->getGrid().getMinGridPoint(i));
237 std::min(gridMax[i], maskInterface->getGrid().getMaxGridPoint(i));
241 auto bounds = definedPointBounds(reactionInterface);
242 mergeDefinedPointBounds(bounds, ambientInterface);
243 if (maskInterface !=
nullptr)
244 mergeDefinedPointBounds(bounds, maskInterface);
246 minIndex = bounds.foundDefinedPoints ? bounds.min : gridMin;
247 maxIndex = bounds.foundDefinedPoints ? bounds.max : gridMax;
250 std::size_t numGridPoints = 1;
251 for (
unsigned i = 0; i <
D; ++i) {
252 if (useRequestedBounds) {
257 Logger::getInstance()
258 .addError(solverName +
": Cartesian solve region is empty.")
267 if (numGridPoints > maxGridPoints) {
268 Logger::getInstance()
269 .addError(solverName +
270 ": Cartesian solve region exceeds maxGridPoints.")
278 bool useRequestedBounds,
281 std::size_t maxGridPoints,
282 const std::string &solverName) {
283 auto &grid = maskInterface->getGrid();
286 auto bounds = definedPointBounds(maskInterface);
287 minIndex = bounds.foundDefinedPoints ? bounds.min : grid.getMinGridPoint();
288 maxIndex = bounds.foundDefinedPoints ? bounds.max : grid.getMaxGridPoint();
290 grid.getMaxGridPoint());
292 std::size_t numGridPoints = 1;
293 for (
unsigned i = 0; i <
D; ++i) {
294 if (useRequestedBounds) {
299 Logger::getInstance()
300 .addError(solverName +
": Cartesian solve region is empty.")
309 if (numGridPoints > maxGridPoints) {
310 Logger::getInstance()
311 .addError(solverName +
312 ": Cartesian solve region exceeds maxGridPoints.")
320 GridBounds definedPointBounds(SmartPointer<
Domain<T, D>> levelSet)
const {
323 for (; !it.isFinished(); ++it) {
327 const auto &index = it.getStartIndices();
328 if (!bounds.foundDefinedPoints) {
331 bounds.foundDefinedPoints =
true;
333 for (
unsigned i = 0; i <
D; ++i) {
334 bounds.min[i] = std::min(bounds.min[i], index[i]);
335 bounds.max[i] = std::max(bounds.max[i], index[i]);
342 void mergeDefinedPointBounds(
GridBounds &target,
343 SmartPointer<Domain<T, D>> levelSet)
const {
344 const auto source = definedPointBounds(levelSet);
345 if (!source.foundDefinedPoints)
347 if (!target.foundDefinedPoints) {
351 for (
unsigned i = 0; i <
D; ++i) {
352 target.min[i] = std::min(target.min[i], source.min[i]);
353 target.max[i] = std::max(target.max[i], source.max[i]);
361 constexpr int padding = 4;
362 for (
unsigned i = 0; i <
D; ++i) {
371 std::max(gridMin[i], std::max(gridMin[i],
minIndex[i]) - padding);
373 std::min(gridMax[i], std::min(gridMax[i],
maxIndex[i]) + padding);
constexpr int D
Definition Epitaxy.cpp:12
double T
Definition Epitaxy.cpp:13
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:27
Common Cartesian-grid infrastructure shared by the three oxidation solver classes (diffusion,...
Definition lsOxidationSolverBase.hpp:90
static constexpr std::size_t noNode
Definition lsOxidationSolverBase.hpp:96
bool crosses(T a, T b) const
Definition lsOxidationSolverBase.hpp:110
std::size_t lookupNode(const IndexType &index) const
Definition lsOxidationSolverBase.hpp:137
std::size_t linearIndex(const IndexType &index) const
Definition lsOxidationSolverBase.hpp:143
void initNodeLookup()
Definition lsOxidationSolverBase.hpp:130
bool inBounds(const IndexType &index) const
Definition lsOxidationSolverBase.hpp:123
std::array< std::size_t, D > strides
Definition lsOxidationSolverBase.hpp:101
T gridDelta
Definition lsOxidationSolverBase.hpp:102
bool initializeGridFromMask(SmartPointer< Domain< T, D > > maskInterface, bool useRequestedBounds, const IndexType &requestedMinIndex, const IndexType &requestedMaxIndex, std::size_t maxGridPoints, const std::string &solverName)
Definition lsOxidationSolverBase.hpp:277
std::vector< std::size_t > nodeLookupFlat
Definition lsOxidationSolverBase.hpp:97
bool initializeGridFromInterfaces(SmartPointer< Domain< T, D > > reactionInterface, SmartPointer< Domain< T, D > > ambientInterface, SmartPointer< Domain< T, D > > maskInterface, bool useRequestedBounds, const IndexType &requestedMinIndex, const IndexType &requestedMaxIndex, std::size_t maxGridPoints, const std::string &solverName)
Definition lsOxidationSolverBase.hpp:207
std::array< std::size_t, D > extents
Definition lsOxidationSolverBase.hpp:100
viennahrle::ConstSparseIterator< typename Domain< T, D >::DomainType > ConstSparseIterator
Definition lsOxidationSolverBase.hpp:93
T valueAt(ConstSparseIterator &it, const IndexType &index) const
Definition lsOxidationSolverBase.hpp:118
bool increment(IndexType &index) const
Definition lsOxidationSolverBase.hpp:152
IndexType minIndex
Definition lsOxidationSolverBase.hpp:98
viennahrle::Index< D > IndexType
Definition lsOxidationSolverBase.hpp:92
std::size_t findNearbyNode(const IndexType &index) const
Definition lsOxidationSolverBase.hpp:166
IndexType maxIndex
Definition lsOxidationSolverBase.hpp:99
tuple bounds
Definition AirGapDeposition.py:63
Definition lsOxidationSolverBase.hpp:20
Vec3D< T > vecAdd(const Vec3D< T > &a, const Vec3D< T > &b)
Definition lsOxidationSolverBase.hpp:48
T levelSetCrossingDistance(T insidePhi, T outsidePhi, T minBoundaryFraction, T gridDelta)
Definition lsOxidationSolverBase.hpp:76
Vec3D< T > vecSubtract(const Vec3D< T > &a, const Vec3D< T > &b)
Definition lsOxidationSolverBase.hpp:56
T clampLevelSetPhi(T v)
Clamp HRLE far-field sentinels (±DBL_MAX) to ±1 before differencing to prevent DBL_MAX² overflow that...
Definition lsOxidationSolverBase.hpp:71
Vec3D< T > vecScaled(const Vec3D< T > &source, T factor)
Definition lsOxidationSolverBase.hpp:40
std::size_t gridIndexHash(const viennahrle::Index< D > &index)
Definition lsOxidationSolverBase.hpp:23
void vecAddTo(Vec3D< T > &target, const Vec3D< T > &source)
Definition lsOxidationSolverBase.hpp:64
Definition lsAdvect.hpp:41
Definition lsOxidationSolverBase.hpp:104
IndexType max
Definition lsOxidationSolverBase.hpp:106
bool foundDefinedPoints
Definition lsOxidationSolverBase.hpp:107
IndexType min
Definition lsOxidationSolverBase.hpp:105
Definition lsOxidationSolverBase.hpp:34
std::size_t operator()(const viennahrle::Index< D > &idx) const
Definition lsOxidationSolverBase.hpp:35