Loading...
Searching...
No Matches
VolumeAdvect.h
Go to the documentation of this file.
// Copyright Contributors to the OpenVDB Project
// SPDX-License-Identifier: MPL-2.0
//
///////////////////////////////////////////////////////////////////////////
//
/// @author Ken Museth
///
/// @file tools/VolumeAdvect.h
///
/// @brief Sparse hyperbolic advection of volumes, e.g. a density or
/// velocity (vs a level set interface).
#ifndef OPENVDB_TOOLS_VOLUME_ADVECT_HAS_BEEN_INCLUDED
#define OPENVDB_TOOLS_VOLUME_ADVECT_HAS_BEEN_INCLUDED
#include <openvdb/Types.h>
#include <openvdb/math/Math.h>
#include <openvdb/util/NullInterrupter.h>
#include <openvdb/thread/Threading.h>
#include "Interpolation.h"// for Sampler
#include "VelocityFields.h" // for VelocityIntegrator
#include "Morphology.h"//for dilateActiveValues
#include "Prune.h"// for prune
#include "Statistics.h" // for extrema
#include <tbb/parallel_for.h>
#include <functional>
namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
namespace tools {
namespace Scheme {
/// @brief Numerical advections schemes.
enum SemiLagrangian { SEMI, MID, RK3, RK4, MAC, BFECC };
/// @brief Flux-limiters employed to stabilize the second-order
/// advection schemes MacCormack and BFECC.
enum Limiter { NO_LIMITER, CLAMP, REVERT };
}
/// @brief Performs advections of an arbitrary type of volume in a
/// static velocity field. The advections are performed by means
/// of various derivatives of Semi-Lagrangian integration, i.e.
/// backwards tracking along the hyperbolic characteristics
/// followed by interpolation.
///
/// @note Optionally a limiter can be combined with the higher-order
/// integration schemes MacCormack and BFECC. There are two
/// types of limiters (CLAMP and REVERT) that suppress
/// non-physical oscillations by means of either claminging or
/// reverting to a first-order schemes when the function is not
/// bounded by the cell values used for tri-linear interpolation.
///
/// @verbatim The supported integrations schemes:
///
/// ================================================================
/// | Lable | Accuracy | Integration Scheme | Interpolations |
/// | |Time/Space| | velocity/volume |
/// ================================================================
/// | SEMI | 1/1 | Semi-Lagrangian | 1/1 |
/// | MID | 2/1 | Mid-Point | 2/1 |
/// | RK3 | 3/1 | 3rd Order Runge-Kutta | 3/1 |
/// | RK4 | 4/1 | 4th Order Runge-Kutta | 4/1 |
/// | MAC | 2/2 | MacCormack | 2/2 |
/// | BFECC | 2/2 | BFECC | 3/2 |
/// ================================================================
/// @endverbatim
template<typename VelocityGridT = Vec3fGrid,
bool StaggeredVelocity = false,
typename InterrupterType = util::NullInterrupter>
class VolumeAdvection
{
public:
/// @brief Constructor
///
/// @param velGrid Velocity grid responsible for the (passive) advection.
/// @param interrupter Optional interrupter used to prematurely end computations.
///
/// @note The velocity field is assumed to be constant for the duration of the
/// advection.
VolumeAdvection(const VelocityGridT& velGrid, InterrupterType* interrupter = nullptr)
: mVelGrid(velGrid)
, mInterrupter(interrupter)
, mIntegrator( Scheme::SEMI )
, mLimiter( Scheme::CLAMP )
, mGrainSize( 128 )
, mSubSteps( 1 )
{
math::Extrema e = extrema(velGrid.cbeginValueAll(), /*threading*/true);
e.add(velGrid.background().length());
mMaxVelocity = e.max();
}
virtual ~VolumeAdvection()
{
}
/// @brief Return the spatial order of accuracy of the advection scheme
///
/// @note This is the optimal order in smooth regions. In
/// non-smooth regions the flux-limiter will drop the order of
/// accuracy to add numerical dissipation.
int spatialOrder() const { return (mIntegrator == Scheme::MAC ||
mIntegrator == Scheme::BFECC) ? 2 : 1; }
/// @brief Return the temporal order of accuracy of the advection scheme
///
/// @note This is the optimal order in smooth regions. In
/// non-smooth regions the flux-limiter will drop the order of
/// accuracy to add numerical dissipation.
int temporalOrder() const {
switch (mIntegrator) {
case Scheme::SEMI: return 1;
case Scheme::MID: return 2;
case Scheme::RK3: return 3;
case Scheme::RK4: return 4;
case Scheme::BFECC:return 2;
case Scheme::MAC: return 2;
}
return 0;//should never reach this point
}
/// @brief Set the integrator (see details in the table above)
void setIntegrator(Scheme::SemiLagrangian integrator) { mIntegrator = integrator; }
/// @brief Return the integrator (see details in the table above)
Scheme::SemiLagrangian getIntegrator() const { return mIntegrator; }
/// @brief Set the limiter (see details above)
void setLimiter(Scheme::Limiter limiter) { mLimiter = limiter; }
/// @brief Retrun the limiter (see details above)
Scheme::Limiter getLimiter() const { return mLimiter; }
/// @brief Return @c true if a limiter will be applied based on
/// the current settings.
bool isLimiterOn() const { return this->spatialOrder()>1 &&
mLimiter != Scheme::NO_LIMITER; }
/// @return the grain-size used for multi-threading
/// @note A grainsize of 0 implies serial execution
size_t getGrainSize() const { return mGrainSize; }
/// @brief Set the grain-size used for multi-threading
/// @note A grainsize of 0 disables multi-threading
/// @warning A small grainsize can degrade performance,
/// both in terms of time and memory footprint!
void setGrainSize(size_t grainsize) { mGrainSize = grainsize; }
/// @return the number of sub-steps per integration (always larger
/// than or equal to 1).
int getSubSteps() const { return mSubSteps; }
/// @brief Set the number of sub-steps per integration.
/// @note The only reason to increase the sub-step above its
/// default value of one is to reduce the memory footprint
/// due to significant dilation. Values smaller than 1 will
/// be clamped to 1!
void setSubSteps(int substeps) { mSubSteps = math::Max(1, substeps); }
/// @brief Return the maximum magnitude of the velocity in the
/// advection velocity field defined during construction.
double getMaxVelocity() const { return mMaxVelocity; }
/// @return Returns the maximum distance in voxel units of @a inGrid
/// that a particle can travel in the time-step @a dt when advected
/// in the velocity field defined during construction.
///
/// @details This method is useful when dilating sparse volume
/// grids to pad boundary regions. Excessive dilation can be
/// computationally expensive so use this method to prevent
/// or warn against run-away computation.
///
/// @throw RuntimeError if @a inGrid does not have uniform voxels.
template<typename VolumeGridT>
int getMaxDistance(const VolumeGridT& inGrid, double dt) const
{
if (!inGrid.hasUniformVoxels()) {
OPENVDB_THROW(RuntimeError, "Volume grid does not have uniform voxels!");
}
const double d = mMaxVelocity*math::Abs(dt)/inGrid.voxelSize()[0];
return static_cast<int>( math::RoundUp(d) );
}
/// @return Returns a new grid that is the result of passive advection
/// of all the active values the input grid by @a timeStep.
///
/// @param inGrid The input grid to be advected (unmodified)
/// @param timeStep Time-step of the Runge-Kutta integrator.
///
/// @details This method will advect all of the active values in
/// the input @a inGrid. To achieve this a
/// deep-copy is dilated to account for the material
/// transport. This dilation step can be slow for large
/// time steps @a dt or a velocity field with large magnitudes.
///
/// @warning If the VolumeSamplerT is of higher order than one
/// (i.e. tri-linear interpolation) instabilities are
/// known to occur. To suppress those monotonicity
/// constrains or flux-limiters need to be applies.
///
/// @throw RuntimeError if @a inGrid does not have uniform voxels.
template<typename VolumeGridT,
typename VolumeSamplerT>//only C++11 allows for a default argument
typename VolumeGridT::Ptr advect(const VolumeGridT& inGrid, double timeStep)
{
typename VolumeGridT::Ptr outGrid = inGrid.deepCopy();
const double dt = timeStep/mSubSteps;
const int n = this->getMaxDistance(inGrid, dt);
dilateActiveValues( outGrid->tree(), n, NN_FACE, EXPAND_TILES);
this->template cook<VolumeGridT, VolumeSamplerT>(*outGrid, inGrid, dt);
for (int step = 1; step < mSubSteps; ++step) {
typename VolumeGridT::Ptr tmpGrid = outGrid->deepCopy();
dilateActiveValues( tmpGrid->tree(), n, NN_FACE, EXPAND_TILES);
this->template cook<VolumeGridT, VolumeSamplerT>(*tmpGrid, *outGrid, dt);
outGrid.swap( tmpGrid );
}
return outGrid;
}
/// @return Returns a new grid that is the result of
/// passive advection of the active values in @a inGrid
/// that intersect the active values in @c mask. The time
/// of the output grid is incremented by @a timeStep.
///
/// @param inGrid The input grid to be advected (unmodified).
/// @param mask The mask of active values defining the active voxels
/// in @c inGrid on which to perform advection. Only
/// if a value is active in both grids will it be modified.
/// @param timeStep Time-step for a single Runge-Kutta integration step.
///
///
/// @details This method will advect all of the active values in
/// the input @a inGrid that intersects with the
/// active values in @a mask. To achieve this a
/// deep-copy is dilated to account for the material
/// transport and finally cropped to the intersection
/// with @a mask. The dilation step can be slow for large
/// time steps @a dt or fast moving velocity fields.
///
/// @warning If the VolumeSamplerT is of higher order the one
/// (i.e. tri-linear interpolation) instabilities are
/// known to occur. To suppress those monotonicity
/// constrains or flux-limiters need to be applies.
///
/// @throw RuntimeError if @a inGrid is not aligned with @a mask
/// or if its voxels are not uniform.
template<typename VolumeGridT,
typename MaskGridT,
typename VolumeSamplerT>//only C++11 allows for a default argument
typename VolumeGridT::Ptr advect(const VolumeGridT& inGrid, const MaskGridT& mask, double timeStep)
{
if (inGrid.transform() != mask.transform()) {
OPENVDB_THROW(RuntimeError, "Volume grid and mask grid are misaligned! Consider "
"resampling either of the two grids into the index space of the other.");
}
typename VolumeGridT::Ptr outGrid = inGrid.deepCopy();
const double dt = timeStep/mSubSteps;
const int n = this->getMaxDistance(inGrid, dt);
dilateActiveValues( outGrid->tree(), n, NN_FACE, EXPAND_TILES);
outGrid->topologyIntersection( mask );
pruneInactive( outGrid->tree(), mGrainSize>0, mGrainSize );
this->template cook<VolumeGridT, VolumeSamplerT>(*outGrid, inGrid, dt);
outGrid->topologyUnion( inGrid );
for (int step = 1; step < mSubSteps; ++step) {
typename VolumeGridT::Ptr tmpGrid = outGrid->deepCopy();
dilateActiveValues( tmpGrid->tree(), n, NN_FACE, EXPAND_TILES);
tmpGrid->topologyIntersection( mask );
pruneInactive( tmpGrid->tree(), mGrainSize>0, mGrainSize );
this->template cook<VolumeGridT, VolumeSamplerT>(*tmpGrid, *outGrid, dt);
tmpGrid->topologyUnion( inGrid );
outGrid.swap( tmpGrid );
}
return outGrid;
}
private:
// disallow copy construction and copy by assignment!
VolumeAdvection(const VolumeAdvection&);// not implemented
VolumeAdvection& operator=(const VolumeAdvection&);// not implemented
void start(const char* str) const
{
if (mInterrupter) mInterrupter->start(str);
}
void stop() const
{
if (mInterrupter) mInterrupter->end();
}
bool interrupt() const
{
if (mInterrupter && util::wasInterrupted(mInterrupter)) {
thread::cancelGroupExecution();
return true;
}
return false;
}
template<typename VolumeGridT, typename VolumeSamplerT>
void cook(VolumeGridT& outGrid, const VolumeGridT& inGrid, double dt)
{
switch (mIntegrator) {
case Scheme::SEMI: {
Advect<VolumeGridT, 1, VolumeSamplerT> adv(inGrid, *this);
adv.cook(outGrid, dt);
break;
}
case Scheme::MID: {
Advect<VolumeGridT, 2, VolumeSamplerT> adv(inGrid, *this);
adv.cook(outGrid, dt);
break;
}
case Scheme::RK3: {
Advect<VolumeGridT, 3, VolumeSamplerT> adv(inGrid, *this);
adv.cook(outGrid, dt);
break;
}
case Scheme::RK4: {
Advect<VolumeGridT, 4, VolumeSamplerT> adv(inGrid, *this);
adv.cook(outGrid, dt);
break;
}
case Scheme::BFECC: {
Advect<VolumeGridT, 1, VolumeSamplerT> adv(inGrid, *this);
adv.cook(outGrid, dt);
break;
}
case Scheme::MAC: {
Advect<VolumeGridT, 1, VolumeSamplerT> adv(inGrid, *this);
adv.cook(outGrid, dt);
break;
}
default:
OPENVDB_THROW(ValueError, "Spatial difference scheme not supported!");
}
pruneInactive(outGrid.tree(), mGrainSize>0, mGrainSize);
}
// Private class that implements the multi-threaded advection
template<typename VolumeGridT, size_t OrderRK, typename SamplerT> struct Advect;
// Private member data of VolumeAdvection
const VelocityGridT& mVelGrid;
double mMaxVelocity;
InterrupterType* mInterrupter;
Scheme::SemiLagrangian mIntegrator;
Scheme::Limiter mLimiter;
size_t mGrainSize;
int mSubSteps;
};//end of VolumeAdvection class
// Private class that implements the multi-threaded advection
template<typename VelocityGridT, bool StaggeredVelocity, typename InterrupterType>
template<typename VolumeGridT, size_t OrderRK, typename SamplerT>
struct VolumeAdvection<VelocityGridT, StaggeredVelocity, InterrupterType>::Advect
{
using TreeT = typename VolumeGridT::TreeType;
using AccT = typename VolumeGridT::ConstAccessor;
using ValueT = typename TreeT::ValueType;
using LeafManagerT = typename tree::LeafManager<TreeT>;
using LeafNodeT = typename LeafManagerT::LeafNodeType;
using LeafRangeT = typename LeafManagerT::LeafRange;
using VelocityIntegratorT = VelocityIntegrator<VelocityGridT, StaggeredVelocity>;
using RealT = typename VelocityIntegratorT::ElementType;
using VoxelIterT = typename TreeT::LeafNodeType::ValueOnIter;
Advect(const VolumeGridT& inGrid, const VolumeAdvection& parent)
: mTask(nullptr)
, mInGrid(&inGrid)
, mVelocityInt(parent.mVelGrid)
, mParent(&parent)
{
}
inline void cook(const LeafRangeT& range)
{
if (mParent->mGrainSize > 0) {
tbb::parallel_for(range, *this);
} else {
(*this)(range);
}
}
void operator()(const LeafRangeT& range) const
{
assert(mTask);
mTask(const_cast<Advect*>(this), range);
}
void cook(VolumeGridT& outGrid, double time_step)
{
namespace ph = std::placeholders;
mParent->start("Advecting volume");
LeafManagerT manager(outGrid.tree(), mParent->spatialOrder()==2 ? 1 : 0);
const LeafRangeT range = manager.leafRange(mParent->mGrainSize);
const RealT dt = static_cast<RealT>(-time_step);//method of characteristics backtracks
if (mParent->mIntegrator == Scheme::MAC) {
mTask = std::bind(&Advect::rk, ph::_1, ph::_2, dt, 0, mInGrid);//out[0]=forward
this->cook(range);
mTask = std::bind(&Advect::rk, ph::_1, ph::_2,-dt, 1, &outGrid);//out[1]=backward
this->cook(range);
mTask = std::bind(&Advect::mac, ph::_1, ph::_2);//out[0] = out[0] + (in[0] - out[1])/2
this->cook(range);
} else if (mParent->mIntegrator == Scheme::BFECC) {
mTask = std::bind(&Advect::rk, ph::_1, ph::_2, dt, 0, mInGrid);//out[0]=forward
this->cook(range);
mTask = std::bind(&Advect::rk, ph::_1, ph::_2,-dt, 1, &outGrid);//out[1]=backward
this->cook(range);
mTask = std::bind(&Advect::bfecc, ph::_1, ph::_2);//out[0] = (3*in[0] - out[1])/2
this->cook(range);
mTask = std::bind(&Advect::rk, ph::_1, ph::_2, dt, 1, &outGrid);//out[1]=forward
this->cook(range);
manager.swapLeafBuffer(1);// out[0] = out[1]
} else {// SEMI, MID, RK3 and RK4
mTask = std::bind(&Advect::rk, ph::_1, ph::_2, dt, 0, mInGrid);//forward
this->cook(range);
}
if (mParent->spatialOrder()==2) manager.removeAuxBuffers();
mTask = std::bind(&Advect::limiter, ph::_1, ph::_2, dt);// out[0] = limiter( out[0] )
this->cook(range);
mParent->stop();
}
// Last step of the MacCormack scheme: out[0] = out[0] + (in[0] - out[1])/2
void mac(const LeafRangeT& range) const
{
if (mParent->interrupt()) return;
assert( mParent->mIntegrator == Scheme::MAC );
AccT acc = mInGrid->getAccessor();
for (typename LeafRangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
ValueT* out0 = leafIter.buffer( 0 ).data();// forward
const ValueT* out1 = leafIter.buffer( 1 ).data();// backward
const LeafNodeT* leaf = acc.probeConstLeaf( leafIter->origin() );
if (leaf != nullptr) {
const ValueT* in0 = leaf->buffer().data();
for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
const Index i = voxelIter.pos();
out0[i] += RealT(0.5) * ( in0[i] - out1[i] );
}
} else {
for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
const Index i = voxelIter.pos();
out0[i] += RealT(0.5) * ( acc.getValue(voxelIter.getCoord()) - out1[i] );
}//loop over active voxels
}
}//loop over leaf nodes
}
// Intermediate step in the BFECC scheme: out[0] = (3*in[0] - out[1])/2
void bfecc(const LeafRangeT& range) const
{
if (mParent->interrupt()) return;
assert( mParent->mIntegrator == Scheme::BFECC );
AccT acc = mInGrid->getAccessor();
for (typename LeafRangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
ValueT* out0 = leafIter.buffer( 0 ).data();// forward
const ValueT* out1 = leafIter.buffer( 1 ).data();// backward
const LeafNodeT* leaf = acc.probeConstLeaf(leafIter->origin());
if (leaf != nullptr) {
const ValueT* in0 = leaf->buffer().data();
for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
const Index i = voxelIter.pos();
out0[i] = RealT(0.5)*( RealT(3)*in0[i] - out1[i] );
}//loop over active voxels
} else {
for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
const Index i = voxelIter.pos();
out0[i] = RealT(0.5)*( RealT(3)*acc.getValue(voxelIter.getCoord()) - out1[i] );
}//loop over active voxels
}
}//loop over leaf nodes
}
// Semi-Lagrangian integration with Runge-Kutta of various orders (1->4)
void rk(const LeafRangeT& range, RealT dt, size_t n, const VolumeGridT* grid) const
{
if (mParent->interrupt()) return;
const math::Transform& xform = mInGrid->transform();
AccT acc = grid->getAccessor();
for (typename LeafRangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
ValueT* phi = leafIter.buffer( n ).data();
for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
ValueT& value = phi[voxelIter.pos()];
Vec3d wPos = xform.indexToWorld(voxelIter.getCoord());
mVelocityInt.template rungeKutta<OrderRK, Vec3d>(dt, wPos);
value = SamplerT::sample(acc, xform.worldToIndex(wPos));
}//loop over active voxels
}//loop over leaf nodes
}
void limiter(const LeafRangeT& range, RealT dt) const
{
if (mParent->interrupt()) return;
const bool doLimiter = mParent->isLimiterOn();
const bool doClamp = mParent->mLimiter == Scheme::CLAMP;
ValueT data[2][2][2], vMin, vMax;
const math::Transform& xform = mInGrid->transform();
AccT acc = mInGrid->getAccessor();
const ValueT backg = mInGrid->background();
for (typename LeafRangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
ValueT* phi = leafIter.buffer( 0 ).data();
for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
ValueT& value = phi[voxelIter.pos()];
if ( doLimiter ) {
assert(OrderRK == 1);
Vec3d wPos = xform.indexToWorld(voxelIter.getCoord());
mVelocityInt.template rungeKutta<1, Vec3d>(dt, wPos);// Explicit Euler
Vec3d iPos = xform.worldToIndex(wPos);
Coord ijk = Coord::floor( iPos );
BoxSampler::getValues(data, acc, ijk);
BoxSampler::extrema(data, vMin, vMax);
if ( doClamp ) {
value = math::Clamp( value, vMin, vMax);
} else if (value < vMin || value > vMax ) {
iPos -= Vec3R(ijk[0], ijk[1], ijk[2]);//unit coordinates
value = BoxSampler::trilinearInterpolation( data, iPos );
}
}
if (math::isApproxEqual(value, backg, math::Delta<ValueT>::value())) {
value = backg;
leafIter->setValueOff( voxelIter.pos() );
}
}//loop over active voxels
}//loop over leaf nodes
}
// Public member data of the private Advect class
typename std::function<void (Advect*, const LeafRangeT&)> mTask;
const VolumeGridT* mInGrid;
const VelocityIntegratorT mVelocityInt;// lightweight!
const VolumeAdvection* mParent;
};// end of private member class Advect
////////////////////////////////////////
// Explicit Template Instantiation
#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
#ifdef OPENVDB_INSTANTIATE_VOLUMEADVECT
#include <openvdb/util/ExplicitInstantiation.h>
#endif
OPENVDB_INSTANTIATE_CLASS VolumeAdvection<Vec3SGrid, true, util::NullInterrupter>;
OPENVDB_INSTANTIATE_CLASS VolumeAdvection<Vec3SGrid, false, util::NullInterrupter>;
OPENVDB_INSTANTIATE FloatGrid::Ptr VolumeAdvection<Vec3SGrid, true, util::NullInterrupter>::advect<FloatGrid, Sampler<1, false>>(const FloatGrid&, double);
OPENVDB_INSTANTIATE DoubleGrid::Ptr VolumeAdvection<Vec3SGrid, true, util::NullInterrupter>::advect<DoubleGrid, Sampler<1, false>>(const DoubleGrid&, double);
OPENVDB_INSTANTIATE Vec3SGrid::Ptr VolumeAdvection<Vec3SGrid, true, util::NullInterrupter>::advect<Vec3SGrid, Sampler<1, false>>(const Vec3SGrid&, double);
OPENVDB_INSTANTIATE FloatGrid::Ptr VolumeAdvection<Vec3SGrid, false, util::NullInterrupter>::advect<FloatGrid, Sampler<1, false>>(const FloatGrid&, double);
OPENVDB_INSTANTIATE DoubleGrid::Ptr VolumeAdvection<Vec3SGrid, false, util::NullInterrupter>::advect<DoubleGrid, Sampler<1, false>>(const DoubleGrid&, double);
OPENVDB_INSTANTIATE Vec3SGrid::Ptr VolumeAdvection<Vec3SGrid, false, util::NullInterrupter>::advect<Vec3SGrid, Sampler<1, false>>(const Vec3SGrid&, double);
#endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
} // namespace tools
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb
#endif // OPENVDB_TOOLS_VOLUME_ADVECT_HAS_BEEN_INCLUDED
ExplicitInstantiation.h
value
ValueT value
Definition GridBuilder.h:1290
Interpolation.h
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Morphology.h
Implementation of morphological dilation and erosion.
NullInterrupter.h
Prune.h
Defined various multi-threaded utility functions for trees.
Statistics.h
Functions to efficiently compute histograms, extrema (min/max) and statistics (mean,...
VelocityFields.h
Defines two simple wrapper classes for advection velocity fields as well as VelocitySampler and Veloc...
openvdb::v10_0::RuntimeError
Definition Exceptions.h:63
openvdb::v10_0::math::Extrema
This class computes the minimum and maximum values of a population of floating-point values.
Definition Stats.h:93
openvdb::v10_0::math::Extrema::add
void add(double val)
Add a single sample.
Definition Stats.h:106
openvdb::v10_0::math::Extrema::max
double max() const
Return the maximum value.
Definition Stats.h:128
openvdb::v10_0::tools::VolumeAdvection
Performs advections of an arbitrary type of volume in a static velocity field. The advections are per...
Definition VolumeAdvect.h:76
openvdb::v10_0::tools::VolumeAdvection::~VolumeAdvection
virtual ~VolumeAdvection()
Definition VolumeAdvect.h:99
openvdb::v10_0::tools::VolumeAdvection::getIntegrator
Scheme::SemiLagrangian getIntegrator() const
Return the integrator (see details in the table above).
Definition VolumeAdvect.h:132
openvdb::v10_0::tools::VolumeAdvection::getSubSteps
int getSubSteps() const
Definition VolumeAdvect.h:157
openvdb::v10_0::tools::VolumeAdvection::getLimiter
Scheme::Limiter getLimiter() const
Retrun the limiter (see details above).
Definition VolumeAdvect.h:138
openvdb::v10_0::tools::VolumeAdvection::setSubSteps
void setSubSteps(int substeps)
Set the number of sub-steps per integration.
Definition VolumeAdvect.h:164
openvdb::v10_0::tools::VolumeAdvection::isLimiterOn
bool isLimiterOn() const
Return true if a limiter will be applied based on the current settings.
Definition VolumeAdvect.h:142
openvdb::v10_0::tools::VolumeAdvection::spatialOrder
int spatialOrder() const
Return the spatial order of accuracy of the advection scheme.
Definition VolumeAdvect.h:108
openvdb::v10_0::tools::VolumeAdvection::setLimiter
void setLimiter(Scheme::Limiter limiter)
Set the limiter (see details above).
Definition VolumeAdvect.h:135
openvdb::v10_0::tools::VolumeAdvection::advect
VolumeGridT::Ptr advect(const VolumeGridT &inGrid, double timeStep)
Definition VolumeAdvect.h:210
openvdb::v10_0::tools::VolumeAdvection::advect
VolumeGridT::Ptr advect(const VolumeGridT &inGrid, const MaskGridT &mask, double timeStep)
Definition VolumeAdvect.h:257
openvdb::v10_0::tools::VolumeAdvection::VolumeAdvection
VolumeAdvection(const VelocityGridT &velGrid, InterrupterType *interrupter=nullptr)
Constructor.
Definition VolumeAdvect.h:86
openvdb::v10_0::tools::VolumeAdvection::getGrainSize
size_t getGrainSize() const
Definition VolumeAdvect.h:147
openvdb::v10_0::tools::VolumeAdvection::getMaxVelocity
double getMaxVelocity() const
Return the maximum magnitude of the velocity in the advection velocity field defined during construct...
Definition VolumeAdvect.h:168
openvdb::v10_0::tools::VolumeAdvection::temporalOrder
int temporalOrder() const
Return the temporal order of accuracy of the advection scheme.
Definition VolumeAdvect.h:116
openvdb::v10_0::tools::VolumeAdvection::setIntegrator
void setIntegrator(Scheme::SemiLagrangian integrator)
Set the integrator (see details in the table above).
Definition VolumeAdvect.h:129
openvdb::v10_0::tools::VolumeAdvection::getMaxDistance
int getMaxDistance(const VolumeGridT &inGrid, double dt) const
Definition VolumeAdvect.h:181
openvdb::v10_0::tools::VolumeAdvection::setGrainSize
void setGrainSize(size_t grainsize)
Set the grain-size used for multi-threading.
Definition VolumeAdvect.h:153
openvdb::v10_0::math::RoundUp
float RoundUp(float x)
Return x rounded up to the nearest integer.
Definition Math.h:787
openvdb::v10_0::math::Max
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition Math.h:595
openvdb::v10_0::math::Vec3d
Vec3< double > Vec3d
Definition Vec3.h:664
openvdb::v10_0::math::Abs
Coord Abs(const Coord &xyz)
Definition Coord.h:515
openvdb::v10_0::tools::Scheme
Definition VolumeAdvect.h:36
openvdb::v10_0::tools::Scheme::Limiter
Limiter
Flux-limiters employed to stabilize the second-order advection schemes MacCormack and BFECC.
Definition VolumeAdvect.h:41
openvdb::v10_0::tools::Scheme::REVERT
@ REVERT
Definition VolumeAdvect.h:41
openvdb::v10_0::tools::Scheme::CLAMP
@ CLAMP
Definition VolumeAdvect.h:41
openvdb::v10_0::tools::Scheme::NO_LIMITER
@ NO_LIMITER
Definition VolumeAdvect.h:41
openvdb::v10_0::tools::Scheme::SemiLagrangian
SemiLagrangian
Numerical advections schemes.
Definition VolumeAdvect.h:38
openvdb::v10_0::tools::Scheme::MID
@ MID
Definition VolumeAdvect.h:38
openvdb::v10_0::tools::Scheme::RK4
@ RK4
Definition VolumeAdvect.h:38
openvdb::v10_0::tools::Scheme::SEMI
@ SEMI
Definition VolumeAdvect.h:38
openvdb::v10_0::tools::Scheme::RK3
@ RK3
Definition VolumeAdvect.h:38
openvdb::v10_0::tools::Scheme::MAC
@ MAC
Definition VolumeAdvect.h:38
openvdb::v10_0::tools::Scheme::BFECC
@ BFECC
Definition VolumeAdvect.h:38
openvdb::v10_0::tools::NN_FACE
@ NN_FACE
Definition Morphology.h:59
openvdb::v10_0::tools::dilateActiveValues
void dilateActiveValues(TreeOrLeafManagerT &tree, const int iterations=1, const NearestNeighbors nn=NN_FACE, const TilePolicy mode=PRESERVE_TILES, const bool threaded=true)
Topologically dilate all active values (i.e. both voxels and tiles) in a tree using one of three near...
Definition Morphology.h:1056
openvdb::v10_0::tools::extrema
math::Extrema extrema(const IterT &iter, bool threaded=true)
Iterate over a scalar grid and compute extrema (min/max) of the values of the voxels that are visited...
Definition Statistics.h:354
openvdb::v10_0::tools::EXPAND_TILES
@ EXPAND_TILES
Definition Morphology.h:81
openvdb::v10_0::tools::pruneInactive
void pruneInactive(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with background tiles any nodes whose values are a...
Definition Prune.h:355
openvdb::v10_0::Index
Index32 Index
Definition Types.h:54
openvdb::v10_0::FloatGrid
Grid< FloatTree > FloatGrid
Definition openvdb.h:75
openvdb::v10_0::Vec3fGrid
Vec3SGrid Vec3fGrid
Definition openvdb.h:85
openvdb::v10_0::Vec3SGrid
Grid< Vec3STree > Vec3SGrid
Definition openvdb.h:81
openvdb::v10_0::Vec3R
math::Vec3< Real > Vec3R
Definition Types.h:72
openvdb::v10_0::DoubleGrid
Grid< DoubleTree > DoubleGrid
Definition openvdb.h:74
openvdb
Definition Exceptions.h:13
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Types.h
openvdb::v10_0::util::NullInterrupter
Base class for interrupters.
Definition NullInterrupter.h:26
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212
OPENVDB_INSTANTIATE_CLASS
#define OPENVDB_INSTANTIATE_CLASS
Definition version.h.in:153
OPENVDB_INSTANTIATE
#define OPENVDB_INSTANTIATE
Definition version.h.in:152