36 #include "GeometryTools.hpp" 37 #include "OffLatticeMigrationRule.hpp" 38 #include "RandomNumberGenerator.hpp" 39 #include "BaseUnits.hpp" 41 template<
unsigned DIM>
44 mGlobalX(unit_vector<double>(3,0)),
45 mGlobalY(unit_vector<double>(3,1)),
46 mGlobalZ(unit_vector<double>(3,2)),
47 mMeanAngles(std::vector<units::quantity<
unit::plane_angle> >(3, 0.0*
unit::radians)),
48 mSdvAngles(std::vector<units::quantity<
unit::plane_angle> >(3, M_PI/18.0*
unit::radians)),
49 mVelocity(20.0 *(1.e-6/3600.0) *
unit::metre_per_second),
50 mChemotacticStrength(1.0),
51 mAttractionStrength(1.0),
52 mProbeLength(5.0 * 1.e-6 *
unit::metres),
53 mCriticalMutualAttractionLength(100.0 * 1.e-6 *
unit::metres)
58 template <
unsigned DIM>
65 template<
unsigned DIM>
71 template<
unsigned DIM>
77 template<
unsigned DIM>
83 template<
unsigned DIM>
89 template<
unsigned DIM>
98 std::vector<DimensionalChastePoint<DIM> > movement_vectors;
102 std::vector<units::quantity<unit::concentration> > probed_solutions;
103 unsigned probes_per_node = (2*DIM)+1;
104 std::vector<DimensionalChastePoint<DIM> > probe_locations(probes_per_node*rNodes.size(),
DimensionalChastePoint<DIM>(0.0, 0.0, 0.0, 1.e-6*unit::metres));
105 std::vector<bool> candidate_locations_inside_domain(probes_per_node*rNodes.size(),
true);
109 for(
unsigned idx=0; idx<rNodes.size(); idx++)
111 std::vector<DimensionalChastePoint<DIM> > local_probe_locations = GetProbeLocationsExternalPoint<DIM>(rNodes[idx]->rGetLocation(),
mProbeLength);
112 for(
unsigned jdx=0;jdx<probes_per_node; jdx++)
114 probe_locations[idx*probes_per_node + jdx] = local_probe_locations[jdx];
117 if(probe_locations.size()>0)
119 probed_solutions = this->
mpSolver->GetConcentrations(probe_locations);
124 candidate_locations_inside_domain = this->
mpBoundingDomain->IsPointInPart(probe_locations);
128 for(
unsigned idx=0; idx<rNodes.size(); idx++)
131 units::quantity<unit::plane_angle> angle_x =
132 RandomNumberGenerator::Instance()->NormalRandomDeviate(
mMeanAngles[0]/unit::radians,
mSdvAngles[0]/unit::radians)*unit::radians;
133 units::quantity<unit::plane_angle> angle_y =
134 RandomNumberGenerator::Instance()->NormalRandomDeviate(
mMeanAngles[1]/unit::radians,
mSdvAngles[1]/unit::radians)*unit::radians;
135 units::quantity<unit::plane_angle> angle_z =
136 RandomNumberGenerator::Instance()->NormalRandomDeviate(
mMeanAngles[2]/unit::radians,
mSdvAngles[2]/unit::radians)*unit::radians;
137 DimensionalChastePoint<DIM> currentDirection = rNodes[idx]->rGetLocation()-rNodes[idx]->GetSegments()[0]->GetOppositeNode(rNodes[idx])->rGetLocation();
138 c_vector<double, DIM> new_direction;
141 c_vector<double, DIM> new_direction_z = RotateAboutAxis<DIM>(currentDirection.
GetUnitVector(),
mGlobalZ, angle_z);
142 c_vector<double, DIM> new_direction_y = RotateAboutAxis<DIM>(new_direction_z,
mGlobalY, angle_y);
143 new_direction = RotateAboutAxis<DIM>(new_direction_y,
mGlobalX, angle_x);
144 new_direction /= norm_2(new_direction);
149 new_direction /= norm_2(new_direction);
156 std::vector<units::quantity<unit::concentration_gradient> > gradients(probes_per_node-1, 0.0*unit::mole_per_metre_pow_4);
157 if(probed_solutions.size()>=idx*probes_per_node+probes_per_node)
159 for(
unsigned jdx=1; jdx<probes_per_node; jdx++)
161 gradients[jdx-1] = ((probed_solutions[idx*probes_per_node+jdx] - probed_solutions[idx*probes_per_node]) /
mProbeLength);
162 if(!candidate_locations_inside_domain[idx*probes_per_node+jdx])
164 gradients[jdx-1] = 0.0*unit::mole_per_metre_pow_4;
170 units::quantity<unit::concentration_gradient> max_grad = 0.0 * unit::mole_per_metre_pow_4;
173 for(
unsigned jdx = 0; jdx<gradients.size(); jdx++)
175 if(gradients[jdx]>max_grad)
177 max_grad = gradients[jdx];
186 else if(my_index == 1)
190 else if(my_index == 2)
194 else if(my_index == 3)
198 else if(my_index == 4)
202 else if(my_index == 5)
207 new_direction /= norm_2(new_direction);
210 std::vector<boost::shared_ptr<VesselNode<DIM> > > nodes = this->
mpVesselNetwork->GetNodes();
211 units::quantity<unit::length> min_distance = 1.e12*unit::metres;
212 c_vector<double, DIM> min_direction = zero_vector<double>(DIM);
214 for(
unsigned jdx=0; jdx<nodes.size(); jdx++)
216 if(IsPointInCone<DIM>(nodes[jdx]->rGetLocation(), rNodes[idx]->rGetLocation(), rNodes[idx]->rGetLocation() +
219 units::quantity<unit::length> distance = rNodes[idx]->rGetLocation().GetDistance(nodes[jdx]->rGetLocation());
220 if(distance < min_distance)
222 min_distance = distance;
229 double strength = 0.0;
234 new_direction += strength * min_direction;
235 new_direction /= norm_2(new_direction);
239 units::quantity<unit::length> increment_length = time_increment*
mVelocity;
240 movement_vectors.push_back(OffsetAlongVector<DIM>(new_direction, increment_length, reference_length));
242 return movement_vectors;
246 template<
unsigned DIM>
249 std::vector<DimensionalChastePoint<DIM> > movement_vectors;
253 std::vector<units::quantity<unit::concentration> > probed_solutions;
254 unsigned probes_per_node = 3;
259 std::vector<DimensionalChastePoint<DIM> > probe_locations(probes_per_node*rNodes.size(),
DimensionalChastePoint<DIM>(0.0, 0.0, 0.0, reference_length));
260 std::vector<bool> candidate_locations_inside_domain(probes_per_node*rNodes.size(),
true);
263 for(
unsigned idx = 0; idx < rNodes.size(); idx++)
265 c_vector<double, DIM> sprout_direction;
266 c_vector<double, DIM> cross_product;
271 cross_product = VectorProduct(rNodes[idx]->GetSegments()[0]->GetUnitTangent(),
272 rNodes[idx]->GetSegments()[1]->GetUnitTangent());
273 for(
unsigned jdx=0; jdx<DIM; jdx++)
275 sum += abs(cross_product[jdx]);
280 c_vector<double, DIM> tangent1 = rNodes[idx]->GetSegments()[0]->GetUnitTangent();
281 c_vector<double, DIM> tangent2 = rNodes[idx]->GetSegments()[1]->GetUnitTangent();
282 for(
unsigned jdx=0; jdx<DIM; jdx++)
284 sum += abs(tangent1[jdx]-tangent2[jdx]);
291 c_vector<double, DIM> normal;
292 c_vector<double, DIM> tangent = rNodes[idx]->GetSegments()[0]->GetUnitTangent();
293 if(DIM==2 or tangent[2]==0.0)
295 if(tangent[1] == 0.0)
303 normal[1] = -tangent[0] /tangent[1];
308 if(std::abs(tangent[0]) + std::abs(tangent[1]) == 0.0)
317 normal[2] = -(tangent[0] + tangent[1])/tangent[2];
320 if(RandomNumberGenerator::Instance()->ranf()>=0.5)
322 sprout_direction = normal/norm_2(normal);
326 sprout_direction = -normal/norm_2(normal);
334 if(RandomNumberGenerator::Instance()->ranf()>=0.5)
336 sprout_direction = cross_product/norm_2(cross_product);
340 sprout_direction = -cross_product/norm_2(cross_product);
345 c_vector<double, DIM> tangent1 = rNodes[idx]->GetSegments()[0]->GetUnitTangent();
346 c_vector<double, DIM> tangent2 = rNodes[idx]->GetSegments()[1]->GetUnitTangent();
347 c_vector<double, DIM> av_tangent = (tangent1 + tangent2)/2.0;
348 av_tangent/=norm_2(av_tangent);
350 c_vector<double, DIM> normal;
351 if(av_tangent[1] == 0.0)
359 normal[1] = -av_tangent[0] /av_tangent[1];
362 if(RandomNumberGenerator::Instance()->ranf()>=0.5)
364 sprout_direction = normal/norm_2(normal);
368 sprout_direction = -normal/norm_2(normal);
373 units::quantity<unit::plane_angle> angle = RandomNumberGenerator::Instance()->NormalRandomDeviate(
mMeanAngles[0]/unit::radians,
375 std::vector<DimensionalChastePoint<DIM> > local_probes = GetProbeLocationsInternalPoint<DIM>(
DimensionalChastePoint<DIM>(sprout_direction, reference_length),
376 rNodes[idx]->rGetLocation(),
380 for(
unsigned jdx=0;jdx<probes_per_node; jdx++)
382 probe_locations[idx*probes_per_node + jdx] = local_probes[jdx];
388 if(probe_locations.size()>0)
390 probed_solutions = this->
mpSolver->GetConcentrations(probe_locations);
395 candidate_locations_inside_domain = this->
mpBoundingDomain->IsPointInPart(probe_locations);
400 for(
unsigned idx=0; idx<rNodes.size(); idx++)
408 std::vector<units::quantity<unit::concentration_gradient> > gradients(probes_per_node-1, 0.0*unit::mole_per_metre_pow_4);
409 if(probed_solutions.size()>=idx*probes_per_node+probes_per_node)
411 for(
unsigned jdx=1; jdx<probes_per_node; jdx++)
413 gradients[jdx-1] = ((probed_solutions[idx*probes_per_node+jdx] - probed_solutions[idx*probes_per_node]) /
mProbeLength);
414 if(!candidate_locations_inside_domain[idx*probes_per_node+jdx])
416 gradients[jdx-1] = 0.0*unit::mole_per_metre_pow_4;
422 units::quantity<unit::concentration_gradient> max_grad = 0.0 * unit::mole_per_metre_pow_4;
424 for(
unsigned jdx = 0; jdx<gradients.size(); jdx++)
426 if(gradients[jdx]>max_grad)
428 max_grad = gradients[jdx];
434 new_direction = probe_locations[idx*probes_per_node+1]-rNodes[idx]->rGetLocation();
436 else if(my_index == 1)
438 new_direction = probe_locations[idx*probes_per_node+2]-rNodes[idx]->rGetLocation();
440 else if(my_index == 2)
442 new_direction = probe_locations[idx*probes_per_node+3]-rNodes[idx]->rGetLocation();
444 else if(my_index == 3)
446 new_direction = probe_locations[idx*probes_per_node+4]-rNodes[idx]->rGetLocation();
451 units::quantity<unit::length> increment_length = time_increment*
mVelocity;
452 movement_vectors.push_back(OffsetAlongVector<DIM>(new_direction, increment_length));
455 return movement_vectors;
units::quantity< unit::length > mCriticalMutualAttractionLength
OffLatticeMigrationRule()
units::quantity< unit::velocity > mVelocity
units::quantity< unit::length > GetReferenceLengthScale() const
c_vector< double, 3 > mGlobalZ
std::vector< units::quantity< unit::plane_angle > > mMeanAngles
boost::shared_ptr< AbstractDiscreteContinuumSolver< DIM > > mpSolver
c_vector< double, 3 > mGlobalX
units::quantity< unit::time > GetReferenceTimeScale()
units::quantity< unit::length > mProbeLength
void SetChemotacticStrength(double strength)
virtual ~OffLatticeMigrationRule()
static boost::shared_ptr< OffLatticeMigrationRule< DIM > > Create()
std::vector< DimensionalChastePoint< DIM > > GetDirectionsForSprouts(const std::vector< boost::shared_ptr< VesselNode< DIM > > > &rNodes)
double mAttractionStrength
c_vector< double, DIM > GetUnitVector() const
c_vector< double, 3 > mGlobalY
c_vector< double, DIM > GetLocation(units::quantity< unit::length > scale)
boost::shared_ptr< Part< DIM > > mpBoundingDomain
static BaseUnits * Instance()
std::vector< DimensionalChastePoint< DIM > > GetDirections(const std::vector< boost::shared_ptr< VesselNode< DIM > > > &rNodes)
std::vector< units::quantity< unit::plane_angle > > mSdvAngles
boost::shared_ptr< VesselNetwork< DIM > > mpVesselNetwork
void SetSproutingVelocity(units::quantity< unit::velocity > velocity)
double mChemotacticStrength
void SetAttractionStrength(double strength)
units::quantity< unit::length > GetReferenceLengthScale()