source: Sophya/trunk/SophyaLib/NTools/rk4cdifeq.cc@ 3737

Last change on this file since 3737 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

File size: 4.3 KB
RevLine 
[2615]1#include "sopnamsp.h"
[244]2#include "machdefs.h"
[220]3#include "rk4cdifeq.h"
4#include "ctimer.h"
[2322]5#include <iostream>
[220]6
7inline double max_dbl(double a, double b) { return ((a < b) ? b : a); }
8
9//++
10// Class RK4CDiffEq
11// Lib Outils++
12// include rk4cdifeq.h
13//
14// Classe de résolution d'équadif par la méthode de
15// Runge-Kutta d'ordre 4 adaptatif.
16// Voir DiffEqSolver et R4KDiffEq pour les méthodes.
17//
18// On peut demander une précision relative ou absolue
19// sur chacune des fonctions du système. Le pas d'intégration
20// est adapté automatiquement pour fournir au moins
21// cette précision.
22//--
23
24//++
25// Links Parents
26// RK4DiffEq
27// DiffEqSolver
28//--
29
30//++
31// Titre Constructeurs
32// Voir RK4DiffEq et DiffEqSolver
33//--
34
35//++
36RK4CDiffEq::RK4CDiffEq()
37//
38//--
39: RK4DiffEq(), eps(1.e-4), relAccuracy(true), accScale(10), yTemp(10), ySave(10)
40{}
41
42//++
43RK4CDiffEq::RK4CDiffEq(DiffEqFunction* f)
44//
45//--
46: RK4DiffEq(f), eps(1.e-4), relAccuracy(true), accScale(f->NFuncReal()), yTemp(f->NFuncReal()), ySave(f->NFuncReal())
47{}
48
49//++
50RK4CDiffEq::RK4CDiffEq(DIFEQFCN1 f)
51//
52//--
53: RK4DiffEq(f), eps(1.e-4), relAccuracy(true), accScale(1), yTemp(1), ySave(1)
54{}
55
56//++
57// Titre Méthodes
58//--
59
60//++
61// RK4CDiffEq& RK4CDiffEq::Accuracy(double eps)
62// Fixe la précision requise sur les fonctions. Cette précision
63// est par défaut relative. Elle peut être absolue, auquel cas
64// il faut fixer, pour chaque fonction, un facteur d'échelle, et
65// la précision sur chaque fonction est alors scale[i]*eps.
66//--
67
68RK4CDiffEq&
69RK4CDiffEq::Accuracy(double x)
70{
71 eps = x;
72 return *this;
73}
74
75//++
76RK4CDiffEq&
[514]77RK4CDiffEq::AbsAccuracy(Vector const& vScal)
[220]78//
79// On souhaite une précision absolue, et le vecteur vScal contient
80// le facteur d'échelle pour chaque fonction (voir Accuracy).
81//--
82{
83 accScale = vScal;
84 relAccuracy = false;
85 return *this;
86}
87
88//++
89RK4CDiffEq&
90RK4CDiffEq::AbsAccuracy(double scal)
91//
92// On souhaite une précision absolue, et le vecteur scal contient
93// le facteur d'échelle à appliquer à toutes les fonctions.
94// La précision absolue souhaitée est alors eps*scal.
95//--
96{
97 for (int i=0; i<accScale.NElts(); i++)
98 accScale(i) = scal;
99 relAccuracy = false;
100 return *this;
101}
102
103//++
104RK4CDiffEq&
105RK4CDiffEq::RelAccuracy()
106//
107// On souhaite une précision relative. En quelque sorte, le facteur d'échelle
108// pour chaque fonction est alors la valeur de la fonction.
109//--
110{
111 relAccuracy = true;
112 return *this;
113}
114
115static const double pgrow = -0.20;
116static const double pshrink = -0.25;
117static const double safety = 0.9;
118static const double errcon = pow((4/safety),1/pgrow);
119
120void
[514]121RK4CDiffEq::RKCStep(Vector& newY, Vector const& y0, Vector const& yScale,
[220]122 double dttry, double& dtdone, double& dtnext)
123{
124 double err;
125 ySave = y0;
126 do {
127 // Deux petits pas
128 RKStep(yTemp, ySave, dttry/2.);
129 RKStep(newY, yTemp, dttry/2.);
130
131 // Un grand pas
132 RKStep(yTemp, ySave, dttry);
133
134 yTemp -= newY; // l'erreur courante
135
136 err = 0;
137 for (int i=0; i<yTemp.NElts(); i++)
138 err = max_dbl(fabs(yScale(i) ? (yTemp(i)/yScale(i)) : yTemp(i)), err);
139
140 err /= eps;
141 if (err > 1)
142 dttry *= safety*pow(err,pshrink);
143 else {
144 dtdone = dttry;
145 if (err > errcon)
146 dtnext = safety*dttry*pow(err,pgrow);
147 else
148 dtnext = dttry*4;
149 }
150 } while (err > 1);
151
152 // Et on corrige a l'ordre 5
153
[514]154 newY += yTemp/15.;
[220]155}
156
157void
[514]158RK4CDiffEq::SolveArr(Matrix& y, double* t, double tf, int n)
[220]159{
160 //TIMEF;
161 // Les intervalles a stocker dans la matrice des resultats
162
163 double dxres = (tf - mXStart)/n;
164
[1087]165 Vector yt(mYStart,false);
[220]166
167 k1.Realloc(mFunc->NFuncReal());
168 k2.Realloc(mFunc->NFuncReal());
169 k3.Realloc(mFunc->NFuncReal());
170 k4.Realloc(mFunc->NFuncReal());
171 yTemp.Realloc(mFunc->NFuncReal());
172 ySave.Realloc(mFunc->NFuncReal());
173
174 double x = mXStart;
175 double step = mStep;
176 double nstep;
177
178 for (int i=0; i<n; i++) {
179 double xEndStep = (i+1)*dxres + mXStart;
180 do {
181 if (relAccuracy) accScale = yt;
182 if ((x+step-xEndStep)*(x+step-mXStart)>0) step = xEndStep-x;
183 RKCStep(yt, yt, accScale, step, step, nstep);
184 x += step;
185 //cout << x << " " << step << endl;
186 step = nstep;
187 } while ((x-xEndStep)*(x-mXStart) < 0);
188 for (int j=0; j<mFunc->NFunc(); j++)
189 y(i,j) = yt(j);
190 t[i] = xEndStep;
191 //cout << "fin boucle "<<i<<" "<<x<<" "<<yt(0)<<endl;
192 }
193
194}
Note: See TracBrowser for help on using the repository browser.