Swarm-NG  1.1
module.cpp
Go to the documentation of this file.
1 #include "swarm/swarm.h"
2 #include "swarm/snapshot.hpp"
3 #include "swarm/kepler.h"
4 #include <boost/python.hpp>
5 #include <boost/python/suite/indexing/map_indexing_suite.hpp>
6 
20 extern "C" int python_hexversion(){ return PY_VERSION_HEX; }
21 extern "C" char* python_version(){ return PY_VERSION; }
22 
23 
24 using std::string;
25 using namespace boost::python;
26 using boost::noncopyable;
27 using namespace swarm;
28 
29 gpu::Pintegrator create_gpu_integrator(const config& cfg){
30  return boost::dynamic_pointer_cast<gpu::integrator>(integrator::create(cfg));
31 }
32 
33 #define PROPERTY_ACCESSOR(CLASS,PROPERTY,TYPE) \
34  void set_##PROPERTY( CLASS &r, const TYPE & t) \
35  { r.PROPERTY() = t; } \
36  TYPE get_##PROPERTY( CLASS &r) \
37  { return r.PROPERTY(); }
38 
39 PROPERTY_ACCESSOR(ensemble::SystemRef, time, double )
40 PROPERTY_ACCESSOR(ensemble::SystemRef, id , int )
41 PROPERTY_ACCESSOR(ensemble::SystemRef, state , int )
42 
43 PROPERTY_ACCESSOR(ensemble::Body , mass, double )
44 PROPERTY_ACCESSOR(ensemble::Body::Component, pos, double )
45 PROPERTY_ACCESSOR(ensemble::Body::Component, vel, double )
46 
47 config load_config(const std::string &fn){
48  return config::load(fn);
49 }
50 
51 void set_pos_list(ensemble::Body& b, const list& p ){
52  b[0].pos() = extract<double>(p[0]);
53  b[1].pos() = extract<double>(p[1]);
54  b[2].pos() = extract<double>(p[2]);
55 }
56 
57 list get_pos_list(const ensemble::Body& b){
58  list p;
59  p.append( b[0].pos() );
60  p.append( b[1].pos() );
61  p.append( b[2].pos() );
62  return p;
63 }
64 
65 list calc_keplerian_for_cartesian_wrap(const double& x,const double& y, const double& z, const double vx, const double& vy, const double& vz, const double GM)
66 {
67  double a, e, i, O, w, M;
68  calc_keplerian_for_cartesian( a, e, i, O, w, M, x, y, z, vx, vy, vz, GM);
69  list p;
70  p.append( a );
71  p.append( e );
72  p.append( i );
73  p.append( O );
74  p.append( w );
75  p.append( M );
76  return p;
77 }
78 
79 list calc_cartesian_for_keplerian_wrap(const double& a, const double& e, const double& i, const double& O, const double& w, const double& M)
80 {
81  double x,y,z, vx,vy,vz, GM;
82  calc_cartesian_for_ellipse(x,y,z,vx,vy,vz, a,e,i,O,w,M, GM);
83  list p;
84  p.append( x );
85  p.append( y );
86  p.append( z );
87  p.append( vx );
88  p.append( vy );
89  p.append( vz );
90  return p;
91 }
92 
93 
94 void set_vel_list(ensemble::Body& b, const list& v ){
95  b[0].vel() = extract<double>(v[0]);
96  b[1].vel() = extract<double>(v[1]);
97  b[2].vel() = extract<double>(v[2]);
98 }
99 
100 list get_vel_list(const ensemble::Body& b){
101  list v;
102  v.append( b[0].vel() );
103  v.append( b[1].vel() );
104  v.append( b[2].vel() );
105  return v;
106 }
107 
108 ensemble::SystemRef ens_getitem(ensemble& ens, const int& i){
109  if( i >= 0 && i < ens.nsys())
110  return ens.getitem(i);
111  else{
112  PyErr_SetString(PyExc_IndexError,"");
113  throw_error_already_set();
114  }
115 
116 }
117 
118 ensemble::Body& sys_getitem(ensemble::SystemRef& sys, const int& i){
119  if( i >= 0 && i < sys.nbod())
120  return sys.getitem(i);
121  else{
122  PyErr_SetString(PyExc_IndexError,"");
123  throw_error_already_set();
124  }
125 }
126 
127 ensemble::Body::Component& bod_getitem(ensemble::Body& bod,const int& i){
128  if( i >= 0 && i < 3)
129  return bod.getitem(i);
130  else{
131  PyErr_SetString(PyExc_IndexError,"");
132  throw_error_already_set();
133  }
134 }
135 
136 int sysattr_len(ensemble::Sys::attributes_t& sysattr){
137  return NUM_SYSTEM_ATTRIBUTES;
138 }
139 
140 double sysattr_getitem(ensemble::Sys::attributes_t& sysattr, const int& i){
141  if( i >= 0 && i < NUM_SYSTEM_ATTRIBUTES)
142  return sysattr.getitem(i);
143  else{
144  PyErr_SetString(PyExc_IndexError,"");
145  throw_error_already_set();
146  }
147 }
148 
149 int bodattr_len(ensemble::Body::attributes_t& bodattr){
150  return NUM_PLANET_ATTRIBUTES;
151 }
152 
153 double bodattr_getitem(ensemble::Body::attributes_t& bodattr, const int& i){
154  if( i >= 0 && i < NUM_PLANET_ATTRIBUTES)
155  return bodattr.getitem(i);
156  else{
157  PyErr_SetString(PyExc_IndexError,"");
158  throw_error_already_set();
159  }
160 }
161 
162 void sysattr_setitem(ensemble::Sys::attributes_t& sysattr, const int& i, const double& value){
163  if( i >= 0 && i < NUM_SYSTEM_ATTRIBUTES)
164  return sysattr.setitem(i,value);
165  else{
166  PyErr_SetString(PyExc_IndexError,"");
167  throw_error_already_set();
168  }
169 }
170 
171 void bodattr_setitem(ensemble::Body::attributes_t& bodattr, const int& i, const double& value){
172  if( i >= 0 && i < NUM_PLANET_ATTRIBUTES)
173  return bodattr.setitem(i,value);
174  else{
175  PyErr_SetString(PyExc_IndexError,"");
176  throw_error_already_set();
177  }
178 }
179 
180 
181 BOOST_PYTHON_MODULE(libswarmng_ext) {
182 
183  def("init", swarm::init );
184  def("generate_ensemble", generate_ensemble );
185  def("sync", cudaThreadSynchronize );
186  def("calc_keplerian_for_cartesian", calc_keplerian_for_cartesian_wrap);
187  def("calc_cartesian_for_keplerian", calc_cartesian_for_keplerian_wrap);
188 
189  class_<config>("Config")
190  .def( map_indexing_suite< config >() )
191  .def("load", &load_config)
192  .staticmethod("load")
193  ;
194 
195  class_<ensemble::Sys::attributes_t, noncopyable >( "System.Attributes", no_init )
196  .def("__getitem__", &sysattr_getitem )
197  .def("__setitem__", &sysattr_setitem )
198  .def("__len__", &sysattr_len)
199  ;
200 
201  class_<ensemble::Body::attributes_t, noncopyable >( "Body.Attributes", no_init )
202  .def("__getitem__", &bodattr_getitem )
203  .def("__setitem__", &bodattr_setitem )
204  .def("__len__", &bodattr_len)
205  ;
206 
207  class_<ensemble::Body::Component >("Body.Components", no_init)
208  .add_property("pos", &get_pos, &set_pos )
209  .add_property("vel", &get_vel, &set_vel )
210  ;
211 
212  /* All the essential properties are covered
213  * However, we can make some convenience access
214  * methods like x,y,z,vy,vx,vz
215  * or get positions and velocities as a python list
216  * or set the body from a python list, etc.
217  *
218  *
219  */
220  class_<ensemble::Body >("Body", no_init )
221  .add_property("mass", &get_mass, &set_mass)
222  .def("distance_to_origin", &ensemble::Body::distance_to_origin )
223  .def("speed", &ensemble::Body::speed )
224  .add_property("attributes", make_function(&ensemble::Body::attributes, return_value_policy<reference_existing_object>()) )
225  .def("__getitem__", &bod_getitem, return_value_policy<reference_existing_object>() )
226  .add_property("pos", &get_pos_list, &set_pos_list )
227  .add_property("vel", &get_vel_list, &set_vel_list )
228  ;
229 
230  /*
231  * All important methods are covered for this class
232  */
233  class_<ensemble::SystemRef >("System", no_init )
234  .def("__len__", &ensemble::SystemRef::nbod , return_value_policy<copy_const_reference>())
235  .add_property("time", &get_time, &set_time)
236  .add_property("id", &get_id, &set_id)
237  .add_property("total_energy", &ensemble::SystemRef::total_energy)
238  .add_property("state", &get_state, &set_state)
239  .add_property("attributes", make_function(&ensemble::SystemRef::attributes, return_value_policy<reference_existing_object>()) )
240  .def("is_active", &ensemble::SystemRef::is_active )
241  .def("is_inactive", &ensemble::SystemRef::is_inactive )
242  .def("is_enabled", &ensemble::SystemRef::is_enabled )
243  .def("set_active", &ensemble::SystemRef::set_active )
244  .def("set_inactive", &ensemble::SystemRef::set_inactive )
245  .def("set_disabled", &ensemble::SystemRef::set_disabled )
246  .def("__getitem__", &sys_getitem, return_value_policy<reference_existing_object>() )
247 
248  ;
249 
250  class_<ensemble, noncopyable >("Ensemble", no_init )
251  .def("__len__", &ensemble::nsys , return_value_policy<copy_const_reference>())
252  .add_property("nsys", make_function(&ensemble::nsys , return_value_policy<copy_const_reference>() ) )
253  .add_property("nbod", make_function(&ensemble::nbod , return_value_policy<copy_const_reference>() ) )
254  .def("__getitem__", &ens_getitem )
255  ;
256 
257  class_<defaultEnsemble, bases<ensemble> >("DefaultEnsemble")
258  .def("create", &defaultEnsemble::create )
259  .staticmethod("create")
260  .def( "clone", &defaultEnsemble::clone )
261  .def("save_to_bin", &snapshot::save)
262  .def("save_to_text", &snapshot::save_text)
263  .def("load_from_bin", &snapshot::load)
264  .def("load_from_text", &snapshot::load_text)
265  .staticmethod("load_from_bin")
266  .staticmethod("load_from_text")
267  ;
268 
269 
270  class_<integrator, Pintegrator, noncopyable >("Integrator", no_init )
271  .def("create",&integrator::create)
272  .staticmethod("create")
273  .def("integrate", &integrator::integrate )
274  .add_property("ensemble", make_function(&integrator::get_ensemble, return_value_policy<reference_existing_object>() ), &integrator::set_ensemble)
275  .add_property("destination_time", &integrator::get_destination_time, &integrator::set_destination_time)
276  ;
277 
278  void (gpu::integrator::*gpu_set_ensemble)(defaultEnsemble&) = &gpu::integrator::set_ensemble;
279 
280  class_<gpu::integrator, bases<integrator> , gpu::Pintegrator, noncopyable>("GpuIntegrator", no_init)
281  .def("create", &create_gpu_integrator )
282  .staticmethod("create")
283  .def("integrate", &gpu::integrator::integrate )
284  .def("core_integrate", &gpu::integrator::core_integrate )
285  .def("download_ensemble", &gpu::integrator::download_ensemble )
286  .def("upload_ensemble", &gpu::integrator::upload_ensemble )
287  .add_property("ensemble", make_function(&integrator::get_ensemble, return_value_policy<reference_existing_object>() ), gpu_set_ensemble)
288  ;
289 
290  def("find_max_energy_conservation_error", find_max_energy_conservation_error );
291 
292 
293 
294 
295 
296 }