VPTissue Reference Manual
CoupledSim.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 "CoupledSim.h"
21 
22 #include "CoreData.h"
24 #include "TimeSlicer.h"
25 #include "Sim.h"
27 #include "util/misc/Exception.h"
28 
29 #include <iostream>
30 #include <thread>
31 
32 using namespace std;
33 using boost::property_tree::ptree;
34 using namespace SimPT_Sim::ClockMan;
35 using namespace SimPT_Sim::Util;
36 
37 namespace SimPT_Sim {
38 
39 CoupledSim::CoupledSim()
40  : m_sim_step(0), m_sim_ODE_steps(0)
41 {
42 }
43 
44 const ptree& CoupledSim::GetParameters() const
45 {
46  return *m_cd.m_parameters;
47 }
48 
50 {
51  return m_project_name;
52 }
53 
54 string CoupledSim::GetRunDate() const
55 {
56  return m_run_date;
57 }
58 
60 {
61  return m_sim_step;
62 }
63 
64 CoupledSim::Timings CoupledSim::GetTimings() const
65 {
66  Timings timings = m_timings;
67  for (const auto& simPair : m_simulators) {
68  timings.Merge(simPair.second->GetTimings());
69  }
70  return timings;
71 }
72 
73 void CoupledSim::Initialize(const ptree& pt, const std::vector<std::shared_ptr<Sim>>& simulators)
74 {
75  for (const auto &sim : simulators) {
76  if (m_simulators.count(sim->GetProjectName()) == 0) {
77  m_simulators[sim->GetProjectName()] = sim;
78  } else {
79  throw Exception("Subsimulations with the same name!");
80  }
81  }
82 
83  const ptree& sim_pt = pt.get_child("vleaf2");
84  m_project_name = sim_pt.get<std::string>("project");
85  m_run_date = TimeStamp().ToString();
86  m_sim_step = sim_pt.get<unsigned int>("sim_step", 0U);
87  m_sim_ODE_steps = sim_pt.get<unsigned int>("sim_ODE_coupling_steps", 1U);
88  m_cd.m_parameters = make_shared<ptree>();
89  Reinitialize(sim_pt.get_child("parameters"));
90 }
91 
93 {
94  bool status = true;
95  for (const auto& simPair : m_simulators) {
96  status = status && simPair.second->IsAtTermination();
97  if (!status) break;
98  }
99  return status;
100 }
101 
103 {
104  bool status = true;
105  for (const auto& simPair : m_simulators) {
106  status = status && simPair.second->IsStationary();
107  if (!status) break;
108  }
109  return status;
110 }
111 
112 void CoupledSim::Reinitialize(const ptree& parameters)
113 {
114  // Read couplers from parameters
116  const auto& coupler_array_pt = parameters.get_child("coupler_array");
117  for (const auto& pair : coupler_array_pt) {
118 
119  const auto type = pair.second.get<std::string>("type");
120  const auto from = pair.second.get<std::string>("from");
121  const auto to = pair.second.get<std::string>("to");
122 
123  if (!factory.IsValid(type))
124  throw Exception("Couldn't find coupler type: " + type);
125 
126  auto fromIt = m_simulators.find(from);
127  if (fromIt == m_simulators.end()) {
128  throw Exception("Couldn't find 'from'-simulation used in coupler: " + from);
129  }
130  auto toIt = m_simulators.find(to);
131  if (toIt == m_simulators.end()) {
132  throw Exception("Couldn't find 'to'-simulation used in coupler: " + to);
133  }
134  auto coupler = factory.Get(type)();
135  coupler->Initialize(pair.second.get_child("parameters"),
136  fromIt->second->GetCoreData(), toIt->second->GetCoreData());
137  m_couplers.push_back(coupler);
138  }
139 }
140 
142 {
143  // Compute the time slice.
144  const int n = m_sim_ODE_steps;
145  const auto params = m_simulators.begin()->second->GetCoreData().m_parameters;
146  const double time_slice = params->get<double>("model.time_step")/static_cast<double>(n);
147 
148  // Produce the TimeSlicers.
149  vector<unique_ptr<TimeSlicer>> t_slicers;
150  for (const auto& sim : m_simulators) {
151  t_slicers.push_back(sim.second->TimeSlicing());
152  }
153 
154  // Transport ODE's using time slices interleaved by coupling.
155  vector<std::thread> sim_threads;
156  for (int i = 0; i < n; ++i) {
157  for (const auto& t_slicer : t_slicers) {
158  sim_threads.push_back(thread(
159  [&t_slicer, time_slice] () {t_slicer->Go(time_slice, SimPhase::_1);}
160  ));
161  }
162 
163  // Join all threads, then clear thread vector.
164  for (auto& thread : sim_threads) {
165  thread.join();
166  }
167  sim_threads.clear();
168 
169  // Couple all sub-simulations
170  Stopclock couplerChrono("couplers", true);
171  for (auto coupler : m_couplers) {
172  coupler->Exec();
173  }
174  m_timings.Record(couplerChrono.GetName(), couplerChrono.Get());
175  }
176 
177  // Mechanics and Houskeeping (sim_threads has been cleared, so it's ready for use).
178  for (const auto& t_slicer : t_slicers) {
179  sim_threads.push_back(thread(
180  [&t_slicer] () {
181  t_slicer->Go(0.0, SimPhase::_2);
182  t_slicer->IncrementStepCount(); // Time step completely finished.
183  }
184  ));
185  }
186  for (auto& thread : sim_threads) {
187  thread.join();
188  }
189 
190  // Timestep updating for coupled sim.
192 }
193 
194 } // namespace
STL namespace.
std::string GetRunDate() const
Definition: CoupledSim.cpp:54
Core data used during model execution.
Namespace for miscellaneous utilities.
Definition: PTreeFile.cpp:44
void Initialize(const boost::property_tree::ptree &pt, const std::vector< std::shared_ptr< Sim >> &simulators)
Initialize with full configuration (complete setup prior to first use).
Definition: CoupledSim.cpp:73
void IncrementStepCount()
Increase the current time step counter by one.
Definition: CoupledSim.h:72
std::string GetProjectName() const
Definition: CoupledSim.cpp:49
std::string GetName() const
Return name of this stopwatch.
Definition: Stopwatch.h:88
bool IsStationary() const
Definition: CoupledSim.cpp:102
const boost::property_tree::ptree & GetParameters() const
Definition: CoupledSim.cpp:44
Extremely simple Exception root class.
Definition: Exception.h:28
void Reinitialize(const boost::property_tree::ptree &parameters)
Definition: CoupledSim.cpp:112
Namespace for the core simulator.
bool IsAtTermination() const
Definition: CoupledSim.cpp:92
bool IsValid(const std::string &name) const
Check whether function name is present.
Definition: FunctionMap.h:63
A coupler factory map that is used to register names for these couplers.
TimeStamp class.
Sim, the actual simulator.
T::duration Get() const
Returns the accumulated value without altering the stopwatch state.
Definition: Stopwatch.h:94
FunctionType Get(const std::string &name) const
Return function for given name.
Definition: FunctionMap.h:57
Provides wall-clock time stamp using the time call.
Definition: TimeStamp.h:37
Provides a stopwatch interface to time: it accumulates time between start/stop pairs.
Definition: Stopwatch.h:39
Header file for Exception class.
Timings GetTimings() const
Definition: CoupledSim.cpp:64
std::string ToString() const
Returns string with the time stamp after eliminating newline.
Definition: TimeStamp.h:44
int GetSimStep() const
Definition: CoupledSim.cpp:59
Time slice propagation.
Interface for CouplerFactories.
Interface for CoupledSim.
Namespace for clock and timekeeping related classes.
Definition: ClockCLib.h:27