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