Chaste  Build::
DiscreteContinuumBoundaryCondition.cpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4  All rights reserved.
5 
6  University of Oxford means the Chancellor, Masters and Scholars of the
7  University of Oxford, having an administrative office at Wellington
8  Square, Oxford OX1 2JD, UK.
9 
10  This file is part of Chaste.
11 
12  Redistribution and use in source and binary forms, with or without
13  modification, 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 
23  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34  */
35 
36 #include "Facet.hpp"
37 #include "DiscreteContinuumBoundaryCondition.hpp"
38 #include "VesselSegment.hpp"
39 #include "UnitCollection.hpp"
40 #include "BaseUnits.hpp"
41 #include "GeometryTools.hpp"
42 
43 template<unsigned DIM>
45  : mpDomain(),
46  mPoints(),
47  mType(BoundaryConditionType::OUTER),
48  mSource(BoundaryConditionSource::PRESCRIBED),
49  mLabel("Default"),
50  mValue(),
51  mpRegularGrid(),
52  mpMesh(),
53  mpNetwork(),
54  mReferenceConcentration(BaseUnits::Instance()->GetReferenceConcentrationScale())
55 {
56 
57 }
58 
59 template<unsigned DIM>
61 {
62 
63 }
64 
65 template<unsigned DIM>
67 {
68  mpNetwork = pNetwork;
69 }
70 
71 template<unsigned DIM>
72 boost::shared_ptr<DiscreteContinuumBoundaryCondition<DIM> > DiscreteContinuumBoundaryCondition<DIM>::Create()
73 {
75  return pSelf;
76 }
77 
78 template<unsigned DIM>
79 units::quantity<unit::concentration> DiscreteContinuumBoundaryCondition<DIM>::GetValue()
80 {
81  return mValue;
82 }
83 
84 template<unsigned DIM>
86 {
87  return mType;
88 }
89 
90 template<unsigned DIM>
91 void DiscreteContinuumBoundaryCondition<DIM>::UpdateBoundaryConditionContainer(boost::shared_ptr<BoundaryConditionsContainer<DIM, DIM, 1> > pContainer)
92 {
93  double node_distance_tolerance = 1.e-3;
94  bool apply_boundary = true;
95  bool use_boundry_nodes = false;
96  units::quantity<unit::length> length_scale = mpMesh->GetReferenceLengthScale();
97 
98  if(mType == BoundaryConditionType::OUTER)
99  {
100  pContainer->DefineConstantDirichletOnMeshBoundary(mpMesh.get(), mValue/mReferenceConcentration);
101  apply_boundary = false;
102  }
103  else if(mType == BoundaryConditionType::FACET || mType == BoundaryConditionType::VESSEL_VOLUME)
104  {
105  use_boundry_nodes = true;
106  }
107 
108  if(apply_boundary)
109  {
110  if(!use_boundry_nodes)
111  {
112  // Collect the node locations
113 
114  if(mType == BoundaryConditionType::IN_PART)
115  {
116  if(!mpDomain)
117  {
118  EXCEPTION("A part is required for this type of boundary condition");
119  }
120  else
121  {
122  std::vector<DimensionalChastePoint<DIM> > locations(mpMesh->GetNumNodes());
123  std::vector<unsigned> mesh_nodes(mpMesh->GetNumNodes());
124 
125  typename DiscreteContinuumMesh<DIM, DIM>::NodeIterator iter = mpMesh->GetNodeIteratorBegin();
126  unsigned counter=0;
127  while (iter != mpMesh->GetNodeIteratorEnd())
128  {
129  locations[counter] = DimensionalChastePoint<DIM>((*iter).GetPoint().rGetLocation(), length_scale);
130  mesh_nodes[counter] = (*iter).GetIndex();
131  counter++;
132  ++iter;
133  }
134  std::vector<bool> inside_flags = mpDomain->IsPointInPart(locations);
135  for(unsigned idx=0; idx<inside_flags.size(); idx++)
136  {
137  if(inside_flags[idx])
138  {
139  ConstBoundaryCondition<DIM>* p_fixed_boundary_condition = new ConstBoundaryCondition<DIM>(mValue/mReferenceConcentration);
140  pContainer->AddDirichletBoundaryCondition(mpMesh->GetNode(mesh_nodes[idx]), p_fixed_boundary_condition, 0, false);
141  }
142  }
143  }
144  }
145  else
146  {
147  typename DiscreteContinuumMesh<DIM, DIM>::NodeIterator iter = mpMesh->GetNodeIteratorBegin();
148 
149  while (iter != mpMesh->GetNodeIteratorEnd())
150  {
151  DimensionalChastePoint<DIM> probe_location((*iter).GetPoint().rGetLocation(), length_scale);
152  std::pair<bool,units::quantity<unit::concentration> > result = GetValue(probe_location, node_distance_tolerance);
153  if(result.first)
154  {
155  ConstBoundaryCondition<DIM>* p_fixed_boundary_condition = new ConstBoundaryCondition<DIM>(result.second/mReferenceConcentration);
156  pContainer->AddDirichletBoundaryCondition(&(*iter), p_fixed_boundary_condition, 0, false);
157  }
158  ++iter;
159  }
160  }
161  }
162  else
163  {
164  typename DiscreteContinuumMesh<DIM, DIM>::BoundaryNodeIterator iter = mpMesh->GetBoundaryNodeIteratorBegin();
165 
166  while (iter < mpMesh->GetBoundaryNodeIteratorEnd())
167  {
168  DimensionalChastePoint<DIM> probe_location((*iter)->GetPoint().rGetLocation(), length_scale);
169  std::pair<bool,units::quantity<unit::concentration> > result = GetValue(probe_location, node_distance_tolerance);
170  if(result.first)
171  {
172  ConstBoundaryCondition<DIM>* p_fixed_boundary_condition = new ConstBoundaryCondition<DIM>(result.second/mReferenceConcentration);
173  pContainer->AddDirichletBoundaryCondition(*iter, p_fixed_boundary_condition);
174  }
175  ++iter;
176  }
177  }
178  }
179 }
180 
181 template<unsigned DIM>
182 std::pair<bool, units::quantity<unit::concentration> > DiscreteContinuumBoundaryCondition<DIM>::GetValue(DimensionalChastePoint<DIM> location, double tolerance)
183 {
184  units::quantity<unit::length> length_scale = location.GetReferenceLengthScale();
185  std::pair<bool, units::quantity<unit::concentration> > result(false, 0.0*unit::mole_per_metre_cubed);
186  if(mType == BoundaryConditionType::POINT)
187  {
188  if(mPoints.size()==0)
189  {
190  EXCEPTION("A point is required for this type of boundary condition");
191  }
192  else
193  {
194  for(unsigned jdx=0; jdx<mPoints.size(); jdx++)
195  {
196  if(GetDistance<DIM>(location, mPoints[jdx]) < tolerance*length_scale)
197  {
198  return std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
199  }
200  }
201  }
202  }
203  else if(mType == BoundaryConditionType::FACET)
204  {
205  if(!mpDomain)
206  {
207  EXCEPTION("A part is required for this type of boundary condition");
208  }
209  else
210  {
211  std::vector<boost::shared_ptr<Facet<DIM> > > facets = mpDomain->GetFacets();
212  for(unsigned jdx=0; jdx<facets.size();jdx++)
213  {
214  if(facets[jdx]->ContainsPoint(location) && (facets[jdx]->GetLabel() == mLabel))
215  {
216  return std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
217  }
218  }
219  }
220  }
221 
222  else if(mType == BoundaryConditionType::VESSEL_LINE)
223  {
224  if(!mpNetwork)
225  {
226  EXCEPTION("A vessel network is required for this type of boundary condition");
227  }
228  else
229  {
230  std::vector<boost::shared_ptr<VesselSegment<DIM> > > segments = this->mpNetwork->GetVesselSegments();
231  for (unsigned jdx = 0; jdx < segments.size(); jdx++)
232  {
233  if (segments[jdx]->GetDistance(location) <= tolerance*length_scale)
234  {
235  if(BoundaryConditionSource::PRESCRIBED)
236  {
237  return std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
238  }
239  }
240  }
241  }
242  }
243 
244  else if(mType == BoundaryConditionType::VESSEL_VOLUME)
245  {
246  if(!mpNetwork)
247  {
248  EXCEPTION("A vessel network is required for this type of boundary condition");
249  }
250  else
251  {
252  std::vector<boost::shared_ptr<VesselSegment<DIM> > > segments = this->mpNetwork->GetVesselSegments();
253  for (unsigned jdx = 0; jdx < segments.size(); jdx++)
254  {
255  if (segments[jdx]->GetDistance(location) <= segments[jdx]->GetRadius() + tolerance*length_scale)
256  {
257  if(BoundaryConditionSource::PRESCRIBED)
258  {
259  return std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
260  }
261  }
262  }
263  }
264  }
265 
266  else if(mType == BoundaryConditionType::CELL)
267  {
268  EXCEPTION("Cell based boundary conditions are not yet supported.");
269  }
270  else if(mType == BoundaryConditionType::IN_PART)
271  {
272  if(!mpDomain)
273  {
274  EXCEPTION("A part is required for this type of boundary condition");
275  }
276  else
277  {
278  if(mpDomain->IsPointInPart(location))
279  {
280  if(BoundaryConditionSource::PRESCRIBED)
281  {
282  return std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
283  }
284  else
285  {
286  return std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
287  }
288  }
289  }
290  }
291  return result;
292 }
293 
294 template<unsigned DIM>
295 void DiscreteContinuumBoundaryCondition<DIM>::UpdateRegularGridPointBoundaryConditions(boost::shared_ptr<std::vector<std::pair<bool, units::quantity<unit::concentration> > > >pBoundaryConditions)
296 {
297  if(mPoints.size()==0)
298  {
299  EXCEPTION("A point is required for this type of boundary condition");
300  }
301  else
302  {
303  std::vector<std::vector<unsigned> > point_point_map = mpRegularGrid->GetPointPointMap(mPoints);
304  for(unsigned idx=0; idx<point_point_map.size(); idx++)
305  {
306  if(point_point_map[idx].size()>0)
307  {
308  (*pBoundaryConditions)[idx] = std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
309  }
310  }
311  }
312 }
313 
314 template<unsigned DIM>
315 void DiscreteContinuumBoundaryCondition<DIM>::UpdateRegularGridFacetBoundaryConditions(boost::shared_ptr<std::vector<std::pair<bool, units::quantity<unit::concentration> > > >pBoundaryConditions)
316 {
317  if(!mpDomain)
318  {
319  EXCEPTION("A part is required for this type of boundary condition");
320  }
321  else
322  {
323  double y_max = double(mpRegularGrid->GetExtents()[1]-1) * mpRegularGrid->GetSpacing()/mpRegularGrid->GetReferenceLengthScale();
324  for(unsigned idx=0; idx<mpRegularGrid->GetNumberOfPoints(); idx++)
325  {
326  if(mpRegularGrid->GetLocationOf1dIndex(idx).GetLocation(mpRegularGrid->GetReferenceLengthScale())[1] == y_max)
327  {
328  (*pBoundaryConditions)[idx] = std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
329  }
330 
331 // std::vector<boost::shared_ptr<Facet<DIM> > > facets = mpDomain->GetFacets();
332 // for(unsigned jdx=0; jdx<facets.size();jdx++)
333 // {
334 // if(facets[jdx]->ContainsPoint(mpRegularGrid->GetLocationOf1dIndex(idx)))
335 // {
336 // if(BoundaryConditionSource::PRESCRIBED)
337 // {
338 // (*pBoundaryConditions)[idx] = std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
339 // break;
340 // }
341 // else
342 // {
343 // if(facets[jdx]->GetLabel() == mLabel)
344 // {
345 // (*pBoundaryConditions)[idx] = std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
346 // break;
347 // }
348 // }
349 // }
350 // }
351  }
352  }
353 }
354 
355 template<unsigned DIM>
356 void DiscreteContinuumBoundaryCondition<DIM>::UpdateRegularGridSegmentBoundaryConditions(boost::shared_ptr<std::vector<std::pair<bool, units::quantity<unit::concentration> > > >pBoundaryConditions)
357 {
358  std::vector<std::vector<boost::shared_ptr<VesselSegment<DIM> > > > point_segment_map = mpRegularGrid->GetPointSegmentMap(true, !(mType == BoundaryConditionType::VESSEL_LINE));
359  for(unsigned idx=0; idx<point_segment_map.size(); idx++)
360  {
361  if(point_segment_map[idx].size()>0)
362  {
363  if(BoundaryConditionSource::PRESCRIBED)
364  {
365  (*pBoundaryConditions)[idx] = std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
366  }
367  }
368  }
369 }
370 
371 template<unsigned DIM>
372 void DiscreteContinuumBoundaryCondition<DIM>::UpdateRegularGridCellBoundaryConditions(boost::shared_ptr<std::vector<std::pair<bool, units::quantity<unit::concentration> > > >pBoundaryConditions)
373 {
374  EXCEPTION("Cell based boundary conditions are not yet supported.");
375 }
376 
377 template<unsigned DIM>
378 void DiscreteContinuumBoundaryCondition<DIM>::UpdateRegularGridPartBoundaryConditions(boost::shared_ptr<std::vector<std::pair<bool, units::quantity<unit::concentration> > > >pBoundaryConditions)
379 {
380  if(!mpDomain)
381  {
382  EXCEPTION("A part is required for this type of boundary condition");
383  }
384  else
385  {
386  for(unsigned idx=0; idx<mpRegularGrid->GetNumberOfPoints(); idx++)
387  {
388  if(mpDomain->IsPointInPart(mpRegularGrid->GetLocationOf1dIndex(idx)))
389  {
390  if(BoundaryConditionSource::PRESCRIBED)
391  {
392  (*pBoundaryConditions)[idx] = std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
393  break;
394  }
395  else
396  {
397  (*pBoundaryConditions)[idx] = std::pair<bool, units::quantity<unit::concentration> >(true, mValue);
398  break;
399  }
400  }
401  }
402  }
403 }
404 
405 template<unsigned DIM>
406 void DiscreteContinuumBoundaryCondition<DIM>::UpdateRegularGridBoundaryConditions(boost::shared_ptr<std::vector<std::pair<bool, units::quantity<unit::concentration> > > >pBoundaryConditions)
407 {
408  if(! mpRegularGrid)
409  {
410  EXCEPTION("A grid has not been set for the determination of boundary condition values. For FE solvers use GetBoundaryConditionContainer()");
411  }
412 
413  // Check the boundary condition type
414  if(mType == BoundaryConditionType::OUTER)
415  {
416  for(unsigned idx=0; idx<mpRegularGrid->GetNumberOfPoints(); idx++)
417  {
418  (*pBoundaryConditions)[idx] = std::pair<bool, units::quantity<unit::concentration> > (mpRegularGrid->IsOnBoundary(idx), mValue);
419  }
420  }
421  else if(mType == BoundaryConditionType::POINT)
422  {
423  UpdateRegularGridPointBoundaryConditions(pBoundaryConditions);
424  }
425  else if(mType == BoundaryConditionType::FACET)
426  {
427  UpdateRegularGridFacetBoundaryConditions(pBoundaryConditions);
428  }
429  else if(mType == BoundaryConditionType::VESSEL_LINE or mType == BoundaryConditionType::VESSEL_VOLUME)
430  {
431  UpdateRegularGridSegmentBoundaryConditions(pBoundaryConditions);
432  }
433  else if(mType == BoundaryConditionType::CELL)
434  {
435  UpdateRegularGridCellBoundaryConditions(pBoundaryConditions);
436  }
437  else if(mType == BoundaryConditionType::IN_PART)
438  {
439  UpdateRegularGridPartBoundaryConditions(pBoundaryConditions);
440  }
441 }
442 
443 template<unsigned DIM>
445 {
446  mpDomain = pDomain;
447 }
448 
449 template<unsigned DIM>
451 {
452  mPoints = points;
453 }
454 
455 template<unsigned DIM>
456 void DiscreteContinuumBoundaryCondition<DIM>::SetSource(BoundaryConditionSource::Value boundarySource)
457 {
458  mSource = boundarySource;
459 }
460 
461 template<unsigned DIM>
463 {
464  mType = boundaryType;
465 }
466 
467 template<unsigned DIM>
469 {
470  mpRegularGrid = pRegularGrid;
471 }
472 
473 template<unsigned DIM>
475 {
476  mpMesh = pMesh;
477 }
478 
479 template<unsigned DIM>
481 {
482  mLabel = label;
483 }
484 
485 template<unsigned DIM>
486 void DiscreteContinuumBoundaryCondition<DIM>::SetValue(units::quantity<unit::concentration> value)
487 {
488  mValue = value;
489 }
490 
491 // Explicit instantiation
void SetSource(BoundaryConditionSource::Value boundarySource)
units::quantity< unit::length > GetReferenceLengthScale() const
void SetValue(units::quantity< unit::concentration > value)
void SetPoints(std::vector< DimensionalChastePoint< DIM > > points)
void SetType(BoundaryConditionType::Value boundaryType)
void UpdateBoundaryConditionContainer(boost::shared_ptr< BoundaryConditionsContainer< DIM, DIM, 1 > > pContainer)
boost::shared_ptr< RegularGrid< DIM > > mpRegularGrid
void SetDomain(boost::shared_ptr< Part< DIM > > pDomain)
static boost::shared_ptr< DiscreteContinuumBoundaryCondition< DIM > > Create()
void SetRegularGrid(boost::shared_ptr< RegularGrid< DIM > > pRegularGrid)
void SetMesh(boost::shared_ptr< DiscreteContinuumMesh< DIM, DIM > > pMesh)
void UpdateRegularGridBoundaryConditions(boost::shared_ptr< std::vector< std::pair< bool, units::quantity< unit::concentration > > > > pBoundaryConditions)
units::quantity< unit::concentration > GetValue()
std::vector< DimensionalChastePoint< DIM > > mPoints
Definition: Part.hpp:60
units::quantity< unit::concentration > mValue
boost::shared_ptr< DiscreteContinuumMesh< DIM, DIM > > mpMesh