Chaste  Release::3.4
PlaneBoundaryCondition.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 "PlaneBoundaryCondition.hpp"
37 #include "AbstractCentreBasedCellPopulation.hpp"
38 #include "VertexBasedCellPopulation.hpp"
39 #include "RandomNumberGenerator.hpp"
40 
41 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
43  c_vector<double, SPACE_DIM> point,
44  c_vector<double, SPACE_DIM> normal)
45  : AbstractCellPopulationBoundaryCondition<ELEMENT_DIM,SPACE_DIM>(pCellPopulation),
46  mPointOnPlane(point),
47  mUseJiggledNodesOnPlane(false)
48 {
49  assert(norm_2(normal) > 0.0);
50  mNormalToPlane = normal/norm_2(normal);
51 }
52 
53 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
54 const c_vector<double, SPACE_DIM>& PlaneBoundaryCondition<ELEMENT_DIM,SPACE_DIM>::rGetPointOnPlane() const
55 {
56  return mPointOnPlane;
57 }
58 
59 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
60 const c_vector<double, SPACE_DIM>& PlaneBoundaryCondition<ELEMENT_DIM,SPACE_DIM>::rGetNormalToPlane() const
61 {
62  return mNormalToPlane;
63 }
64 
65 
66 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
68 {
69  mUseJiggledNodesOnPlane = useJiggledNodesOnPlane;
70 }
71 
72 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
74 {
75  return mUseJiggledNodesOnPlane;
76 }
77 
78 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
79 void PlaneBoundaryCondition<ELEMENT_DIM,SPACE_DIM>::ImposeBoundaryCondition(const std::map<Node<SPACE_DIM>*, c_vector<double, SPACE_DIM> >& rOldLocations)
80 {
82  if (dynamic_cast<AbstractOffLatticeCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(this->mpCellPopulation)==NULL)
83  {
84  EXCEPTION("PlaneBoundaryCondition requires a subclass of AbstractOffLatticeCellPopulation.");
85  }
86 
87  assert((dynamic_cast<AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(this->mpCellPopulation))
88  || (SPACE_DIM==ELEMENT_DIM && (dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(this->mpCellPopulation))) );
89 
90  // THis is a magic number.
91  double max_jiggle = 1e-4;
92 
93  if (SPACE_DIM != 1)
94  {
95  if (dynamic_cast<AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(this->mpCellPopulation))
96  {
97  for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->mpCellPopulation->Begin();
98  cell_iter != this->mpCellPopulation->End();
99  ++cell_iter)
100  {
101  unsigned node_index = this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
102  Node<SPACE_DIM>* p_node = this->mpCellPopulation->GetNode(node_index);
103 
104  c_vector<double, SPACE_DIM> node_location = p_node->rGetLocation();
105 
106  double signed_distance = inner_prod(node_location - mPointOnPlane, mNormalToPlane);
107  if (signed_distance > 0.0)
108  {
109  // For the closest point on the plane we travel from node_location the signed_distance in the direction of -mNormalToPlane
110  c_vector<double, SPACE_DIM> nearest_point;
111  if (mUseJiggledNodesOnPlane)
112  {
113  nearest_point = node_location - (signed_distance+max_jiggle*RandomNumberGenerator::Instance()->ranf())*mNormalToPlane;
114  }
115  else
116  {
117  nearest_point = node_location - signed_distance*mNormalToPlane;
118  }
119  p_node->rGetModifiableLocation() = nearest_point;
120  }
121  }
122  }
123  else
124  {
125  assert(SPACE_DIM==ELEMENT_DIM);
126  assert(dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(this->mpCellPopulation));
127 
128  // Iterate over all nodes and update their positions according to the boundary conditions
129  unsigned num_nodes = this->mpCellPopulation->GetNumNodes();
130  for (unsigned node_index=0; node_index<num_nodes; node_index++)
131  {
132  Node<SPACE_DIM>* p_node = this->mpCellPopulation->GetNode(node_index);
133  c_vector<double, SPACE_DIM> node_location = p_node->rGetLocation();
134 
135  double signed_distance = inner_prod(node_location - mPointOnPlane, mNormalToPlane);
136  if (signed_distance > 0.0)
137  {
138  // For the closest point on the plane we travel from node_location the signed_distance in the direction of -mNormalToPlane
139  c_vector<double, SPACE_DIM> nearest_point;
140  if (mUseJiggledNodesOnPlane)
141  {
142  nearest_point = node_location - (signed_distance+max_jiggle*RandomNumberGenerator::Instance()->ranf())*mNormalToPlane;
143  }
144  else
145  {
146  nearest_point = node_location - signed_distance*mNormalToPlane;
147  }
148  p_node->rGetModifiableLocation() = nearest_point;
149  }
150  }
151  }
152  }
153  else
154  {
155  // DIM == 1
157  //PlaneBoundaryCondition::ImposeBoundaryCondition is not implemented in 1D
158  }
159 }
160 
161 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
163 {
164  bool condition_satisfied = true;
165 
166  if (SPACE_DIM == 1)
167  {
168  EXCEPTION("PlaneBoundaryCondition is not implemented in 1D");
169  }
170  else
171  {
172  for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->mpCellPopulation->Begin();
173  cell_iter != this->mpCellPopulation->End();
174  ++cell_iter)
175  {
176  c_vector<double, SPACE_DIM> cell_location = this->mpCellPopulation->GetLocationOfCellCentre(*cell_iter);
177 
178  if (inner_prod(cell_location - mPointOnPlane, mNormalToPlane) > 0.0)
179  {
180  condition_satisfied = false;
181  break;
182  }
183  }
184  }
185 
186  return condition_satisfied;
187 }
188 
189 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
191 {
192  *rParamsFile << "\t\t\t<PointOnPlane>";
193  for (unsigned index=0; index != SPACE_DIM-1U; index++) // Note: inequality avoids testing index < 0U when DIM=1
194  {
195  *rParamsFile << mPointOnPlane[index] << ",";
196  }
197  *rParamsFile << mPointOnPlane[SPACE_DIM-1] << "</PointOnPlane>\n";
198 
199  *rParamsFile << "\t\t\t<NormalToPlane>";
200  for (unsigned index=0; index != SPACE_DIM-1U; index++) // Note: inequality avoids testing index < 0U when DIM=1
201  {
202  *rParamsFile << mNormalToPlane[index] << ",";
203  }
204  *rParamsFile << mNormalToPlane[SPACE_DIM-1] << "</NormalToPlane>\n";
205  *rParamsFile << "\t\t\t<UseJiggledNodesOnPlane>" << mUseJiggledNodesOnPlane << "</UseJiggledNodesOnPlane>\n";
206 
207  // Call method on direct parent class
209 }
210 
211 // Explicit instantiation
212 template class PlaneBoundaryCondition<1,1>;
213 template class PlaneBoundaryCondition<1,2>;
214 template class PlaneBoundaryCondition<2,2>;
215 template class PlaneBoundaryCondition<1,3>;
216 template class PlaneBoundaryCondition<2,3>;
217 template class PlaneBoundaryCondition<3,3>;
218 
219 // Serialization for Boost >= 1.36
Definition: Node.hpp:58
#define EXCEPTION(message)
Definition: Exception.hpp:143
#define NEVER_REACHED
Definition: Exception.hpp:206
void ImposeBoundaryCondition(const std::map< Node< SPACE_DIM > *, c_vector< double, SPACE_DIM > > &rOldLocations)
static RandomNumberGenerator * Instance()
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
void OutputCellPopulationBoundaryConditionParameters(out_stream &rParamsFile)
const c_vector< double, SPACE_DIM > & rGetLocation() const
Definition: Node.cpp:140
c_vector< double, SPACE_DIM > mNormalToPlane
PlaneBoundaryCondition(AbstractCellPopulation< ELEMENT_DIM, SPACE_DIM > *pCellPopulation, c_vector< double, SPACE_DIM > point, c_vector< double, SPACE_DIM > normal)
void SetUseJiggledNodesOnPlane(bool useJiggledNodesOnPlane)
const c_vector< double, SPACE_DIM > & rGetNormalToPlane() const
c_vector< double, SPACE_DIM > & rGetModifiableLocation()
Definition: Node.cpp:152
virtual void OutputCellPopulationBoundaryConditionParameters(out_stream &rParamsFile)=0
const c_vector< double, SPACE_DIM > & rGetPointOnPlane() const