5#include <hrleSparseIterator.hpp>
18using namespace viennacore;
25 return v >
T(1) ?
T(1) : (v <
T(-1) ?
T(-1) : v);
30 T minBoundaryFraction,
T gridDelta) {
31 const T denom = std::abs(insidePhi) + std::abs(outsidePhi);
32 if (denom <= std::numeric_limits<T>::epsilon())
34 return std::max(minBoundaryFraction * gridDelta,
35 gridDelta * std::abs(insidePhi) / denom);
47 viennahrle::ConstSparseIterator<typename Domain<T, D>::DomainType>;
49 static constexpr std::size_t
noNode = std::numeric_limits<std::size_t>::max();
67 constexpr T eps =
T(1e-9);
68 return (a <= eps && b >= -eps) || (a >= -eps && b <= eps);
72 it.goToIndices(index);
77 for (
unsigned i = 0; i <
D; ++i)
84 std::size_t total = 1;
85 for (
unsigned i = 0; i <
D; ++i)
98 return std::numeric_limits<std::size_t>::max();
99 std::size_t result = 0;
100 for (
unsigned i = 0; i <
D; ++i)
101 result +=
static_cast<std::size_t
>(index[i] -
minIndex[i]) *
strides[i];
106 for (
unsigned i = 0; i <
D; ++i) {
120 for (
int radius = 1; radius <= 4; ++radius) {
121 T bestDistance2 = std::numeric_limits<T>::max();
122 std::size_t bestNode = std::numeric_limits<std::size_t>::max();
125 offset.fill(-radius);
129 for (
unsigned i = 0; i <
D; ++i) {
130 candidate[i] += offset[i];
131 distance2 +=
static_cast<T>(offset[i] * offset[i]);
134 if (distance2 > 0 &&
inBounds(candidate)) {
136 if (foundId !=
noNode && distance2 < bestDistance2) {
137 bestDistance2 = distance2;
143 for (; dim <
D; ++dim) {
144 if (offset[dim] < radius) {
148 offset[dim] = -radius;
154 if (bestNode != std::numeric_limits<std::size_t>::max())
157 return std::numeric_limits<std::size_t>::max();
163 SmartPointer<
Domain<T, D>> maskInterface,
bool useRequestedBounds,
165 std::size_t maxGridPoints,
const std::string &solverName) {
166 auto &reactionGrid = reactionInterface->getGrid();
167 auto &ambientGrid = ambientInterface->getGrid();
170 if (std::abs(
gridDelta - ambientGrid.getGridDelta()) >
171 std::numeric_limits<T>::epsilon() ||
172 (maskInterface !=
nullptr &&
173 std::abs(
gridDelta - maskInterface->getGrid().getGridDelta()) >
174 std::numeric_limits<T>::epsilon())) {
175 Logger::getInstance()
176 .addError(solverName +
": Interface grid deltas must match.")
181 IndexType gridMin = reactionGrid.getMinGridPoint();
182 IndexType gridMax = reactionGrid.getMaxGridPoint();
183 for (
unsigned i = 0; i <
D; ++i) {
184 gridMin[i] = std::max(gridMin[i], ambientGrid.getMinGridPoint(i));
185 gridMax[i] = std::min(gridMax[i], ambientGrid.getMaxGridPoint(i));
186 if (maskInterface !=
nullptr) {
188 std::max(gridMin[i], maskInterface->getGrid().getMinGridPoint(i));
190 std::min(gridMax[i], maskInterface->getGrid().getMaxGridPoint(i));
194 auto bounds = definedPointBounds(reactionInterface);
195 mergeDefinedPointBounds(bounds, ambientInterface);
196 if (maskInterface !=
nullptr)
197 mergeDefinedPointBounds(bounds, maskInterface);
199 minIndex = bounds.foundDefinedPoints ? bounds.min : gridMin;
200 maxIndex = bounds.foundDefinedPoints ? bounds.max : gridMax;
203 std::size_t numGridPoints = 1;
204 for (
unsigned i = 0; i <
D; ++i) {
205 if (useRequestedBounds) {
210 Logger::getInstance()
211 .addError(solverName +
": Cartesian solve region is empty.")
220 if (numGridPoints > maxGridPoints) {
221 Logger::getInstance()
222 .addError(solverName +
223 ": Cartesian solve region exceeds maxGridPoints.")
231 bool useRequestedBounds,
234 std::size_t maxGridPoints,
235 const std::string &solverName) {
236 auto &grid = maskInterface->getGrid();
239 auto bounds = definedPointBounds(maskInterface);
240 minIndex = bounds.foundDefinedPoints ? bounds.min : grid.getMinGridPoint();
241 maxIndex = bounds.foundDefinedPoints ? bounds.max : grid.getMaxGridPoint();
243 grid.getMaxGridPoint());
245 std::size_t numGridPoints = 1;
246 for (
unsigned i = 0; i <
D; ++i) {
247 if (useRequestedBounds) {
252 Logger::getInstance()
253 .addError(solverName +
": Cartesian solve region is empty.")
262 if (numGridPoints > maxGridPoints) {
263 Logger::getInstance()
264 .addError(solverName +
265 ": Cartesian solve region exceeds maxGridPoints.")
273 GridBounds definedPointBounds(SmartPointer<
Domain<T, D>> levelSet)
const {
276 for (; !it.isFinished(); ++it) {
280 const auto &index = it.getStartIndices();
281 if (!bounds.foundDefinedPoints) {
284 bounds.foundDefinedPoints =
true;
286 for (
unsigned i = 0; i <
D; ++i) {
287 bounds.min[i] = std::min(bounds.min[i], index[i]);
288 bounds.max[i] = std::max(bounds.max[i], index[i]);
295 void mergeDefinedPointBounds(
GridBounds &target,
296 SmartPointer<Domain<T, D>> levelSet)
const {
297 const auto source = definedPointBounds(levelSet);
298 if (!source.foundDefinedPoints)
300 if (!target.foundDefinedPoints) {
304 for (
unsigned i = 0; i <
D; ++i) {
305 target.min[i] = std::min(target.min[i], source.min[i]);
306 target.max[i] = std::max(target.max[i], source.max[i]);
314 constexpr int padding = 4;
315 for (
unsigned i = 0; i <
D; ++i) {
324 std::max(gridMin[i], std::max(gridMin[i],
minIndex[i]) - padding);
326 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:43
static constexpr std::size_t noNode
Definition lsOxidationSolverBase.hpp:49
bool crosses(T a, T b) const
Definition lsOxidationSolverBase.hpp:63
std::size_t lookupNode(const IndexType &index) const
Definition lsOxidationSolverBase.hpp:90
std::size_t linearIndex(const IndexType &index) const
Definition lsOxidationSolverBase.hpp:96
void initNodeLookup()
Definition lsOxidationSolverBase.hpp:83
bool inBounds(const IndexType &index) const
Definition lsOxidationSolverBase.hpp:76
std::array< std::size_t, D > strides
Definition lsOxidationSolverBase.hpp:54
T gridDelta
Definition lsOxidationSolverBase.hpp:55
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:230
std::vector< std::size_t > nodeLookupFlat
Definition lsOxidationSolverBase.hpp:50
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:160
std::array< std::size_t, D > extents
Definition lsOxidationSolverBase.hpp:53
viennahrle::ConstSparseIterator< typename Domain< T, D >::DomainType > ConstSparseIterator
Definition lsOxidationSolverBase.hpp:46
T valueAt(ConstSparseIterator &it, const IndexType &index) const
Definition lsOxidationSolverBase.hpp:71
bool increment(IndexType &index) const
Definition lsOxidationSolverBase.hpp:105
IndexType minIndex
Definition lsOxidationSolverBase.hpp:51
viennahrle::Index< D > IndexType
Definition lsOxidationSolverBase.hpp:45
std::size_t findNearbyNode(const IndexType &index) const
Definition lsOxidationSolverBase.hpp:119
IndexType maxIndex
Definition lsOxidationSolverBase.hpp:52
tuple bounds
Definition AirGapDeposition.py:63
Definition lsOxidationSolverBase.hpp:20
T levelSetCrossingDistance(T insidePhi, T outsidePhi, T minBoundaryFraction, T gridDelta)
Definition lsOxidationSolverBase.hpp:29
T clampLevelSetPhi(T v)
Clamp HRLE far-field sentinels (±DBL_MAX) to ±1 before differencing to prevent DBL_MAX² overflow that...
Definition lsOxidationSolverBase.hpp:24
Definition lsAdvect.hpp:41
Definition lsOxidationSolverBase.hpp:57
IndexType max
Definition lsOxidationSolverBase.hpp:59
bool foundDefinedPoints
Definition lsOxidationSolverBase.hpp:60
IndexType min
Definition lsOxidationSolverBase.hpp:58