diff options
Diffstat (limited to 'extern/mantaflow/preprocessed/fluidsolver.cpp')
-rw-r--r-- | extern/mantaflow/preprocessed/fluidsolver.cpp | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/extern/mantaflow/preprocessed/fluidsolver.cpp b/extern/mantaflow/preprocessed/fluidsolver.cpp new file mode 100644 index 00000000000..814d5444b15 --- /dev/null +++ b/extern/mantaflow/preprocessed/fluidsolver.cpp @@ -0,0 +1,397 @@ + + +// DO NOT EDIT ! +// This file is generated using the MantaFlow preprocessor (prep generate). + +/****************************************************************************** + * + * MantaFlow fluid solver framework + * Copyright 2011 Tobias Pfaff, Nils Thuerey + * + * This program is free software, distributed under the terms of the + * Apache License, Version 2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Main class for the fluid solver + * + ******************************************************************************/ + +#include "fluidsolver.h" +#include "grid.h" +#include <sstream> +#include <fstream> + +using namespace std; +namespace Manta { + +//****************************************************************************** +// Gridstorage-related members + +template<class T> void FluidSolver::GridStorage<T>::free() +{ + if (used != 0) + errMsg("can't clean grid cache, some grids are still in use"); + for (size_t i = 0; i < grids.size(); i++) + delete[] grids[i]; + grids.clear(); +} +template<class T> T *FluidSolver::GridStorage<T>::get(Vec3i size) +{ + if ((int)grids.size() <= used) { + debMsg("FluidSolver::GridStorage::get Allocating new " << size.x << "," << size.y << "," + << size.z << " ", + 3); + grids.push_back(new T[(long long)(size.x) * size.y * size.z]); + } + if (used > 200) + errMsg("too many temp grids used -- are they released properly ?"); + return grids[used++]; +} +template<class T> void FluidSolver::GridStorage<T>::release(T *ptr) +{ + // rewrite pointer, as it may have changed due to swap operations + used--; + if (used < 0) + errMsg("temp grid inconsistency"); + grids[used] = ptr; +} + +template<> int *FluidSolver::getGridPointer<int>() +{ + return mGridsInt.get(mGridSize); +} +template<> Real *FluidSolver::getGridPointer<Real>() +{ + return mGridsReal.get(mGridSize); +} +template<> Vec3 *FluidSolver::getGridPointer<Vec3>() +{ + return mGridsVec.get(mGridSize); +} +template<> Vec4 *FluidSolver::getGridPointer<Vec4>() +{ + return mGridsVec4.get(mGridSize); +} +template<> void FluidSolver::freeGridPointer<int>(int *ptr) +{ + mGridsInt.release(ptr); +} +template<> void FluidSolver::freeGridPointer<Real>(Real *ptr) +{ + mGridsReal.release(ptr); +} +template<> void FluidSolver::freeGridPointer<Vec3>(Vec3 *ptr) +{ + mGridsVec.release(ptr); +} +template<> void FluidSolver::freeGridPointer<Vec4>(Vec4 *ptr) +{ + mGridsVec4.release(ptr); +} + +// 4d data (work around for now, convert to 1d length) + +template<> int *FluidSolver::getGrid4dPointer<int>() +{ + return mGrids4dInt.get(Vec3i(mGridSize[0] * mGridSize[1], mGridSize[2], mFourthDim)); +} +template<> Real *FluidSolver::getGrid4dPointer<Real>() +{ + return mGrids4dReal.get(Vec3i(mGridSize[0] * mGridSize[1], mGridSize[2], mFourthDim)); +} +template<> Vec3 *FluidSolver::getGrid4dPointer<Vec3>() +{ + return mGrids4dVec.get(Vec3i(mGridSize[0] * mGridSize[1], mGridSize[2], mFourthDim)); +} +template<> Vec4 *FluidSolver::getGrid4dPointer<Vec4>() +{ + return mGrids4dVec4.get(Vec3i(mGridSize[0] * mGridSize[1], mGridSize[2], mFourthDim)); +} +template<> void FluidSolver::freeGrid4dPointer<int>(int *ptr) +{ + mGrids4dInt.release(ptr); +} +template<> void FluidSolver::freeGrid4dPointer<Real>(Real *ptr) +{ + mGrids4dReal.release(ptr); +} +template<> void FluidSolver::freeGrid4dPointer<Vec3>(Vec3 *ptr) +{ + mGrids4dVec.release(ptr); +} +template<> void FluidSolver::freeGrid4dPointer<Vec4>(Vec4 *ptr) +{ + mGrids4dVec4.release(ptr); +} + +//****************************************************************************** +// FluidSolver members + +FluidSolver::FluidSolver(Vec3i gridsize, int dim, int fourthDim) + : PbClass(this), + mDt(1.0), + mTimeTotal(0.), + mFrame(0), + mCflCond(1000), + mDtMin(1.), + mDtMax(1.), + mFrameLength(1.), + mGridSize(gridsize), + mDim(dim), + mTimePerFrame(0.), + mLockDt(false), + mFourthDim(fourthDim) +{ + if (dim == 4 && mFourthDim > 0) + errMsg("Don't create 4D solvers, use 3D with fourth-dim parameter >0 instead."); + assertMsg(dim == 2 || dim == 3, "Only 2D and 3D solvers allowed."); + assertMsg(dim != 2 || gridsize.z == 1, "Trying to create 2D solver with size.z != 1"); +} + +FluidSolver::~FluidSolver() +{ + mGridsInt.free(); + mGridsReal.free(); + mGridsVec.free(); + mGridsVec4.free(); + + mGrids4dInt.free(); + mGrids4dReal.free(); + mGrids4dVec.free(); + mGrids4dVec4.free(); +} + +PbClass *FluidSolver::create(PbType t, PbTypeVec T, const string &name) +{ +#if NOPYTHON != 1 + _args.add("nocheck", true); + if (t.str() == "") + errMsg( + "Need to specify object type. Use e.g. Solver.create(FlagGrid, ...) or " + "Solver.create(type=FlagGrid, ...)"); + + PbClass *ret = PbClass::createPyObject(t.str() + T.str(), name, _args, this); +#else + PbClass *ret = NULL; +#endif + return ret; +} + +void FluidSolver::step() +{ + // update simulation time with adaptive time stepping + // (use eps value to prevent roundoff errors) + mTimePerFrame += mDt; + mTimeTotal += mDt; + + if ((mTimePerFrame + VECTOR_EPSILON) > mFrameLength) { + mFrame++; + + // re-calc total time, prevent drift... + mTimeTotal = (double)mFrame * mFrameLength; + mTimePerFrame = 0.; + mLockDt = false; + } + + updateQtGui(true, mFrame, mTimeTotal, "FluidSolver::step"); +} + +void FluidSolver::printMemInfo() +{ + std::ostringstream msg; + msg << "Allocated grids: int " << mGridsInt.used << "/" << mGridsInt.grids.size() << ", "; + msg << " real " << mGridsReal.used << "/" << mGridsReal.grids.size() << ", "; + msg << " vec3 " << mGridsVec.used << "/" << mGridsVec.grids.size() << ". "; + msg << " vec4 " << mGridsVec4.used << "/" << mGridsVec4.grids.size() << ". "; + if (supports4D()) { + msg << "Allocated 4d grids: int " << mGrids4dInt.used << "/" << mGrids4dInt.grids.size() + << ", "; + msg << " real " << mGrids4dReal.used << "/" << mGrids4dReal.grids.size() + << ", "; + msg << " vec3 " << mGrids4dVec.used << "/" << mGrids4dVec.grids.size() + << ". "; + msg << " vec4 " << mGrids4dVec4.used << "/" << mGrids4dVec4.grids.size() + << ". "; + } + printf("%s\n", msg.str().c_str()); +} + +//! warning, uses 10^-4 epsilon values, thus only use around "regular" FPS time scales, e.g. 30 +//! frames per time unit pass max magnitude of current velocity as maxvel, not yet scaled by dt! +void FluidSolver::adaptTimestep(Real maxVel) +{ + const Real mvt = maxVel * mDt; + if (!mLockDt) { + // calculate current timestep from maxvel, clamp range + mDt = std::max(std::min(mDt * (Real)(mCflCond / (mvt + 1e-05)), mDtMax), mDtMin); + if ((mTimePerFrame + mDt * 1.05) > mFrameLength) { + // within 5% of full step? add epsilon to prevent roundoff errors... + mDt = (mFrameLength - mTimePerFrame) + 1e-04; + } + else if ((mTimePerFrame + mDt + mDtMin) > mFrameLength || + (mTimePerFrame + (mDt * 1.25)) > mFrameLength) { + // avoid tiny timesteps and strongly varying ones, do 2 medium size ones if necessary... + mDt = (mFrameLength - mTimePerFrame + 1e-04) * 0.5; + mLockDt = true; + } + } + debMsg("Frame " << mFrame << ", max vel per step: " << mvt << " , dt: " << mDt << ", frame time " + << mTimePerFrame << "/" << mFrameLength << "; lock:" << mLockDt, + 2); + + // sanity check + assertMsg((mDt > (mDtMin / 2.)), "Invalid dt encountered! Shouldnt happen..."); +} + +//****************************************************************************** +// Generic helpers (no PYTHON funcs in general.cpp, thus they're here...) + +//! helper to unify printing from python scripts and printing internal messages (optionally pass +//! debug level to control amount of output) +void mantaMsg(const std::string &out, int level = 1) +{ + debMsg(out, level); +} +static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds) +{ + try { + PbArgs _args(_linargs, _kwds); + FluidSolver *parent = _args.obtainParent(); + bool noTiming = _args.getOpt<bool>("notiming", -1, 0); + pbPreparePlugin(parent, "mantaMsg", !noTiming); + PyObject *_retval = 0; + { + ArgLocker _lock; + const std::string &out = _args.get<std::string>("out", 0, &_lock); + int level = _args.getOpt<int>("level", 1, 1, &_lock); + _retval = getPyNone(); + mantaMsg(out, level); + _args.check(); + } + pbFinalizePlugin(parent, "mantaMsg", !noTiming); + return _retval; + } + catch (std::exception &e) { + pbSetError("mantaMsg", e.what()); + return 0; + } +} +static const Pb::Register _RP_mantaMsg("", "mantaMsg", _W_0); +extern "C" { +void PbRegister_mantaMsg() +{ + KEEP_UNUSED(_RP_mantaMsg); +} +} + +std::string printBuildInfo() +{ + string infoString = buildInfoString(); + debMsg("Build info: " << infoString.c_str() << " ", 1); + return infoString; +} +static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds) +{ + try { + PbArgs _args(_linargs, _kwds); + FluidSolver *parent = _args.obtainParent(); + bool noTiming = _args.getOpt<bool>("notiming", -1, 0); + pbPreparePlugin(parent, "printBuildInfo", !noTiming); + PyObject *_retval = 0; + { + ArgLocker _lock; + _retval = toPy(printBuildInfo()); + _args.check(); + } + pbFinalizePlugin(parent, "printBuildInfo", !noTiming); + return _retval; + } + catch (std::exception &e) { + pbSetError("printBuildInfo", e.what()); + return 0; + } +} +static const Pb::Register _RP_printBuildInfo("", "printBuildInfo", _W_1); +extern "C" { +void PbRegister_printBuildInfo() +{ + KEEP_UNUSED(_RP_printBuildInfo); +} +} + +//! set debug level for messages (0 off, 1 regular, higher = more, up to 10) +void setDebugLevel(int level = 1) +{ + gDebugLevel = level; +} +static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds) +{ + try { + PbArgs _args(_linargs, _kwds); + FluidSolver *parent = _args.obtainParent(); + bool noTiming = _args.getOpt<bool>("notiming", -1, 0); + pbPreparePlugin(parent, "setDebugLevel", !noTiming); + PyObject *_retval = 0; + { + ArgLocker _lock; + int level = _args.getOpt<int>("level", 0, 1, &_lock); + _retval = getPyNone(); + setDebugLevel(level); + _args.check(); + } + pbFinalizePlugin(parent, "setDebugLevel", !noTiming); + return _retval; + } + catch (std::exception &e) { + pbSetError("setDebugLevel", e.what()); + return 0; + } +} +static const Pb::Register _RP_setDebugLevel("", "setDebugLevel", _W_2); +extern "C" { +void PbRegister_setDebugLevel() +{ + KEEP_UNUSED(_RP_setDebugLevel); +} +} + +//! helper function to check for numpy compilation +void assertNumpy() +{ +#if NUMPY == 1 + // all good, nothing to do... +#else + errMsg("This scene requires numpy support. Enable compilation in cmake with \"-DNUMPY=1\" "); +#endif +} +static PyObject *_W_3(PyObject *_self, PyObject *_linargs, PyObject *_kwds) +{ + try { + PbArgs _args(_linargs, _kwds); + FluidSolver *parent = _args.obtainParent(); + bool noTiming = _args.getOpt<bool>("notiming", -1, 0); + pbPreparePlugin(parent, "assertNumpy", !noTiming); + PyObject *_retval = 0; + { + ArgLocker _lock; + _retval = getPyNone(); + assertNumpy(); + _args.check(); + } + pbFinalizePlugin(parent, "assertNumpy", !noTiming); + return _retval; + } + catch (std::exception &e) { + pbSetError("assertNumpy", e.what()); + return 0; + } +} +static const Pb::Register _RP_assertNumpy("", "assertNumpy", _W_3); +extern "C" { +void PbRegister_assertNumpy() +{ + KEEP_UNUSED(_RP_assertNumpy); +} +} + +} // namespace Manta |