Swarm-NG  1.1
tutorial_monitor.hpp
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) 2009-2010 by Eric Ford & the Swarm-NG Development Team *
3  * *
4  * This program is free software; you can redistribute it and/or modify *
5  * it under the terms of the GNU General Public License as published by *
6  * the Free Software Foundation; either version 3 of the License. *
7  * *
8  * This program is distributed in the hope that it will be useful, *
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11  * GNU General Public License for more details. *
12  * *
13  * You should have received a copy of the GNU General Public License *
14  * along with this program; if not, write to the *
15  * Free Software Foundation, Inc., *
16  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
17  ************************************************************************/
18 
24 /*
25  * This is a simple tutorial used in doxygen pages
26  * should go through program2doxygen before it
27  * can be used by doxygen.
28  *
29  *
30  */
31 // @page TutorialMonitor Tutorial for making a monitor (stopper/logger)
32 // A “monitor” class is responsible for determining when the system state
33 // should be logged and when the GPU should cease integrating a given system.
34 // If the monitor determines that logging is needed, then the system’s current
35 // state is written to a buffer in the GPU global device memory.
36 //
37 //
38 // Let's examine the tutorial included in this distribution @ref src/tutorials/tutorial_monitor.hpp.
39 // In this tutorial, we write a monitor that examines the distance of bodies to the origin.
40 // For planetary systems with barycenter or star at origin, this is generally means that
41 // the planet is is considered *ejected* and is no longer not considered part of the planetary system.
42 //
43 // If any planet is too far from origin, planet's information is written to a log and the system
44 // will be disabled. Disabling a
45 // system (by setting the system state to disabled) prevents the system from advancing
46 // in time until the state is set back to active. Usually the user
47 // application should examine the system and decide if the system should be
48 // re-activated.
49 //
50 // Let's take a look at the code, first comes the preamble:
51 
52 #pragma once
53 #include <limits>
54 
55 const double POSITIVE_INFINITY = std::numeric_limits<double>::max();
56 
57 namespace swarm { namespace monitors {
58 
59 // Similar to a propagator, the parameters that need to be speficied
60 // in the configuration files should be stored in a separate struct because
61 // the main class is a template.
62 //
63 // For our simple monitor we only need to read in the maximum allowed distance
64 // of planet to origin.
65 //
66 // Notice that the parameter is optional, if it is not provided, we use
67 // a default value of POSITIVE_INFINITY, meaning that by default there
68 // is no restriction.
69 struct TutorialMonitor_params
70 {
71  double max_distance_from_origin;
73  TutorialMonitor_params(const config &cfg)
74  {
75  max_distance_from_origin = cfg.optional("max_distance_from_origin",POSITIVE_INFINITY);
76  }
77 };
78 
79 // Now the defining class of the monitor begins. The class should work with any implementation
80 // of logging system (There are two in Swarm-NG: host log and GPU log). So the log_t class is
81 // provided as a template parameter.
82 //
83 template<class log_t>
84 class TutorialMonitor
85 {
86 
87 // The parameter struct should be typedefed as params so the
88 // generic integrator can find it.
89 public:
90 typedef TutorialMonitor_params params;
91 
92 // These references are necessary for the monitor to function
93 // _params is our parameters, _sys is a reference to the system
94 // we are working on, and _log is a reference to the object
95 // the performs all the logging.
96 //
97 // These variable are provided in the constructor.
98 private:
99 params _params;
100 ensemble::SystemRef& _sys;
101 log_t& _log;
102 
104 public:
105 GPUAPI TutorialMonitor(const params& p,ensemble::SystemRef& s,log_t& l)
106  :_params(p),_sys(s),_log(l){}
107 
108 
109 // The monitor is implemented as a function object. It has a default
110 // function: to monitor the system. When it is called like a function
111 // with the system relative thread ID, it should perform the test
112 // and make changes as necessary. The parameter thread_in_system is
113 // provided for multi-threaded monitors. For single-threaded monitors
114 // We just use the thread 0 and don't do anything for other threads.
115 //
116 GPUAPI void operator () (const int thread_in_system)
117 {
118  if(thread_in_system == 0)
119  {
120  bool need_to_take_action = is_there_any_ejection();
121 
122  if(need_to_take_action)
123  {
124  log::system(_log, _sys);
125  _sys.disable();
126  }
127  }
128 }
129 // The plan is simple, we test the system to see if there
130 // is any ejection (more details below). If there is any,
131 // we need to take action, otherwise our work is done
132 // We take two actions:
133 //
134 // 1. Write current state of the system to the log.
135 // 2. Disable the system
136 //
137 // The developer is free choose to do any of these two, or both.
138 // Here we show both actions.
139 //
140 //
141 // For the test, we write a loop over all the bodies and use
142 // the accessor method distance_to_origin to get the value.
143 // If the distance is greater than the provided parameter
144 // then we break out of the loop and report that there is
145 // an ejection.
146 //
147 // Otherwise, the test returns false.
149 GPUAPI bool is_there_any_ejection()
150 {
151  for(int b = 0; b < _sys.nbod(); b++){
152  double distance_to_origin = _sys[b].distance_to_origin();
153  if(distance_to_origin > _params.max_distance_from_origin)
154  return true;
155  }
156  return false;
157 }
158 
159 // This concludes the implementation of the monitor
160 //
161 // The following three lines are just closing braces for class and namespace
162 }; // end class TutorialMonitor
163 } } // end namespace monitor, end namespace swarm
164