Chaste Commit::6e4f5fe395bca70eb7641cf6e0e87f450383ca5a
ImmersedBoundaryMesh.hpp
1/*
2
3Copyright (c) 2005-2026, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14 * Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 * Neither the name of the University of Oxford nor the names of its
20 contributors may be used to endorse or promote products derived from this
21 software without specific prior written permission.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#ifndef IMMERSEDBOUNDARYMESH_HPP_
37#define IMMERSEDBOUNDARYMESH_HPP_
38
39// Forward declaration prevents circular include chain
40template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
42
43#include <set>
44#include <vector>
45
46#include <boost/polygon/voronoi.hpp>
47#include <boost/serialization/base_object.hpp>
48#include <boost/serialization/split_member.hpp>
49#include <boost/serialization/vector.hpp>
50
51#include "AbstractMesh.hpp"
52#include "ArchiveLocationInfo.hpp"
54#include "FluidSource.hpp"
55#include "ImmersedBoundaryArray.hpp"
56#include "ImmersedBoundaryElement.hpp"
57#include "ImmersedBoundaryMeshReader.hpp"
58#include "ImmersedBoundaryMeshWriter.hpp"
59#include "Node.hpp"
60
61
68template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
69class ImmersedBoundaryMesh : public AbstractMesh<ELEMENT_DIM, SPACE_DIM>
70{
71 friend class TestImmersedBoundaryMesh;
72
73protected:
75 unsigned mNumGridPtsX;
76
78 unsigned mNumGridPtsY;
79
82
85
88
94
98 static constexpr double mVoronoiHalo = 0.1;
99
101 std::vector<unsigned> mDeletedNodeIndices;
102
104 std::vector<unsigned> mDeletedElementIndices;
105
107 multi_array<double, 3> m2dVelocityGrids;
108
110 multi_array<double, 4> m3dVelocityGrids;
111
113 std::vector<ImmersedBoundaryElement<ELEMENT_DIM, SPACE_DIM>*> mElements;
114
116 std::vector<ImmersedBoundaryElement<ELEMENT_DIM - 1, SPACE_DIM>*> mLaminas;
117
119 std::vector<std::shared_ptr<FluidSource<SPACE_DIM>>> mElementFluidSources;
120
122 std::vector<std::shared_ptr<FluidSource<SPACE_DIM>>> mBalancingFluidSources;
123
125 boost::polygon::voronoi_diagram<double> mNodeLocationsVoronoiDiagram;
126
135
143 unsigned SolveNodeMapping(unsigned index) const;
144
152 unsigned SolveElementMapping(unsigned index) const;
153
161 unsigned SolveBoundaryElementMapping(unsigned index) const;
162
171 void TagBoundaryElements();
172
185 unsigned nodeAIndex,
186 unsigned nodeBIndex,
187 c_vector<double, SPACE_DIM> centroid,
188 c_vector<double, SPACE_DIM> axisOfDivision);
189
192
200 template <class Archive>
201 void save(Archive& archive, const unsigned int version) const
202 {
203 archive& boost::serialization::base_object<AbstractMesh<ELEMENT_DIM, SPACE_DIM> >(*this);
204
205 // Create a mesh writer pointing to the correct file and directory
208 false);
209 mesh_writer.WriteFilesUsingMesh(*(const_cast<ImmersedBoundaryMesh<ELEMENT_DIM, SPACE_DIM>*>(this)));
210 }
211
218 template <class Archive>
219 void load(Archive& archive, const unsigned int version)
220 {
221 archive& boost::serialization::base_object<AbstractMesh<ELEMENT_DIM, SPACE_DIM> >(*this);
222
224 this->ConstructFromMeshReader(mesh_reader);
225 }
226 BOOST_SERIALIZATION_SPLIT_MEMBER()
227
228public:
230 class ImmersedBoundaryElementIterator;
231
233 class ImmersedBoundaryLaminaIterator;
234
238 const std::vector<Node<SPACE_DIM>*>& rGetNodes() const;
239
245 inline ImmersedBoundaryElementIterator GetElementIteratorBegin(bool skipDeletedElements = true);
246
250 inline ImmersedBoundaryElementIterator GetElementIteratorEnd();
251
257 inline ImmersedBoundaryLaminaIterator GetLaminaIteratorBegin(bool skipDeletedLaminas = true);
258
262 inline ImmersedBoundaryLaminaIterator GetLaminaIteratorEnd();
263
273 ImmersedBoundaryMesh(std::vector<Node<SPACE_DIM>*> nodes,
274 std::vector<ImmersedBoundaryElement<ELEMENT_DIM, SPACE_DIM>*> elements,
275 std::vector<ImmersedBoundaryElement<ELEMENT_DIM - 1, SPACE_DIM>*> laminas = {},
276 unsigned numGridPtsX = 128u,
277 unsigned numGridPtsY = 128u);
278
283
287 virtual ~ImmersedBoundaryMesh();
288
292 virtual unsigned GetNumNodes() const;
293
297 virtual unsigned GetNumElements() const;
298
302 unsigned GetNumAllElements() const;
303
307 unsigned GetNumLaminas() const;
308
312 unsigned GetNumGridPtsX() const;
313
317 unsigned GetNumGridPtsY() const;
318
322 double GetCharacteristicNodeSpacing() const;
323
327 double GetSpacingRatio() const;
328
332 unsigned GetMaxNodeIndex() const;
333
337 unsigned GetMaxElementIndex() const;
338
342 unsigned GetMaxLaminaIndex() const;
343
354 c_vector<double, SPACE_DIM> GetVectorFromAtoB(const c_vector<double, SPACE_DIM>& rLocation1, const c_vector<double, SPACE_DIM>& rLocation2);
355
362 void SetNode(unsigned nodeIndex, ChastePoint<SPACE_DIM> point);
363
371 void ConformToGeometry(c_vector<double, SPACE_DIM>& rLocation);
372
376 const multi_array<double, 3>& rGet2dVelocityGrids() const;
377
381 //const multi_array<double, 4>& rGet3dVelocityGrids() const;
382
386 multi_array<double, 3>& rGetModifiable2dVelocityGrids();
387
391 void SetNumGridPtsX(unsigned meshPointsX);
392
396 void SetNumGridPtsY(unsigned meshPointsY);
397
401 void SetNumGridPtsXAndY(unsigned numGridPts);
402
406 void SetCharacteristicNodeSpacing(double nodeSpacing);
407
413 unsigned AddNode(Node<SPACE_DIM>* pNewNode);
414
418 std::vector<std::shared_ptr<FluidSource<SPACE_DIM>>>& rGetElementFluidSources();
419
423 std::vector<std::shared_ptr<FluidSource<SPACE_DIM>>>& rGetBalancingFluidSources();
424
431 std::set<unsigned> GetNeighbouringNodeIndices(unsigned nodeIndex);
432
439
445 ImmersedBoundaryElement<ELEMENT_DIM - 1, SPACE_DIM>* GetLamina(unsigned index) const;
446
462 virtual c_vector<double, SPACE_DIM> GetCentroidOfElement(unsigned index);
463
470
474 virtual void Clear();
475
485 virtual double GetVolumeOfElement(unsigned index);
486
496 virtual double GetSurfaceAreaOfElement(unsigned index);
497
506 double GetVoronoiSurfaceAreaOfElement(unsigned elemIdx);
507
515 double GetAverageNodeSpacingOfElement(unsigned index, bool recalculate = true);
516
524 double GetAverageNodeSpacingOfLamina(unsigned index, bool recalculate = true);
525
555 virtual c_vector<double, 3> CalculateMomentsOfElement(unsigned index);
556
567 double GetElongationShapeFactorOfElement(unsigned elementIndex);
568
575 double GetTortuosityOfMesh();
576
587 double GetSkewnessOfElementMassDistributionAboutAxis(unsigned elemIndex, c_vector<double, SPACE_DIM> axis);
588
596
622 c_vector<double, SPACE_DIM> GetShortAxisOfElement(unsigned index);
623
637 c_vector<double, SPACE_DIM> axisOfDivision,
638 bool placeOriginalElementBelow = false);
639
649 bool placeOriginalElementBelow = false);
650
655
659 void SetElementDivisionSpacing(double elementDivisionSpacing);
660
664 double GetNeighbourDist() const;
665
669 void SetNeighbourDist(double neighbourDist);
670
676
682 void ReMesh(bool randomOrder=false);
683
690 void ReMeshElement(ImmersedBoundaryElement<ELEMENT_DIM, SPACE_DIM>* pElement, bool randomOrder);
691
699
708
715 std::set<unsigned> GetNeighbouringElementIndices(unsigned elemIdx);
716
723 double CalculateLengthOfVoronoiEdge(const boost::polygon::voronoi_diagram<double>::edge_type& rEdge);
724
733 std::array<unsigned, 13> GetPolygonDistribution();
734
740 const boost::polygon::voronoi_diagram<double>& rGetNodeLocationsVoronoiDiagram(bool update=true);
741
743 const std::vector<unsigned int>& GetVoronoiCellIdsIndexedByNodeIndex() const;
744
751 int ScaleUpToVoronoiCoordinate(double location) const;
752
759 double ScaleDistanceDownFromVoronoi(const double distance) const;
760
761
766 {
767 public:
774
780
787
792 inline ImmersedBoundaryElementIterator& operator++();
793
804 ImmersedBoundaryElementIterator(ImmersedBoundaryMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
805 typename std::vector<ImmersedBoundaryElement<ELEMENT_DIM, SPACE_DIM>*>::iterator elementIter,
806 bool skipDeletedElements = true);
807
808 private:
811
813 typename std::vector<ImmersedBoundaryElement<ELEMENT_DIM, SPACE_DIM>*>::iterator mElementIter;
814
817
822 inline bool IsAtEnd();
823
828 inline bool IsAllowedElement();
829 };
830
835 {
836 public:
842 inline ImmersedBoundaryElement<ELEMENT_DIM - 1, SPACE_DIM>& operator*();
843
848 inline ImmersedBoundaryElement<ELEMENT_DIM - 1, SPACE_DIM>* operator->();
849
856
861 inline ImmersedBoundaryLaminaIterator& operator++();
862
873 ImmersedBoundaryLaminaIterator(ImmersedBoundaryMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
874 typename std::vector<ImmersedBoundaryElement<ELEMENT_DIM - 1, SPACE_DIM>*>::iterator laminaIter,
875 bool skipDeletedLaminas = true);
876
877 private:
880
882 typename std::vector<ImmersedBoundaryElement<ELEMENT_DIM - 1, SPACE_DIM>*>::iterator mLaminaIter;
883
886
891 inline bool IsAtEnd();
892
897 inline bool IsAllowedLamina();
898 };
899};
900
903
904
905// ImmersedBoundaryElementIterator class implementation - most methods are inlined //
907
908template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
914
915template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
920
921template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
927
928template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
934
935template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
940
941template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
943{
944 do
945 {
946 ++mElementIter;
947 } while (!IsAtEnd() && !IsAllowedElement());
948
949 return (*this);
950}
951
952template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
955 typename std::vector<ImmersedBoundaryElement<ELEMENT_DIM, SPACE_DIM>*>::iterator elementIter,
956 bool skipDeletedElements)
957 : mrMesh(rMesh),
958 mElementIter(elementIter),
959 mSkipDeletedElements(skipDeletedElements)
960{
961 if (mrMesh.mElements.empty())
962 {
963 // Cope with empty meshes
965 }
966 else
967 {
968 // Make sure we start at an allowed element
969 if (mElementIter == mrMesh.mElements.begin() && !IsAllowedElement())
970 {
971 ++(*this);
972 }
973 }
974}
975
976template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
978{
979 return mElementIter == mrMesh.mElements.end();
980}
981
982template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
984{
985 return !(mSkipDeletedElements && (*this)->IsDeleted());
986}
987
989// ImmersedBoundaryLaminaIterator class implementation - most methods are inlined //
991
992template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
998
999template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1004
1005template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1007{
1008 assert(!IsAtEnd());
1009 return **mLaminaIter;
1010}
1011
1012template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1014{
1015 assert(!IsAtEnd());
1016 return *mLaminaIter;
1017}
1018
1019template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1024
1025template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1027{
1028 do
1029 {
1030 ++mLaminaIter;
1031 } while (!IsAtEnd() && !IsAllowedLamina());
1032
1033 return (*this);
1034}
1035
1036template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1039 typename std::vector<ImmersedBoundaryElement<ELEMENT_DIM - 1, SPACE_DIM>*>::iterator laminaIter,
1040 bool skipDeletedLaminas)
1041 : mrMesh(rMesh),
1042 mLaminaIter(laminaIter),
1043 mSkipDeletedLaminas(skipDeletedLaminas)
1044{
1045 if (mrMesh.mLaminas.empty())
1046 {
1047 // Cope with empty meshes
1048 mLaminaIter = mrMesh.mLaminas.end();
1049 }
1050 else
1051 {
1052 // Make sure we start at an allowed lamina
1053 if (mLaminaIter == mrMesh.mLaminas.begin() && !IsAllowedLamina())
1054 {
1055 ++(*this);
1056 }
1057 }
1058}
1059
1060template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1062{
1063 return mLaminaIter == mrMesh.mLaminas.end();
1064}
1065
1066template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1068{
1069 return !(mSkipDeletedLaminas && (*this)->IsDeleted());
1070}
1071
1072#endif /*IMMERSEDBOUNDARYMESH_HPP_*/
gcov doesn't like this file...
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
static std::string GetMeshFilename()
static std::string GetArchiveDirectory()
static std::string GetArchiveRelativePath()
void WriteFilesUsingMesh(ImmersedBoundaryMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
std::vector< ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > * >::iterator mElementIter
ImmersedBoundaryElementIterator(ImmersedBoundaryMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, typename std::vector< ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > * >::iterator elementIter, bool skipDeletedElements=true)
ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > & operator*()
ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > * operator->()
bool operator!=(const typename ImmersedBoundaryMesh< ELEMENT_DIM, SPACE_DIM >::ImmersedBoundaryElementIterator &rOther)
bool operator!=(const typename ImmersedBoundaryMesh< ELEMENT_DIM, SPACE_DIM >::ImmersedBoundaryLaminaIterator &rOther)
ImmersedBoundaryElement< ELEMENT_DIM - 1, SPACE_DIM > & operator*()
ImmersedBoundaryLaminaIterator(ImmersedBoundaryMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, typename std::vector< ImmersedBoundaryElement< ELEMENT_DIM - 1, SPACE_DIM > * >::iterator laminaIter, bool skipDeletedLaminas=true)
std::vector< ImmersedBoundaryElement< ELEMENT_DIM-1, SPACE_DIM > * >::iterator mLaminaIter
ImmersedBoundaryElement< ELEMENT_DIM - 1, SPACE_DIM > * operator->()
ChasteCuboid< SPACE_DIM > CalculateBoundingBoxOfElement(unsigned index)
std::vector< ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > * > mElements
void ReMesh(bool randomOrder=false)
virtual double GetVolumeOfElement(unsigned index)
double GetCharacteristicNodeSpacing() const
void SetNeighbourDist(double neighbourDist)
bool NodesInDifferentElementOrLamina(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
unsigned DivideElement(ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > *pElement, unsigned nodeAIndex, unsigned nodeBIndex, c_vector< double, SPACE_DIM > centroid, c_vector< double, SPACE_DIM > axisOfDivision)
const std::vector< Node< SPACE_DIM > * > & rGetNodes() const
unsigned GetMaxElementIndex() const
std::vector< unsigned > mVoronoiCellIdsIndexedByNodeIndex
multi_array< double, 3 > & rGetModifiable2dVelocityGrids()
void save(Archive &archive, const unsigned int version) const
std::vector< unsigned > mDeletedNodeIndices
unsigned SolveElementMapping(unsigned index) const
ImmersedBoundaryElement< ELEMENT_DIM - 1, SPACE_DIM > * GetLamina(unsigned index) const
void load(Archive &archive, const unsigned int version)
void ReMeshLamina(ImmersedBoundaryElement< ELEMENT_DIM - 1, SPACE_DIM > *pLamina, bool randomOrder)
void SetNode(unsigned nodeIndex, ChastePoint< SPACE_DIM > point)
ImmersedBoundaryElementIterator GetElementIteratorEnd()
ImmersedBoundaryLaminaIterator GetLaminaIteratorBegin(bool skipDeletedLaminas=true)
double GetSkewnessOfElementMassDistributionAboutAxis(unsigned elemIndex, c_vector< double, SPACE_DIM > axis)
ImmersedBoundaryElementIterator GetElementIteratorBegin(bool skipDeletedElements=true)
multi_array< double, 4 > m3dVelocityGrids
static constexpr double mVoronoiHalo
void SetNumGridPtsXAndY(unsigned numGridPts)
double ScaleDistanceDownFromVoronoi(const double distance) const
void SetCharacteristicNodeSpacing(double nodeSpacing)
ImmersedBoundaryLaminaIterator GetLaminaIteratorEnd()
std::array< unsigned, 13 > GetPolygonDistribution()
double CalculateLengthOfVoronoiEdge(const boost::polygon::voronoi_diagram< double >::edge_type &rEdge)
std::vector< std::shared_ptr< FluidSource< SPACE_DIM > > > mElementFluidSources
std::vector< std::shared_ptr< FluidSource< SPACE_DIM > > > & rGetElementFluidSources()
virtual unsigned GetNumNodes() const
std::vector< unsigned > mDeletedElementIndices
double GetElongationShapeFactorOfElement(unsigned elementIndex)
unsigned SolveNodeMapping(unsigned index) const
boost::polygon::voronoi_diagram< double > mNodeLocationsVoronoiDiagram
std::vector< std::shared_ptr< FluidSource< SPACE_DIM > > > mBalancingFluidSources
unsigned AddNode(Node< SPACE_DIM > *pNewNode)
double GetAverageNodeSpacingOfElement(unsigned index, bool recalculate=true)
virtual c_vector< double, 3 > CalculateMomentsOfElement(unsigned index)
void ConformToGeometry(c_vector< double, SPACE_DIM > &rLocation)
const boost::polygon::voronoi_diagram< double > & rGetNodeLocationsVoronoiDiagram(bool update=true)
void ReMeshElement(ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > *pElement, bool randomOrder)
multi_array< double, 3 > m2dVelocityGrids
std::set< unsigned > GetNeighbouringNodeIndices(unsigned nodeIndex)
unsigned DivideElementAlongGivenAxis(ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > *pElement, c_vector< double, SPACE_DIM > axisOfDivision, bool placeOriginalElementBelow=false)
virtual unsigned GetNumElements() const
friend class boost::serialization::access
void SetNumGridPtsX(unsigned meshPointsX)
std::vector< std::shared_ptr< FluidSource< SPACE_DIM > > > & rGetBalancingFluidSources()
double GetAverageNodeSpacingOfLamina(unsigned index, bool recalculate=true)
int ScaleUpToVoronoiCoordinate(double location) const
unsigned SolveBoundaryElementMapping(unsigned index) const
unsigned DivideElementAlongShortAxis(ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > *pElement, bool placeOriginalElementBelow=false)
virtual c_vector< double, SPACE_DIM > GetCentroidOfElement(unsigned index)
void SetElementDivisionSpacing(double elementDivisionSpacing)
c_vector< double, SPACE_DIM > GetShortAxisOfElement(unsigned index)
std::set< unsigned > GetNeighbouringElementIndices(unsigned elemIdx)
const multi_array< double, 3 > & rGet2dVelocityGrids() const
std::vector< ImmersedBoundaryElement< ELEMENT_DIM - 1, SPACE_DIM > * > mLaminas
void ConstructFromMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)
ImmersedBoundaryElement< ELEMENT_DIM, SPACE_DIM > * GetElement(unsigned index) const
double GetVoronoiSurfaceAreaOfElement(unsigned elemIdx)
virtual double GetSurfaceAreaOfElement(unsigned index)
const std::vector< unsigned int > & GetVoronoiCellIdsIndexedByNodeIndex() const
c_vector< double, SPACE_DIM > GetVectorFromAtoB(const c_vector< double, SPACE_DIM > &rLocation1, const c_vector< double, SPACE_DIM > &rLocation2)
void SetNumGridPtsY(unsigned meshPointsY)
unsigned GetNumAllElements() const
Definition Node.hpp:59