erk_adjoint_export.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ACADO Toolkit.
3  *
4  * ACADO Toolkit -- A Toolkit for Automatic Control and Dynamic Optimization.
5  * Copyright (C) 2008-2014 by Boris Houska, Hans Joachim Ferreau,
6  * Milan Vukov, Rien Quirynen, KU Leuven.
7  * Developed within the Optimization in Engineering Center (OPTEC)
8  * under supervision of Moritz Diehl. All rights reserved.
9  *
10  * ACADO Toolkit is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 3 of the License, or (at your option) any later version.
14  *
15  * ACADO Toolkit is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with ACADO Toolkit; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  */
25 
26 
27 
36 
37 using namespace std;
38 
40 
41 //
42 // PUBLIC MEMBER FUNCTIONS:
43 //
44 
46  const std::string& _commonHeaderName
47  ) : ExplicitRungeKuttaExport( _userInteraction,_commonHeaderName )
48 {
49 }
50 
51 
53  ) : ExplicitRungeKuttaExport( arg )
54 {
55 }
56 
57 
59 {
60  clear( );
61 }
62 
63 
64 
66 {
67  int sensGen;
68  get( DYNAMIC_SENSITIVITY,sensGen );
69 
70  OnlineData dummy0;
71  Control dummy1;
72  DifferentialState dummy2;
73  AlgebraicState dummy3;
75  dummy0.clearStaticCounters();
76  dummy1.clearStaticCounters();
77  dummy2.clearStaticCounters();
78  dummy3.clearStaticCounters();
79  dummy4.clearStaticCounters();
80 
81  x = DifferentialState("", NX, 1);
83  z = AlgebraicState("", NXA, 1);
84  u = Control("", NU, 1);
85  od = OnlineData("", NOD, 1);
86 
87  if( NDX > 0 && NDX != NX ) {
89  }
90  if( rhs_.getNumRows() != (NX+NXA) ) {
92  }
93 
94  DifferentialEquation f, f_ODE;
95  // add usual ODE
96  f_ODE << rhs_;
97  if( f_ODE.getNDX() > 0 ) {
99  }
100 
101  if( (ExportSensitivityType)sensGen == BACKWARD ) {
102  DifferentialState lx("", NX,1), lu("", NU,1);
103 
104  f << backwardDerivative(rhs_, x, lx);
105  f << backwardDerivative(rhs_, u, lx);
106  }
107  else {
108  return ACADOERROR( RET_INVALID_OPTION );
109  }
110  if( f.getNT() > 0 ) timeDependant = true;
111 
112  return rhs.init(f_ODE, "rhs", NX, 0, NU, NP, NDX, NOD)
113  & diffs_rhs.init(f, "rhs_back", 2*NX + NU, 0, NU, NP, NDX, NOD);
114 }
115 
116 
118 {
119  int sensGen;
120  get( DYNAMIC_SENSITIVITY,sensGen );
122 
123  // NOT SUPPORTED: since the forward sweep needs to be saved
125 
126  // NOT SUPPORTED: since the adjoint derivatives could be 'arbitrarily bad'
128 
129  LOG( LVL_DEBUG ) << "Preparing to export AdjointERKExport... " << endl;
130 
131  // export RK scheme
132  uint rhsDim = 2*NX+NU;
133  inputDim = 2*NX+NU + NU + NOD;
134  const uint rkOrder = getNumStages();
135 
136  double h = (grid.getLastTime() - grid.getFirstTime())/grid.getNumIntervals();
137 
138  ExportVariable Ah ( "A*h", DMatrix( AA )*=h );
139  ExportVariable b4h( "b4*h", DMatrix( bb )*=h );
140 
141  rk_index = ExportVariable( "rk_index", 1, 1, INT, ACADO_LOCAL, true );
142  rk_eta = ExportVariable( "rk_eta", 1, inputDim );
143 // seed_backward.setup( "seed", 1, NX );
144 
145  int useOMP;
146  get(CG_USE_OPENMP, useOMP);
147  ExportStruct structWspace;
148  structWspace = useOMP ? ACADO_LOCAL : ACADO_WORKSPACE;
149 
150  rk_ttt.setup( "rk_ttt", 1, 1, REAL, structWspace, true );
151  uint timeDep = 0;
152  if( timeDependant ) timeDep = 1;
153 
154  rk_xxx.setup("rk_xxx", 1, inputDim+timeDep, REAL, structWspace);
155  rk_kkk.setup("rk_kkk", rkOrder, NX+NU, REAL, structWspace);
156  rk_forward_sweep.setup("rk_sweep1", 1, grid.getNumIntervals()*rkOrder*NX, REAL, structWspace);
157 
158  if ( useOMP )
159  {
160  ExportVariable auxVar;
161 
162  auxVar = getAuxVariable();
163  auxVar.setName( "odeAuxVar" );
164  auxVar.setDataStruct( ACADO_LOCAL );
165  rhs.setGlobalExportVariable( auxVar );
167  }
168 
169  ExportIndex run( "run1" );
170 
171  // setup INTEGRATE function
172  integrate = ExportFunction( "integrate", rk_eta, reset_int );
174  rk_eta.setDoc( "Working array to pass the input values and return the results." );
175  reset_int.setDoc( "The internal memory of the integrator can be reset." );
176  rk_index.setDoc( "Number of the shooting interval." );
177  error_code.setDoc( "Status code of the integrator." );
178  integrate.doc( "Performs the integration and sensitivity propagation for one shooting interval." );
179  integrate.addIndex( run );
180 
182 
183  if( inputDim > rhsDim ) {
184 // integrate.addStatement( rk_eta.getCols( NX,2*NX ) == seed_backward );
185  integrate.addStatement( rk_eta.getCols( 2*NX,2*NX+NU ) == zeros<double>( 1,NU ) );
186  // FORWARD SWEEP FIRST
187  integrate.addStatement( rk_xxx.getCols( NX,NX+NU+NOD ) == rk_eta.getCols( rhsDim,inputDim ) );
188  }
190 
191  // integrator loop: FORWARD SWEEP
192  ExportForLoop loop = ExportForLoop( run, 0, grid.getNumIntervals() );
193  for( uint run1 = 0; run1 < rkOrder; run1++ )
194  {
195  loop.addStatement( rk_xxx.getCols( 0,NX ) == rk_eta.getCols( 0,NX ) + Ah.getRow(run1)*rk_kkk.getCols( 0,NX ) );
196  // save forward trajectory
197  loop.addStatement( rk_forward_sweep.getCols( run*rkOrder*NX+run1*NX,run*rkOrder*NX+run1*NX+NX ) == rk_xxx.getCols( 0,NX ) );
198  if( timeDependant ) loop.addStatement( rk_xxx.getCol( NX+NU+NOD ) == rk_ttt + ((double)cc(run1))/grid.getNumIntervals() );
200  }
201  loop.addStatement( rk_eta.getCols( 0,NX ) += b4h^rk_kkk.getCols( 0,NX ) );
202  loop.addStatement( rk_ttt += DMatrix(1.0/grid.getNumIntervals()) );
203  // end of integrator loop: FORWARD SWEEP
204  integrate.addStatement( loop );
205 
206 // if( !is_symmetric ) {
207 // integrate.addStatement( rk_xxx.getCols( 0,NX ) == rk_eta.getCols( 0,NX ) );
208 // }
209  if( inputDim > rhsDim ) {
210  // BACKWARD SWEEP NEXT
212  }
213  // integrator loop: BACKWARD SWEEP
214  ExportForLoop loop2 = ExportForLoop( run, 0, grid.getNumIntervals() );
215  for( uint run1 = 0; run1 < rkOrder; run1++ )
216  {
217  // load forward trajectory
218 // if( is_symmetric ) {
219  loop2.addStatement( rk_xxx.getCols( 0,NX ) == rk_forward_sweep.getCols( (grid.getNumIntervals()-run)*rkOrder*NX-run1*NX-NX,(grid.getNumIntervals()-run)*rkOrder*NX-run1*NX ) );
220 // }
221  loop2.addStatement( rk_xxx.getCols( NX,2*NX+NU ) == rk_eta.getCols( NX,2*NX+NU ) + Ah.getRow(run1)*rk_kkk );
222  if( timeDependant ) loop2.addStatement( rk_xxx.getCol( inputDim ) == rk_ttt - ((double)cc(run1))/grid.getNumIntervals() );
224 // if( !is_symmetric ) {
225 // loop2.addStatement( rk_xxx.getCols( 0,NX ) == rk_forward_sweep.getCols( (grid.getNumIntervals()-run)*rkOrder*NX-run1*NX-NX,(grid.getNumIntervals()-run)*rkOrder*NX-run1*NX ) );
226 // }
227  }
228  loop2.addStatement( rk_eta.getCols( NX,2*NX+NU ) += b4h^rk_kkk );
229  loop2.addStatement( rk_ttt -= DMatrix(1.0/grid.getNumIntervals()) );
230  // end of integrator loop: BACKWARD SWEEP
231  integrate.addStatement( loop2 );
232 
234 
235  LOG( LVL_DEBUG ) << "done" << endl;
236 
237  return SUCCESSFUL_RETURN;
238 }
239 
240 
242  ExportStruct dataStruct
243  ) const
244 {
245  ExplicitRungeKuttaExport::getDataDeclarations( declarations, dataStruct );
246 
247  declarations.addDeclaration( rk_forward_sweep,dataStruct );
248 
249  return SUCCESSFUL_RETURN;
250 }
251 
252 
254  )
255 {
256  int useOMP;
257  get(CG_USE_OPENMP, useOMP);
258  if ( useOMP )
259  {
261 
262  code << "#pragma omp threadprivate( "
263  << getAuxVariable().getFullName() << ", "
264  << rk_xxx.getFullName() << ", "
265  << rk_ttt.getFullName() << ", "
266  << rk_kkk.getFullName() << ", "
268  << " )\n\n";
269  }
270 
271  int sensGen;
272  get( DYNAMIC_SENSITIVITY,sensGen );
273  if( exportRhs ) {
274  code.addFunction( rhs );
275  code.addFunction( diffs_rhs );
276  }
277 
278  double h = (grid.getLastTime() - grid.getFirstTime())/grid.getNumIntervals();
279  code.addComment(std::string("Fixed step size:") + toString(h));
280  code.addFunction( integrate );
281 
282  return SUCCESSFUL_RETURN;
283 }
284 
285 
286 // PROTECTED:
287 
288 
289 
291 
292 // end of file.
#define LOG(level)
Just define a handy macro for getting the logger.
Lowest level, the debug level.
ExportVariable getRow(const ExportIndex &idx) const
Expression backwardDerivative(const Expression &arg1, const Expression &arg2)
Allows to export a tailored explicit Runge-Kutta integrator for fast model predictive control...
Definition: erk_export.hpp:54
AdjointERKExport(UserInteraction *_userInteraction=0, const std::string &_commonHeaderName="")
double getFirstTime() const
ExportVariable & setup(const std::string &_name, uint _nRows=1, uint _nCols=1, ExportType _type=REAL, ExportStruct _dataStruct=ACADO_LOCAL, bool _callItByValue=false, const std::string &_prefix=std::string())
ExportAcadoFunction diffs_rhs
int getNDX() const
Definition: function.cpp:217
ExportVariable rk_index
virtual ExportVariable getAuxVariable() const
Definition: erk_export.cpp:386
Allows to pass back messages to the calling function.
ExportVariable rk_kkk
Definition: rk_export.hpp:189
DifferentialState x
virtual returnValue setup()
uint getNumRows() const
returnValue addComment(const std::string &_comment)
BEGIN_NAMESPACE_ACADO typedef unsigned int uint
Definition: acado_types.hpp:42
Allows to export code of a for-loop.
string toString(T const &value)
returnValue setName(const std::string &_name)
Definition: export_data.cpp:61
#define CLOSE_NAMESPACE_ACADO
GenericMatrix< double > DMatrix
Definition: matrix.hpp:457
const std::string getNameDiffsRHS() const
Defines a scalar-valued index variable to be used for exporting code.
Base class for all variables within the symbolic expressions family.
Definition: expression.hpp:56
virtual returnValue setDoc(const std::string &_doc)
ExportVariable rk_eta
ExportStruct
virtual ExportFunction & doc(const std::string &_doc)
ExportVariable getCols(const ExportIndex &idx1, const ExportIndex &idx2) const
const std::string getNameRHS() const
ExportVariable reset_int
ExportVariable rk_forward_sweep
Encapsulates all user interaction for setting options, logging data and plotting results.
Allows to export code of an arbitrary function.
returnValue setDataStruct(ExportStruct _dataStruct)
Definition: export_data.cpp:80
returnValue addStatement(const ExportStatement &_statement)
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
int getNT() const
Definition: function.cpp:251
ExportFunction integrate
std::string getFullName() const
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
Definition: erk_export.cpp:290
returnValue addLinebreak(uint num=1)
ExportFunction & setReturnValue(const ExportVariable &_functionReturnValue, bool _returnAsPointer=false)
uint getNumIntervals() const
virtual returnValue setDifferentialEquation(const Expression &rhs)
returnValue setGlobalExportVariable(const ExportVariable &var)
ExportVariable rk_xxx
DifferentialStateDerivative dx
returnValue addDeclaration(const ExportVariable &_data, ExportStruct _dataStruct=ACADO_ANY)
double getLastTime() const
ExportVariable rk_ttt
#define BEGIN_NAMESPACE_ACADO
ExportVariable error_code
returnValue clearStaticCounters()
Definition: expression.hpp:398
returnValue addFunction(const ExportFunction &_function)
virtual returnValue clear()
Allows to export code for a block of statements.
Allows to export a tailored explicit Runge-Kutta integrator with adjoint first order sensitivity prop...
ExportArgument getAddress(const ExportIndex &_rowIdx, const ExportIndex &_colIdx=emptyConstExportIndex) const
ExportVariable getCol(const ExportIndex &idx) const
virtual returnValue getCode(ExportStatementBlock &code)
returnValue init(const Function &_f, const std::string &_name="acadoFcn", const uint _numX=0, const uint _numXA=0, const uint _numU=0, const uint _numP=0, const uint _numDX=0, const uint _numOD=0)
ExportFunction & addIndex(const ExportIndex &_index)
#define ACADOERROR(retval)
virtual bool equidistantControlGrid() const
Defines a matrix-valued variable to be used for exporting code.
ExportAcadoFunction rhs
returnValue addFunctionCall(const std::string &_fName, const ExportArgument &_argument1=emptyConstExportArgument, const ExportArgument &_argument2=emptyConstExportArgument, const ExportArgument &_argument3=emptyConstExportArgument, const ExportArgument &_argument4=emptyConstExportArgument, const ExportArgument &_argument5=emptyConstExportArgument, const ExportArgument &_argument6=emptyConstExportArgument, const ExportArgument &_argument7=emptyConstExportArgument, const ExportArgument &_argument8=emptyConstExportArgument, const ExportArgument &_argument9=emptyConstExportArgument)
Allows to setup and evaluate differential equations (ODEs and DAEs) based on SymbolicExpressions.
BooleanType is_symmetric
Definition: rk_export.hpp:194


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Mon Jun 10 2019 12:34:33