7 #include "imstkSphModel.h"     8 #include "imstkParallelUtils.h"     9 #include "imstkPointSet.h"    10 #include "imstkTaskGraph.h"    11 #include "imstkVTKMeshIO.h"    15 SphModelConfig::SphModelConfig(
const double particleRadius)
    18     if (std::abs(particleRadius) > 1.0e-6)
    20         LOG_IF(WARNING, (particleRadius < 0)) << 
"Particle radius supplied is negative! Using absolute value of the supplied radius.";
    21         m_particleRadius = std::abs(particleRadius);
    25         LOG(WARNING) << 
"Particle radius too small! Setting to 1.e-6";
    26         m_particleRadius = 1.e-6;
    31 SphModelConfig::SphModelConfig(
const double particleRadius, 
const double speedOfSound, 
const double restDensity)
    33     if (std::abs(particleRadius) > 1.0e-6)
    35         LOG_IF(WARNING, (particleRadius < 0)) << 
"Particle radius supplied is negative! Using absolute value of the supplied radius.";
    36         m_particleRadius = std::abs(particleRadius);
    40         LOG(WARNING) << 
"Particle radius too small! Setting to 1.e-6";
    41         m_particleRadius = 1.e-6;
    46         LOG(WARNING) << 
"Speed of sound is negative! Setting speed of sound to default value.";
    50         m_speedOfSound = speedOfSound;
    55         LOG(WARNING) << 
"Rest density is negative! Setting rest density to default value.";
    59         m_restDensity = restDensity;
    65 SphModelConfig::initialize()
    74     m_kernelRadius    = m_particleRadius * m_kernelOverParticleRadiusRatio;
    77     m_pressureStiffness = m_restDensity * m_speedOfSound * m_speedOfSound / 7.0;
    80 SphModel::SphModel() : DynamicalModel<SphState>(
DynamicalModelType::SmoothedParticleHydrodynamics)
    82     m_validGeometryTypes = { 
"PointSet" };
    84     m_findParticleNeighborsNode = m_taskGraph->addFunction(
"SPHModel_Partition", std::bind(&SphModel::findParticleNeighbors, 
this));
    85     m_computeDensityNode = m_taskGraph->addFunction(
"SPHModel_ComputeDensity", [&]()
    87             computeNeighborRelativePositions();
    91     m_normalizeDensityNode = m_taskGraph->addFunction(
"SPHModel_NormalizeDensity", std::bind(&SphModel::normalizeDensity, 
this));
    93     m_collectNeighborDensityNode = m_taskGraph->addFunction(
"SPHModel_CollectNeighborDensity", std::bind(&SphModel::collectNeighborDensity, 
this));
    95     m_computeTimeStepSizeNode =
    96         m_taskGraph->addFunction(
"SPHModel_ComputeTimestep", std::bind(&SphModel::computeTimeStepSize, 
this));
    98     m_computePressureAccelNode =
    99         m_taskGraph->addFunction(
"SPHModel_ComputePressureAccel", std::bind(&SphModel::computePressureAcceleration, 
this));
   101     m_computeSurfaceTensionNode =
   102         m_taskGraph->addFunction(
"SPHModel_ComputeSurfaceTensionAccel", std::bind(&SphModel::computeSurfaceTension, 
this));
   104     m_computeViscosityNode =
   105         m_taskGraph->addFunction(
"SPHModel_ComputeViscosity", std::bind(&SphModel::computeViscosity, 
this));
   108         m_taskGraph->addFunction(
"SPHModel_Integrate", std::bind(&SphModel::sumAccels, 
this));
   110     m_updateVelocityNode =
   111         m_taskGraph->addFunction(
"SPHModel_UpdateVelocity", [&]()
   113                 updateVelocity(getTimeStep());
   116     m_moveParticlesNode =
   117         m_taskGraph->addFunction(
"SPHModel_MoveParticles", [&]()
   119                 moveParticles(getTimeStep());
   132     LOG_IF(FATAL, (!this->getModelGeometry())) << 
"Model geometry is not yet set! Cannot initialize without model geometry.";
   133     m_pointSetGeometry = std::dynamic_pointer_cast<
PointSet>(m_geometry);
   137     m_initialState = std::make_shared<SphState>(numParticles);
   138     m_currentState = std::make_shared<SphState>(numParticles);
   141     if (m_initialVelocities != 
nullptr)
   143         m_currentState->setVelocities(m_initialVelocities);
   147     m_initialState->setState(m_currentState);
   150     m_currentState->setPositions(m_pointSetGeometry->getVertexPositions());
   151     m_initialState->setPositions(m_pointSetGeometry->getInitialVertexPositions());
   154     m_kernels.initialize(m_modelParameters->m_kernelRadius);
   157     m_neighborSearcher = std::make_shared<NeighborSearch>(m_modelParameters->m_neighborSearchMethod,
   158       m_modelParameters->m_kernelRadius);
   160     m_pressureAccels = std::make_shared<VecDataArray<double, 3>>(numParticles);
   161     std::fill_n(m_pressureAccels->getPointer(), m_pressureAccels->size(), Vec3d(0, 0, 0));
   164     m_surfaceTensionAccels = std::make_shared<VecDataArray<double, 3>>(numParticles);
   165     std::fill_n(m_surfaceTensionAccels->getPointer(), m_surfaceTensionAccels->size(), Vec3d(0, 0, 0));
   167     m_viscousAccels = std::make_shared<VecDataArray<double, 3>>(numParticles);
   168     std::fill_n(m_viscousAccels->getPointer(), m_viscousAccels->size(), Vec3d(0, 0, 0));
   170     m_neighborVelContr = std::make_shared<VecDataArray<double, 3>>(numParticles);
   171     std::fill_n(m_neighborVelContr->getPointer(), m_neighborVelContr->size(), Vec3d(0, 0, 0));
   173     m_particleShift = std::make_shared<VecDataArray<double, 3>>(numParticles);
   174     std::fill_n(m_particleShift->getPointer(), m_particleShift->size(), Vec3d(0, 0, 0));
   177     m_pointSetGeometry->setVertexAttribute(
"Pressure Accels", m_pressureAccels);
   178     m_pointSetGeometry->setVertexAttribute(
"Surface Tension Accels", m_surfaceTensionAccels);
   179     m_pointSetGeometry->setVertexAttribute(
"Viscous Accels", m_viscousAccels);
   180     m_pointSetGeometry->setVertexAttribute(
"Densities", m_currentState->getDensities());
   181     m_pointSetGeometry->setVertexAttribute(
"Velocities", m_currentState->getVelocities());
   182     m_pointSetGeometry->setVertexAttribute(
"Diffuse Velocities", m_currentState->getDiffuseVelocities());
   183     m_pointSetGeometry->setVertexAttribute(
"Normals", m_currentState->getNormals());
   184     m_pointSetGeometry->setVertexAttribute(
"Accels", m_currentState->getAccelerations());
   193     m_taskGraph->addEdge(source, m_findParticleNeighborsNode);
   194     m_taskGraph->addEdge(m_findParticleNeighborsNode, m_computeDensityNode);
   195     m_taskGraph->addEdge(m_computeDensityNode, m_normalizeDensityNode);
   196     m_taskGraph->addEdge(m_normalizeDensityNode, m_collectNeighborDensityNode);
   199     m_taskGraph->addEdge(m_collectNeighborDensityNode, m_computePressureAccelNode);
   200     m_taskGraph->addEdge(m_collectNeighborDensityNode, m_computeSurfaceTensionNode);
   201     m_taskGraph->addEdge(m_collectNeighborDensityNode, m_computeViscosityNode);
   202     m_taskGraph->addEdge(m_collectNeighborDensityNode, m_computeTimeStepSizeNode);
   204     m_taskGraph->addEdge(m_computePressureAccelNode, m_integrateNode);
   205     m_taskGraph->addEdge(m_computeSurfaceTensionNode, m_integrateNode);
   206     m_taskGraph->addEdge(m_computeViscosityNode, m_integrateNode);
   207     m_taskGraph->addEdge(m_computeTimeStepSizeNode, m_integrateNode);
   209     m_taskGraph->addEdge(m_integrateNode, m_updateVelocityNode);
   210     m_taskGraph->addEdge(m_updateVelocityNode, m_moveParticlesNode);
   211     m_taskGraph->addEdge(m_moveParticlesNode, sink);
   215 SphModel::computeTimeStepSize()
   217     m_dt = (this->m_timeStepSizeType == TimeSteppingType::Fixed) ? m_defaultDt : computeCFLTimeStepSize();
   221 SphModel::computeCFLTimeStepSize()
   223     auto maxVel = ParallelUtils::findMaxL2Norm(*getCurrentState()->getFullStepVelocities());
   226     double timestep = maxVel > 1.0e-6 ?
   227                       m_modelParameters->m_cflFactor * (2.0 * m_modelParameters->m_particleRadius / (m_modelParameters->m_speedOfSound + maxVel)) :
   228                       m_modelParameters->m_maxTimestep;
   231     if (timestep > m_modelParameters->m_maxTimestep)
   233         timestep = m_modelParameters->m_maxTimestep;
   235     else if (timestep < m_modelParameters->m_minTimestep)
   237         timestep = m_modelParameters->m_minTimestep;
   243 SphModel::findParticleNeighbors()
   245     m_neighborSearcher->getNeighbors(getCurrentState()->getFluidNeighborLists(), *getCurrentState()->getPositions());
   247     if (m_modelParameters->m_bDensityWithBoundary)   
   249         m_neighborSearcher->getNeighbors(getCurrentState()->getBoundaryNeighborLists(),
   250             *getCurrentState()->getPositions(),
   251             *getCurrentState()->getBoundaryParticlePositions());
   256 SphModel::computeNeighborRelativePositions()
   258     auto computeRelativePositions = [&](
const Vec3d& ppos, 
const std::vector<size_t>& neighborList,
   261                                         for (
const size_t q : neighborList)
   263                                             const Vec3d& qpos = allPositions[q];
   264                                             const Vec3d  r    = ppos - qpos;
   265                                             neighborInfo.push_back({ r, m_modelParameters->m_restDensity });
   269     std::shared_ptr<VecDataArray<double, 3>> positionsPtr = getCurrentState()->getPositions();
   272     std::vector<std::vector<NeighborInfo>>& neighborInfos = getCurrentState()->getNeighborInfo();
   274     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   277             if (m_sphBoundaryConditions
   278                 && m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Buffer)
   283             const Vec3d& ppos = positions[p];
   284             std::vector<NeighborInfo>& neighborInfo = neighborInfos[p];
   286             neighborInfo.reserve(48);
   288             computeRelativePositions(ppos, getCurrentState()->getFluidNeighborLists()[p], *getCurrentState()->getPositions(), neighborInfo);
   290             if (m_modelParameters->m_bDensityWithBoundary)
   292                 computeRelativePositions(ppos, getCurrentState()->getBoundaryNeighborLists()[p], *getCurrentState()->getBoundaryParticlePositions(), neighborInfo);
   298 SphModel::collectNeighborDensity()
   303     std::shared_ptr<DataArray<double>> densitiesPtr = getCurrentState()->getDensities();
   306     const std::vector<std::vector<size_t>>&                 neighborLists = getCurrentState()->getFluidNeighborLists();
   307     const std::vector<SphBoundaryConditions::ParticleType>& particleTypes = m_sphBoundaryConditions->getParticleTypes();
   309     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   312             if (m_sphBoundaryConditions && particleTypes[p] == SphBoundaryConditions::ParticleType::Buffer)
   317             auto& neighborInfo = getCurrentState()->getNeighborInfo()[p];
   318             if (neighborInfo.size() <= 1)
   323             const auto& fluidNeighborList = neighborLists[p];
   324             for (
size_t i = 0; i < fluidNeighborList.size(); ++i)
   326                 auto q = fluidNeighborList[i];
   327                 neighborInfo[i].density = densities[q];
   333 SphModel::computeDensity()
   335     std::shared_ptr<DataArray<double>> densitiesPtr = getCurrentState()->getDensities();
   338     const std::vector<std::vector<NeighborInfo>>& neighborInfos = getCurrentState()->getNeighborInfo();
   340     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   343             if (m_sphBoundaryConditions && m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Buffer)
   348             const std::vector<NeighborInfo>& neighborInfo = neighborInfos[p];
   349             if (neighborInfo.size() <= 1)
   354             double pdensity = 0.0;
   355             for (
const auto& qInfo : neighborInfo)
   357                 pdensity += m_kernels.W(qInfo.relativePos);
   359             pdensity    *= m_modelParameters->m_particleMass;
   360             densities[p] = pdensity;
   377 SphModel::normalizeDensity()
   379     if (!m_modelParameters->m_bNormalizeDensity)
   384     std::shared_ptr<DataArray<double>> densitiesPtr = getCurrentState()->getDensities();
   387     const std::vector<std::vector<size_t>>&                 neighborLists = getCurrentState()->getFluidNeighborLists();
   388     const std::vector<std::vector<NeighborInfo>>&           neighborInfos = getCurrentState()->getNeighborInfo();
   389     const std::vector<SphBoundaryConditions::ParticleType>& particleTypes = m_sphBoundaryConditions->getParticleTypes();
   391     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   394             if (m_sphBoundaryConditions && particleTypes[p] == SphBoundaryConditions::ParticleType::Buffer)
   399             const std::vector<NeighborInfo>& neighborInfo = neighborInfos[p];
   400             if (neighborInfo.size() <= 1)
   405             const auto& fluidNeighborList = neighborLists[p];
   408             for (
size_t i = 0; i < fluidNeighborList.size(); ++i)
   410                 const auto& qInfo = neighborInfo[i];
   413                 const auto q = fluidNeighborList[i];
   414                 const auto qdensity = densities[q];
   415                 tmp += m_kernels.W(qInfo.relativePos) / qdensity;
   418             densities[p] /= (tmp * m_modelParameters->m_particleMass);
   423 SphModel::computePressureAcceleration()
   425     std::shared_ptr<DataArray<double>> densitiesPtr   = getCurrentState()->getDensities();
   429     const std::vector<std::vector<NeighborInfo>>&           neighborInfos = getCurrentState()->getNeighborInfo();
   430     const std::vector<SphBoundaryConditions::ParticleType>& particleTypes = m_sphBoundaryConditions->getParticleTypes();
   432     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   435             if (m_sphBoundaryConditions && particleTypes[p] == SphBoundaryConditions::ParticleType::Buffer)
   440             Vec3d accel = Vec3d::Zero();
   441             const std::vector<NeighborInfo>& neighborInfo = neighborInfos[p];
   442             if (neighborInfo.size() <= 1)
   444                 pressureAccels[p] = accel;
   448             const auto pdensity  = densities[p];
   449             const auto ppressure = getParticlePressure(pdensity);
   451             for (
size_t idx = 0; idx < neighborInfo.size(); ++idx)
   453                 const auto& qInfo    = neighborInfo[idx];
   454                 const auto r         = qInfo.relativePos;
   455                 const auto qdensity  = qInfo.density;
   456                 const auto qpressure = getParticlePressure(qdensity);
   458                 accel += -(ppressure / (pdensity * pdensity) + qpressure / (qdensity * qdensity)) * m_kernels.gradW(r);
   461             accel *= m_modelParameters->m_particleMass;
   464             pressureAccels[p] = accel;
   469 SphModel::computeViscosity()
   476     const std::vector<std::vector<NeighborInfo>>& neighborInfos = getCurrentState()->getNeighborInfo();
   477     const std::vector<std::vector<size_t>>&       neighborLists = getCurrentState()->getFluidNeighborLists();
   479     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   482             if (m_sphBoundaryConditions
   483                 && (m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Buffer
   484                     || m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Wall))
   489             const std::vector<NeighborInfo>& neighborInfo = neighborInfos[p];
   490             if (neighborInfo.size() <= 1)
   492                 neighborVelContr[p] = Vec3d::Zero();
   493                 viscousAccels[p]    = Vec3d::Zero();
   497             Vec3d neighborVelContributionsNumerator    = Vec3d::Zero();
   498             double neighborVelContributionsDenominator = 0.0;
   499             Vec3d particleShifts = Vec3d::Zero();
   501             const Vec3d& pvel = halfStepVelocities[p];
   502             const std::vector<size_t>& fluidNeighborList = neighborLists[p];
   504             Vec3d diffuseFluid = Vec3d::Zero();
   505             for (
size_t i = 0; i < fluidNeighborList.size(); ++i)
   507                 const auto q        = fluidNeighborList[i];
   508                 const auto& qvel    = halfStepVelocities[q];
   509                 const auto& qInfo   = neighborInfo[i];
   510                 const auto r        = qInfo.relativePos;
   511                 const auto qdensity = qInfo.density;
   512                 diffuseFluid       += (1.0 / qdensity) * m_kernels.laplace(r) * (qvel - pvel);
   514                 neighborVelContributionsNumerator   += (qvel - pvel) * m_kernels.W(r);
   515                 neighborVelContributionsDenominator += m_kernels.W(r);
   516                 particleShifts += m_kernels.gradW(r);
   520             const double particleRadius = m_modelParameters->m_particleRadius;
   521             particleShifts     *= 4 / 3 * PI * particleRadius * particleRadius * particleRadius * 0.5 * m_modelParameters->m_kernelRadius * halfStepVelocities[p].norm();
   522             diffuseFluid       *= m_modelParameters->m_dynamicViscosityCoeff * m_modelParameters->m_particleMass;
   523             neighborVelContr[p] = neighborVelContributionsNumerator * m_modelParameters->m_eta / neighborVelContributionsDenominator;
   524             particleShift[p]    = -particleShifts;
   526             viscousAccels[p] = diffuseFluid;
   531 SphModel::computeSurfaceTension()
   535     const std::vector<std::vector<NeighborInfo>>& neighborInfos = getCurrentState()->getNeighborInfo();
   538     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   541             if (m_sphBoundaryConditions && m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Buffer)
   546             Vec3d n(0.0, 0.0, 0.0);
   547             const std::vector<NeighborInfo>& neighborInfo = neighborInfos[p];
   548             if (neighborInfo.size() <= 1)
   550                 surfaceNormals[p] = n;
   554             for (
size_t i = 0; i < neighborInfo.size(); ++i)
   556                 const auto& qInfo   = neighborInfo[i];
   557                 const auto r        = qInfo.relativePos;
   558                 const auto qdensity = qInfo.density;
   559                 n += (1.0 / qdensity) * m_kernels.gradW(r);
   562             n *= m_modelParameters->m_kernelRadius * m_modelParameters->m_particleMass;
   563             surfaceNormals[p] = n;
   569     const std::vector<std::vector<size_t>>& neighborLists = getCurrentState()->getFluidNeighborLists();
   572     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   575             if (m_sphBoundaryConditions
   576                 && (m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Buffer
   577                     || m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Wall))
   582             const std::vector<size_t>& fluidNeighborList = neighborLists[p];
   583             if (fluidNeighborList.size() <= 1)
   588             const Vec3d& ni          = surfaceNormals[p];
   589             const double pdensity    = densities[p];
   590             const auto& neighborInfo = neighborInfos[p];
   592             Vec3d accel = Vec3d::Zero();
   593             for (
size_t i = 0; i < fluidNeighborList.size(); ++i)
   595                 const size_t q = fluidNeighborList[i];
   601                 const double qdensity     = qInfo.
density;
   604                 const double K_ij = 2.0 * m_modelParameters->m_restDensity / (pdensity + qdensity);
   608                 const double d2 = r.squaredNorm();
   611                     accel -= K_ij * m_modelParameters->m_particleMass * (r / std::sqrt(d2)) * m_kernels.cohesionW(r);
   615                 const Vec3d& nj = surfaceNormals[q];
   616                 accel -= K_ij * (ni - nj);
   619             accel *= m_modelParameters->m_surfaceTensionStiffness;
   621             surfaceTensionAccels[p] = accel;
   626 SphModel::sumAccels()
   633     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   636             if (m_sphBoundaryConditions
   637                 && (m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Buffer
   638                     || m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Wall))
   643             accels[p] = pressureAccels[p] + surfaceTensionAccels[p] + viscousAccels[p];
   648 SphModel::updateVelocity(
const double timestep)
   655     ParallelUtils::parallelFor(getCurrentState()->getNumParticles(),
   658             if (m_sphBoundaryConditions
   659                 && (m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Buffer
   660                     || m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Wall))
   666             if (m_timeStepCount == 0)
   668                 halfStepVelocities[p]  = fullStepVelocities[p] + (m_modelParameters->m_gravity + accels[p]) * timestep * 0.5;
   669                 fullStepVelocities[p] += (m_modelParameters->m_gravity + accels[p]) * timestep;
   673                 halfStepVelocities[p] += (m_modelParameters->m_gravity + accels[p]) * timestep;
   674                 fullStepVelocities[p]  = halfStepVelocities[p] + (m_modelParameters->m_gravity + accels[p]) * timestep * 0.5;
   676             if (m_sphBoundaryConditions && m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Inlet)
   678                 halfStepVelocities[p] = m_sphBoundaryConditions->computeParabolicInletVelocity(positions[p]);
   679                 fullStepVelocities[p] = m_sphBoundaryConditions->computeParabolicInletVelocity(positions[p]);
   685 SphModel::moveParticles(
const double timestep)
   696     for (
int p = 0; p < static_cast<int>(getCurrentState()->getNumParticles()); p++)
   698         if (m_sphBoundaryConditions
   699             && (m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Buffer
   700                 || m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Wall))
   705         Vec3d oldPosition = positions[p];
   706         Vec3d newPosition = oldPosition + particleShift[p] * timestep + (halfStepVelocities[p] + neighborVelContr[p]) * timestep;
   708         positions[p] = newPosition;
   710         if (m_sphBoundaryConditions)
   712             std::vector<SphBoundaryConditions::ParticleType>& particleTypes = m_sphBoundaryConditions->getParticleTypes();
   713             if (particleTypes[p] == SphBoundaryConditions::ParticleType::Inlet
   714                 && !m_sphBoundaryConditions->isInInletDomain(newPosition))
   717                 particleTypes[p] = SphBoundaryConditions::ParticleType::Fluid;
   721                 const size_t bufferParticleIndex = m_sphBoundaryConditions->getBufferIndices().back();
   722                 m_sphBoundaryConditions->getBufferIndices().pop_back();
   723                 particleTypes[bufferParticleIndex] = SphBoundaryConditions::ParticleType::Inlet;
   725                 positions[bufferParticleIndex] = m_sphBoundaryConditions->placeParticleAtInlet(oldPosition);
   726                 halfStepVelocities[bufferParticleIndex] = m_sphBoundaryConditions->computeParabolicInletVelocity(positions[bufferParticleIndex]);
   727                 fullStepVelocities[bufferParticleIndex] = m_sphBoundaryConditions->computeParabolicInletVelocity(positions[bufferParticleIndex]);
   729             else if (particleTypes[p] == SphBoundaryConditions::ParticleType::Outlet
   730                      && !m_sphBoundaryConditions->isInOutletDomain(newPosition))
   732                 particleTypes[p] = SphBoundaryConditions::ParticleType::Buffer;
   734                 positions[p] = m_sphBoundaryConditions->getBufferCoord();
   735                 m_sphBoundaryConditions->getBufferIndices().
push_back(p);
   737             else if (particleTypes[p] == SphBoundaryConditions::ParticleType::Fluid
   738                      && m_sphBoundaryConditions->isInOutletDomain(newPosition))
   740                 particleTypes[p] = SphBoundaryConditions::ParticleType::Outlet;
   742             else if (particleTypes[p] == SphBoundaryConditions::ParticleType::Fluid
   743                      && !m_sphBoundaryConditions->isInFluidDomain(newPosition))
   745                 particleTypes[p] = SphBoundaryConditions::ParticleType::Buffer;
   746                 positions[p]     = m_sphBoundaryConditions->getBufferCoord();
   747                 m_sphBoundaryConditions->getBufferIndices().push_back(p);
   755 SphModel::getParticlePressure(
const double density)
   757     const double d     = density / m_modelParameters->m_restDensity;
   758     const double d2    = d * d;
   759     const double d4    = d2 * d2;
   760     const double error = m_modelParameters->m_pressureStiffness * (d4 * d2 * d - 1.0);
   762     return error > 0.0 ? error : 0.0;
   766 SphModel::setInitialVelocities(
const size_t numParticles, 
const Vec3d& initialVelocity)
   768     m_initialVelocities->clear();
   769     m_initialVelocities->reserve(static_cast<int>(numParticles));
   770     for (
size_t p = 0; p < numParticles; p++)
   772         if (m_sphBoundaryConditions
   773             && (m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Buffer
   774                 || m_sphBoundaryConditions->getParticleTypes()[p] == SphBoundaryConditions::ParticleType::Wall))
   776             m_initialVelocities->push_back(Vec3d::Zero());
   780             m_initialVelocities->push_back(initialVelocity);
   789     for (
size_t i = 0; i < static_cast<size_t>(points.size()); i++)
   791         double minDistance = 1e10;
   793         for (
const size_t j : indices[i])
   795             const Vec3d  p1       = positions[j];
   796             const double distance = (points[i] - p1).norm();
   797             if (distance < minDistance)
   799                 minDistance = distance;
   803         m_minIndices[i] = minIndex;
 Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
 
double m_particleMassScale
scale particle mass to a smaller value to maintain stability 
 
void resize(const int size) override
Resize data array to hold exactly size number of values. 
 
void push_back(const ValueType &val)
Append the data array to hold the new value, resizes if neccesary. 
 
DynamicalModelType
Type of the time dependent mathematical model. 
 
void findNearestParticleToVertex(const VecDataArray< double, 3 > &points, const std::vector< std::vector< size_t >> &indices)
Write the state to external file. 
 
double m_particleRadiusSqr
 
double density
density of neighbor particle 
 
Vec3d relativePos
relative position 
 
int getNumVertices() const
Returns the number of total vertices in the mesh. 
 
bool initialize() override
Initialize the dynamical model. 
 
The helper struct to store relative positions and densities of neighbor particlcles. 
 
void initGraphEdges()
Initializes the edges of the graph.