VPTissue Reference Manual
Grow.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2016 Universiteit Antwerpen
3  *
4  * Licensed under the EUPL, Version 1.1 or as soon they will be approved by
5  * the European Commission - subsequent versions of the EUPL (the "Licence");
6  * You may not use this work except in compliance with the Licence.
7  * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl5
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the Licence is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the Licence for the specific language governing
13  * permissions and limitations under the Licence.
14  */
20 #include "Grow.h"
21 
22 #include "algo/NodeInserter.h"
23 #include "algo/NodeMover.h"
24 #include "bio/Mesh.h"
25 //#include "math/CSRMatrix.h"
26 //#include "math/MeshTopology.h"
27 //#include "util/config/ConfigInfo.h"
28 
29 #include <boost/circular_buffer.hpp>
30 //#include <omp.h>
31 #include <algorithm>
32 #include <cmath>
33 #include <tuple>
34 
35 namespace SimPT_Default {
36 namespace TimeEvolver {
37 
38 using namespace std;
39 using namespace boost::property_tree;
40 using namespace SimPT_Sim::Util;
41 
42 Grow::Grow(const CoreData& cd)
43 {
44  Initialize(cd);
45 }
46 
47 void Grow::Initialize(const CoreData& cd)
48 {
49  assert( cd.Check() && "CoreData not ok.");
50  m_cd = cd;
51 
52  const auto& p = m_cd.m_parameters;
53  m_mc_cell_step_size = p->get<double>("cell_mechanics.mc_cell_stepsize");
54 
55  m_mc_retry_limit = p->get<unsigned int>("cell_mechanics.mc_retry_limit");
56  m_mc_sliding_window = p->get<unsigned int>("cell_mechanics.mc_sliding_window");
57  m_mc_step_size = p->get<double>("cell_mechanics.mc_stepsize");
58  m_mc_sweep_limit = p->get<double>("cell_mechanics.mc_sweep_limit");
59  m_mc_temperature = p->get<double>("cell_mechanics.mc_temperature");
60  m_stationarity_check = p->get<bool>("termination.stationarity_check");
61 
62  const double abs_tol = abs(p->get<double>("cell_mechanics.mc_abs_tolerance"));
63  m_mc_abs_tolerance = abs_tol;
64  const double rel_tol = abs(p->get<double>("cell_mechanics.mc_rel_tolerance"));
65  const bool stringent = p->get<bool>("cell_mechanics.mc_stringent_tolerance", false);
66  if (stringent) {
67  m_within_tolerance = [abs_tol, rel_tol](double dh, double e) {
68  return (dh <= 0.0) && (abs(dh) < min(abs_tol, abs(e * rel_tol)));
69  };
70  } else {
71  m_within_tolerance = [abs_tol, rel_tol](double dh, double e) {
72  return (dh <= 0.0) && (abs(dh) < max(abs_tol, abs(e * rel_tol)));
73  };
74  }
75 }
76 
77 std::tuple<SimTimingTraits::CumulativeTimings, bool> Grow::operator()(double, SimPhase)
78 {
79  // --------------------------------------------------------------------------
80  // Intro
81  // --------------------------------------------------------------------------
82  Stopclock chrono_grow("growth", true);
83 
84  // --------------------------------------------------------------------------
85  // Node insertion.
86  // --------------------------------------------------------------------------
87  NodeInserter node_inserter;
88  node_inserter.Initialize(m_cd);
89  const unsigned int nodes_inserted = node_inserter.InsertNodes();
90 
91  // --------------------------------------------------------------------------
92  // Node motion (elastic relaxation). No time increase here.
93  // --------------------------------------------------------------------------
94  NodeMover node_mover;
95  node_mover.Initialize(m_cd);
96  double temperature = m_mc_temperature;
97  const double alpha_temperature = 0.95; // annealing schedule: T -> alpha * T
98  const double e_tissue_before = node_mover.GetTissueEnergy();
99 
100  // ----------- Energy sliding window and counters.
101  boost::circular_buffer<double> cb(m_mc_sliding_window);
102  double mean_dh = 0.0;
103  unsigned int sweep_count = 0U;
104  unsigned int retry_count = 0U;
105  unsigned int total_move_down_count = 0U;
106  bool go_on = false;
107 
108  // ----------- Calculate cell based node incidence and edge based node incidence if needed.
109 // CSRMatrix cell_incidence;
110 // CSRMatrix edge_incidence;
111 // if (ConfigInfo::HaveOpenMP()) {
112 // cell_incidence = MeshTopology::NodeCellNodeIncidence(m_cd.m_mesh);
113 // if (node_mover.UsesDeltaHamiltonian()) {
114 // edge_incidence = MeshTopology::NodeEdgeNodeIncidence(m_cd.m_mesh);
115 // }
116 // }
117 
118  // ----------- Sweep over mesh until convergence criteria are satisfied.
119  do {
120  ++sweep_count;
121  ++retry_count;
122 
123  // Actual node moves.
125 // if (ConfigInfo::HaveOpenMP() && node_mover.UsesDeltaHamiltonian()) {
126 // info = node_mover.SweepOverNodes(cell_incidence, edge_incidence, m_mc_step_size, temperature);
127 // } else if (ConfigInfo::HaveOpenMP()) {
128 // info = node_mover.SweepOverNodes(cell_incidence, m_mc_step_size, temperature);
129 //
130 // } else {
131 // info = node_mover.SweepOverNodes(m_mc_step_size, temperature);
132 // }
133 
134  info = node_mover.SweepOverNodes(m_mc_step_size, temperature);
135 
136  // Process the situation.
137  total_move_down_count += info.down_count;
138  cb.push_back(info.down_dh + info.up_dh);
139  mean_dh = std::accumulate(cb.begin(), cb.end(), 0.0) / cb.size();
140 
141  // If the energy has dropped a lot we reset the retry counter for
142  // to zero because we need to explore further.
143  retry_count = mean_dh < -abs(m_mc_abs_tolerance) ? 0U : retry_count;
144 
145  // Stopping condition:
146  // Criterion 1: We want to decide depending on average energy drop
147  // over a number of sweeps. So be sure you've made that many sweeps.
148  // Criterion 2: If the energy has dropped a lot (defined as more than the
149  // tolerance value, either absolute or relative) we want to go on.
150  // Criterion 3: If there was an energy increase, we want to retry a number
151  // of times before giving up.
152  go_on = (sweep_count < m_mc_sliding_window) || (! m_within_tolerance(mean_dh, e_tissue_before))
153  || (mean_dh > 0.0 && retry_count < m_mc_retry_limit);
154 
155  // Adjust temperature for next sweep.
156  temperature *= alpha_temperature;
157 
158  } while (go_on && sweep_count < m_mc_sweep_limit);
159 
160  const bool is_stationary = (nodes_inserted == 0U) && (total_move_down_count == 0U);
161 
162  // -------------------------------------------------------------------------------
163  // We are done ...
164  // -------------------------------------------------------------------------------
165  CumulativeTimings timings;
166  timings.Record(chrono_grow.GetName(), chrono_grow.Get());
167  return make_tuple(timings, is_stationary);
168 }
169 
170 } // namespace
171 } // namespace
172 
void Initialize(const CoreData &cd)
Initializes based on values in property tree.
Core data with mesh, parameters, random engine and time data.
Definition: CoreData.h:38
STL namespace.
void Initialize(const CoreData &cd)
Initialize or re-initialize.
Definition: Grow.cpp:47
Namespace for miscellaneous utilities.
Definition: PTreeFile.cpp:44
double GetTissueEnergy() const
Get current energy for the whole tissue.
Definition: NodeMover.h:96
Interface for NodeMover.
std::string GetName() const
Return name of this stopwatch.
Definition: Stopwatch.h:88
MetropolisInfo SweepOverNodes(double step_size, double temperature)
Sweep over all nodes, do metropolis move for each of them.
Definition: NodeMover.cpp:234
Cell mechanics by displacement and insertion of nodes.
Definition: NodeMover.h:46
Namespace for components of the Default model group.
std::tuple< SimTimingTraits::CumulativeTimings, bool > operator()(double time_slice=0.0, SimPhase phase=SimPhase::NONE)
Take a time evolution step.
Definition: Grow.cpp:77
Utility class to record durations in a cumulative manner.
Insertion of nodes in existing edges (contributes to the cell mechanics).
Definition: NodeInserter.h:34
T::duration Get() const
Returns the accumulated value without altering the stopwatch state.
Definition: Stopwatch.h:94
void Initialize(const CoreData &cd)
Initializes based on values in property tree.
Definition: NodeMover.cpp:81
unsigned int InsertNodes()
Insert nodes in those edges that have been stretched.
Provides a stopwatch interface to time: it accumulates time between start/stop pairs.
Definition: Stopwatch.h:39
Interface for NodeInserter.
Time evolver for Grow only.
void Record(const std::string &name, const std::chrono::duration< R, P > &duration)
Record the duration for the given name.
Grow(const CoreData &cd)
Initializing constructor.
Definition: Grow.cpp:42
Information gathered to evaluat effects of Metropolis Algorithm.
Definition: NodeMover.h:52
bool Check() const
Verify all pointers non-null.
Definition: CoreData.h:53
Interface for Mesh.