1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
/*----------------------------------------------------------------------------
ADOL-C -- Automatic Differentiation by Overloading in C++
File: ext_diff_func.cpp
Revision: $Id: ext_diff_func.cpp 370 2012-11-22 13:18:52Z kulshres $
Contents: example for external differentiated functions
Copyright (c) Andrea Walther
This file is part of ADOL-C. This software is provided as open source.
Any use, reproduction, or distribution of the software constitutes
recipient's acceptance of the terms of the accompanying license file.
---------------------------------------------------------------------------*/
#include <math.h>
#include <adolc/adolc.h>
#define h 0.01
#define steps 100
// time step function
// double version
int euler_step(int n, double *yin, int m, double *yout);
// adouble version
void euler_step_act(int n, adouble *yin, int m, adouble *yout);
// versions for usage as external differentiated function
ADOLC_ext_fct zos_for_euler_step;
ADOLC_ext_fct_fos_reverse fos_rev_euler_step;
ext_diff_fct *edf;
int tag_full, tag_part, tag_ext_fct;
int main()
{
// time interval
double t0, tf;
// state, double and adouble version
adouble y[2];
adouble ynew[2];
int n, m;
// control, double and adouble version
adouble con[2];
double conp[2];
// target value;
double f;
//variables for derivative caluclation
double yp[2], ynewp[2];
double u[2], z[2];
double grad[2];
int i,j;
// tape identifiers
tag_full = 1;
tag_part = 2;
tag_ext_fct = 3;
// two input variables for external differentiated function
n = 2;
// two output variables for external differentiated function
m = 2;
// time interval
t0 = 0.0;
tf = 1.0;
//control
conp[0] = 1.0;
conp[1] = 1.0;
trace_on(tag_full);
con[0] <<= conp[0];
con[1] <<= conp[1];
y[0] = con[0];
y[1] = con[1];
for(i=0;i<steps;i++)
{
euler_step_act(n,y,m,ynew);
for(j=0;j<2;j++)
y[j] = ynew[j];
}
y[0] + y[1] >>= f;
trace_off(1);
gradient(tag_full,2,conp,grad);
printf(" full taping:\n gradient=( %f, %f)\n\n",grad[0],grad[1]);
// Now using external function facilities
// tape external differentiated function
trace_on(tag_ext_fct);
y[0] <<= conp[0];
y[1] <<= conp[1];
euler_step_act(2,y,2,ynew);
ynew[0] >>= f;
ynew[1] >>= f;
trace_off(1);
// register external function
edf = reg_ext_fct(euler_step);
// information for Zero-Order-Scalar (=zos) forward
// yp = new double[2];
// ynewp = new double[2];
edf->zos_forward = zos_for_euler_step;
edf->dp_x = yp;
edf->dp_y = ynewp;
// information for First-Order-Scalar (=fos) reverse
edf->fos_reverse = fos_rev_euler_step;
edf->dp_U = u;
edf->dp_Z = z;
trace_on(tag_part);
con[0] <<= conp[0];
con[1] <<= conp[1];
y[0] = con[0];
y[1] = con[1];
for(i=0;i<steps;i++)
{
call_ext_fct(edf, 2, yp, y, 2, ynewp, ynew);
for(j=0;j<2;j++)
y[j] = ynew[j];
}
y[0] + y[1] >>= f;
trace_off(1);
gradient(tag_part,2,conp,grad);
printf(" taping with external function facility:\n gradient=( %f, %f)\n\n",grad[0],grad[1]);
return 0;
}
void euler_step_act(int n, adouble *yin, int m, adouble *yout)
{
// Euler step, adouble version
yout[0] = yin[0]+h*yin[0];
yout[1] = yin[1]+h*2*yin[1];
}
int euler_step(int n, double *yin, int m, double *yout)
{
// Euler step, double version
yout[0] = yin[0]+h*yin[0];
yout[1] = yin[1]+h*2*yin[1];
return 1;
}
int zos_for_euler_step(int n, double *yin, int m, double *yout)
{
int rc;
rc = zos_forward(tag_ext_fct, 2, 2, 0, yin, yout);
return rc;
}
int fos_rev_euler_step(int n, double *u, int m, double *z, double */* unused */, double */*unused*/)
{
int rc;
zos_forward(tag_ext_fct, 2, 2, 1, edf->dp_x, edf->dp_y);
rc = fos_reverse(tag_ext_fct, 2, 2, u, z);
return rc;
}
|