iMSTK
Interactive Medical Simulation Toolkit
imstkSphBoundaryConditions.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkSphBoundaryConditions.h"
8 
9 #include <numeric>
10 
11 namespace imstk
12 {
13 SphBoundaryConditions::SphBoundaryConditions(std::pair<Vec3d, Vec3d>& inletCoords, std::vector<std::pair<Vec3d, Vec3d>>& outletCoords, std::pair<Vec3d, Vec3d>& fluidCoords,
14  const Vec3d& inletNormal, const StdVectorOfVec3d&, const double inletRadius, const Vec3d& inletCenterPt, const double inletFlowRate,
15  StdVectorOfVec3d& mainParticlePositions, const StdVectorOfVec3d& wallParticlePositions) :
16  m_inletDomain(inletCoords), m_outletDomain(outletCoords),
17  m_fluidDomain(fluidCoords),
18  m_bufferCoord(Vec3d(100.0, 0.0, 0.0)),
19  m_inletCenterPoint(inletCenterPt),
20  m_inletRadius(inletRadius),
21  m_inletNormal(inletNormal.normalized()),
22  m_inletCrossSectionalArea(PI * m_inletRadius * m_inletRadius)
23 {
24  setInletVelocity(inletFlowRate);
25  setParticleTypes(mainParticlePositions, wallParticlePositions.size());
26 
27  addBoundaryParticles(mainParticlePositions, wallParticlePositions);
28 }
29 
30 bool
31 SphBoundaryConditions::isInInletDomain(const Vec3d& position)
32 {
33  if (position.x() >= m_inletDomain.first.x() && position.y() >= m_inletDomain.first.y() && position.z() >= m_inletDomain.first.z()
34  && position.x() <= m_inletDomain.second.x() && position.y() <= m_inletDomain.second.y() && position.z() <= m_inletDomain.second.z())
35  {
36  return true;
37  }
38 
39  return false;
40 }
41 
42 bool
43 SphBoundaryConditions::isInOutletDomain(const Vec3d& position)
44 {
45  for (const auto& i : m_outletDomain)
46  {
47  if (position.x() >= i.first.x() && position.y() >= i.first.y() && position.z() >= i.first.z()
48  && position.x() <= i.second.x() && position.y() <= i.second.y() && position.z() <= i.second.z())
49  {
50  return true;
51  }
52  }
53 
54  return false;
55 }
56 
57 bool
58 SphBoundaryConditions::isInFluidDomain(const Vec3d& position)
59 {
60  const double error = 0.1;
61  if (position.x() >= m_fluidDomain.first.x() - error && position.y() >= m_fluidDomain.first.y() - error && position.z() >= m_fluidDomain.first.z() - error
62  && position.x() <= m_fluidDomain.second.x() + error && position.y() <= m_fluidDomain.second.y() + error && position.z() <= m_fluidDomain.second.z() + error)
63  {
64  return true;
65  }
66 
67  return false;
68 }
69 
73 void
74 SphBoundaryConditions::setParticleTypes(const StdVectorOfVec3d& mainParticlePositions, const size_t numWallParticles)
75 {
76  m_particleTypes.reserve(mainParticlePositions.size() + numWallParticles + m_numBufferParticles);
77 
78  for (auto const& i : mainParticlePositions)
79  {
80  ParticleType type;
81  if (isInInletDomain(i))
82  {
83  type = ParticleType::Inlet;
84  }
85  else if (isInOutletDomain(i))
86  {
87  type = ParticleType::Outlet;
88  }
89  else
90  {
91  type = ParticleType::Fluid;
92  }
93  m_particleTypes.push_back(type);
94  }
95 
96  m_particleTypes.insert(m_particleTypes.end(), numWallParticles, ParticleType::Wall);
97  m_particleTypes.insert(m_particleTypes.end(), m_numBufferParticles, ParticleType::Buffer);
98  m_bufferIndices.resize(m_numBufferParticles);
99  std::iota(std::begin(m_bufferIndices), std::end(m_bufferIndices), m_particleTypes.size() - m_numBufferParticles);
100 }
101 
102 Vec3d
103 SphBoundaryConditions::computeParabolicInletVelocity(const Vec3d& particlePosition)
104 {
105  // compute distance of point
106  const Vec3d inletRegionCenterPoint = (Vec3d(1.0, 1.0, 1.0) + m_inletNormal).array() * m_inletCenterPoint.array() + particlePosition.dot(m_inletNormal) * m_inletNormal.array();
107  const double distance = (particlePosition - inletRegionCenterPoint).norm();
108  Vec3d inletParabolicVelocity;
109  if (distance > m_inletRadius)
110  {
111  inletParabolicVelocity = Vec3d::Zero();
112  }
113  else
114  {
115  inletParabolicVelocity = m_inletVelocity * (1.0 - (distance / m_inletRadius) * (distance / m_inletRadius));
116  }
117  return inletParabolicVelocity;
118 }
119 
120 void
121 SphBoundaryConditions::addBoundaryParticles(StdVectorOfVec3d& mainParticlePositions, const StdVectorOfVec3d& wallParticlePositions)
122 {
123  mainParticlePositions.insert(mainParticlePositions.end(), wallParticlePositions.begin(), wallParticlePositions.end());
124  mainParticlePositions.insert(mainParticlePositions.end(), m_numBufferParticles, Vec3d(100.0, 0.0, 0.0));
125 }
126 
127 void
128 SphBoundaryConditions::setInletVelocity(const double flowRate)
129 {
130  m_inletVelocity = -m_inletNormal * (flowRate / m_inletCrossSectionalArea * 2.0);
131 }
132 
133 Vec3d
134 SphBoundaryConditions::placeParticleAtInlet(const Vec3d& position)
135 {
136  const Vec3d inletPosition = (Vec3d(1.0, 1.0, 1.0) + m_inletNormal).cwiseProduct(position) - m_inletCenterPoint.cwiseProduct(m_inletNormal);
137  return inletPosition;
138 }
139 } // namespace imstk
Compound Geometry.
void setParticleTypes(const StdVectorOfVec3d &mainParticlePositions, const size_t numWallParticles)
set particle type (fluid, wall, inlet, outlet, buffer)