1 
2 /*----------------------------------------------------------------------------
3  ADOL-C -- Automatic Differentiation by Overloading in C++
4  File:     fixpoint.c
5  Revision: $Id: fixpoint.cpp 608 2015-08-10 20:06:55Z kulshres $
6  Contents: all C functions directly accessing at least one of the four tapes
7            (operations, locations, constants, value stack)
8 
9  Copyright (c) Andreas Kowarz, Sebastian Schlenkrich
10 
11  This file is part of ADOL-C. This software is provided as open source.
12  Any use, reproduction, or distribution of the software constitutes
13  recipient's acceptance of the terms of the accompanying license file.
14 
15 ----------------------------------------------------------------------------*/
16 
17 #include "taping_p.h"
18 #include <adolc/adolc.h>
19 #include <adolc/fixpoint.h>
20 #include "dvlparms.h"
21 
22 #include <vector>
23 
24 using namespace std;
25 
26 
27 /*--------------------------------------------------------------------------*/
28 
29 /* F(x,u,y,dim_x,dim_u) */
30 /* norm(x,dim_x)        */
31 typedef struct {
32     locint     edf_index;
33     int        sub_tape_num;
34     int      (*double_F)(double*, double* ,double*, int, int);
35     int      (*adouble_F)(adouble*, adouble*, adouble*, int, int);
36     double   (*norm)(double*, int);
37     double   (*norm_deriv)(double*, int);
38     double     epsilon;
39     double     epsilon_deriv;
40     int        N_max;
41     int        N_max_deriv;
42 }
43 fpi_data;
44 
45 
46 static vector<fpi_data*> fpi_stack;
47 
48 
iteration(int dim_xu,double * xu,int dim_x,double * x_fix)49 static int iteration ( int dim_xu, double *xu, int dim_x, double *x_fix ) {
50     int i, k;
51     double err;
52     fpi_data *current = fpi_stack.back();
53     for (i=0; i<dim_x; i++) x_fix[i] = xu[i];
54     for (k=1; k<=current->N_max; k++) {
55         for (i=0; i<dim_x; i++) xu[i] = x_fix[i];
56         (*current->double_F)( xu, xu+dim_x, x_fix, dim_x, dim_xu-dim_x );
57         for (i=0; i<dim_x; i++) xu[i] = x_fix[i] - xu[i];
58         err = (*current->norm)(xu,dim_x);
59         if (err<current->epsilon) return k;
60     }
61     return -1;
62 }
63 
64 
fp_zos_forward(int dim_xu,double * xu,int dim_x,double * x_fix)65 static int fp_zos_forward ( int dim_xu, double *xu, int dim_x, double *x_fix ) {
66     int i, k;
67     double err;
68     ADOLC_OPENMP_THREAD_NUMBER;
69     ADOLC_OPENMP_GET_THREAD_NUMBER;
70     locint edf_index = ADOLC_CURRENT_TAPE_INFOS.ext_diff_fct_index;
71     fpi_data *current=0;
72     vector<fpi_data*>::iterator fpi_stack_iterator;
73     for (fpi_stack_iterator=fpi_stack.begin();
74             fpi_stack_iterator!=fpi_stack.end();
75             ++fpi_stack_iterator) {
76         current = *fpi_stack_iterator;
77         if (edf_index==current->edf_index) break;
78     }
79     if (fpi_stack_iterator==fpi_stack.end()) {
80         fprintf(stderr,"ADOL-C Error! No edf found for fixpoint iteration.\n");
81         adolc_exit(-1,"",__func__,__FILE__,__LINE__);
82     }
83     for (i=0; i<dim_x; i++) x_fix[i] = xu[i];
84     for (k=1; k<=current->N_max; k++) {
85         for (i=0; i<dim_x; i++) xu[i] = x_fix[i];
86         (*current->double_F)( xu, xu+dim_x, x_fix, dim_x, dim_xu-dim_x );
87         for (i=0; i<dim_x; i++) xu[i] = x_fix[i] - xu[i];
88         err = (*current->norm)(xu,dim_x);
89         if (err<current->epsilon) return k;
90     }
91     return -1;
92 }
93 
fp_fos_forward(int dim_xu,double * xu,double * xu_dot,int dim_x,double * x_fix,double * x_fix_dot)94 static int fp_fos_forward ( int dim_xu, double *xu, double *xu_dot,
95                             int dim_x, double *x_fix, double *x_fix_dot) {
96     // Piggy back
97     int i, k;
98     double err, err_deriv;
99     ADOLC_OPENMP_THREAD_NUMBER;
100     ADOLC_OPENMP_GET_THREAD_NUMBER;
101     locint edf_index = ADOLC_CURRENT_TAPE_INFOS.ext_diff_fct_index;
102     fpi_data *current=0;
103     vector<fpi_data*>::iterator fpi_stack_iterator;
104     for (fpi_stack_iterator=fpi_stack.begin();
105             fpi_stack_iterator!=fpi_stack.end();
106             ++fpi_stack_iterator) {
107         current = *fpi_stack_iterator;
108         if (edf_index==current->edf_index) break;
109     }
110     if (fpi_stack_iterator==fpi_stack.end()) {
111         fprintf(stderr,"ADOL-C Error! No edf found for fixpoint iteration.\n");
112         adolc_exit(-1,"",__func__,__FILE__,__LINE__);
113     }
114     for (k=1; (k<current->N_max_deriv)|(k<current->N_max); k++) {
115         for (i=0; i<dim_x; i++) xu[i] = x_fix[i];
116         for (i=0; i<dim_x; i++) xu_dot[i] = x_fix_dot[i];
117         fos_forward ( current->sub_tape_num, dim_x, dim_xu, 0, xu, xu_dot, x_fix, x_fix_dot);
118         for (i=0; i<dim_x; i++)  xu[i] = x_fix[i] - xu[i];
119         err = (*current->norm)(xu,dim_x);
120         for (i=0; i<dim_x; i++) xu_dot[i] = x_fix_dot[i] -  xu_dot[i];
121         err_deriv = (*current->norm_deriv)(xu_dot,dim_x);
122         if ((err<current->epsilon)&(err_deriv<current->epsilon_deriv)) {
123             return k;
124         }
125     }
126     return -1;
127 }
128 
fp_fos_reverse(int dim_x,double * x_fix_bar,int dim_xu,double * xu_bar,double *,double *)129 static int fp_fos_reverse ( int dim_x, double *x_fix_bar, int dim_xu, double *xu_bar, double* /*unused*/, double* /*unused*/) {
130     // (d x_fix) / (d x_0) = 0 (!)
131     int i, k;
132     double err;
133     ADOLC_OPENMP_THREAD_NUMBER;
134     ADOLC_OPENMP_GET_THREAD_NUMBER;
135     locint edf_index = ADOLC_CURRENT_TAPE_INFOS.ext_diff_fct_index;
136     fpi_data *current=0;
137     vector<fpi_data*>::iterator fpi_stack_iterator;
138     for (fpi_stack_iterator=fpi_stack.begin();
139             fpi_stack_iterator!=fpi_stack.end();
140             ++fpi_stack_iterator) {
141         current = *fpi_stack_iterator;
142         if (edf_index==current->edf_index) break;
143     }
144     if (fpi_stack_iterator==fpi_stack.end()) {
145         fprintf(stderr,"ADOL-C Error! No edf found for fixpoint iteration.\n");
146         adolc_exit(-1,"",__func__,__FILE__,__LINE__);
147     }
148     double *U = new double[dim_xu];
149     double *xi = new double[dim_x];
150 
151     for (k=1; k<current->N_max_deriv; k++) {
152         for (i=0; i<dim_x; i++) xi[i] = U[i];
153         fos_reverse ( current->sub_tape_num, dim_x, dim_xu, xi, U );
154         for (i=0; i<dim_x; i++) U[i] += x_fix_bar[i];
155         for (i=0; i<dim_x; i++) xi[i] = U[i] - xi[i];
156         err = (*current->norm_deriv)(xi,dim_x);
157         printf(" fp_fos_reverse: k = %d  err = %e\n",k,err);
158         if (err<current->epsilon_deriv) {
159             for (i=0; i<dim_xu-dim_x; i++) {
160                 xu_bar[dim_x+i] += U[dim_x+i];
161             }
162 
163             delete[] xi;
164             delete[] U;
165             return k;
166         }
167     }
168     for (i=0; i<dim_xu-dim_x; i++) xu_bar[dim_x+i] += U[dim_x+i];
169     delete[] xi;
170     delete[] U;
171     return -1;
172 }
173 
174 
fp_iteration(int sub_tape_num,int (* double_F)(double *,double *,double *,int,int),int (* adouble_F)(adouble *,adouble *,adouble *,int,int),double (* norm)(double *,int),double (* norm_deriv)(double *,int),double epsilon,double epsilon_deriv,int N_max,int N_max_deriv,adouble * x_0,adouble * u,adouble * x_fix,int dim_x,int dim_u)175 int fp_iteration ( int        sub_tape_num,
176                    int      (*double_F)(double*, double* ,double*, int, int),
177                    int      (*adouble_F)(adouble*, adouble*, adouble*, int, int),
178                    double   (*norm)(double*, int),
179                    double   (*norm_deriv)(double*, int),
180                    double     epsilon,
181                    double     epsilon_deriv,
182                    int        N_max,
183                    int        N_max_deriv,
184                    adouble   *x_0,
185                    adouble   *u,
186                    adouble   *x_fix,
187                    int        dim_x,
188                    int        dim_u ) {
189     int i, k;
190     double dummy;
191     // add new fp information
192     fpi_data *data = new fpi_data;
193     data->sub_tape_num = sub_tape_num;
194     data->double_F     = double_F;
195     data->adouble_F    = adouble_F;
196     data->norm         = norm;
197     data->norm_deriv   = norm_deriv;
198     data->epsilon      = epsilon;
199     data->epsilon_deriv = epsilon_deriv;
200     data->N_max        = N_max;
201     data->N_max_deriv  = N_max_deriv;
202     fpi_stack.push_back(data);
203 
204     // declare extern differentiated function and data
205     ext_diff_fct *edf_iteration = reg_ext_fct(&iteration);
206     data->edf_index = edf_iteration->index;
207     edf_iteration->zos_forward = &fp_zos_forward;
208     edf_iteration->fos_forward = &fp_fos_forward;
209     edf_iteration->fos_reverse = &fp_fos_reverse;
210 
211     // put x and u together
212     adouble   *xu      = new adouble[dim_x+dim_u];
213     for (i=0; i<dim_x; i++) xu[i] = x_0[i];
214     for (i=0; i<dim_u; i++) xu[dim_x+i] = u[i];
215 
216     k = call_ext_fct ( edf_iteration, dim_x+dim_u, xu,
217                        dim_x, x_fix );
218 
219     // tape near solution
220     trace_on(sub_tape_num,1);
221     for (i=0; i<dim_x; i++) xu[i] <<= x_fix[i].getValue();
222     for (i=0; i<dim_u; i++) xu[dim_x+i] <<= u[i].getValue();
223     adouble_F(xu, xu+dim_x, x_fix, dim_x, dim_u);
224     for (i=0; i<dim_x; i++) x_fix[i] >>= dummy;
225     trace_off();
226 
227     delete[] xu;
228     return k;
229 }
230