37 #ifndef OPENVDB_TOOLS_LEVEL_SET_ADVECT_HAS_BEEN_INCLUDED 38 #define OPENVDB_TOOLS_LEVEL_SET_ADVECT_HAS_BEEN_INCLUDED 40 #include <tbb/parallel_for.h> 41 #include <tbb/parallel_reduce.h> 97 template<
typename GridT,
98 typename FieldT = EnrightField<typename GridT::ValueType>,
99 typename InterruptT = util::NullInterrupter>
113 mTracker(grid, interrupt), mField(field),
115 mTemporalScheme(math::
TVD_RK2) {}
131 return mTracker.getSpatialScheme();
135 mTracker.setSpatialScheme(scheme);
139 return mTracker.getTemporalScheme();
143 mTracker.setTemporalScheme(scheme);
163 size_t advect(ValueType time0, ValueType time1);
178 Advect(
const Advect& other);
180 virtual ~Advect() {
if (mIsMaster) this->clearField(); }
183 size_t advect(ValueType time0, ValueType time1);
185 void operator()(
const LeafRange& r)
const 187 if (mTask) mTask(const_cast<Advect*>(
this), r);
191 void cook(
const char* msg,
size_t swapBuffer = 0);
193 typename GridT::ValueType sampleField(ValueType time0, ValueType time1);
194 template <
bool Aligned>
void sample(
const LeafRange& r, ValueType t0, ValueType t1);
195 inline void sampleXformed(
const LeafRange& r, ValueType t0, ValueType t1)
197 this->sample<false>(r, t0, t1);
199 inline void sampleAligned(
const LeafRange& r, ValueType t0, ValueType t1)
201 this->sample<true>(r, t0, t1);
206 template <
int Nominator,
int Denominator>
207 void euler(
const LeafRange&, ValueType,
Index,
Index);
208 inline void euler01(
const LeafRange& r, ValueType t) {this->euler<0,1>(r, t, 0, 1);}
209 inline void euler12(
const LeafRange& r, ValueType t) {this->euler<1,2>(r, t, 1, 1);}
210 inline void euler34(
const LeafRange& r, ValueType t) {this->euler<3,4>(r, t, 1, 2);}
211 inline void euler13(
const LeafRange& r, ValueType t) {this->euler<1,3>(r, t, 1, 2);}
213 LevelSetAdvection& mParent;
214 VectorType* mVelocity;
217 typename std::function<void (Advect*,
const LeafRange&)> mTask;
218 const bool mIsMaster;
221 template<math::BiasedGradientScheme SpatialScheme>
222 size_t advect1(ValueType time0, ValueType time1);
226 size_t advect2(ValueType time0, ValueType time1);
231 size_t advect3(ValueType time0, ValueType time1);
242 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
246 switch (mSpatialScheme) {
248 return this->advect1<math::FIRST_BIAS >(time0, time1);
250 return this->advect1<math::SECOND_BIAS >(time0, time1);
252 return this->advect1<math::THIRD_BIAS >(time0, time1);
254 return this->advect1<math::WENO5_BIAS >(time0, time1);
256 return this->advect1<math::HJWENO5_BIAS>(time0, time1);
264 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
265 template<math::BiasedGradientScheme SpatialScheme>
269 switch (mTemporalScheme) {
271 return this->advect2<SpatialScheme, math::TVD_RK1>(time0, time1);
273 return this->advect2<SpatialScheme, math::TVD_RK2>(time0, time1);
275 return this->advect2<SpatialScheme, math::TVD_RK3>(time0, time1);
283 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
284 template<math::BiasedGradientScheme SpatialScheme, math::TemporalIntegrationScheme TemporalScheme>
286 LevelSetAdvection<GridT, FieldT, InterruptT>::advect2(ValueType time0, ValueType time1)
289 if (trans.
mapType() == math::UniformScaleMap::mapType()) {
290 return this->advect3<SpatialScheme, TemporalScheme, math::UniformScaleMap>(time0, time1);
291 }
else if (trans.
mapType() == math::UniformScaleTranslateMap::mapType()) {
292 return this->advect3<SpatialScheme, TemporalScheme, math::UniformScaleTranslateMap>(
294 }
else if (trans.
mapType() == math::UnitaryMap::mapType()) {
295 return this->advect3<SpatialScheme, TemporalScheme, math::UnitaryMap >(time0, time1);
296 }
else if (trans.
mapType() == math::TranslationMap::mapType()) {
297 return this->advect3<SpatialScheme, TemporalScheme, math::TranslationMap>(time0, time1);
305 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
311 LevelSetAdvection<GridT, FieldT, InterruptT>::advect3(ValueType time0, ValueType time1)
313 Advect<MapT, SpatialScheme, TemporalScheme> tmp(*
this);
314 return tmp.advect(time0, time1);
321 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
327 LevelSetAdvection<GridT, FieldT, InterruptT>::
328 Advect<MapT, SpatialScheme, TemporalScheme>::
329 Advect(LevelSetAdvection& parent)
333 , mMap(parent.mTracker.grid().transform().template constMap<MapT>().get())
340 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
346 LevelSetAdvection<GridT, FieldT, InterruptT>::
347 Advect<MapT, SpatialScheme, TemporalScheme>::
348 Advect(
const Advect& other)
349 : mParent(other.mParent)
350 , mVelocity(other.mVelocity)
351 , mOffsets(other.mOffsets)
359 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
367 advect(ValueType time0, ValueType time1)
369 namespace ph = std::placeholders;
374 const bool isForward = time0 < time1;
375 while ((isForward ? time0<time1 : time0>time1) && mParent.mTracker.checkInterrupter()) {
378 mParent.mTracker.leafs().rebuildAuxBuffers(TemporalScheme ==
math::TVD_RK3 ? 2 : 1);
381 const ValueType dt = this->sampleField(time0, time1);
385 switch(TemporalScheme) {
389 mTask = std::bind(&Advect::euler01, ph::_1, ph::_2, dt);
392 this->cook(
"Advecting level set using TVD_RK1", 1);
397 mTask = std::bind(&Advect::euler01, ph::_1, ph::_2, dt);
400 this->cook(
"Advecting level set using TVD_RK1 (step 1 of 2)", 1);
404 mTask = std::bind(&Advect::euler12, ph::_1, ph::_2, dt);
407 this->cook(
"Advecting level set using TVD_RK1 (step 2 of 2)", 1);
412 mTask = std::bind(&Advect::euler01, ph::_1, ph::_2, dt);
415 this->cook(
"Advecting level set using TVD_RK3 (step 1 of 3)", 1);
419 mTask = std::bind(&Advect::euler34, ph::_1, ph::_2, dt);
422 this->cook(
"Advecting level set using TVD_RK3 (step 2 of 3)", 2);
426 mTask = std::bind(&Advect::euler13, ph::_1, ph::_2, dt);
429 this->cook(
"Advecting level set using TVD_RK3 (step 3 of 3)", 2);
432 OPENVDB_THROW(ValueError,
"Temporal integration scheme not supported!");
436 time0 += isForward ? dt : -dt;
438 mParent.mTracker.leafs().removeAuxBuffers();
441 mParent.mTracker.track();
447 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
452 inline typename GridT::ValueType
453 LevelSetAdvection<GridT, FieldT, InterruptT>::
454 Advect<MapT, SpatialScheme, TemporalScheme>::
455 sampleField(ValueType time0, ValueType time1)
457 namespace ph = std::placeholders;
459 const int grainSize = mParent.mTracker.getGrainSize();
460 const size_t leafCount = mParent.mTracker.leafs().leafCount();
461 if (leafCount==0)
return ValueType(0.0);
464 size_t size=0, voxelCount=mParent.mTracker.leafs().getPrefixSum(mOffsets, size, grainSize);
467 if (mParent.mField.transform() == mParent.mTracker.grid().transform()) {
468 mTask = std::bind(&Advect::sampleAligned, ph::_1, ph::_2, time0, time1);
470 mTask = std::bind(&Advect::sampleXformed, ph::_1, ph::_2, time0, time1);
472 assert(voxelCount == mParent.mTracker.grid().activeVoxelCount());
473 mVelocity =
new VectorType[ voxelCount ];
474 this->cook(
"Sampling advection field");
477 ValueType maxAbsV = 0;
478 VectorType* v = mVelocity;
479 for (
size_t i = 0; i < voxelCount; ++i, ++v) {
480 maxAbsV =
math::Max(maxAbsV, ValueType(v->lengthSqr()));
485 #ifndef _MSC_VER // Visual C++ doesn't guarantee thread-safe initialization of local statics 488 const ValueType CFL = (TemporalScheme ==
math::TVD_RK1 ? ValueType(0.3) :
489 TemporalScheme == math::
TVD_RK2 ? ValueType(0.9) :
490 ValueType(1.0))/math::
Sqrt(ValueType(3.0));
491 const ValueType dt =
math::Abs(time1 - time0), dx = mParent.mTracker.voxelSize();
496 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
501 template<
bool Aligned>
503 LevelSetAdvection<GridT, FieldT, InterruptT>::
504 Advect<MapT, SpatialScheme, TemporalScheme>::
505 sample(
const LeafRange& range, ValueType time0, ValueType time1)
507 const bool isForward = time0 < time1;
508 using VoxelIterT =
typename LeafType::ValueOnCIter;
509 const MapT& map = *mMap;
510 const FieldT field( mParent.mField );
511 mParent.mTracker.checkInterrupter();
512 for (
typename LeafRange::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
513 VectorType* vel = mVelocity + mOffsets[ leafIter.pos() ];
514 for (VoxelIterT iter = leafIter->cbeginValueOn(); iter; ++iter, ++vel) {
515 const VectorType v = Aligned ? field(iter.getCoord(), time0) :
516 field(map.applyMap(iter.getCoord().asVec3d()), time0);
517 *vel = isForward ? v : -v;
523 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
529 LevelSetAdvection<GridT, FieldT, InterruptT>::
530 Advect<MapT, SpatialScheme, TemporalScheme>::
540 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
546 LevelSetAdvection<GridT, FieldT, InterruptT>::
547 Advect<MapT, SpatialScheme, TemporalScheme>::
548 cook(
const char* msg,
size_t swapBuffer)
550 mParent.mTracker.startInterrupter( msg );
552 const int grainSize = mParent.mTracker.getGrainSize();
553 const LeafRange range = mParent.mTracker.leafs().leafRange(grainSize);
555 grainSize == 0 ? (*this)(range) : tbb::parallel_for(range, *
this);
557 mParent.mTracker.leafs().swapLeafBuffer(swapBuffer, grainSize == 0);
559 mParent.mTracker.endInterrupter();
565 template<
typename Gr
idT,
typename FieldT,
typename InterruptT>
570 template <
int Nominator,
int Denominator>
572 LevelSetAdvection<GridT, FieldT, InterruptT>::
573 Advect<MapT, SpatialScheme, TemporalScheme>::
574 euler(
const LeafRange& range, ValueType dt,
Index phiBuffer,
Index resultBuffer)
576 using SchemeT = math::BIAS_SCHEME<SpatialScheme>;
577 using StencilT =
typename SchemeT::template ISStencil<GridType>::StencilType;
578 using VoxelIterT =
typename LeafType::ValueOnCIter;
579 using GradT = math::GradientBiased<MapT, SpatialScheme>;
581 static const ValueType Alpha = ValueType(Nominator)/ValueType(Denominator);
582 static const ValueType Beta = ValueType(1) - Alpha;
584 mParent.mTracker.checkInterrupter();
585 const MapT& map = *mMap;
586 StencilT stencil(mParent.mTracker.grid());
587 for (
typename LeafRange::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
588 const VectorType* vel = mVelocity + mOffsets[ leafIter.pos() ];
589 const ValueType* phi = leafIter.buffer(phiBuffer).data();
590 ValueType* result = leafIter.buffer(resultBuffer).data();
591 for (VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter, ++vel) {
592 const Index i = voxelIter.pos();
593 stencil.moveTo(voxelIter);
595 stencil.getValue() - dt * vel->dot(GradT::result(map, stencil, *vel));
596 result[i] = Nominator ? Alpha * phi[i] + Beta * a : a;
605 #endif // OPENVDB_TOOLS_LEVEL_SET_ADVECT_HAS_BEEN_INCLUDED
Performs multi-threaded interface tracking of narrow band level sets. This is the building-block for ...
Index32 Index
Definition: Types.h:61
Defines two simple wrapper classes for advection velocity fields as well as VelocitySampler and Veloc...
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition: Math.h:320
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:715
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:610
Definition: FiniteDifference.h:197
Definition: FiniteDifference.h:198
TemporalIntegrationScheme
Temporal integration schemes.
Definition: FiniteDifference.h:261
Definition: FiniteDifference.h:196
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:308
Definition: FiniteDifference.h:265
Definition: Exceptions.h:40
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:549
Definition: FiniteDifference.h:263
Definition: FiniteDifference.h:195
Coord Abs(const Coord &xyz)
Definition: Coord.h:513
static T value()
Definition: Math.h:124
Definition: Exceptions.h:92
BiasedGradientScheme
Biased Gradients are limited to non-centered differences.
Definition: FiniteDifference.h:192
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
Definition: FiniteDifference.h:194
Definition: FiniteDifference.h:264