"Fossies" - the Fresh Open Source Software Archive 
Member "laspack/examples/mlstest/mlstest.c" (8 Aug 1995, 44332 Bytes) of package /linux/privat/old/laspack.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /****************************************************************************/
2 /* mlstest.c */
3 /****************************************************************************/
4 /* */
5 /* Multi-Level Solver TEST program for 1d and 2d poisson problems */
6 /* */
7 /* Copyright (C) 1992-1995 Tomas Skalicky. All rights reserved. */
8 /* */
9 /****************************************************************************/
10 /* */
11 /* ANY USE OF THIS CODE CONSTITUTES ACCEPTANCE OF THE TERMS */
12 /* OF THE COPYRIGHT NOTICE (SEE FILE COPYRGHT.H) */
13 /* */
14 /****************************************************************************/
15
16 #include <stdio.h>
17 #include <math.h>
18 #include <ctype.h>
19 #include <time.h>
20 #include <float.h>
21
22 #include <laspack/errhandl.h>
23 #include <laspack/vector.h>
24 #include <laspack/matrix.h>
25 #include <laspack/qmatrix.h>
26 #include <laspack/operats.h>
27 #include <laspack/factor.h>
28 #include <laspack/precond.h>
29 #include <laspack/eigenval.h>
30 #include <laspack/rtc.h>
31 #include <laspack/itersolv.h>
32 #include <laspack/mlsolv.h>
33 #include <laspack/version.h>
34 #include <laspack/copyrght.h>
35
36 #include "mlstest.h"
37 #include "extrsolv.h"
38
39 typedef enum {
40 Case1DDirich,
41 Case2DDirich
42 } ProblemType;
43
44 static QMatrix *L;
45 static Vector *uw, *fr;
46 static Matrix *R, *P;
47
48 static void MGParmInput(ProblemType *Problem, int *NoLevels, size_t *MaxNoInt,
49 IterIdType *MLSolverId, Boolean *NestedMG, int *NoMGIter,
50 int *Gamma, int *RestrType,
51 IterProcType *SmoothProc, int *Nu1, int *Nu2,
52 PrecondProcType *PrecondProc, double *Omea,
53 IterProcType *SolvProc, int *NuC,
54 PrecondProcType *PrecondProcC, double *OmegaC,
55 int *MaxIter, double *Eps);
56 static void QVMConstr(int NoLevels, size_t *Dim);
57 static void QVMDestr(int NoLevels);
58 static void MGEqsGen1DDirich(int NoLevels, size_t *Dim, int RestrType);
59 static void MGEqsGen2DDirich(int NoLevels, size_t *Dim1, int RestrType);
60 static void MGSolver(int NoLevels, IterIdType MLSolverId,
61 Boolean NestedMG, int NoMGIter, int Gamma,
62 IterProcType SmoothProc, int Nu1, int Nu2,
63 PrecondProcType PrecondProc, double Omega,
64 IterProcType SolvProc, int NuC,
65 PrecondProcType PrecondProcC, double OmegaC,
66 int MaxIter, double Eps);
67 static void MGResOutput1DDirich(int NoLevels);
68 static void GenL1DDirich(int Level, size_t *Dim);
69 static void Genf1DDirich(int Level, size_t *Dim);
70 static void GenRSimple1DDirich(int Level, size_t *Dim);
71 static void GenRWeight1DDirich(int Level, size_t *Dim);
72 static void GenP1DDirich(int Level, size_t *Dim);
73 static void GenL2DDirich(int Level, size_t *Dim1);
74 static void Genf2DDirich(int Level, size_t *Dim1);
75 static void GenRSimple2DDirich(int Level, size_t *Dim1);
76 static void GenRWeight2DDirich(int Level, size_t *Dim1);
77 static void GenP2DDirich(int Level, size_t *Dim1);
78 static void IterStatus(int Iter, double rNorm, double bNorm, IterIdType IterId);
79
80 int main(void)
81 {
82 int NoLevels; /* number of grid levels */
83 int RestrType; /* type of restriction operator */
84 int Gamma; /* multigrid iteration parameter */
85 int Nu1; /* number of pre-smoothing iterations */
86 int Nu2; /* number of post-smoothing iterations */
87 int NuC; /* number of iterations on coarse grid */
88 int MaxIter; /* maximum number of iterations */
89 int NoMGIter; /* number of multigrid iterations within one MGPCG step */
90 int Level;
91 double Omega; /* relaxation parameter for smoothing iterations */
92 double OmegaC; /* relaxation parameter for iterations on coarse grid */
93 double Eps; /* epsilon - break off accurary */
94 size_t MaxNoInt; /* maximal number of intervals */
95 size_t *Dim; /* dimension, point number */
96 size_t *Dim1; /* dimension, point number in one direction */
97 Boolean NestedMG; /* nested multigrid iteration */
98 IterIdType MLSolverId; /* identifier of the chosen multi-level solver */
99 IterProcType SmoothProc; /* pointer to a procedure for smoothing iterations */
100 IterProcType SolvProc; /* pointer to a procedure for solving on coarsest grid */
101 PrecondProcType PrecondProc; /* pointer to preconditioner for smoothing iterations */
102 PrecondProcType PrecondProcC; /* pointer to preconditioner on coarsest grid */
103 ProblemType Problem; /* kind of problem */
104
105 fprintf(stderr, "mlstest Version %s\n", LASPACK_VERSION);
106 fprintf(stderr, " (C) 1992-1995 Tomas Skalicky\n");
107 fprintf(stderr,"\n\n");
108 fprintf(stderr,"Multilevel solution of a Poisson problem\n");
109 fprintf(stderr,"----------------------------------------\n");
110 fprintf(stderr,"\n");
111 /* multigrid paramater input */
112 MGParmInput(&Problem, &NoLevels, &MaxNoInt,
113 &MLSolverId, &NestedMG, &NoMGIter, &Gamma, &RestrType,
114 &SmoothProc, &Nu1, &Nu2, &PrecondProc, &Omega,
115 &SolvProc, &NuC, &PrecondProcC, &OmegaC, &MaxIter, &Eps);
116
117 /* allocation of dynamic variables */
118 Dim = (size_t *)malloc(NoLevels * sizeof(size_t));
119 Dim1 = (size_t *)malloc(NoLevels * sizeof(size_t));
120 L = (QMatrix *)malloc(NoLevels * sizeof(QMatrix));
121 uw = (Vector *)malloc(NoLevels * sizeof(Vector));
122 fr = (Vector *)malloc(NoLevels * sizeof(Vector));
123 R = (Matrix *)malloc(NoLevels * sizeof(Matrix));
124 P = (Matrix *)malloc(NoLevels * sizeof(Matrix));
125 if (Dim != NULL && Dim1 != NULL && L != NULL && uw != NULL && fr != NULL &&
126 R != NULL && P != NULL) {
127 /* setting of dimensions for all grid levels */
128 Dim1[NoLevels - 1] = MaxNoInt - 1;
129 for (Level = NoLevels - 2; Level >= 0; Level--)
130 Dim1[Level] = (Dim1[Level + 1] + 1) / 2 - 1;
131 switch (Problem) {
132 case Case1DDirich:
133 for (Level = NoLevels - 1; Level >= 0; Level--)
134 Dim[Level] = Dim1[Level];
135 break;
136 case Case2DDirich:
137 for (Level = NoLevels - 1; Level >= 0; Level--)
138 Dim[Level] = Dim1[Level] * Dim1[Level];
139 break;
140 }
141 /* allocation of matrices, vectors and operators */
142 QVMConstr(NoLevels, Dim);
143 /* generation of system of equations */
144 switch (Problem) {
145 case Case1DDirich:
146 MGEqsGen1DDirich(NoLevels, Dim, RestrType);
147 break;
148 case Case2DDirich:
149 MGEqsGen2DDirich(NoLevels, Dim1, RestrType);
150 break;
151 }
152 /* solving of system of equations with multigrid method */
153 MGSolver(NoLevels, MLSolverId, NestedMG, NoMGIter, Gamma,
154 SmoothProc, Nu1, Nu2, PrecondProc, Omega,
155 SolvProc, NuC, PrecondProcC, OmegaC, MaxIter, Eps);
156 /* solution output */
157 if (LASResult() == LASOK && Problem == Case1DDirich)
158 MGResOutput1DDirich(NoLevels);
159 /* release of matrices, vectors and operators */
160 QVMDestr(NoLevels);
161 } else {
162 /* error message */
163 fprintf(stderr, "\n");
164 fprintf(stderr, "Not enought memory running mgtest.\n");
165 }
166
167 /* release of dynamic variables */
168 if (Dim != NULL)
169 free(Dim);
170 if (Dim1 != NULL)
171 free(Dim1);
172 if (L != NULL)
173 free(L);
174 if (uw != NULL)
175 free(uw);
176 if (fr != NULL)
177 free(fr);
178 if (R != NULL)
179 free(R);
180 if (P != NULL)
181 free(P);
182
183 /* LASPack error messages */
184 if (LASResult() != LASOK) {
185 fprintf(stderr, "\n");
186 fprintf(stderr, "LASPack error: ");
187 WriteLASErrDescr(stderr);
188 }
189 fprintf(stderr, "\n");
190
191 return(0);
192 }
193
194 static void MGParmInput(ProblemType *Problem, int *NoLevels, size_t *MaxNoInt,
195 IterIdType *MLSolverId, Boolean *NestedMG, int *NoMGIter,
196 int *Gamma, int *RestrType,
197 IterProcType *SmoothProc, int *Nu1, int *Nu2,
198 PrecondProcType *PrecondProc, double *Omega,
199 IterProcType *SolvProc, int *NuC,
200 PrecondProcType *PrecondProcC, double *OmegaC,
201 int *MaxIter, double *Eps)
202 /* multigrid parameter input */
203 {
204 char Key[2];
205 int Level;
206 int ProblemId; /* problem identifier */
207 int MainMethId; /* main method identifier */
208 int SmoothMethId; /* smoothing method identifier */
209 int SolvMethId; /* solving method on coarse grid identifier */
210 int PrecondId; /* preconditioning identifier */
211 unsigned long AuxSize;
212 size_t CoarseCoef; /* coarsing coefficient */
213 Boolean InputOK;
214
215 fprintf(stderr, "\n");
216 fprintf(stderr, "Problem type: 1D, Dirichlet boundary condition ... 1\n");
217 fprintf(stderr, " 2D, Dirichlet boundary condition ... 2\n");
218 fprintf(stderr, "Chosen type: ");
219 do {
220 scanf("%d", &ProblemId);
221 if (ProblemId < 1 || ProblemId > 2)
222 fprintf(stderr, "??? : ");
223 } while (ProblemId < 1 || ProblemId > 2);
224 switch (ProblemId) {
225 case 1:
226 *Problem = Case1DDirich;
227 break;
228 case 2:
229 *Problem = Case2DDirich;
230 break;
231 }
232 do {
233 fprintf(stderr, "\n");
234 fprintf(stderr, "Number of grid levels: ");
235 scanf("%d", NoLevels);
236 CoarseCoef = 1;
237 for (Level = *NoLevels - 1; Level > 0; Level--)
238 CoarseCoef = 2 * CoarseCoef;
239 fprintf(stderr, "Number of intervals: ");
240 scanf("%lu", &AuxSize);
241 *MaxNoInt = (size_t)AuxSize;
242 InputOK = (*MaxNoInt % CoarseCoef == 0 && *MaxNoInt / CoarseCoef > 2);
243 if (!InputOK) {
244 fprintf(stderr, "Discretisation by this choice is impossible!\n");
245 }
246 } while (!InputOK);
247
248 fprintf(stderr, "\n");
249 fprintf(stderr, "Solution method: multigrid ..................... 1\n");
250 fprintf(stderr, " multigrid preconditioned CG ... 2\n");
251 fprintf(stderr, " BPX preconditioned CG ......... 3\n");
252 fprintf(stderr, "Chosen method: ");
253 do {
254 scanf("%d", &MainMethId);
255 if (MainMethId < 1 || MainMethId > 3)
256 fprintf(stderr, "??? : ");
257 } while (MainMethId < 1 || MainMethId > 3);
258 switch (MainMethId) {
259 case 1:
260 *MLSolverId = MGIterId;
261 fprintf(stderr, "\n");
262 do {
263 fprintf(stderr, "Nested multigrid iterations? (y/n) ");
264 scanf("%1s", Key);
265 Key[0] = toupper(Key[0]);
266 } while (Key[0] != 'Y' && Key[0] != 'N');
267 if (Key[0] == 'Y')
268 *NestedMG = True;
269 else
270 *NestedMG = False;
271 break;
272 case 2:
273 *MLSolverId = MGPCGIterId;
274 fprintf(stderr, "\n");
275 fprintf(stderr, "Number of multigrid iterations whithin one MGPCG step: ");
276 scanf("%d", NoMGIter);
277 break;
278 case 3:
279 *MLSolverId = BPXPCGIterId;
280 break;
281 }
282 if (*MLSolverId == MGIterId || *MLSolverId == MGPCGIterId) {
283 fprintf(stderr, "\n");
284 fprintf(stderr, "Type of multigrid: V cycle ... 1\n");
285 fprintf(stderr, " W cycle ... 2\n");
286 fprintf(stderr, "Chosen type: ");
287 scanf("%d", Gamma);
288 }
289 fprintf(stderr, "\n");
290 fprintf(stderr, "Type of restriction: simple ..... 1\n");
291 fprintf(stderr, " weighted ... 2\n");
292 fprintf(stderr, "Chosen type: ");
293 do {
294 scanf("%d", RestrType);
295 if (*RestrType != 1 && *RestrType != 2)
296 fprintf(stderr, "??? : ");
297 } while (*RestrType != 1 && *RestrType != 2);
298
299 fprintf(stderr, "\n");
300 fprintf(stderr, "Iterative methods: Jacobi ................... 1\n");
301 fprintf(stderr, " SOR forward .............. 2\n");
302 fprintf(stderr, " SOR backward ............. 3\n");
303 fprintf(stderr, " SOR symmetric ............ 4\n");
304 fprintf(stderr, " Chebyshev ................ 5\n");
305 fprintf(stderr, " CG ....................... 6\n");
306 fprintf(stderr, " CGN ...................... 7\n");
307 fprintf(stderr, " GMRES(10) ................ 8\n");
308 fprintf(stderr, " BiCG ..................... 9\n");
309 fprintf(stderr, " QMR ..................... 10\n");
310 fprintf(stderr, " CGS ..................... 11\n");
311 fprintf(stderr, " Bi-CGSTAB ............... 12\n");
312 fprintf(stderr, " Test .................... 13\n");
313 fprintf(stderr, "Smoothing method: ");
314 do {
315 scanf("%d", &SmoothMethId);
316 if (SmoothMethId < 1 || SmoothMethId > 13)
317 fprintf(stderr, "??? : ");
318 } while (SmoothMethId < 1 || SmoothMethId > 13);
319 switch (SmoothMethId) {
320 case 1:
321 *SmoothProc = JacobiIter;
322 break;
323 case 2:
324 *SmoothProc = SORForwIter;
325 break;
326 case 3:
327 *SmoothProc = SORBackwIter;
328 break;
329 case 4:
330 *SmoothProc = SSORIter;
331 break;
332 case 5:
333 *SmoothProc = ChebyshevIter;
334 break;
335 case 6:
336 *SmoothProc = CGIter;
337 break;
338 case 7:
339 *SmoothProc = CGNIter;
340 break;
341 case 8:
342 *SmoothProc = GMRESIter;
343 break;
344 case 9:
345 *SmoothProc = BiCGIter;
346 break;
347 case 10:
348 *SmoothProc = QMRIter;
349 break;
350 case 11:
351 *SmoothProc = CGSIter;
352 break;
353 case 12:
354 *SmoothProc = BiCGSTABIter;
355 break;
356 case 13:
357 *SmoothProc = TestIter;
358 break;
359 }
360 if (*MLSolverId == MGIterId || *MLSolverId == MGPCGIterId) {
361 fprintf(stderr, "Number of pre-smoothing iterations: ");
362 scanf("%d", Nu1);
363 fprintf(stderr, "Number of post-smoothing iterations: ");
364 scanf("%d", Nu2);
365 } else {
366 fprintf(stderr, "Number of smoothing iterations: ");
367 scanf("%d", Nu1);
368 Nu2 = 0;
369 }
370 fprintf(stderr, "Preconditioning: none .......... 0\n");
371 fprintf(stderr, " Jacobi ........ 1\n");
372 fprintf(stderr, " SSOR ......... 2\n");
373 fprintf(stderr, " ILU/ICH ....... 3\n");
374 fprintf(stderr, "Preconditioning for smoothing iterations: ");
375 do {
376 scanf("%d", &PrecondId);
377 if (PrecondId < 0 || PrecondId > 3)
378 fprintf(stderr, "??? : ");
379 } while (PrecondId < 0 || PrecondId > 3);
380 switch (PrecondId) {
381 case 0:
382 *PrecondProc = (PrecondProcType)NULL;
383 break;
384 case 1:
385 *PrecondProc = JacobiPrecond;
386 break;
387 case 2:
388 *PrecondProc = SSORPrecond;
389 break;
390 case 3:
391 *PrecondProc = ILUPrecond;
392 break;
393 }
394 fprintf(stderr, "Relaxation parameter for smoothing: ");
395 scanf("%lf", Omega);
396
397 fprintf(stderr, "Iterative methods: Jacobi ................... 1\n");
398 fprintf(stderr, " SOR forward .............. 2\n");
399 fprintf(stderr, " SOR backward ............. 3\n");
400 fprintf(stderr, " SOR symmetric ............ 4\n");
401 fprintf(stderr, " Chebyshev ................ 5\n");
402 fprintf(stderr, " CG ....................... 6\n");
403 fprintf(stderr, " CGN ...................... 7\n");
404 fprintf(stderr, " GMRES(10) ................ 8\n");
405 fprintf(stderr, " BiCG ..................... 9\n");
406 fprintf(stderr, " QMR ..................... 10\n");
407 fprintf(stderr, " CGS ..................... 11\n");
408 fprintf(stderr, " Bi-CGSTAB ............... 12\n");
409 fprintf(stderr, " Test .................... 13\n");
410 fprintf(stderr, "Solution method on coarsest grid: ");
411 do {
412 scanf("%d", &SolvMethId);
413 if (SolvMethId < 1 || SolvMethId > 13)
414 fprintf(stderr, "??? : ");
415 } while (SolvMethId < 1 || SolvMethId > 13);
416 switch (SolvMethId) {
417 case 1:
418 *SolvProc = JacobiIter;
419 break;
420 case 2:
421 *SolvProc = SORForwIter;
422 break;
423 case 3:
424 *SolvProc = SORBackwIter;
425 break;
426 case 4:
427 *SolvProc = SSORIter;
428 break;
429 case 5:
430 *SolvProc = ChebyshevIter;
431 break;
432 case 6:
433 *SolvProc = CGIter;
434 break;
435 case 7:
436 *SolvProc = CGNIter;
437 break;
438 case 8:
439 *SolvProc = GMRESIter;
440 break;
441 case 9:
442 *SolvProc = BiCGIter;
443 break;
444 case 10:
445 *SolvProc = QMRIter;
446 break;
447 case 11:
448 *SolvProc = CGSIter;
449 break;
450 case 12:
451 *SolvProc = BiCGSTABIter;
452 break;
453 case 13:
454 *SolvProc = TestIter;
455 break;
456 }
457 fprintf(stderr, "Number of iterations on coarsest grid: ");
458 scanf("%d", NuC);
459 fprintf(stderr, "Preconditioning: none .......... 0\n");
460 fprintf(stderr, " Jacobi ........ 1\n");
461 fprintf(stderr, " SSOR ......... 2\n");
462 fprintf(stderr, " ILU/ICH ....... 3\n");
463 fprintf(stderr, "Preconditioning on coarsest grid: ");
464 do {
465 scanf("%d", &PrecondId);
466 if (PrecondId < 0 || PrecondId > 3)
467 fprintf(stderr, "??? : ");
468 } while (PrecondId < 0 || PrecondId > 3);
469 switch (PrecondId) {
470 case 0:
471 *PrecondProcC = (PrecondProcType)NULL;
472 break;
473 case 1:
474 *PrecondProcC = JacobiPrecond;
475 break;
476 case 2:
477 *PrecondProcC = SSORPrecond;
478 break;
479 case 3:
480 *PrecondProcC = ILUPrecond;
481 break;
482 }
483 fprintf(stderr, "Relaxation parameter on coarsest grid: ");
484 scanf("%lf", OmegaC);
485
486 fprintf(stderr, "\n");
487 fprintf(stderr, "Maximum number of iterations: ");
488 scanf("%d", MaxIter);
489 fprintf(stderr, "Break off accurary for the residual: ");
490 scanf("%lf", Eps);
491 }
492
493 static void QVMConstr(int NoLevels, size_t *Dim)
494 /* calling of constructors for matrices, vectors of unknowns,
495 vectors of right hand side, restriction and prolongation operators */
496 {
497 int Level;
498
499 char Name[10];
500
501 for (Level = NoLevels - 1; Level >= 0; Level--) {
502 sprintf(Name, "L[%d]", Level % 1000);
503 #ifdef SYM_STOR
504 Q_Constr(&L[Level], Name, Dim[Level], True, Rowws, Normal, True);
505 #else
506 Q_Constr(&L[Level], Name, Dim[Level], False, Rowws, Normal, True);
507 #endif /* SYM_STOR */
508 sprintf(Name, "uw[%d]", Level % 1000);
509 V_Constr(&uw[Level], Name, Dim[Level], Normal, True);
510 sprintf(Name, "fr[%d]", Level % 1000);
511 V_Constr(&fr[Level], Name, Dim[Level], Normal, True);
512 if (Level < NoLevels - 1) {
513 sprintf(Name, "R[%d]", Level % 1000);
514 M_Constr(&R[Level], Name, Dim[Level], Dim[Level + 1], Rowws, Normal, True);
515 }
516 if (Level > 0) {
517 sprintf(Name, "P[%d]", Level % 1000);
518 M_Constr(&P[Level], Name, Dim[Level], Dim[Level - 1], Clmws, Normal, True);
519 }
520 }
521 }
522
523 static void QVMDestr(int NoLevels)
524 /* calling of destructors for matrices, vectors of unknowns,
525 vectors of right hand side, restriction and prolongation operators */
526 {
527 int Level;
528 for (Level = NoLevels - 1; Level >= 0; Level--) {
529 Q_Destr(&L[Level]);
530 V_Destr(&uw[Level]);
531 V_Destr(&fr[Level]);
532 if (Level < NoLevels - 1)
533 M_Destr(&R[Level]);
534 if (Level > 0)
535 M_Destr(&P[Level]);
536 }
537 }
538
539 static void MGEqsGen1DDirich(int NoLevels, size_t *Dim, int RestrType)
540 /* generation of system of equations for all grid levels for 1D case,
541 Dirichlet boundary condition */
542 {
543 int Level;
544 double ClockFactor, CPUTime;
545 clock_t BegClock, EndClock;
546
547 /* start of time counting */
548 ClockFactor = 1.0 / (double)CLOCKS_PER_SEC;
549 BegClock = clock();
550 /* generation of matrices L */
551 printf("\n");
552 printf("Generation of matrices ... \n");
553 for (Level = NoLevels - 1; Level >= 0; Level--)
554 GenL1DDirich(Level, Dim);
555 /* generation of right hand side f */
556 printf("Generation of vectors ... \n");
557 for (Level = NoLevels - 1; Level >= 0; Level--)
558 Genf1DDirich(Level, Dim);
559 /* generation of restriction operators */
560 printf("Generation of restriction operators ... \n");
561 for (Level = NoLevels - 2; Level >= 0; Level--) {
562 if (RestrType == 1) {
563 /* for simple restriction operators */
564 GenRSimple1DDirich(Level, Dim);
565 }
566 if (RestrType == 2) {
567 /* for wighted restriction operators */
568 GenRWeight1DDirich(Level, Dim);
569 }
570 }
571 printf("Generation of prolongation operators ... \n");
572 for (Level = NoLevels - 1; Level >= 1; Level--)
573 GenP1DDirich(Level, Dim);
574 /* end of time counting and geting out of CPU time */
575 EndClock = clock();
576 CPUTime = (double)(EndClock - BegClock) * ClockFactor;
577 printf("\n");
578 printf(" CPU time: %7.2f s\n", CPUTime);
579 }
580
581 static void MGEqsGen2DDirich(int NoLevels, size_t *Dim1, int RestrType)
582 /* generation of system of equations for all grid levels for 2D case,
583 Dirichlet boundary condition */
584 {
585 int Level;
586 double ClockFactor, CPUTime;
587 clock_t BegClock, EndClock;
588
589 /* start of time counting */
590 ClockFactor = 1.0 / (double)CLOCKS_PER_SEC;
591 BegClock = clock();
592 /* generation of matrices L */
593 printf("\n");
594 printf("Generation of matrices ... \n");
595 for (Level = NoLevels - 1; Level >= 0; Level--)
596 GenL2DDirich(Level, Dim1);
597 /* generation of right hand side f */
598 printf("Generation of vectors ... \n");
599 for (Level = NoLevels - 1; Level >= 0; Level--)
600 Genf2DDirich(Level, Dim1);
601 /* generation of restriction operators */
602 printf("Generation of restriction operators ... \n");
603 for (Level = NoLevels - 2; Level >= 0; Level--) {
604 if (RestrType == 1) {
605 /* for simple restriction operators */
606 GenRSimple2DDirich(Level, Dim1);
607 }
608 if (RestrType == 2) {
609 /* for wighted restriction operators */
610 GenRWeight2DDirich(Level, Dim1);
611 }
612 }
613 /* generation of prolongation operators P */
614 printf("Generation of prolongation operators ... \n");
615 for (Level = NoLevels - 1; Level >= 1; Level--)
616 GenP2DDirich(Level, Dim1);
617 /* end of time counting and geting out of CPU time */
618 EndClock = clock();
619 CPUTime = (double)(EndClock - BegClock) * ClockFactor;
620 printf("\n");
621 printf(" CPU time: %7.2f s\n", CPUTime);
622 }
623
624 static void MGSolver(int NoLevels, IterIdType MLSolverId,
625 Boolean NestedMG, int NoMGIter, int Gamma,
626 IterProcType SmoothProc, int Nu1, int Nu2,
627 PrecondProcType PrecondProc, double Omega,
628 IterProcType SolvProc, int NuC,
629 PrecondProcType PrecondProcC, double OmegaC,
630 int MaxIter, double Eps)
631 /* solution of discret problem with multigrid solver */
632 {
633 int NoIter; /* number of performed iterations */
634 int Level;
635 double AccBeg, AccEnd; /* reached accuracy (of residuum) */
636 double ContrRatePerMGIter, ContrRatePerSec;
637 double ClockFactor, CPUTime;
638 clock_t BegClock, EndClock;
639
640 /* setting of RTC parameters */
641 SetRTCAccuracy(Eps);
642 SetRTCAuxProc(IterStatus);
643
644 /* estimate extremal eigenvalues */
645 if(SmoothProc == ChebyshevIter || SolvProc == ChebyshevIter) {
646 /* start of time counting */
647 ClockFactor = 1.0 / (double)CLOCKS_PER_SEC;
648 BegClock = clock();
649
650 /* initialization random-number generator */
651 srand(1);
652
653 printf("\n");
654 printf("Estimating extremal eigenvalues ...\n");
655 if(SmoothProc == ChebyshevIter) {
656 for (Level = NoLevels - 1; Level > 0; Level--) {
657 GetMinEigenval(&L[Level], PrecondProc, Omega);
658 GetMaxEigenval(&L[Level], PrecondProc, Omega);
659 }
660 }
661 if(SolvProc == ChebyshevIter) {
662 GetMinEigenval(&L[0], PrecondProcC, OmegaC);
663 GetMaxEigenval(&L[0], PrecondProcC, OmegaC);
664 }
665
666 /* end of time counting and geting out the CPU time */
667 EndClock = clock();
668 CPUTime = (double)(EndClock - BegClock) * ClockFactor;
669 printf("\n");
670 printf(" CPU time: %7.2f s\n", CPUTime);
671 }
672
673 /* factorize matrices */
674 if(PrecondProc == ILUPrecond || PrecondProcC == ILUPrecond) {
675 /* start of time counting */
676 ClockFactor = 1.0 / (double)CLOCKS_PER_SEC;
677 BegClock = clock();
678
679 printf("\n");
680 printf("Incomplete factorization of matrices ...\n");
681 if(PrecondProc == ILUPrecond
682 && SmoothProc != JacobiIter
683 && SmoothProc != SORForwIter
684 && SmoothProc != SORBackwIter
685 && SmoothProc != SSORIter) {
686 for (Level = NoLevels - 1; Level > 0; Level--)
687 ILUFactor(&L[Level]);
688 }
689 if(PrecondProcC == ILUPrecond
690 && SolvProc != JacobiIter
691 && SolvProc != SORForwIter
692 && SolvProc != SORBackwIter
693 && SolvProc != SSORIter) {
694 ILUFactor(&L[0]);
695 }
696
697 /* end of time counting and geting out the CPU time */
698 EndClock = clock();
699 CPUTime = (double)(EndClock - BegClock) * ClockFactor;
700 printf("\n");
701 printf(" CPU time: %7.2f s\n", CPUTime);
702 }
703
704 /* solving of system of equations by nested multigrid method */
705 if (MLSolverId == MGIterId && NestedMG) {
706 /* initialisation of vector of unknowns */
707 V_SetAllCmp(&uw[0], 0.0);
708
709 /* approximation of solution by nested multigrid method */
710 printf("\n");
711 printf("Doing nested multigrid iterations ...\n");
712 NestedMGIter(NoLevels, L, uw, fr, R, P, Gamma,
713 SmoothProc, Nu1, Nu2, PrecondProc, Omega,
714 SolvProc, NuC, PrecondProcC ,OmegaC);
715
716 AccBeg = GetLastAccuracy();
717 } else {
718 /* initialisation of vector of unknowns */
719 V_SetAllCmp(&uw[NoLevels - 1], 0.0);
720
721 AccBeg = 1.0;
722 }
723
724 /* start of time counting */
725 ClockFactor = 1.0 / (double)CLOCKS_PER_SEC;
726 BegClock = clock();
727
728 /* solving of system of equations */
729 switch (MLSolverId) {
730 case MGIterId:
731 printf("\n");
732 printf("Doing multigrid iterations ... \n\n");
733 MGIter(NoLevels, L, uw, fr, R, P, MaxIter, Gamma,
734 SmoothProc, Nu1, Nu2, PrecondProc, Omega,
735 SolvProc, NuC, PrecondProcC, OmegaC);
736 break;
737 case MGPCGIterId:
738 printf("\n");
739 printf("Doing multigrid preconditioned CG iterations ... \n\n");
740 MGPCGIter(NoLevels, L, uw, fr, R, P, MaxIter, NoMGIter, Gamma,
741 SmoothProc, Nu1, Nu2, PrecondProc, Omega,
742 SolvProc, NuC, PrecondProcC, OmegaC);
743 break;
744 case BPXPCGIterId:
745 printf("\n");
746 printf("Doing BPX preconditioned CG iterations ... \n\n");
747 BPXPCGIter(NoLevels, L, uw, fr, R, P, MaxIter,
748 SmoothProc, Nu1, PrecondProc, Omega,
749 SolvProc, NuC, PrecondProcC, OmegaC);
750 break;
751 default:
752 break;
753 }
754
755 /* end of time counting and geting out of CPU time */
756 EndClock = clock();
757 CPUTime = (double)(EndClock - BegClock) * ClockFactor;
758 printf("\n");
759 printf(" CPU time: %7.2f s\n", CPUTime);
760
761 AccEnd = GetLastAccuracy();
762 NoIter = GetLastNoIter();
763
764 /* computing of middle contraction rates */
765 if (NoIter > 0)
766 ContrRatePerMGIter = pow(AccEnd / AccBeg, 1.0 / (double)NoIter);
767 else
768 ContrRatePerMGIter = 0.0;
769 if (CPUTime > DBL_EPSILON)
770 ContrRatePerSec = pow(AccEnd / AccBeg, 1.0 / CPUTime);
771 else
772 ContrRatePerSec = 0.0;
773 printf("\n");
774 printf("Middle contraction rate\n");
775 printf(" referred to one iteration: %10.3e\n", ContrRatePerMGIter);
776 printf(" referred to 1 s CPU time: %10.3e\n", ContrRatePerSec);
777 }
778
779 static void MGResOutput1DDirich(int NoLevels)
780 /* solution output for 1D case, Dirichlet boundary condition */
781 {
782 char Key[2];
783 double x;
784 size_t Ind, Dim;
785
786 fprintf(stderr, "\n");
787 do {
788 fprintf(stderr, "Output solution? (y/n) ");
789 scanf("%1s", Key);
790 Key[0] = toupper(Key[0]);
791 } while (Key[0] != 'Y' && Key[0] != 'N');
792 if (Key[0] == 'Y') {
793 printf("\n");
794 printf(" x u(x) (node)\n");
795 printf("---------------------------------\n");
796 printf(" 0.00000 0.00000\n");
797 Dim = V_GetDim(&uw[NoLevels - 1]);
798 for (Ind = 1; Ind <= Dim; Ind++) {
799 x = (double)Ind / (double)(Dim + 1);
800 printf(" %8.5f %8.5f (%lu)\n", x, V_GetCmp(&uw[NoLevels - 1],Ind),
801 (unsigned long)Ind);
802 }
803 printf(" 1.00000 0.00000\n");
804 printf("---------------------------------\n");
805 }
806 }
807
808 static void GenL1DDirich(int Level, size_t *Dim)
809 /* generation of matrix for 1D case, Dirichlet boundary
810 condition */
811 {
812 double h;
813 size_t Row;
814
815 if (LASResult() == LASOK) {
816 /* computing of the grid parameter */
817 h = 1.0 / (double)(Dim[Level] + 1);
818
819 #ifdef SYM_STOR
820
821 /* setting of matrix elements */
822 for (Row = 1; Row < Dim[Level]; Row++) {
823 Q_SetLen(&L[Level], Row, 2);
824 if (LASResult() == LASOK) {
825 Q_SetEntry(&L[Level], Row, 0, Row, 2.0 / h);
826 Q_SetEntry(&L[Level], Row, 1, Row + 1, -1.0 / h);
827 }
828 }
829 Row = Dim[Level];
830 Q_SetLen(&L[Level], Row, 1);
831 if (LASResult() == LASOK) {
832 Q_SetEntry(&L[Level], Row, 0, Row, 2.0 / h);
833 }
834
835 #else
836
837 Row = 1;
838 Q_SetLen(&L[Level], Row, 2);
839 if (LASResult() == LASOK) {
840 Q_SetEntry(&L[Level], Row, 0, Row, 2.0 / h);
841 Q_SetEntry(&L[Level], Row, 1, Row + 1, -1.0 / h);
842 }
843 for (Row = 2; Row < Dim[Level]; Row++) {
844 Q_SetLen(&L[Level], Row, 3);
845 if (LASResult() == LASOK) {
846 Q_SetEntry(&L[Level], Row, 0, Row, 2.0 / h);
847 Q_SetEntry(&L[Level], Row, 1, Row - 1, -1.0 / h);
848 Q_SetEntry(&L[Level], Row, 2, Row + 1, -1.0 / h);
849 }
850 }
851 Row = Dim[Level];
852 Q_SetLen(&L[Level], Row, 2);
853 if (LASResult() == LASOK) {
854 Q_SetEntry(&L[Level], Row, 0, Row, 2.0 / h);
855 Q_SetEntry(&L[Level], Row, 1, Row - 1, -1.0 / h);
856 }
857
858 #endif /* SYM_STOR */
859
860 }
861 }
862
863 static void Genf1DDirich(int Level, size_t *Dim)
864 /* generation of right hand side for 1D case, Dirichlet boundary condition */
865 {
866 double h;
867 size_t Ind;
868
869 if (LASResult() == LASOK) {
870 /* computing of the grid parameter */
871 h = 1.0 / (double)(Dim[Level] + 1);
872
873 for (Ind = 1; Ind <= Dim[Level]; Ind++) {
874 V_SetCmp(&fr[Level], Ind, 1.0 * h);
875 }
876 }
877 }
878
879 static void GenRSimple1DDirich(int Level, size_t *Dim)
880 /* generation of simple restriction operator (as matrix) for 1D case,
881 Dirichlet boundary condition */
882 {
883 size_t Row;
884
885 if (LASResult() == LASOK) {
886 for (Row = 1; Row <= Dim[Level]; Row++) {
887 M_SetLen(&R[Level], Row, 1);
888 if (LASResult() == LASOK) {
889 M_SetEntry(&R[Level], Row, 0, 2 * Row, 2.0);
890 }
891 }
892 }
893 }
894
895 static void GenRWeight1DDirich(int Level, size_t *Dim)
896 /* generation of weighted restriction operator (as matrix) for 1D case,
897 Dirichlet boundary condition */
898 {
899 size_t Row;
900
901 if (LASResult() == LASOK) {
902 for (Row = 1; Row <= Dim[Level]; Row++) {
903 M_SetLen(&R[Level], Row, 3);
904 if (LASResult() == LASOK) {
905 M_SetEntry(&R[Level], Row, 0, 2 * Row - 1, 0.5);
906 M_SetEntry(&R[Level], Row, 1, 2 * Row, 1.0);
907 M_SetEntry(&R[Level], Row, 2, 2 * Row + 1, 0.5);
908 }
909 }
910 }
911 }
912
913 static void GenP1DDirich(int Level, size_t *Dim)
914 /* generation of prolongation operator (as matrix) for 1D case, Dirichlet
915 boundary condition */
916 {
917 size_t Clm;
918
919 if (LASResult() == LASOK) {
920 for (Clm = 1; Clm <= Dim[Level - 1]; Clm++) {
921 M_SetLen(&P[Level], Clm, 3);
922 if (LASResult() == LASOK) {
923 M_SetEntry(&P[Level], Clm, 0, 2 * Clm - 1, 0.5);
924 M_SetEntry(&P[Level], Clm, 1, 2 * Clm, 1.0);
925 M_SetEntry(&P[Level], Clm, 2, 2 * Clm + 1, 0.5);
926 }
927 }
928 }
929 }
930
931 static void GenL2DDirich(int Level, size_t *Dim1)
932 /* generation of matrix for 2D case, Dirichlet boundary
933 condition */
934 {
935 size_t BlockRow, RowBasis, Row;
936
937 if (LASResult() == LASOK) {
938 #ifdef SYM_STOR
939
940 /* setting of matrix elements */
941 for (BlockRow = 1; BlockRow < Dim1[Level]; BlockRow++) {
942 RowBasis = Dim1[Level] * (BlockRow - 1);
943 for (Row = RowBasis + 1; Row < RowBasis + Dim1[Level]; Row++) {
944 Q_SetLen(&L[Level], Row, 3);
945 if (LASResult() == LASOK) {
946 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
947 Q_SetEntry(&L[Level], Row, 1, Row + 1, -1.0);
948 Q_SetEntry(&L[Level], Row, 2, Row + Dim1[Level], -1.0);
949 }
950 }
951 Row = RowBasis + Dim1[Level];
952 Q_SetLen(&L[Level], Row, 2);
953 if (LASResult() == LASOK) {
954 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
955 Q_SetEntry(&L[Level], Row, 1, Row + Dim1[Level], -1.0);
956 }
957 }
958 BlockRow = Dim1[Level];
959 RowBasis = Dim1[Level] * (BlockRow - 1);
960 for (Row = RowBasis + 1; Row < RowBasis + Dim1[Level]; Row++) {
961 Q_SetLen(&L[Level], Row, 2);
962 if (LASResult() == LASOK) {
963 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
964 Q_SetEntry(&L[Level], Row, 1, Row + 1, -1.0);
965 }
966 }
967 Row = RowBasis + Dim1[Level];
968 Q_SetLen(&L[Level], Row, 1);
969 if (LASResult() == LASOK) {
970 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
971 }
972
973 #else
974
975 BlockRow = 1;
976 RowBasis = Dim1[Level] * (BlockRow - 1);
977 Row = RowBasis + 1;
978 Q_SetLen(&L[Level], Row, 3);
979 if (LASResult() == LASOK) {
980 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
981 Q_SetEntry(&L[Level], Row, 1, Row + 1, -1.0);
982 Q_SetEntry(&L[Level], Row, 2, Row + Dim1[Level], -1.0);
983 }
984 for (Row = RowBasis + 2; Row < RowBasis + Dim1[Level]; Row++) {
985 Q_SetLen(&L[Level], Row, 4);
986 if (LASResult() == LASOK) {
987 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
988 Q_SetEntry(&L[Level], Row, 1, Row - 1, -1.0);
989 Q_SetEntry(&L[Level], Row, 2, Row + 1, -1.0);
990 Q_SetEntry(&L[Level], Row, 3, Row + Dim1[Level], -1.0);
991 }
992 }
993 Row = RowBasis + Dim1[Level];
994 Q_SetLen(&L[Level], Row, 3);
995 if (LASResult() == LASOK) {
996 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
997 Q_SetEntry(&L[Level], Row, 1, Row - 1, -1.0);
998 Q_SetEntry(&L[Level], Row, 2, Row + Dim1[Level], -1.0);
999 }
1000 for (BlockRow = 2; BlockRow < Dim1[Level]; BlockRow++) {
1001 RowBasis = Dim1[Level] * (BlockRow - 1);
1002 Row = RowBasis + 1;
1003 Q_SetLen(&L[Level], Row, 4);
1004 if (LASResult() == LASOK) {
1005 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
1006 Q_SetEntry(&L[Level], Row, 1, Row - Dim1[Level], -1.0);
1007 Q_SetEntry(&L[Level], Row, 2, Row + 1, -1.0);
1008 Q_SetEntry(&L[Level], Row, 3, Row + Dim1[Level], -1.0);
1009 }
1010 for (Row = RowBasis + 2; Row < RowBasis + Dim1[Level]; Row++) {
1011 Q_SetLen(&L[Level], Row, 5);
1012 if (LASResult() == LASOK) {
1013 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
1014 Q_SetEntry(&L[Level], Row, 1, Row - 1, -1.0);
1015 Q_SetEntry(&L[Level], Row, 2, Row - Dim1[Level], -1.0);
1016 Q_SetEntry(&L[Level], Row, 3, Row + 1, -1.0);
1017 Q_SetEntry(&L[Level], Row, 4, Row + Dim1[Level], -1.0);
1018 }
1019 }
1020 Row = RowBasis + Dim1[Level];
1021 Q_SetLen(&L[Level], Row, 4);
1022 if (LASResult() == LASOK) {
1023 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
1024 Q_SetEntry(&L[Level], Row, 1, Row - 1, -1.0);
1025 Q_SetEntry(&L[Level], Row, 2, Row - Dim1[Level], -1.0);
1026 Q_SetEntry(&L[Level], Row, 3, Row + Dim1[Level], -1.0);
1027 }
1028 }
1029 BlockRow = Dim1[Level];
1030 RowBasis = Dim1[Level] * (BlockRow - 1);
1031 Row = RowBasis + 1;
1032 Q_SetLen(&L[Level], Row, 3);
1033 if (LASResult() == LASOK) {
1034 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
1035 Q_SetEntry(&L[Level], Row, 1, Row - Dim1[Level], -1.0);
1036 Q_SetEntry(&L[Level], Row, 2, Row + 1, -1.0);
1037 }
1038 for (Row = RowBasis + 2; Row < RowBasis + Dim1[Level]; Row++) {
1039 Q_SetLen(&L[Level], Row, 4);
1040 if (LASResult() == LASOK) {
1041 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
1042 Q_SetEntry(&L[Level], Row, 1, Row - 1, -1.0);
1043 Q_SetEntry(&L[Level], Row, 2, Row - Dim1[Level], -1.0);
1044 Q_SetEntry(&L[Level], Row, 3, Row + 1, -1.0);
1045 }
1046 }
1047 Row = RowBasis + Dim1[Level];
1048 Q_SetLen(&L[Level], Row, 3);
1049 if (LASResult() == LASOK) {
1050 Q_SetEntry(&L[Level], Row, 0, Row, 4.0);
1051 Q_SetEntry(&L[Level], Row, 1, Row - 1, -1.0);
1052 Q_SetEntry(&L[Level], Row, 2, Row - Dim1[Level], -1.0);
1053 }
1054
1055 #endif /* SYM_STOR */
1056
1057 }
1058 }
1059
1060 static void Genf2DDirich(int Level, size_t *Dim1)
1061 /* generation of right hand side for 2D case, Dirichlet boundary condition */
1062 {
1063 double h, hh;
1064 size_t Block, IndBasis, Ind;
1065
1066 if (LASResult() == LASOK) {
1067 /* computing of grid parameter */
1068 h = 1.0 / (double)(Dim1[Level] + 1);
1069 hh = pow(h, 2.0);
1070
1071 for (Block = 1; Block <= Dim1[Level]; Block++) {
1072 IndBasis = Dim1[Level] * (Block - 1);
1073 for (Ind = IndBasis + 1; Ind <= IndBasis + Dim1[Level]; Ind++) {
1074 V_SetCmp(&fr[Level], Ind, 1.0 * hh);
1075 }
1076 }
1077 }
1078 }
1079
1080 static void GenRSimple2DDirich(int Level, size_t *Dim1)
1081 /* generation of simple restriction operator (as matrix) for 2D case,
1082 Dirichlet boundary condition */
1083 {
1084 size_t BlockRow, RowBasis, RowInBlock, Row;
1085
1086 if (LASResult() == LASOK) {
1087 for (BlockRow = 1; BlockRow <= Dim1[Level]; BlockRow++) {
1088 RowBasis = Dim1[Level] * (BlockRow - 1);
1089 for (RowInBlock = 1; RowInBlock <= Dim1[Level]; RowInBlock++) {
1090 Row = RowBasis + RowInBlock;
1091 M_SetLen(&R[Level], Row, 1);
1092 if (LASResult() == LASOK) {
1093 M_SetEntry(&R[Level], Row, 0, 2 * RowInBlock
1094 + (2 * BlockRow - 1) * Dim1[Level + 1], 4.0);
1095 }
1096 }
1097 }
1098 }
1099 }
1100
1101 static void GenRWeight2DDirich(int Level, size_t *Dim1)
1102 /* generation of weighted restriction operator (as matrix) for 2D case,
1103 Dirichlet boundary condition */
1104 {
1105 size_t BlockRow, RowBasis, RowInBlock, Row;
1106
1107 if (LASResult() == LASOK) {
1108 for (BlockRow = 1; BlockRow <= Dim1[Level]; BlockRow++) {
1109 RowBasis = Dim1[Level] * (BlockRow - 1);
1110 for (RowInBlock = 1; RowInBlock <= Dim1[Level]; RowInBlock++) {
1111 Row = RowBasis + RowInBlock;
1112 M_SetLen(&R[Level], Row, 9);
1113 if (LASResult() == LASOK) {
1114 M_SetEntry(&R[Level], Row, 0, 2 * RowInBlock
1115 + (2 * BlockRow - 2) * Dim1[Level + 1] - 1, 0.25);
1116 M_SetEntry(&R[Level], Row, 1, 2 * RowInBlock
1117 + (2 * BlockRow - 2) * Dim1[Level + 1], 0.5);
1118 M_SetEntry(&R[Level], Row, 2, 2 * RowInBlock
1119 + (2 * BlockRow - 2) * Dim1[Level + 1] + 1, 0.25);
1120 M_SetEntry(&R[Level], Row, 3, 2 * RowInBlock
1121 + (2 * BlockRow - 1) * Dim1[Level + 1] - 1, 0.5);
1122 M_SetEntry(&R[Level], Row, 4, 2 * RowInBlock
1123 + (2 * BlockRow - 1) * Dim1[Level + 1], 1.0);
1124 M_SetEntry(&R[Level], Row, 5, 2 * RowInBlock
1125 + (2 * BlockRow - 1) * Dim1[Level + 1] + 1, 0.5);
1126 M_SetEntry(&R[Level], Row, 6, 2 * RowInBlock
1127 + (2 * BlockRow) * Dim1[Level + 1] - 1, 0.25);
1128 M_SetEntry(&R[Level], Row, 7, 2 * RowInBlock
1129 + (2 * BlockRow) * Dim1[Level + 1], 0.5);
1130 M_SetEntry(&R[Level], Row, 8, 2 * RowInBlock
1131 + (2 * BlockRow) * Dim1[Level + 1] + 1, 0.25);
1132 }
1133 }
1134 }
1135 }
1136 }
1137
1138 static void GenP2DDirich(int Level, size_t *Dim1)
1139 /* generation of prolongation operator (as matrix) for 2D case, Dirichlet
1140 boundary condition */
1141 {
1142 size_t BlockClm, ClmBasis, ClmInBlock, Clm;
1143
1144 if (LASResult() == LASOK) {
1145 for (BlockClm = 1; BlockClm <= Dim1[Level - 1]; BlockClm++) {
1146 ClmBasis = Dim1[Level - 1] * (BlockClm - 1);
1147 for (ClmInBlock = 1; ClmInBlock <= Dim1[Level - 1]; ClmInBlock++) {
1148 Clm = ClmBasis + ClmInBlock;
1149 M_SetLen(&P[Level], Clm, 9);
1150 if (LASResult() == LASOK) {
1151 M_SetEntry(&P[Level], Clm, 0, 2 * ClmInBlock
1152 + (2 * BlockClm - 2) * Dim1[Level] - 1, 0.25);
1153 M_SetEntry(&P[Level], Clm, 1, 2 * ClmInBlock
1154 + (2 * BlockClm - 2) * Dim1[Level], 0.5);
1155 M_SetEntry(&P[Level], Clm, 2, 2 * ClmInBlock
1156 + (2 * BlockClm - 2) * Dim1[Level] + 1, 0.25);
1157 M_SetEntry(&P[Level], Clm, 3, 2 * ClmInBlock
1158 + (2 * BlockClm - 1) * Dim1[Level] - 1, 0.5);
1159 M_SetEntry(&P[Level], Clm, 4, 2 * ClmInBlock
1160 + (2 * BlockClm - 1) * Dim1[Level], 1.0);
1161 M_SetEntry(&P[Level], Clm, 5, 2 * ClmInBlock
1162 + (2 * BlockClm - 1) * Dim1[Level] + 1, 0.5);
1163 M_SetEntry(&P[Level], Clm, 6, 2 * ClmInBlock
1164 + (2 * BlockClm) * Dim1[Level] - 1, 0.25);
1165 M_SetEntry(&P[Level], Clm, 7, 2 * ClmInBlock
1166 + (2 * BlockClm) * Dim1[Level], 0.5);
1167 M_SetEntry(&P[Level], Clm, 8, 2 * ClmInBlock
1168 + (2 * BlockClm) * Dim1[Level] + 1, 0.25);
1169 }
1170 }
1171 }
1172 }
1173 }
1174
1175 static void IterStatus(int Iter, double rNorm, double bNorm, IterIdType IterId)
1176 /* put out accuracy after each multigrid iteration */
1177 {
1178 if (IterId == MGIterId || IterId == MGPCGIterId || IterId == BPXPCGIterId) {
1179 printf("%3d. iteration ... accuracy = ", Iter);
1180 if (!IsZero(bNorm))
1181 printf("%11.4e\n", rNorm / bNorm);
1182 else
1183 printf(" ---\n");
1184 }
1185 }