ccgsl 2.7.2
C++wrappersforGnuScientificLibrary
odeiv2_system.hpp
Go to the documentation of this file.
1/*
2 * $Id: odeiv2_system.hpp 289 2012-12-04 15:32:17Z jdl3 $
3 * Copyright (C) 2012, 2016, 2021 John D Lamb
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef CCGSL_ODEIV2_SYSTEM_HPP
21#define CCGSL_ODEIV2_SYSTEM_HPP
22
23#include"exception.hpp"
24#include"vector.hpp"
25#include"matrix.hpp"
26#include<gsl/gsl_odeiv2.h>
27
28namespace gsl {
29 namespace odeiv2 {
30 class system;
31 template<typename T>
32 void system_constructor( system& sys, T& t );
66 class system : public gsl_odeiv2_system {
67 public:
75 struct Concept {
84 template<typename T>
85 int function( double const t, T const& y, T& dydt );
95 template<typename T,typename U>
96 int jacobian( double const t, T const&, U& dfdy, T& dfdt ){
102 virtual size_t size() const = 0;
103 };
104#ifndef DOXYGEN_SKIP
105 private:
109 struct base_F {
113 typedef int (*function_t)(double const,double const*,double*,void*);
117 typedef int (*jacobian_t)(double const,double const*,double*,double*,void*);
121 virtual ~base_F(){};
125 virtual bool has_jacobian() const = 0;
126 };
130 template<typename T>
131 struct Function : public base_F {
132 public:
137 Function( T& t ) : t( t ){
138 size_t const size = t.size();
139 vy.size = size;
140 vy.stride = 1;
141 vy.data = 0;
142 vy.block = 0;
143 vy.owner = 0;
144 yv.wrap_gsl_vector_without_ownership( &vy );
145 vdydt.size = size;
146 vdydt.stride = 1;
147 vdydt.data = 0;
148 vdydt.block = 0;
149 vdydt.owner = 0;
150 dydtv.wrap_gsl_vector_without_ownership( &vdydt );
151 vdfdy.size = size * size;
152 vdfdy.stride = 1;
153 vdfdy.data = 0;
154 vdfdy.block = 0;
155 vdfdy.owner = 0;
156 dfdyv.wrap_gsl_vector_without_ownership( &vdfdy );
157 mdfdy.size1 = size;
158 mdfdy.size2 = size;
159 mdfdy.tda = size;
160 mdfdy.data = 0;
161 mdfdy.block = 0;
162 mdfdy.owner = 0;
163 dfdym.wrap_gsl_matrix_without_ownership( &mdfdy );
164 vdfdt.size = size;
165 vdfdt.stride = 1;
166 vdfdt.data = 0;
167 vdfdt.block = 0;
168 vdfdt.owner = 0;
169 dfdtv.wrap_gsl_vector_without_ownership( &vdfdt );
170 }
171 public:
180 static int function( double const t, double const* y, double* dydt, void* params ){
181 Function<T>* this_t = reinterpret_cast<Function<T>*>( params );
182 return this_t->function_detail( t, y, dydt );
183 }
192 static int jacobian( double const t, double const* y, double* dfdy, double* dfdt,
193 void* params ){
194 Function<T>* this_t = reinterpret_cast<Function<T>*>( params );
195 return this_t->jacobian_detail( t, y, dfdy, dfdt );
196 }
197 private:
201 template<bool N> struct bool_to_type {};
205 template<typename V>
206 struct Fvector {
207 template<typename W,int (V::*)(double const,gsl::vector const&,gsl::vector&)> struct S{};
208 template<typename W> static char test( S<W,&W::function>* );
209 template<typename W,int (V::*)(double const,gsl::vector&,gsl::vector&)> struct Su{};
210 template<typename W> static char test( Su<W,&W::function>* );
211 template<typename W> static int test( ... );
212 static const bool vector = sizeof(test<V>( 0 )) == sizeof(char);
213 };
217 enum { ptr_ptr = 0, ptr_vec = 1, ptr_mat = 2, vec_ptr = 4, vec_vec = 5, vec_mat = 6,
218 undefined = 8 };
222 template<typename V>
223 struct Jacobian {
224 template<typename W,int (V::*)(double const,double const*,double*,double const*)>
225 struct PtrPtr{};
226 template<typename W> static char test_ptr_ptr( PtrPtr<W,&W::jacobian>* );
227 template<typename W,int (V::*)(double const,double*,double*,double*)>
228 struct UPtrPtr{};
229 template<typename W> static char test_ptr_ptr( UPtrPtr<W,&W::jacobian>* );
230 template<typename W> static int test_ptr_ptr( ... );
231 template<typename W,int (V::*)(double const,double const*,gsl::vector&,double*)>
232 struct PtrVec{};
233 template<typename W> static char test_ptr_vec( PtrVec<W,&W::jacobian>* );
234 template<typename W,int (V::*)(double const,double*,gsl::vector&,double*)>
235 struct UPtrVec{};
236 template<typename W> static char test_ptr_vec( UPtrVec<W,&W::jacobian>* );
237 template<typename W> static int test_ptr_vec( ... );
238 template<typename W,int (V::*)(double const,double const*,gsl::matrix&,double*)>
239 struct PtrMat{};
240 template<typename W> static char test_ptr_mat( PtrMat<W,&W::jacobian>* );
241 template<typename W,int (V::*)(double const,double*,gsl::matrix&,double*)>
242 struct UPtrMat{};
243 template<typename W> static char test_ptr_mat( UPtrMat<W,&W::jacobian>* );
244 template<typename W> static int test_ptr_mat( ... );
245 template<typename W,int (V::*)(double const,gsl::vector const&,double*,gsl::vector&)>
246 struct VecPtr{};
247 template<typename W> static char test_vec_ptr( VecPtr<W,&W::jacobian>* );
248 template<typename W,int (V::*)(double const,gsl::vector&,double*,gsl::vector&)>
249 struct UVecPtr{};
250 template<typename W> static char test_vec_ptr( UVecPtr<W,&W::jacobian>* );
251 template<typename W> static int test_vec_ptr( ... );
252 template<typename W,int (V::*)(double const,gsl::vector const&,gsl::vector&,gsl::vector&)>
253 struct VecVec{};
254 template<typename W> static char test_vec_vec( VecVec<W,&W::jacobian>* );
255 template<typename W,int (V::*)(double const,gsl::vector&,gsl::vector&,gsl::vector&)>
256 struct UVecVec{};
257 template<typename W> static char test_vec_vec( UVecVec<W,&W::jacobian>* );
258 template<typename W> static int test_vec_vec( ... );
259 template<typename W,int (V::*)(double const,gsl::vector const&,gsl::matrix,gsl::vector&)>
260 struct VecMat{};
261 template<typename W> static char test_vec_mat( VecMat<W,&W::jacobian>* );
262 template<typename W,int (V::*)(double const,gsl::vector&,gsl::matrix,gsl::vector&)>
263 struct UVecMat{};
264 template<typename W> static char test_vec_mat( UVecMat<W,&W::jacobian>* );
265 template<typename W> static int test_vec_mat( ... );
266 static const int type
267 = sizeof(test_ptr_ptr<V>( 0 )) == sizeof(char) ? ptr_ptr :
268 sizeof(test_ptr_vec<V>( 0 )) == sizeof(char) ? ptr_vec :
269 sizeof(test_ptr_mat<V>( 0 )) == sizeof(char) ? ptr_mat :
270 sizeof(test_vec_ptr<V>( 0 )) == sizeof(char) ? vec_ptr :
271 sizeof(test_vec_vec<V>( 0 )) == sizeof(char) ? vec_vec :
272 sizeof(test_vec_mat<V>( 0 )) == sizeof(char) ? vec_mat :
273 undefined;
274 };
278 bool has_jacobian() const { return Jacobian<T>::type != undefined; }
282 template<int N> struct int_to_type {};
286 template<typename U>
287 int function( double const t, double const* y, double* dydt, U& u, bool_to_type<true> ){
288 vy.data = const_cast<double*>( y );
289 vdydt.data = dydt;
290 return u.function( t, yv, dydtv );
291 }
295 template<typename U>
296 int function( double const t, double const* y, double* dydt, U& u, bool_to_type<false> ){
297 return u.function( t, y, dydt );
298 }
302 int function_detail( double const t, double const* y, double* dydt ){
303 return function( t, y, dydt, this->t, bool_to_type<Fvector<T>::vector>() );
304 }
308 template<typename U>
309 int jacobian( double const t, double const* y, double* dfdy, double* dfdt,
310 U& u, int_to_type<undefined> ){
311 return 0;
312 }
316 template<typename U>
317 int jacobian( double const t, double const* y, double* dfdy, double* dfdt,
318 U& u, int_to_type<ptr_ptr> ){
319 return u.jacobian( t, y, dfdy, dfdt );
320 }
324 template<typename U>
325 int jacobian( double const t, double const* y, gsl::vector& dfdy, double* dfdt,
326 U& u, int_to_type<ptr_vec> ){
327 vdfdy.data = dfdy;
328 return u.jacobian( t, y, dfdyv, dfdt );
329 }
333 template<typename U>
334 int jacobian( double const t, double const* y, gsl::vector& dfdy, double* dfdt,
335 U& u, int_to_type<ptr_mat> ){
336 mdfdy.data = dfdy;
337 return u.jacobian( t, y, dfdym, dfdt );
338 }
342 template<typename U>
343 int jacobian( double const t, gsl::vector const& y, double* dfdy, gsl::vector& dfdt,
344 U& u, int_to_type<vec_ptr> ){
345 vdfdt.data = dfdt;
346 vy.data = y;
347 return u.jacobian( t, yv, dfdy, dfdtv );
348 }
352 template<typename U>
353 int jacobian( double const t, gsl::vector const& y, gsl::vector& dfdy, gsl::vector& dfdt,
354 U& u, int_to_type<vec_vec> ){
355 vdfdt.data = dfdt;
356 vy.data = y;
357 vdfdy.data = dfdy;
358 return u.jacobian( t, yv, dfdyv, dfdtv );
359 }
364 template<typename U>
365 int jacobian( double const t, gsl::vector const& y, gsl::matrix& dfdy, gsl::vector& dfdt,
366 U& u, int_to_type<vec_mat> ){
367 vdfdt.data = dfdt;
368 vy.data = y;
369 mdfdy.data = dfdy;
370 return u.jacobian( t, yv, dfdym, dfdtv );
371 }
375 int jacobian_detail( double const t, double const* y, double* dfdy, double* dfdt ){
376 return jacobian( t, y, dfdy, dfdt, this->t, int_to_type<Jacobian<T>::type>() );
377 }
381 gsl_vector vy;
385 gsl::vector yv;
389 gsl_vector vdydt;
393 gsl::vector dydtv;
397 gsl_vector vdfdy;
401 gsl::vector dfdyv;
405 gsl_matrix mdfdy;
409 gsl::matrix dfdym;
416 gsl_vector vdfdt;
420 gsl::vector dfdtv;
421 T& t;
422 };
423#endif
427 base_F* f;
431 size_t* count;
432 public:
437 f = 0;
438 function = 0;
439 jacobian = 0;
440 dimension = 0;
441 params = 0;
442 count = 0; // initially nullptr will do
443 }
444 template<typename T>
445 friend void system_constructor( system& sys, T& t );
451 explicit system( gsl_odeiv2_system& v ){
452 // explicitly set f = 0 to indicate nothing to be deleted.
453 f = 0;
454 // copy
455 function = v.function;
456 jacobian = v.jacobian;
457 dimension = v.dimension;
458 params = v.params;
459 // just plausibly we could fail to allocate count: no further action needed.
460 count = new size_t;
461 *count = 1; // initially there is just one reference to function
462 }
467 template<typename T>
468 system( T& t ){ system_constructor<T>( *this, t ); }
469
470 // Copy and move constructors
471 // copy constructor
478 system( system const& v ) : f( v.f ), count( v.count ){
479 function = v.function;
480 jacobian = v.jacobian;
481 dimension = v.dimension;
482 params = v.params;
483 if( count != 0 ) ++*count; // system is now shared.
484 }
485 // assignment operator
490 system& operator=( system const& v ){
491 // first, possibly delete anything pointed to by this
492 if( count == 0 or --*count == 0 ){
493 delete f;
494 delete count;
495 }
496 // Then copy
497 f = v.f;
498 function = v.function;
499 jacobian = v.jacobian;
500 dimension = v.dimension;
501 params = v.params;
502 // count = v.count;
503 if( count != 0 ) ++*count; // system is now shared.
504 return *this;
505 }
506#ifdef __GXX_EXPERIMENTAL_CXX0X__
511 system( system&& v ) : f( v.f ), count( nullptr ){
512 std::swap( function, v.function );
513 std::swap( jacobian, v.jacobian );
514 std::swap( dimension, v.dimension );
515 std::swap( params, v.params );
516 std::swap( count, v.count );
517 v.function = nullptr;
518 }
525 std::swap( f, v.f );
526 std::swap( function, v.function );
527 std::swap( jacobian, v.jacobian );
528 std::swap( dimension, v.dimension );
529 std::swap( params, v.params );
530 std::swap( count, v.count );
531 return *this;
532 }
533#endif
538 // first, possibly delete anything pointed to by f
539 if( count == 0 or --*count == 0 ){
540 delete f;
541 delete count;
542 }
543 }
544 };
545#ifndef DOXYGEN_SKIP
551 template<typename T>
552 inline void system_constructor( system& sys, T& t ){
553 sys.function = 0;
554 sys.count = 0;
555 // try constructing from T
556 sys.f = new system::Function<T>( t );
557 sys.function = &system::Function<T>::function;
558 if( sys.f->has_jacobian() )
559 sys.jacobian = 0;
560 else
561 sys.jacobian = &system::Function<T>::jacobian;
562 sys.dimension = t.size();
563 sys.params = sys.f;
564 // just plausibly we could fail to allocate count: no further action needed.
565 sys.count = new size_t;
566 *sys.count = 1; // initially there is just one reference to function
567 }
571 template<>
572 inline void system_constructor( system& sys, system& v ){
573 sys.f = v.f; sys.function = v.function; sys.jacobian = v.jacobian;
574 sys.dimension = v.dimension; sys.params = v.params;
575 if( sys.count != 0 ) ++*sys.count; // system is now shared.
576 /* sys is now shared. */ }
580 template<>
581 inline void system_constructor( system& sys, gsl_odeiv2_system& v ){
582 sys.function = v.function; sys.jacobian = v.jacobian;
583 sys.dimension = v.dimension; sys.params = v.params; }
584#endif
585
591 template<typename T>
592 inline system make_system( T& t ){
593 system fn( t );
594 return fn;
595 }
596
597 }
598}
599#endif
This class handles matrix objects as shared handles.
Definition: matrix.hpp:72
Class that extends gsl_odeiv2_system so that it can be constructed from function objects.
system(T &t)
Construct from an object that implements gsl::odeiv2::system::Concept.
system(system const &v)
The copy constructor.
friend void system_constructor(system &sys, T &t)
system()
The default constructor is only really useful for assigning to.
system & operator=(system &&v)
Move operator.
base_F * f
This gives something for params to point to.
system(gsl_odeiv2_system &v)
Could construct from a gsl_odeiv2_system object.
system(system &&v)
Move constructor.
system & operator=(system const &v)
The assignment operator.
size_t * count
The shared reference count: used for copying this.
~system()
The destructor unshares any shared resource.
This class handles vector objects as shared handles.
Definition: vector.hpp:74
double * data()
Give access to the data block.
Definition: vector.hpp:1177
size_t size(series const &cs)
C++ version of gsl_cheb_size().
Definition: chebyshev.hpp:287
int test(double const xtol, double const gtol, double const ftol, int *info, workspace const &w)
C++ version of gsl_multifit_nlinear_test().
gsl_multilarge_linear_type type
Typedef for shorthand.
Definition: multilarge.hpp:40
void system_constructor(system &sys, T &t)
system make_system(T &t)
Make a gsl::odeiv2::system from a function object that implements gsl::odeiv2::system::concept.
The gsl package creates an interface to the GNU Scientific Library for C++.
Definition: blas.hpp:34
This is an empty base class.
int function(double const t, T const &y, T &dydt)
The function that stores dydt given y and t.
virtual size_t size() const =0
The dimension of the function arguments.
int jacobian(double const t, T const &, U &dfdy, T &dfdt)
As function but also store Jacobian in dfdy.