root/applications/pmsm/simulator_zdenek/ekf_example/ekf_obj.cpp @ 1184

Revision 1183, 14.2 kB (checked in by smidl, 14 years ago)

Test passed for both bierman and thorton

  • Property svn:eol-style set to native
Line 
1
2#include <estim/kalman.h>
3
4#include "ekf_obj.h"
5#include "../simulator.h"
6
7double minQ(double Q){if (Q>1.0){ return 1.0;} else {return Q;};};
8
9void mat_to_int(const imat &M, int *I){
10        for (int i=0;i<M.rows(); i++){
11                for (int j=0;j<M.cols(); j++){
12                        *I++ = M(i,j);
13                }
14        }
15}
16void vec_to_int(const ivec &v, int *I){
17        for (int i=0;i<v.length(); i++){
18                        *I++ = v(i);
19        }
20}
21
22///////////////
23void EKFfixed::bayes(const vec &yt, const vec &ut){
24        ekf(yt(0),yt(1),ut(0),ut(1));
25       
26        vec xhat(4);   
27        //UGLY HACK!!! reliance on a predictor!!
28        xhat(0)=zprevod(x_est[0],Qm)*Iref;
29        xhat(1)=zprevod(x_est[1],Qm)*Iref;
30        xhat(2)=zprevod(x_est[2],Qm)*Wref;
31        xhat(3)=zprevod(x_est[3],15)*Thetaref;
32       
33        E.set_mu(xhat);
34       
35        if ( BM::evalll ) {
36                //from enorm
37                vec xdif(x,4);//first 4 of x
38                //UGLY HACK!!! reliance on a predictor!!
39/*              xdif(0)=x[0]-zprevod(x_pred[0],Qm)*Iref;
40                xdif(1)=x[1]-zprevod(x_pred[1],Qm)*Iref;
41                xdif(2)=x[2]-zprevod(x_pred[2],Qm)*Wref;
42                xdif(3)=x[3]-zprevod(x_pred[3],15);*/
43               
44                xdif -=xhat; //(xdif=x-xhat)
45               
46                mat Pfull(4,4);
47                double* Pp=Pfull._data();
48                for(int i=0;i<16;i++){*(Pp++) = zprevod(P_est[i],15);}
49               
50                E._R()._M()=Pfull;
51               
52               
53                BM::ll = -0.5* ( 4 * 1.83787706640935 +log ( det ( Pfull ) ) +xdif* ( inv(Pfull)*xdif ) );
54        }
55};
56
57
58void EKFfixed::update_psi(void)
59{
60  int t_sin,t_cos,tmp;
61
62  // implementace v PC
63  t_sin=prevod(sin(Thetaref*x_est[3]/32768.),15);
64  t_cos=prevod(cos(Thetaref*x_est[3]/32768.),15);
65
66  PSI[2]=((long)cB*t_sin)>>15;
67  tmp=((long)cH*x_est[2])>>15;
68  PSI[3]=((long)tmp*t_cos)>>15;
69  PSI[6]=-((long)cB*t_cos)>>15;
70  PSI[7]=((long)tmp*t_sin)>>15;
71}
72
73
74void EKFfixed::prediction(int *ux)
75{
76  int t_sin,t_cos, tmp;
77
78  // implementace v PC
79  t_sin=prevod(sin(Thetaref*x_est[3]/32768.),15);
80  t_cos=prevod(cos(Thetaref*x_est[3]/32768.),15);
81
82  tmp=((long)cB*x_est[2])>>15;
83  x_pred[0]=((long)cA*x_est[0]+(long)tmp*t_sin+(long)cC*ux[0])>>15;
84  x_pred[1]=((long)cA*x_est[1]-(long)tmp*t_cos+(long)cC*ux[1])>>15;
85  x_pred[2]=x_est[2];
86  x_pred[3]=(((long)x_est[3]<<15)+(long)cG*x_est[2])>>15;
87
88  update_psi();
89
90  mmult(PSI,P_est,temp15a,3,3,3);
91//  mtrans(PSI,temp15b,5,5);
92  mmultt(temp15a,PSI,P_pred,3,3,3);
93  maddD(P_pred,Q,3,3);
94}
95
96void EKFfixed::correction(void)
97{
98  int Y_error[2];
99  long temp30a[4]; /* matrix [2,2] - temporary matrix for inversion */
100
101  choice_P(P_pred,temp15a,3);
102  maddD(temp15a,R,1,1);
103  minv2(temp15a,temp30a);
104        Ry(0,0)=zprevod(temp15a[0],15);
105        Ry(0,1)=zprevod(temp15a[1],15);
106        Ry(1,0)=zprevod(temp15a[2],15);
107        Ry(1,1)=zprevod(temp15a[3],15);
108 
109  mmultDr(P_pred,temp15a,3,3,1,1);
110  mmult1530(temp15a,temp30a,Kalm,3,1,1);
111
112
113  /* estimate the state system */
114  choice_x(x_pred, temp15a);
115  msub(Y_mes,temp15a,Y_error,1,0);
116  mmult(Kalm,Y_error,temp15a,3,1,0);
117  madd(x_pred,temp15a,x_est,3,0);
118
119  /* matrix of covariances - version without MMULTDL() */
120
121/* Version with MMULTDL() */
122  mmultDl(P_pred,temp15a,1,3,3,1);
123
124  mmult(Kalm,temp15a,P_est,3,1,3);
125  msub(P_pred,P_est,P_est,3,3);
126/* END */
127}
128
129
130void EKFfixed::ekf(double ux, double uy, double isxd, double isyd)
131{
132  // vypocet napeti v systemu (x,y)
133  ukalm[0]=prevod(ux/Uref,Qm);
134  ukalm[1]=prevod(uy/Uref,Qm);
135
136  // zadani mereni
137  Y_mes[0]=prevod(isxd/Iref,Qm);
138  Y_mes[1]=prevod(isyd/Iref,Qm);
139
140  ////// vlastni rutina EKF /////////////////////////
141  prediction(ukalm);
142  correction();
143
144  // navrat estimovanych hodnot regulatoru
145  vec& mu = E._mu();
146  (mu)(0)=zprevod(x_est[0],Qm)*Iref;
147  (mu)(1)=zprevod(x_est[1],Qm)*Iref;
148  (mu)(2)=zprevod(x_est[2],Qm)*Wref;
149  (mu)(3)=zprevod(x_est[3],15)*Thetaref;
150}
151
152void EKFfixed::init_ekf(double Tv)
153{
154  // Tuning of matrix Q
155  Q[0]=prevod(.01,15);       // 0.05
156  Q[5]=Q[0];
157  Q[10]=prevod(0.0001,15);      // 1e-3
158  Q[15]=prevod(0.0001,15);      // 1e-3
159
160  // Tuning of matrix R
161  R[0]=prevod(0.05,15);         // 0.05
162  R[3]=R[0];
163
164  // Motor model parameters
165  cA=prevod(1-Tv*Rs/Ls,15);
166  cB=prevod(Tv*Wref*Fmag/Iref/Ls,15);
167  cC=prevod(Tv/Ls/Iref*Uref,15);
168//  cD=prevod(1-Tv*Bf/J,15);
169//  cE=prevod(kp*p*p*Tv*Fmag*Iref/J/Wref,15);
170//  cF=prevod(p*Tv*Mref/J/Wref,15);
171  cG=prevod(Tv*Wref*4/Thetaref,15);
172  cH=prevod(Tv*Wref*Fmag/Iref/Ls*Thetaref,15);
173//  cI=prevod(kp*p*p*Tv*Fmag*Iref/J/Wref*Thetaref);
174
175  /* Init matrix PSI with permanently constant terms */
176  PSI[0]=cA;
177  PSI[5]=PSI[0];
178  PSI[10]=0x7FFF;
179  PSI[14]=cG;
180  PSI[15]=0x7FFF;
181}
182
183
184void EKF_UDfix::set_parameters ( const shared_ptr<diffbifn> &pfxu0, const shared_ptr<diffbifn> &phxu0, const mat Q0, const vec R0 ) {
185        pfxu = pfxu0;
186        phxu = phxu0;
187       
188        set_dim ( pfxu0->_dimx() );
189        dimy = phxu0->dimension();
190        dimc = pfxu0->_dimu();
191       
192        vec &_mu = est._mu();
193        // if mu is not set, set it to zeros, just for constant terms of A and C
194        if ( _mu.length() != dimension() ) _mu = zeros ( dimension() );
195        A = zeros ( dimension(), dimension() );
196        C = zeros ( dimy, dimension() );
197       
198        //initialize matrices A C, later, these will be only updated!
199        pfxu->dfdx_cond ( _mu, zeros ( dimc ), A, true );
200        //      pfxu->dfdu_cond ( *_mu,zeros ( dimu ),B,true );
201        phxu->dfdx_cond ( _mu, zeros ( dimc ), C, true );
202        //      phxu->dfdu_cond ( *_mu,zeros ( dimu ),D,true );
203       
204        R = R0;
205        Q = Q0;
206       
207        //
208}
209// aux fnc
210void UDtof(const mat &U, const vec &D, imat &Uf, ivec &Df, const vec &xref){
211        mat P= U*diag(D)*U.T();
212        mat T = diag(1.0/(xref));
213        mat Pf = T*P*T;
214       
215        ldmat Pld(Pf);
216       
217        mat Ut=Pld._L().T()*(1<<15); // U is in q15 -- diagonal is 0!!!
218        Uf=round_i(Ut);
219        Df=round_i(Pld._D()*(1<<15));
220        ivec zer=find(Df==0);
221        for(int i=0; i<zer.length(); i++) Df(zer(i))=1;
222}
223
224
225void EKF_UDfix::bayes ( const vec &yt, const vec &cond ) {
226        //preparatory
227        vec &_mu=est._mu();
228        const vec &u=cond;
229        int dim = dimension();
230        ///// !!!!!!!!!!!!!!!!
231        U = est._R()._L().T();
232        D =  est._R()._D();
233       
234        bool DBG=true;
235        if (DBG){
236                mat L;
237                ivec tmp;
238                mat X=randn(5,5);
239                mat XX=X*X.T();
240                mat T=diag(sqrt(1.0/diag(XX)));
241                XX= T*XX*T;
242               
243                ldmat ldd(XX);
244                U = ldd._L().T();
245                D = ldd._D()*0.9;
246        }
247               
248        ////////////
249       
250        pfxu->dfdx_cond ( _mu, u, A, false ); //update A by a derivative of fx
251        phxu->dfdx_cond ( _mu, u, C, false ); //update A by a derivative of fx
252       
253        mat PhiU = A*U;
254
255        //////
256        vec xref(5);
257        xref(0)= 30.0*1.4142;
258        xref(1)= 30.0*1.4142;
259        xref(2)= 6.283185*200.;
260        xref(3) = 3.141593;
261        xref(4) = 34.0;
262       
263        if (DBG){
264                xref = ones(5);
265        }
266       
267        imat Utf;
268        ivec Dtf;
269        UDtof(U,D,Utf,Dtf,xref);
270        mat invxref=diag(1.0/xref);
271        imat Af=round_i(invxref*A*diag(xref)*(1<<15));
272        mat_to_int(Af, PSI);
273        mat_to_int(Utf,Uf);             
274        vec_to_int(Dtf, Df); 
275
276//      cout << Dtf << endl;
277       
278        // A*U == PSI*U
279        mmultAU(PSI,Uf,PSIU,5,5);       
280/*      cout << ivec(PSIU,25) << endl;
281        cout << (Af*Utf)/(1<<15) <<endl;*/
282       
283        vec Din = D;
284        int i,j,k;
285        double sigma;
286        mat G = eye(dim);
287        //////// thorton
288       
289        //move mean;
290        _mu = pfxu->eval(_mu,u);
291       
292        for (i=dim-1; i>=0;i--){
293                sigma = 0.0; 
294                for (j=0; j<dim; j++) {
295                        sigma += PhiU(i,j)*PhiU(i,j) *Din(j); 
296                        sigma += G(i,j)*G(i,j) * Q(j,j);
297                }
298               
299/*              double sigma2= 0.0;
300                for (j=0; j<dim; j++) {
301                        sigma2 += PhiU(i,j)*PhiU(i,j) *Din(j);
302                }
303                sigma2 +=Q(i,i);//*G(i,i)=1.0
304                for (j=i+1; j<dim; j++) {
305                        sigma2 += G(i,j)*G(i,j) * Q(j,j);
306                }*/
307                D(i) = sigma; 
308               
309        /*      UDtof(U,D,Utf,Dtf,xref);
310                cout << "d=sig"<<endl;
311                cout << Dtf << endl;
312        */     
313                for (j=0;j<i;j++){ 
314//                      cout << i << "," << j << endl;
315                        sigma = 0.0; 
316                        for (k=0;k<dim;k++){ 
317                                sigma += PhiU(i,k)*Din(k)*PhiU(j,k); 
318                        }
319                        for (k=0;k<dim;k++){ 
320                                sigma += G(i,k)*Q(k,k)*G(j,k); 
321                        }
322                        //
323                        U(j,i) = sigma/D(i); 
324                       
325/*                      cout << "U=sig/D"<<endl;
326                        UDtof(U,D,Utf,Dtf,xref);
327                        cout << Utf << endl << Dtf << endl;
328                        cout << G << endl << Din << endl<<endl;*/
329                       
330                        for (k=0;k<dim;k++){ 
331                                PhiU(j,k) = PhiU(j,k) - U(j,i)*PhiU(i,k); 
332                        }
333                        for (k=0;k<dim;k++){ 
334                                G(j,k) = G(j,k) - U(j,i)*G(i,k); 
335                        }
336               
337                }
338                UDtof(U,D,Utf,Dtf,xref);
339                //      cout << G << endl << Din << endl;
340                imat Urw=Utf.T();
341                cout << ivec(Urw._data(),25) << endl << Dtf << endl;
342        }
343
344        int Qf[25];
345        imat Qrnd=round_i(diag(elem_div(diag(Q),pow(xref,2)))*(1<<15));
346//      cout << "Qr" << Qrnd<<endl;
347        mat_to_int(Qrnd,Qf);
348
349//      cout << Df <<endl;
350        thorton(Uf,Df,PSIU,Qf,Gf,Dfold,5);
351       
352        if (DBG){
353                _mu = vec("0.500 0.200 0.300 0.400 0.1");
354        }
355       
356        cout << "bierman double I" <<endl;
357        UDtof(U,D,Utf,Dtf,xref);
358        cout << "Uf: " << Utf << endl;
359        cout << "Df: " << Dtf << endl;
360        cout << "xf:" << round_i(elem_div(_mu,xref)*(1<<15)) <<endl;
361        mat_to_int(Utf,Uf);             
362        vec_to_int(Dtf, Df); 
363       
364        // bierman
365       
366        double dz,alpha,gamma,beta,lambda;
367        vec a;
368        vec b;
369        vec yp = phxu->eval(_mu,u);
370        vec xp=_mu; // used in bierman
371       
372        if (DBG){
373                yp = vec("0.40 0.300");
374        }
375       
376        for (int iy=0; iy<dimy; iy++){
377                a     = U.T()*C.get_row(iy);    // a is not modified, but
378                b     = elem_mult(D,a);                          // b is modified to become unscaled Kalman gain.
379                dz    = yt(iy) - yp(iy); 
380               
381                alpha = R(iy); 
382                gamma = 1/alpha; 
383                for (j=0;j<dim;j++){
384                        beta   = alpha; 
385                        alpha  = alpha + a(j)*b(j); 
386                        lambda = -a(j)*gamma; 
387                        gamma  = 1.0/alpha; 
388                        D(j) = beta*gamma*D(j); 
389                       
390                        //                      cout << "a: " << alpha << "g: " << gamma << endl;
391                        for (i=0;i<j;i++){
392                                beta   = U(i,j); 
393                                U(i,j) = beta + b(i)*lambda; 
394                                b(i)   = b(i) + b(j)*beta; 
395                        }
396                }
397                double dzs = gamma*dz;  // apply scaling to innovations
398                _mu   = _mu + dzs*b; // multiply by unscaled Kalman gain
399                //cout << "Ub: " << U << endl;
400                //cout << "Db: " << D << endl <<endl;
401               
402        }
403
404UDtof(U,D,Utf,Dtf,xref);
405cout << "Uf: " << Utf << endl;
406cout << "Df: " << Dtf << endl;
407cout << "xf:" << round_i(elem_div(_mu,xref)*(1<<15)) <<endl;
408
409        int difz[2];
410        vec_to_int(round_i((yt-yp)/xref(0)*(1<<15)), difz);
411        int xf[5];
412        vec_to_int(round_i(elem_div(xp,xref)*(1<<15)), xf);
413        int Rf[2];//={1,1};
414        vec_to_int(round_i(R/pow(xref(0),2)*(1<<15)), Rf);
415        //beirman(int *difz, int *xp, int *U, int *D, int *R, unsigned int dimy, unsigned int dimx
416       
417        cout <<endl<< "bierman fixed" <<endl;
418        cout << "Uf: "; for (i=0; i<25;i++) cout << Uf[i] << ","; cout <<endl;
419        cout << "Df: "; for (i=0; i<5;i++) cout << Df[i] << ","; cout << endl;
420        cout << "xf: "; for (i=0; i<5;i++) cout << xf[i] << ","; cout << endl;
421
422        cout << "dz: "; for (i=0; i<2;i++) cout << difz[i] << ","; cout << endl;
423
424        int xf_old[5];
425        vec_to_int(ivec(xf,5),xf_old);
426        bierman(difz,xf, Uf, Df, Rf, 2, 5);
427       
428        UDtof(U,D,Utf,Dtf,xref);
429        cout << "Uf: "; for (i=0; i<25;i++) cout << Uf[i] << ","; cout <<endl;
430        cout << "Df: "; for (i=0; i<5;i++) cout << Df[i] << ","; cout << endl;
431        cout << "xf: "; for (i=0; i<5;i++) cout << xf[i] << ","; cout << endl;
432        cout << endl;
433       
434       
435       
436        /////
437        est._R().__L()=U.T();
438        est._R().__D()=D;
439       
440        if ( evalll == true ) { //likelihood of observation y
441        }
442}
443
444void EKF_UDfix::from_setting ( const Setting &set ) {
445        BM::from_setting ( set );
446        shared_ptr<diffbifn> IM = UI::build<diffbifn> ( set, "IM", UI::compulsory );
447        shared_ptr<diffbifn> OM = UI::build<diffbifn> ( set, "OM", UI::compulsory );
448       
449        //statistics
450        int dim = IM->dimension();
451        vec mu0;
452        if ( !UI::get ( mu0, set, "mu0" ) )
453                mu0 = zeros ( dim );
454       
455        mat P0;
456        vec dP0;
457        if ( UI::get ( dP0, set, "dP0" ) )
458                P0 = diag ( dP0 );
459        else if ( !UI::get ( P0, set, "P0" ) )
460                P0 = eye ( dim );
461       
462        est._mu()=mu0;
463        est._R()=ldmat(P0);
464       
465        //parameters
466        vec dQ, dR;
467        UI::get ( dQ, set, "dQ", UI::compulsory );
468        UI::get ( dR, set, "dR", UI::compulsory );
469        set_parameters ( IM, OM, diag ( dQ ), dR  );
470       
471        UI::get(log_level, set, "log_level", UI::optional);
472}
473
474
475void EKFfixedUD::bayes(const itpp::vec& yt, const itpp::vec& ut)
476{
477ekf(ut[0],ut[1],yt[0],yt[1]);
478}
479
480
481void EKFfixedUD::ekf(double ux, double uy, double isxd, double isyd)
482{
483        // vypocet napeti v systemu (x,y)
484        int uf[2];
485        uf[0]=prevod(ux/Uref,Qm);
486        uf[1]=prevod(uy/Uref,Qm);
487       
488        int Y_mes[2];
489        // zadani mereni
490        Y_mes[0]=prevod(isxd/Iref,Qm);
491        Y_mes[1]=prevod(isyd/Iref,Qm);
492       
493        ////// vlastni rutina EKF -- /////////////////////////
494        int t_sin,t_cos, tmp;
495       
496        // implementace v PC
497        t_sin=prevod(sin(Thetaref*x_est[3]/32768.),15);
498        t_cos=prevod(cos(Thetaref*x_est[3]/32768.),15);
499       
500        tmp=((long)cB*x_est[2])>>15;
501        x_est[0]=((long)cA*x_est[0]+(long)tmp*t_sin+(long)cC*uf[0])>>15;
502        x_est[1]=((long)cA*x_est[1]-(long)tmp*t_cos+(long)cC*uf[1])>>15;
503        x_est[2]=x_est[2];
504        x_est[3]=(((long)x_est[3]<<15)+(long)cG*x_est[2])>>15;
505       
506        //void EKFfixed::update_psi(void)
507        {               
508                PSI[2]=((long)cB*t_sin)>>15;
509                tmp=((long)cH*x_est[2])>>15;
510                PSI[3]=((long)tmp*t_cos)>>15;
511                PSI[6]=-((long)cB*t_cos)>>15;
512                PSI[7]=((long)tmp*t_sin)>>15;
513        }
514       
515        ///////// end of copy ///////////////
516        mmultAU(PSI,Uf,PSIU,4,4);
517        //thorton(int *U, int *D, int *PSIU, int *Q, int *G, int *Dold, unsigned int dimx);
518        thorton(Uf,Df,PSIU,Q,G,Dfold,4);
519       
520        int difz[2];
521        difz[0]=Y_mes[0]-x_est[0];
522        difz[1]=Y_mes[1]-x_est[1];
523        //bierman(int *difz, int *xp, int *U, int *D, int *R, unsigned int dimy, unsigned int dimx );
524        int dR[2];dR[0]=R[0];dR[1]=R[3];
525        bierman(difz,x_est,Uf,Df,dR,2,4);
526       
527        // navrat estimovanych hodnot regulatoru
528        vec& mu = E._mu();
529        (mu)(0)=zprevod(x_est[0],Qm)*Iref;
530        (mu)(1)=zprevod(x_est[1],Qm)*Iref;
531        (mu)(2)=zprevod(x_est[2],Qm)*Wref;
532        (mu)(3)=zprevod(x_est[3],15)*Thetaref;
533       
534//      mat T=diag(concat(vec_2(Iref,Iref), vec_2(Wref,Thetaref)));
535}
536
537void EKFfixedUD::init_ekf(double Tv)
538{
539        // Tuning of matrix Q
540        Q[0]=prevod(.01,15);       // 0.05
541        Q[5]=Q[0];
542        Q[10]=prevod(0.0001,15);      // 1e-3
543        Q[15]=prevod(0.0001,15);      // 1e-3
544
545        Uf[0]=0x7FFF;       // 0.05
546        Uf[5]=0x7FFF;
547        Uf[10]=0x7FFF;      // 1e-3
548        Uf[15]=0x7FFF;      // 1e-3
549       
550        Df[0]=0x7FFF;
551        Df[1]=0x7FFF;
552        Df[2]=0x7FFF;
553        Df[3]=0x7FFF;
554       
555        // Tuning of matrix R
556        R[0]=prevod(0.05,15);         // 0.05
557        R[3]=R[0];
558       
559        // Motor model parameters
560        cA=prevod(1-Tv*Rs/Ls,15);
561        cB=prevod(Tv*Wref*Fmag/Iref/Ls,15);
562        cC=prevod(Tv/Ls/Iref*Uref,15);
563        //  cD=prevod(1-Tv*Bf/J,15);
564        //  cE=prevod(kp*p*p*Tv*Fmag*Iref/J/Wref,15);
565        //  cF=prevod(p*Tv*Mref/J/Wref,15);
566        cG=prevod(Tv*Wref*4/Thetaref,15);
567        cH=prevod(Tv*Wref*Fmag/Iref/Ls*Thetaref,15);
568        //  cI=prevod(kp*p*p*Tv*Fmag*Iref/J/Wref*Thetaref);
569       
570        /* Init matrix PSI with permanently constant terms */
571        PSI[0]=cA;
572        PSI[5]=PSI[0];
573        PSI[10]=0x7FFF;
574        PSI[14]=cG;
575        PSI[15]=0x7FFF;
576       
577        //////////////////////// =================
578        ///// TEST thorton vs. thorton_fast
579       
580/*      int Ut[16]={0x7FFF, 100, 200, 300, 0, 0x7FFF, 500, 600, 0,0,0x7FFF, 800, 0,0,0, 0x7FFF};
581        int Dt[4]={100,200,300,400};
582        int PSIu[16] = {100, 200,300, 400 , 500, 600,700,800, 900,1000,1100,1200, 1300,1400,1500,1600};
583        int Dold[4];
584       
585        thorton(Ut,Dt,PSIu,Q,G,Dold,4);
586        int Ut2[16]={0x7FFF, 100, 200, 300, 0, 0x7FFF, 500, 600, 0,0,0x7FFF, 800, 0,0,0, 0x7FFF};
587        int Dt2[4]={100,200,300,400};
588        int PSIu2[16] = {100, 200,300, 400 , 500, 600,700,800, 900,1000,1100,1200, 1300,1400,1500,1600};
589        thorton_fast(Ut2,Dt2,PSIu2,Q,G,Dold,4);
590        cout<< Q<<endl;*/
591}
Note: See TracBrowser for help on using the browser.