1 |
#include "gestionversion.h"
|
2 |
//---------------------------------------------------------------------------
|
3 |
#include "matcreuse.h"
|
4 |
|
5 |
#pragma hdrstop
|
6 |
|
7 |
|
8 |
//---------------------------------------------------------------------------
|
9 |
|
10 |
#pragma package(smart_init)
|
11 |
|
12 |
|
13 |
|
14 |
void ::MatCr::Row::add(int index, double val) {
|
15 |
for(int i=0; i<size(); i++) {
|
16 |
if((*this)[i].index == index) {
|
17 |
(*this)[i].a += val ;
|
18 |
return ;
|
19 |
}
|
20 |
}
|
21 |
if(val!=0.)
|
22 |
std::vector<Coeff>::push_back(Coeff(index, val)) ;
|
23 |
}
|
24 |
double ::MatCr::Row::get(int j) {
|
25 |
for(int i=0; i<size(); i++) {
|
26 |
if((*this)[i].index == j)
|
27 |
return(*this)[i].a ;
|
28 |
|
29 |
}
|
30 |
return 0.;
|
31 |
}
|
32 |
void ::MatCr::Row::set(int index, double val)
|
33 |
{
|
34 |
if(val!=0.)
|
35 |
{
|
36 |
for(int i=0; i<size(); i++) {
|
37 |
if((*this)[i].index == index) {
|
38 |
(*this)[i].a = val ;
|
39 |
return ;
|
40 |
}
|
41 |
}
|
42 |
}
|
43 |
if(val!=0.)
|
44 |
std::vector<Coeff>::push_back(Coeff(index, val)) ;
|
45 |
}
|
46 |
double ::MatCr::Row::row_max()
|
47 |
{
|
48 |
double max=fabs((*this)[0].a);
|
49 |
for(int i=0; i<size(); i++) {
|
50 |
if(fabs((*this)[i].a) > max) max=fabs((*this)[i].a);
|
51 |
return max;
|
52 |
|
53 |
}
|
54 |
}
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
MatCr::MatCr(int dim) : dimension(dim)
|
61 |
{
|
62 |
row = new Row[dim] ;
|
63 |
}
|
64 |
|
65 |
MatCr::~MatCr()
|
66 |
{
|
67 |
delete[] row;
|
68 |
}
|
69 |
// aij <- aij + val
|
70 |
void MatCr::add(int i, int j, double val) {
|
71 |
if(j>=i)
|
72 |
row[i].add(j, val) ;
|
73 |
}
|
74 |
void MatCr::set(int i, int j, double val) {
|
75 |
row[i].set(j, val) ;
|
76 |
}
|
77 |
double MatCr::get(int i, int j) {
|
78 |
if(i>j){
|
79 |
int tmp=j;
|
80 |
j=i;
|
81 |
i=tmp;}
|
82 |
return row[i].get(j) ;
|
83 |
}
|
84 |
|
85 |
|
86 |
|
87 |
double MatCr:: get_max()
|
88 |
{
|
89 |
double max=0.;
|
90 |
for(int i=0;i<dimension;i++)
|
91 |
{
|
92 |
double maxi=row[i].row_max();
|
93 |
if (maxi>max) max=maxi;
|
94 |
}
|
95 |
return max;
|
96 |
}
|
97 |
void MatCr::diag(double* tmp_diag)
|
98 |
{
|
99 |
for(int i=0;i<dimension;i++)
|
100 |
{
|
101 |
tmp_diag[i]=get(i,i);
|
102 |
}
|
103 |
}
|
104 |
// A <- 0
|
105 |
void MatCr::clear() {
|
106 |
for(int i=0; i<dimension; i++) {
|
107 |
row[i].clear() ;
|
108 |
}
|
109 |
}
|
110 |
// number of non-zero coefficients
|
111 |
int MatCr::nnz() const {
|
112 |
int result = 0 ;
|
113 |
for(int i=0; i<dimension; i++) {
|
114 |
result += row[i].size() ;
|
115 |
}
|
116 |
return result ;
|
117 |
}
|
118 |
|
119 |
/*
|
120 |
void MatCr::mul(double* y, const double* x)
|
121 |
{
|
122 |
for(int i=0; i<this->dimension; i++)
|
123 |
{
|
124 |
y[i] = 0 ;
|
125 |
const Row& R = this->row[i] ;
|
126 |
for(int jj=0; jj<this->dimension; jj++)
|
127 |
{
|
128 |
y[i] += this->get(i,jj)* x[jj] ;
|
129 |
}
|
130 |
/*
|
131 |
for(int jj=0; jj<R.size(); jj++)
|
132 |
{
|
133 |
y[i] += R[jj].a * x[ R[jj].index ] ;
|
134 |
} /
|
135 |
}
|
136 |
} */
|
137 |
|
138 |
void MatCr::convert_to_CRS(const MatCr& M, CRSMatrix& M_CRS,int array_base) // 0 pour le C, 1 pour le Fortran
|
139 |
{
|
140 |
M_CRS.N = M.dimension ;
|
141 |
M_CRS.NNZ = M.nnz() ;
|
142 |
M_CRS.a = new double[M_CRS.NNZ] ;
|
143 |
M_CRS.col_ind = new int[M_CRS.NNZ] ;
|
144 |
M_CRS.row_ptr = new int[M_CRS.N+1] ;
|
145 |
int count = 0 ;
|
146 |
for(int i=0; i<M_CRS.N; i++)
|
147 |
{
|
148 |
const MatCr::Row& R = M.row[i] ;
|
149 |
M_CRS.row_ptr[i] = count + array_base ;
|
150 |
for(int jj=0; jj<R.size(); jj++)
|
151 |
{
|
152 |
M_CRS.a[count] = R[jj].a ;
|
153 |
M_CRS.col_ind[count] = R[jj].index + array_base ;
|
154 |
count++ ;
|
155 |
}
|
156 |
}
|
157 |
M_CRS.row_ptr[M_CRS.N] = M_CRS.NNZ + array_base ;
|
158 |
}
|
159 |
|
160 |
void MatCr::mult(double* y, CRSMatrix* M, double* x)
|
161 |
{
|
162 |
for(int i=0; i<M->N; i++) {
|
163 |
y[i] = 0.0 ;
|
164 |
for(int jj=M->row_ptr[i]; jj<M->row_ptr[i+1]; jj++) {
|
165 |
y[i] += M->a[jj] * x[M->col_ind[jj]] ;
|
166 |
}
|
167 |
}
|
168 |
}
|
169 |
|
170 |
|
171 |
void MatCr::pcg(double* b,double*x,double eps)
|
172 |
{
|
173 |
|
174 |
/*
|
175 |
CGS(const Matrix &A, Vector &x, const Vector &b,
|
176 |
const Preconditioner &M, int &max_iter, Real &tol)
|
177 |
{
|
178 |
double resid;
|
179 |
Vector rho_1(1), rho_2(1), alpha(1), beta(1);
|
180 |
Vector p, phat, q, qhat, vhat, u, uhat;
|
181 |
|
182 |
double normb = get_norm(b,n);
|
183 |
Vector r = b - A*x;
|
184 |
Vector rtilde = r;
|
185 |
|
186 |
if (normb == 0.0)
|
187 |
normb = 1;
|
188 |
|
189 |
if ((resid = norm(r) / normb) <= tol) {
|
190 |
tol = resid;
|
191 |
max_iter = 0;
|
192 |
return 0;
|
193 |
}
|
194 |
|
195 |
for (int i = 1; i <= max_iter; i++) {
|
196 |
rho_1(0) = dot(rtilde, r);
|
197 |
if (rho_1(0) == 0) {
|
198 |
tol = norm(r) / normb;
|
199 |
return 2;
|
200 |
}
|
201 |
if (i == 1) {
|
202 |
u = r;
|
203 |
p = u;
|
204 |
} else {
|
205 |
beta(0) = rho_1(0) / rho_2(0);
|
206 |
u = r + beta(0) * q;
|
207 |
p = u + beta(0) * (q + beta(0) * p);
|
208 |
}
|
209 |
phat = M.solve(p);
|
210 |
vhat = A*phat;
|
211 |
alpha(0) = rho_1(0) / dot(rtilde, vhat);
|
212 |
q = u - alpha(0) * vhat;
|
213 |
uhat = M.solve(u + q);
|
214 |
x += alpha(0) * uhat;
|
215 |
qhat = A * uhat;
|
216 |
r -= alpha(0) * qhat;
|
217 |
rho_2(0) = rho_1(0);
|
218 |
if ((resid = norm(r) / normb) < tol) {
|
219 |
tol = resid;
|
220 |
max_iter = i;
|
221 |
return 0;
|
222 |
}
|
223 |
}
|
224 |
|
225 |
tol = resid;
|
226 |
return 1; */
|
227 |
}
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
/*
|
236 |
double *r=new double[dimension];
|
237 |
double *d=new double[dimension];
|
238 |
double *z=new double[dimension];
|
239 |
double *Adk=new double[dimension];
|
240 |
double *s=new double[dimension];
|
241 |
double *dig=new double[dimension];
|
242 |
this->diag(dig);
|
243 |
double delta_zero;
|
244 |
double delta_new=0;
|
245 |
|
246 |
//mul(q,b);
|
247 |
for(int i=0;i<dimension;i++)
|
248 |
{
|
249 |
x[i]=0.;
|
250 |
r[i]=b[i]; //ro=b-A.xo i=0;
|
251 |
z[i]=(1./dig[i]) *r[i];
|
252 |
d[i]=z[i] ;
|
253 |
delta_new+=r[i]*d[i];
|
254 |
}
|
255 |
|
256 |
delta_zero=delta_new ;
|
257 |
|
258 |
while (fabs(delta_new)>eps)
|
259 |
{
|
260 |
double dkAdk=0.;
|
261 |
double zkrk= 0.;
|
262 |
mul(Adk,d);
|
263 |
for(int i=0;i<dimension;i++)
|
264 |
{
|
265 |
dkAdk+=d[i]*Adk[i];
|
266 |
zkrk+=z[i]*r[i];
|
267 |
}
|
268 |
double alpha=zkrk/ dkAdk;
|
269 |
for(int i=0;i<dimension;i++)
|
270 |
{
|
271 |
x[i]+=alpha*d[i];
|
272 |
r[i]-=alpha*Adk[i];
|
273 |
z[i]+=(1./dig[i]) *r[i];
|
274 |
}
|
275 |
|
276 |
double delta_old=zkrk;
|
277 |
delta_new=0.;
|
278 |
for(int i=0;i<dimension;i++)
|
279 |
{
|
280 |
delta_new+=z[i]*r[i];
|
281 |
}
|
282 |
|
283 |
|
284 |
double beta=delta_new/delta_old;
|
285 |
for(int i=0;i<dimension;i++)
|
286 |
{
|
287 |
d[i]=z[i]+beta*d[i];
|
288 |
}
|
289 |
|
290 |
}
|
291 |
delete [] r;
|
292 |
delete [] d;
|
293 |
//delete [] q;
|
294 |
delete [] s;
|
295 |
delete [] dig;
|
296 |
} */
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
MatCr& MatCr::Get_LU(int*perm,double&d)
|
302 |
{ |
303 |
static const double petit=double(1.0e-20); |
304 |
int taille=dimension; |
305 |
int imax,i,j,k; |
306 |
vector<double> v1(taille); |
307 |
double maxi,temp,som,dum; |
308 |
d=1; |
309 |
|
310 |
for(int i=0;i<taille;i++) |
311 |
{
|
312 |
maxi=row[i].row_max();
|
313 |
v1[i]=1./maxi;
|
314 |
} |
315 |
|
316 |
for(j=0;j<taille;j++) |
317 |
{ |
318 |
//cherche les colonnnes de lamatrice L (triangulaire inferieur |
319 |
for(i=0;i<j;i++) |
320 |
{ |
321 |
som=get(i,j);//[i][j]; |
322 |
for(k=0;k<i;k++) |
323 |
som-=get(i,k)*get(k,j); |
324 |
set(i,j,som); |
325 |
} |
326 |
maxi=0; |
327 |
|
328 |
//cherches les lignes de la matrice triangulaire superieur |
329 |
for(i=j;i<taille;i++) |
330 |
{ |
331 |
som=get(i,j); |
332 |
for(k=0;k<j;k++) |
333 |
som-=get(i,k)*get(k,j); |
334 |
set(i,j,som); |
335 |
//vèrificstion de pivot |
336 |
if((dum=v1[i]*fabs(som))>=maxi) |
337 |
{ |
338 |
maxi=dum; |
339 |
imax=i; |
340 |
} |
341 |
} |
342 |
//permuation des lignes imax et j |
343 |
if(j!=imax) |
344 |
{ |
345 |
for(k=0;k<taille;k++) |
346 |
{ |
347 |
dum=get(imax,k); |
348 |
set(imax,k,get(j,k)); |
349 |
set(j,k,dum); |
350 |
} |
351 |
d*=-1; |
352 |
v1[imax]=v1[j]; |
353 |
} |
354 |
// stoker dans perm la permuattion |
355 |
perm[j]=imax; |
356 |
// si le pivot est null |
357 |
if(get(j,j)==0.0)//Data[j][j]==0.0) |
358 |
set(j,j,petit);//[j][j]=petit; |
359 |
if(j!=taille-1) |
360 |
{ |
361 |
dum=1./get(j,j);//Data[j][j]; |
362 |
for(i=j+1;i<taille;i++) |
363 |
set(i,j,get(i,j)*dum);//Data[i][j]*=dum; |
364 |
} |
365 |
} |
366 |
|
367 |
return *this; |
368 |
}
|
369 |
|
370 |
|
371 |
void MatCr::Get_Solution(int*perm,const double* b,double* r1)
|
372 |
{ |
373 |
//Vecteur r1; |
374 |
int taille=dimension,i,j,ip,ii=-1; |
375 |
double som; |
376 |
|
377 |
// if(taille&&taille==NbCols&&taille==(int)b.Get_Size()) |
378 |
// { |
379 |
for(i=0;i<taille;i++) |
380 |
r1[i]=b[i]; |
381 |
for(i=0;i<taille;i++) |
382 |
{ |
383 |
ip=perm[i]; |
384 |
som=r1[ip]; |
385 |
r1[ip]=r1[i]; |
386 |
if(ii>=0) |
387 |
for(j=ii;j<=i-1;j++) |
388 |
som-=get(i,j)*r1[j]; |
389 |
else if(som) ii=i; |
390 |
r1[i]=som; |
391 |
} |
392 |
for(i=taille-1;i>=0;i--) |
393 |
{ |
394 |
som=r1[i]; |
395 |
for(j=i+1;j<taille;j++) |
396 |
som-=get(i,j)*r1[j]; |
397 |
r1[i]=som/get(i,i); |
398 |
} |
399 |
// } |
400 |
//return r1; |
401 |
} |
402 |
|
403 |
|
404 |
|
405 |
|
406 |
|
407 |
|
408 |
vecteur MatCr::prod(MatCr& M, vecteur& v) |
409 |
{ |
410 |
vecteur y(v.getDim()); |
411 |
for(int i=0; i<M.dimension; i++) |
412 |
{
|
413 |
y[i] = 0 ;
|
414 |
const Row& R = M.row[i] ;
|
415 |
for(int jj=0; jj<M.dimension; jj++)
|
416 |
{
|
417 |
y[i] += M.get(i,jj)* v[jj] ;
|
418 |
} |
419 |
} |
420 |
return y; |
421 |
} |
422 |
|