34 #include "AlarconHaematocritSolver.hpp" 35 #include "LinearSystem.hpp" 36 #include "VesselNode.hpp" 38 #include "Exception.hpp" 39 #include "ReplicatableVector.hpp" 41 template<
unsigned DIM>
50 template<
unsigned DIM>
56 template<
unsigned DIM>
60 std::vector<boost::shared_ptr<Vessel<DIM> > > vessels = this->
mpNetwork->GetVessels();
61 for(
unsigned idx=0; idx<vessels.size(); idx++)
63 vessels[idx]->SetId(idx);
67 PetscInt lhsVectorSize = vessels.size();
68 unsigned max_vessels_per_branch = 5;
71 if(vessels.size() < max_vessels_per_branch)
73 max_vessels_per_branch = unsigned(lhsVectorSize);
75 LinearSystem linearSystem(lhsVectorSize, max_vessels_per_branch);
81 linearSystem.SetPcType(
"lu");
84 #ifndef PETSC_HAVE_HYPRE 85 linearSystem.SetPcType(
"hypre");
86 #endif //PETSC_HAVE_HYPRE 87 linearSystem.SetKspType(
"preonly");
90 for(
unsigned idx=0; idx<vessels.size(); idx++)
93 linearSystem.SetMatrixElement(idx, idx, 1);
96 if(vessels[idx]->GetStartNode()->GetFlowProperties()->IsInputNode() or vessels[idx]->GetEndNode()->GetFlowProperties()->IsInputNode())
101 else if(vessels[idx]->GetFlowProperties()->GetFlowRate()==0.0*unit::metre_cubed_per_second)
103 linearSystem.SetRhsVectorElement(idx, 0.0);
108 boost::shared_ptr<VesselNode<DIM> > p_inflow_node;
109 units::quantity<unit::flow_rate> flow_rate = vessels[idx]->GetFlowProperties()->GetFlowRate();
110 if(flow_rate >0.0 * unit::metre_cubed_per_second)
112 p_inflow_node = vessels[idx]->GetStartNode();
116 p_inflow_node = vessels[idx]->GetEndNode();
121 if(p_inflow_node->GetNumberOfSegments()>1)
123 std::vector<boost::shared_ptr<Vessel<DIM> > > parent_vessels;
124 std::vector<boost::shared_ptr<Vessel<DIM> > > competitor_vessels;
125 for(
unsigned jdx=0; jdx<p_inflow_node->GetSegments().size(); jdx++)
128 if(p_inflow_node->GetSegment(jdx)->GetVessel()!=vessels[idx])
130 units::quantity<unit::flow_rate> inflow_rate = p_inflow_node->GetSegment(jdx)->GetVessel()->GetFlowProperties()->GetFlowRate();
131 if(p_inflow_node->GetSegment(jdx)->GetVessel()->GetEndNode()==p_inflow_node)
133 if(inflow_rate>0.0 * unit::metre_cubed_per_second)
135 parent_vessels.push_back(p_inflow_node->GetSegment(jdx)->GetVessel());
137 else if(inflow_rate<0.0 * unit::metre_cubed_per_second)
139 competitor_vessels.push_back(p_inflow_node->GetSegment(jdx)->GetVessel());
142 if(p_inflow_node->GetSegment(jdx)->GetVessel()->GetStartNode()==p_inflow_node)
144 if(inflow_rate>0.0 * unit::metre_cubed_per_second)
146 competitor_vessels.push_back(p_inflow_node->GetSegment(jdx)->GetVessel());
148 else if(inflow_rate<0.0 * unit::metre_cubed_per_second)
150 parent_vessels.push_back(p_inflow_node->GetSegment(jdx)->GetVessel());
157 if(competitor_vessels.size()==0)
159 for(
unsigned jdx=0; jdx<parent_vessels.size();jdx++)
161 linearSystem.SetMatrixElement(idx, parent_vessels[jdx]->GetId(), -1);
167 if(competitor_vessels.size()>1 or parent_vessels.size()>1)
169 EXCEPTION(
"This solver can only work with branches with connectivity 3");
173 units::quantity<unit::length> my_radius = vessels[idx]->GetRadius();
174 units::quantity<unit::length> competitor_radius = competitor_vessels[0]->GetRadius();
175 units::quantity<unit::velocity> my_velocity = units::fabs(flow_rate)/(M_PI * my_radius * my_radius);
176 units::quantity<unit::velocity> competitor_velocity = units::fabs(competitor_vessels[0]->GetFlowProperties()->GetFlowRate())/(M_PI * competitor_radius * competitor_radius);
178 if(my_velocity>
mTHR*competitor_velocity)
181 linearSystem.SetMatrixElement(idx, parent_vessels[0]->GetId(), -1);
183 else if(my_velocity*
mTHR>competitor_velocity)
186 if(my_velocity>competitor_velocity)
188 linearSystem.SetMatrixElement(idx, parent_vessels[0]->GetId(), -1.0/(1.0+(competitor_velocity/(my_velocity*
mAlpha))));
190 else if(my_velocity<competitor_velocity)
192 linearSystem.SetMatrixElement(idx, parent_vessels[0]->GetId(), -1.0/(1.0+(
mAlpha*competitor_velocity/(my_velocity))));
198 if(vessels[idx]->GetId()>competitor_vessels[0]->GetId())
200 linearSystem.SetMatrixElement(idx, parent_vessels[0]->GetId(), -1.0/(1.0+(
mAlpha*competitor_velocity/(my_velocity))));
204 linearSystem.SetMatrixElement(idx, parent_vessels[0]->GetId(), -1.0/(1.0+(competitor_velocity/(my_velocity*
mAlpha))));
214 Vec solution = PetscTools::CreateVec(vessels.size());
215 linearSystem.AssembleFinalLinearSystem();
216 solution = linearSystem.Solve();
217 ReplicatableVector a(solution);
220 for (
unsigned idx = 0; idx < vessels.size(); idx++)
222 for (
unsigned jdx = 0; jdx < vessels[idx]->GetNumberOfSegments(); jdx++)
224 vessels[idx]->GetSegments()[jdx]->GetFlowProperties()->SetHaematocrit(a[idx]);
228 PetscTools::Destroy(solution);
231 template<
unsigned DIM>
238 template<
unsigned DIM>
246 template<
unsigned DIM>
~AlarconHaematocritSolver()
AlarconHaematocritSolver()
*
units::quantity< unit::dimensionless > mAlpha
boost::shared_ptr< VesselNetwork< DIM > > mpNetwork
void SetHaematocrit(units::quantity< unit::dimensionless > haematocrit)
void SetAlpha(units::quantity< unit::dimensionless > alpha)
units::quantity< unit::dimensionless > mHaematocrit
units::quantity< unit::dimensionless > mTHR
void SetTHR(units::quantity< unit::dimensionless > thr)