Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
EqSolver.cpp
Go to the documentation of this file.
1 // Include files
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 // from Gaudi
7 // from GSL
8 #include "gsl/gsl_blas.h"
9 #include "gsl/gsl_errno.h"
10 #include "gsl/gsl_linalg.h"
11 #include "gsl/gsl_math.h"
12 #include "gsl/gsl_matrix.h"
13 #include "gsl/gsl_multimin.h"
14 #include "gsl/gsl_vector.h"
15 
16 // local
17 #include "EqSolver.h"
18 
26 // Declaration of the Tool Factory
28 
29 // ============================================================================
30 // ============================================================================
31 EqSolver::EqSolverMisc::EqSolverMisc( const EqSolver::Equations& funcs, EqSolver::Arg& arg )
32  : m_argum( arg ), m_eqs( &funcs ) {
33  const size_t N = funcs.size();
34  for ( size_t i = 0; i < N; ++i ) {
35  Equations last;
36  for ( size_t j = 0; j < N; ++j ) {
37  Genfun::GENFUNCTION fij = funcs[i]->partial( j );
38  last.push_back( fij.clone() );
39  }
40  m_jac.push_back( last );
41  }
42 }
43 // ============================================================================
44 
45 // ============================================================================
47  while ( !m_jac.empty() ) {
48  Equations& last = m_jac.back();
49  while ( !last.empty() ) {
50  delete last.back();
51  last.pop_back();
52  }
53  m_jac.pop_back();
54  }
55 }
56 // ============================================================================
57 
58 namespace {
59  using namespace Genfun;
60 
63  int fun_gsl( const gsl_vector* v, void* params, gsl_vector* f ) {
64  EqSolver::EqSolverMisc* local = static_cast<EqSolver::EqSolverMisc*>( params );
65  const EqSolver::Equations& eqs = *( local->equations() );
66  Argument& arg = local->argument();
67 
68  for ( unsigned int i = 0; i < v->size; ++i ) { arg[i] = gsl_vector_get( v, i ); }
69 
70  for ( unsigned int i = 0; i < v->size; ++i ) { gsl_vector_set( f, i, ( *eqs[i] )( arg ) ); }
71  return GSL_SUCCESS;
72  }
73 
76  int dfun_gsl( const gsl_vector* v, void* params, gsl_matrix* df ) {
77  EqSolver::EqSolverMisc* local = static_cast<EqSolver::EqSolverMisc*>( params );
78  const EqSolver::Jacobi& jac = local->jacobi();
79  Argument& arg = local->argument();
80 
81  for ( unsigned int i = 0; i < v->size; ++i ) { arg[i] = gsl_vector_get( v, i ); }
82 
83  for ( unsigned int i = 0; i < v->size; ++i ) {
84  for ( unsigned int j = 0; j < v->size; ++j ) {
85  Genfun::GENFUNCTION f = *( jac[i][j] );
86  gsl_matrix_set( df, i, j, f( arg ) );
87  }
88  }
89  return GSL_SUCCESS;
90  }
91 
95  int fdfun_gsl( const gsl_vector* v, void* params, gsl_vector* f, gsl_matrix* df ) {
96  EqSolver::EqSolverMisc* local = static_cast<EqSolver::EqSolverMisc*>( params );
97  const EqSolver::Equations& eqs = *( local->equations() );
98  const EqSolver::Jacobi& jac = local->jacobi();
99  Argument& arg = local->argument();
100 
101  for ( unsigned int i = 0; i < v->size; ++i ) { arg[i] = gsl_vector_get( v, i ); }
102 
103  for ( unsigned int i = 0; i < v->size; ++i ) {
104  gsl_vector_set( f, i, ( *eqs[i] )( arg ) );
105  for ( unsigned int j = 0; j < v->size; ++j ) {
106  Genfun::GENFUNCTION f1 = *( jac[i][j] );
107  gsl_matrix_set( df, i, j, f1( arg ) );
108  }
109  }
110  return GSL_SUCCESS;
111  }
112 } // namespace
113 
114 //=============================================================================
119 StatusCode EqSolver::solver( const Equations& funcs, Arg& arg ) const
120 //=============================================================================
121 {
122  using namespace Genfun;
123 
124  gsl_vector_view vect = gsl_vector_view_array( &arg[0], arg.dimension() );
125  EqSolverMisc local( funcs, arg );
126 
127  const gsl_multiroot_fdfsolver_type* T = m_type;
128  gsl_multiroot_fdfsolver* s = nullptr;
129  int status = 0;
130  size_t iter = 0;
131 
132  gsl_multiroot_function_fdf function;
133 
134  function.f = &fun_gsl;
135  function.df = &dfun_gsl;
136  function.fdf = &fdfun_gsl;
137  function.n = vect.vector.size;
138  function.params = &local;
139 
140  s = gsl_multiroot_fdfsolver_alloc( T, vect.vector.size );
141  gsl_multiroot_fdfsolver_set( s, &function, &vect.vector );
142 
143  for ( iter = 0; iter < m_max_iter; ++iter ) {
144  status = gsl_multiroot_fdfsolver_iterate( s );
145  if ( status ) {
146  return Error( "Error from gsl_gsl_multiroot_fdfsolver_iterate '" + std::string( gsl_strerror( status ) ) + "'" );
147  }
148 
149  status = gsl_multiroot_test_residual( s->f, m_norm_residual );
150 
151  if ( status != GSL_CONTINUE ) { break; }
152  }
153 
154  for ( unsigned int i = 0; i < vect.vector.size; ++i ) {
155  gsl_vector_set( &vect.vector, i, gsl_vector_get( s->x, i ) );
156  }
157 
158  if ( status == GSL_SUCCESS ) {
159  debug() << "We stopped in the method on the " << iter << " iteration (we have maximum " << m_max_iter
160  << " iterations)" << endmsg;
161  } else if ( status == GSL_CONTINUE && iter <= m_max_iter ) {
162  return Error( "Method finished with '" + std::string( gsl_strerror( status ) ) + "' error" );
163  } else {
164  return Error( "Method finished with '" + std::string( gsl_strerror( status ) ) + "' error" );
165  }
166 
167  gsl_multiroot_fdfsolver_free( s );
168 
169  if ( status ) { return Error( "Method finished with '" + std::string( gsl_strerror( status ) ) + "' error" ); }
170 
171  return StatusCode( GSL_SUCCESS );
172 }
173 
174 //=============================================================================
177  if ( sc.isFailure() ) { return Error( "Could not initiliaze base class GaudiTool", sc ); }
178 
179  /* The algorithm for multiional root-finding
180  (solving nonlinear systems with n equations in n unknowns)*/
181 
182  if ( "fdfsolver_hybridsj" == m_algType ) {
183  m_type = gsl_multiroot_fdfsolver_hybridsj;
184  debug() << "Root finding algorithm to be used: "
185  << "'gsl_multiroot_fdfsolver_hybridsj'" << endmsg;
186  } else if ( "fdfsolver_hybridj" == m_algType ) {
187  m_type = gsl_multiroot_fdfsolver_hybridj;
188  debug() << "Root finding algorithm to be used: "
189  << "'gsl_multiroot_fdfsolver_hybridj'" << endmsg;
190  } else if ( "fdfsolver_newton" == m_algType ) {
191  m_type = gsl_multiroot_fdfsolver_newton;
192  debug() << "Root findind algorithm to be used: "
193  << "'gsl_multiroot_fdfsolver_newton'" << endmsg;
194  } else if ( "fdfsolver_gnewton" == m_algType ) {
195  m_type = gsl_multiroot_fdfsolver_gnewton;
196  debug() << "Root findind algorithm to be used: "
197  << "'gsl_multiroot_fdfsolver_gnewton'" << endmsg;
198  } else {
199  return Error( " Unknown algorithm type '" + std::string( m_algType ) + "'" );
200  }
201 
202  return StatusCode::SUCCESS;
203 }
204 //=============================================================================
T empty(T...args)
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
const Jacobi & jacobi() const
Definition: EqSolver.h:51
bool isFailure() const
Definition: StatusCode.h:130
STL class.
#define DECLARE_COMPONENT(type)
Gaudi::Property< std::string > m_algType
Definition: EqSolver.h:79
int N
Definition: IOTest.py:99
The simplest concrete implementation of IEqSolver interface.
Definition: EqSolver.h:23
Gaudi::Property< double > m_max_iter
Definition: EqSolver.h:81
StatusCode initialize() override
Overriding initialize.
Definition: EqSolver.cpp:175
const Arg & argument() const
Definition: EqSolver.h:48
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
const Equations * equations() const
Definition: EqSolver.h:50
T pop_back(T...args)
StatusCode solver(const Equations &funcs, Arg &arg) const override
Solving nonlinear system with N equations in N unknowns of the function "GenFunc".
Definition: EqSolver.cpp:119
StatusCode Error(const std::string &msg, const StatusCode st=StatusCode::FAILURE, const size_t mx=10) const
Print the error message and return with the given StatusCode.
Definition: GaudiTool.h:663
T back(T...args)
string s
Definition: gaudirun.py:312
const gsl_multiroot_fdfsolver_type * m_type
Definition: EqSolver.h:84
CLHEP.
Definition: IEqSolver.h:13
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
Gaudi::Property< double > m_norm_residual
Definition: EqSolver.h:82
StatusCode initialize() override
standard initialization method
Definition: GaudiTool.cpp:144