7.0
general documentation
cs_sles_it_priv.h
Go to the documentation of this file.
1 #ifndef __CS_SLES_IT_PRIV_H__
2 #define __CS_SLES_IT_PRIV_H__
3 
4 /*============================================================================
5  * Sparse Linear Equation Solvers: Iterative solvers
6  *============================================================================*/
7 
8 /*
9  This file is part of Code_Saturne, a general-purpose CFD tool.
10 
11  Copyright (C) 1998-2021 EDF S.A.
12 
13  This program is free software; you can redistribute it and/or modify it under
14  the terms of the GNU General Public License as published by the Free Software
15  Foundation; either version 2 of the License, or (at your option) any later
16  version.
17 
18  This program is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
21  details.
22 
23  You should have received a copy of the GNU General Public License along with
24  this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
25  Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 */
27 
28 /*----------------------------------------------------------------------------*/
29 
30 #include "cs_defs.h"
31 
32 /*----------------------------------------------------------------------------
33  * Standard C library headers
34  *----------------------------------------------------------------------------*/
35 
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <assert.h>
41 #include <math.h>
42 
43 #if defined(HAVE_MPI)
44 #include <mpi.h>
45 #endif
46 
47 /*----------------------------------------------------------------------------
48  * Local headers
49  *----------------------------------------------------------------------------*/
50 
51 #include "bft_mem.h"
52 #include "bft_error.h"
53 #include "bft_printf.h"
54 
55 #include "cs_base.h"
56 #include "cs_blas.h"
57 #include "cs_file.h"
58 #include "cs_log.h"
59 #include "cs_halo.h"
60 #include "cs_mesh.h"
61 #include "cs_matrix.h"
62 #include "cs_matrix_default.h"
63 #include "cs_matrix_util.h"
64 #include "cs_post.h"
65 #include "cs_timer.h"
66 #include "cs_time_plot.h"
67 
68 /*----------------------------------------------------------------------------
69  * Header for the current file
70  *----------------------------------------------------------------------------*/
71 
72 #include "cs_sles.h"
73 #include "cs_sles_it.h"
74 #include "cs_sles_pc.h"
75 
76 /*----------------------------------------------------------------------------*/
77 
79 
82 /*=============================================================================
83  * Local Macro Definitions
84  *============================================================================*/
85 
86 #if !defined(HUGE_VAL)
87 #define HUGE_VAL 1.E+12
88 #endif
89 
90 #define DB_SIZE_MAX 8
91 
92 /*=============================================================================
93  * Local Structure Definitions
94  *============================================================================*/
95 
96 /*----------------------------------------------------------------------------
97  * Function pointer for actual resolution of a linear system.
98  *
99  * parameters:
100  * c <-- pointer to solver context info
101  * a <-- linear equation matrix
102  * rotation_mode <-- halo update option for rotational periodicity
103  * convergence <-- convergence information structure
104  * rhs <-- right hand side
105  * vx --> system solution
106  * aux_size <-- number of elements in aux_vectors (in bytes)
107  * aux_vectors --- optional working area (allocation otherwise)
108  *
109  * returns:
110  * convergence status
111  *----------------------------------------------------------------------------*/
112 
114 (cs_sles_it_solve_t) (cs_sles_it_t *c,
115  const cs_matrix_t *a,
116  cs_lnum_t diag_block_size,
117  cs_halo_rotation_t rotation_mode,
118  cs_sles_it_convergence_t *convergence,
119  const cs_real_t *rhs,
120  cs_real_t *restrict vx,
121  size_t aux_size,
122  void *aux_vectors);
123 
124 /* Solver setup data */
125 /*-------------------*/
126 
127 typedef struct _cs_sles_it_setup_t {
128 
129  double initial_residue; /* last initial residue value */
130 
131  cs_lnum_t n_rows; /* number of associated rows */
132 
133  const cs_real_t *ad_inv; /* pointer to diagonal inverse */
134  cs_real_t *_ad_inv; /* private pointer to
135  diagonal inverse */
136 
137  void *pc_context; /* preconditioner context */
138  cs_sles_pc_apply_t *pc_apply; /* preconditioner apply */
139 
140 } cs_sles_it_setup_t;
141 
142 /* Solver additional data */
143 /*------------------------*/
144 
145 typedef struct _cs_sles_it_add_t {
146 
147  cs_lnum_t *order; /* ordering */
148 
149 } cs_sles_it_add_t;
150 
151 /* Basic per linear system options and logging */
152 /*---------------------------------------------*/
153 
154 struct _cs_sles_it_t {
155 
156  /* Base settings */
157 
158  cs_sles_it_type_t type; /* Solver type */
159 
160  bool update_stats; /* do stats need to be updated ? */
161  bool ignore_convergence; /* ignore convergence for some
162  solvers used as preconditioners */
163 
164  int n_max_iter; /* maximum number of iterations */
165 
166  cs_sles_it_solve_t *solve; /* pointer to solve function */
167 
168  cs_sles_pc_t *pc; /* pointer to possibly shared
169  preconditioner object */
170  cs_sles_pc_t *_pc; /* pointer to owned
171  preconditioner object */
172 
173  /* Performance data */
174 
175  unsigned n_setups; /* Number of times system setup */
176  unsigned n_solves; /* Number of times system solved */
177 
178  unsigned n_iterations_last; /* Number of iterations for last
179  system resolution */
180  unsigned n_iterations_min; /* Minimum number ot iterations
181  in system resolution history */
182  unsigned n_iterations_max; /* Maximum number ot iterations
183  in system resolution history */
184  unsigned long long n_iterations_tot; /* Total accumulated number of
185  iterations */
186 
187  cs_timer_counter_t t_setup; /* Total setup */
188  cs_timer_counter_t t_solve; /* Total time used */
189 
190  /* Plot info */
191 
192  int plot_time_stamp; /* Plot time stamp */
193  cs_time_plot_t *plot; /* Pointer to plot structure,
194  which may be owned or shared */
195  cs_time_plot_t *_plot; /* Pointer to own plot structure */
196 
197  /* Communicator used for reduction operations
198  (if left at NULL, main communicator will be used) */
199 
200 # if defined(HAVE_MPI)
201  MPI_Comm comm;
202  MPI_Comm caller_comm;
203  int caller_n_ranks;
204 # endif
205 
206  /* Solver setup */
207 
208  const struct _cs_sles_it_t *shared; /* pointer to context sharing some
209  setup and preconditioner data,
210  or NULL */
211 
212  cs_sles_it_add_t *add_data; /* additional data */
213 
214  cs_sles_it_setup_t *setup_data; /* setup data */
215 
216  /* Alternative solvers (fallback or heuristics) */
217 
218  cs_sles_convergence_state_t fallback_cvg; /* threshold for fallback
219  convergence */
220  cs_sles_it_t *fallback; /* fallback solver */
221 
222 };
223 
224 /* Convergence testing and tracking */
225 /*----------------------------------*/
226 
227 struct _cs_sles_it_convergence_t {
228 
229  const char *name; /* Pointer to name string */
230 
231  int verbosity; /* Verbosity level */
232 
233  unsigned n_iterations; /* Current number of iterations */
234  unsigned n_iterations_max; /* Maximum number of iterations */
235 
236  double precision; /* Precision limit */
237  double r_norm; /* Residue normalization */
238  double residue; /* Current residue */
239 
240 };
241 
242 /*============================================================================
243  * Inline static function definitions
244  *============================================================================*/
245 
246 /*----------------------------------------------------------------------------
247  * Compute dot product, summing result over all ranks.
248  *
249  * parameters:
250  * c <-- pointer to solver context info
251  * x <-- first vector in s = x.y
252  * y <-- second vector in s = x.y
253  *
254  * returns:
255  * result of s = x.y
256  *----------------------------------------------------------------------------*/
257 
258 inline static double
259 _dot_product(const cs_sles_it_t *c,
260  const cs_real_t *x,
261  const cs_real_t *y)
262 {
263  double s = cs_dot(c->setup_data->n_rows, x, y);
264 
265 #if defined(HAVE_MPI)
266 
267  if (c->comm != MPI_COMM_NULL) {
268  double _sum;
269  MPI_Allreduce(&s, &_sum, 1, MPI_DOUBLE, MPI_SUM, c->comm);
270  s = _sum;
271  }
272 
273 #endif /* defined(HAVE_MPI) */
274 
275  return s;
276 }
277 
278 /*----------------------------------------------------------------------------
279  * Compute dot product x.x, summing result over all ranks.
280  *
281  * parameters:
282  * c <-- pointer to solver context info
283  * x <-- vector in s = x.x
284  *
285  * returns:
286  * result of s = x.x
287  *----------------------------------------------------------------------------*/
288 
289 inline static double
290 _dot_product_xx(const cs_sles_it_t *c,
291  const cs_real_t *x)
292 {
293  double s;
294 
295  s = cs_dot_xx(c->setup_data->n_rows, x);
296 
297 #if defined(HAVE_MPI)
298 
299  if (c->comm != MPI_COMM_NULL) {
300  double _sum;
301  MPI_Allreduce(&s, &_sum, 1, MPI_DOUBLE, MPI_SUM, c->comm);
302  s = _sum;
303  }
304 
305 #endif /* defined(HAVE_MPI) */
306 
307  return s;
308 }
309 
310 /*----------------------------------------------------------------------------
311  * Compute 2 dot products x.x and x.y, summing result over all ranks.
312  *
313  * parameters:
314  * c <-- pointer to solver context info
315  * x <-- vector in s1 = x.x and s2 = x.y
316  * y <-- vector in s2 = x.y
317  * s1 --> result of s1 = x.x
318  * s2 --> result of s2 = x.y
319  *----------------------------------------------------------------------------*/
320 
321 inline static void
322 _dot_products_xx_xy(const cs_sles_it_t *c,
323  const cs_real_t *x,
324  const cs_real_t *y,
325  double *s1,
326  double *s2)
327 {
328  double s[2];
329 
330  cs_dot_xx_xy(c->setup_data->n_rows, x, y, s, s+1);
331 
332 #if defined(HAVE_MPI)
333 
334  if (c->comm != MPI_COMM_NULL) {
335  double _sum[2];
336  MPI_Allreduce(s, _sum, 2, MPI_DOUBLE, MPI_SUM, c->comm);
337  s[0] = _sum[0];
338  s[1] = _sum[1];
339  }
340 
341 #endif /* defined(HAVE_MPI) */
342 
343  *s1 = s[0];
344  *s2 = s[1];
345 }
346 
347 /*----------------------------------------------------------------------------
348  * Compute 2 dot products x.x and x.y, summing result over all ranks.
349  *
350  * parameters:
351  * c <-- pointer to solver context info
352  * x <-- vector in s1 = x.y
353  * y <-- vector in s1 = x.y and s2 = y.z
354  * z <-- vector in s2 = y.z
355  * s1 --> result of s1 = x.y
356  * s2 --> result of s2 = y.z
357  *----------------------------------------------------------------------------*/
358 
359 inline static void
360 _dot_products_xy_yz(const cs_sles_it_t *c,
361  const cs_real_t *x,
362  const cs_real_t *y,
363  const cs_real_t *z,
364  double *s1,
365  double *s2)
366 {
367  double s[2];
368 
369  cs_dot_xy_yz(c->setup_data->n_rows, x, y, z, s, s+1);
370 
371 #if defined(HAVE_MPI)
372 
373  if (c->comm != MPI_COMM_NULL) {
374  double _sum[2];
375  MPI_Allreduce(s, _sum, 2, MPI_DOUBLE, MPI_SUM, c->comm);
376  s[0] = _sum[0];
377  s[1] = _sum[1];
378  }
379 
380 #endif /* defined(HAVE_MPI) */
381 
382  *s1 = s[0];
383  *s2 = s[1];
384 }
385 
386 /*----------------------------------------------------------------------------
387  * Compute 3 dot products, summing result over all ranks.
388  *
389  * parameters:
390  * c <-- pointer to solver context info
391  * x <-- first vector
392  * y <-- second vector
393  * z <-- third vector
394  * s1 --> result of s1 = x.x
395  * s2 --> result of s2 = x.y
396  * s3 --> result of s3 = y.z
397  *----------------------------------------------------------------------------*/
398 
399 inline static void
400 _dot_products_xx_xy_yz(const cs_sles_it_t *c,
401  const cs_real_t *x,
402  const cs_real_t *y,
403  const cs_real_t *z,
404  double *s1,
405  double *s2,
406  double *s3)
407 {
408  double s[3];
409 
410  cs_dot_xx_xy_yz(c->setup_data->n_rows, x, y, z, s, s+1, s+2);
411 
412 #if defined(HAVE_MPI)
413 
414  if (c->comm != MPI_COMM_NULL) {
415  double _sum[3];
416 
417  MPI_Allreduce(s, _sum, 3, MPI_DOUBLE, MPI_SUM, c->comm);
418  s[0] = _sum[0];
419  s[1] = _sum[1];
420  s[2] = _sum[2];
421  }
422 
423 #endif /* defined(HAVE_MPI) */
424 
425  *s1 = s[0];
426  *s2 = s[1];
427  *s3 = s[2];
428 }
429 
430 /*----------------------------------------------------------------------------
431  * Compute 5 dot products, summing result over all ranks.
432  *
433  * parameters:
434  * c <-- pointer to solver context info
435  * x <-- first vector
436  * y <-- second vector
437  * z <-- third vector
438  * xx --> result of x.x
439  * yy --> result of y.y
440  * xy --> result of x.y
441  * xz --> result of x.z
442  * yz --> result of y.z
443  *----------------------------------------------------------------------------*/
444 
445 inline static void
446 _dot_products_xx_yy_xy_xz_yz(const cs_sles_it_t *c,
447  const cs_real_t *x,
448  const cs_real_t *y,
449  const cs_real_t *z,
450  double *xx,
451  double *yy,
452  double *xy,
453  double *xz,
454  double *yz)
455 {
456  double s[5];
457 
458  cs_dot_xx_yy_xy_xz_yz(c->setup_data->n_rows, x, y, z, s, s+1, s+2, s+3, s+4);
459 
460 #if defined(HAVE_MPI)
461 
462  if (c->comm != MPI_COMM_NULL) {
463  double _sum[5];
464  MPI_Allreduce(s, _sum, 5, MPI_DOUBLE, MPI_SUM, c->comm);
465  memcpy(s, _sum, 5*sizeof(double));
466  }
467 
468 #endif /* defined(HAVE_MPI) */
469 
470  *xx = s[0];
471  *yy = s[1];
472  *xy = s[2];
473  *xz = s[3];
474  *yz = s[4];
475 }
476 
477 /*----------------------------------------------------------------------------
478  * Compute 4 dot products, summing result over all ranks.
479  *
480  * parameters:
481  * c <-- pointer to solver context info
482  * v <-- first vector
483  * r <-- second vector
484  * w <-- third vector
485  * q <-- fourth vector
486  * s1 --> result of s1 = v.r
487  * s2 --> result of s2 = v.w
488  * s3 --> result of s3 = v.q
489  * s4 --> result of s4 = r.r
490  *----------------------------------------------------------------------------*/
491 
492 inline static void
493 _dot_products_vr_vw_vq_rr(const cs_sles_it_t *c,
494  const cs_real_t *v,
495  const cs_real_t *r,
496  const cs_real_t *w,
497  const cs_real_t *q,
498  double *s1,
499  double *s2,
500  double *s3,
501  double *s4)
502 {
503  double s[4];
504 
505  /* Use two separate call as cs_blas.c does not yet hav matching call */
506 
507  cs_dot_xy_yz(c->setup_data->n_rows, w, v, q, s+1, s+2);
508  cs_dot_xx_xy(c->setup_data->n_rows, r, v, s+3, s);
509 
510 #if defined(HAVE_MPI)
511 
512  if (c->comm != MPI_COMM_NULL) {
513  double _sum[4];
514  MPI_Allreduce(s, _sum, 4, MPI_DOUBLE, MPI_SUM, c->comm);
515  memcpy(s, _sum, 4*sizeof(double));
516  }
517 
518 #endif /* defined(HAVE_MPI) */
519 
520  *s1 = s[0];
521  *s2 = s[1];
522  *s3 = s[2];
523  *s4 = s[3];
524 }
525 
526 /*----------------------------------------------------------------------------
527  * Block Jacobi utilities.
528  * Compute forward and backward to solve an LU 3*3 system.
529  *
530  * parameters:
531  * mat <-- 3*3*dim matrix
532  * x --> solution
533  * b --> 1st part of RHS (c - b)
534  * c --> 2nd part of RHS (c - b)
535  *----------------------------------------------------------------------------*/
536 
537 inline static void
538 _fw_and_bw_lu33(const cs_real_t mat[],
539  cs_real_t x[restrict],
540  const cs_real_t b[restrict],
541  const cs_real_t c[restrict])
542 {
543  cs_real_t aux[3];
544 
545  aux[0] = (c[0] - b[0]);
546  aux[1] = (c[1] - b[1]) - aux[0]*mat[3];
547  aux[2] = (c[2] - b[2]) - aux[0]*mat[6] - aux[1]*mat[7];
548 
549  x[2] = aux[2]/mat[8];
550  x[1] = (aux[1] - mat[5]*x[2])/mat[4];
551  x[0] = (aux[0] - mat[1]*x[1] - mat[2]*x[2])/mat[0];
552 }
553 
554 /*----------------------------------------------------------------------------
555  * Block Jacobi utilities.
556  * Compute forward and backward to solve an LU P*P system.
557  *
558  * parameters:
559  * mat <-- P*P*dim matrix
560  * db_size <-- matrix size
561  * x --> solution
562  * b --> 1st part of RHS (c - b)
563  * c --> 2nd part of RHS (c - b)
564  *----------------------------------------------------------------------------*/
565 
566 inline static void
567 _fw_and_bw_lu(const cs_real_t mat[],
568  int db_size,
569  cs_real_t x[restrict],
570  const cs_real_t b[restrict],
571  const cs_real_t c[restrict])
572 {
573  assert(db_size <= DB_SIZE_MAX);
574  cs_real_t aux[DB_SIZE_MAX];
575 
576  /* forward */
577  for (int ii = 0; ii < db_size; ii++) {
578  aux[ii] = (c[ii] - b[ii]);
579  for (int jj = 0; jj < ii; jj++) {
580  aux[ii] -= aux[jj]*mat[ii*db_size + jj];
581  }
582  }
583 
584  /* backward */
585  for (int ii = db_size - 1; ii >= 0; ii-=1) {
586  x[ii] = aux[ii];
587  for (int jj = db_size - 1; jj > ii; jj-=1) {
588  x[ii] -= x[jj]*mat[ii*db_size + jj];
589  }
590  x[ii] /= mat[ii*(db_size + 1)];
591  }
592 }
593 
594 /*----------------------------------------------------------------------------
595  * Block Gauss-Seidel utilities.
596  * Compute forward and backward to solve an LU P*P system.
597  *
598  * parameters:
599  * mat <-- P*P*dim matrix
600  * db_size <-- matrix size
601  * x --> solution
602  * b <-> RHS in, work array
603  *----------------------------------------------------------------------------*/
604 
605 inline static void
606 _fw_and_bw_lu_gs(const cs_real_t mat[],
607  int db_size,
608  cs_real_t x[restrict],
609  const cs_real_t b[restrict])
610 {
611  assert(db_size <= DB_SIZE_MAX);
612 
613  /* forward */
614  for (int ii = 0; ii < db_size; ii++) {
615  x[ii] = b[ii];
616  for (int jj = 0; jj < ii; jj++)
617  x[ii] -= x[jj]*mat[ii*db_size + jj];
618  }
619 
620  /* backward */
621  for (int ii = db_size - 1; ii >= 0; ii--) {
622  for (int jj = db_size - 1; jj > ii; jj--)
623  x[ii] -= x[jj]*mat[ii*db_size + jj];
624  x[ii] /= mat[ii*(db_size + 1)];
625  }
626 }
627 
628 /*============================================================================
629  * Public function definitions
630  *============================================================================*/
631 
632 /*----------------------------------------------------------------------------*/
646 /*----------------------------------------------------------------------------*/
647 
648 void
649 cs_sles_it_convergence_init(cs_sles_it_convergence_t *convergence,
650  const char *solver_name,
651  int verbosity,
652  unsigned n_iter_max,
653  double precision,
654  double r_norm,
655  double *residue);
656 
657 /*----------------------------------------------------------------------------
658  * Setup context for iterative linear solver.
659  *
660  * This function is common to most solvers
661  *
662  * parameters:
663  * c <-> pointer to solver context info
664  * name <-- pointer to system name
665  * a <-- matrix
666  * verbosity <-- verbosity level
667  * diag_block_size <-- diagonal block size
668  * block_nn_inverse <-- if diagonal block size is 3 or 6, compute inverse of
669  * block if true, inverse of block diagonal otherwise
670  *----------------------------------------------------------------------------*/
671 
672 void
673 cs_sles_it_setup_priv(cs_sles_it_t *c,
674  const char *name,
675  const cs_matrix_t *a,
676  int verbosity,
677  int diag_block_size,
678  bool block_nn_inverse);
679 
682 /*----------------------------------------------------------------------------*/
683 
685 
686 #endif /* __CS_SLES_IT_PRIV_H__ */
#define restrict
Definition: cs_defs.h:127
void cs_dot_xx_xy_yz(cs_lnum_t n, const cs_real_t *restrict x, const cs_real_t *restrict y, const cs_real_t *restrict z, double *xx, double *xy, double *yz)
Return 3 dot products of 3 vectors: x.x, x.y, and y.z.
Definition: cs_blas.c:1581
cs_halo_rotation_t
Definition: cs_halo.h:60
void cs_dot_xy_yz(cs_lnum_t n, const cs_real_t *restrict x, const cs_real_t *restrict y, const cs_real_t *restrict z, double *xy, double *yz)
Return 2 dot products of 3 vectors: x.y, and y.z.
Definition: cs_blas.c:1552
cs_sles_it_type_t
Definition: cs_sles_it.h:57
double cs_dot(cs_lnum_t n, const cs_real_t *x, const cs_real_t *y)
Return the dot product of 2 vectors: x.y.
Definition: cs_blas.c:1424
#define BEGIN_C_DECLS
Definition: cs_defs.h:495
struct _cs_sles_pc_t cs_sles_pc_t
Definition: cs_sles_pc.h:66
cs_sles_pc_state_t() cs_sles_pc_apply_t(void *context, cs_halo_rotation_t rotation_mode, const cs_real_t *x_in, cs_real_t *x_out)
Function pointer for application of a preconditioner.
Definition: cs_sles_pc.h:144
struct _cs_sles_it_t cs_sles_it_t
Definition: cs_sles_it.h:86
double cs_real_t
Floating-point value.
Definition: cs_defs.h:307
void cs_dot_xx_xy(cs_lnum_t n, const cs_real_t *restrict x, const cs_real_t *restrict y, double *xx, double *xy)
Return 2 dot products of 2 vectors: x.x, and x.y.
Definition: cs_blas.c:1525
struct _cs_matrix_t cs_matrix_t
Definition: cs_matrix.h:94
struct _cs_time_plot_t cs_time_plot_t
Definition: cs_time_plot.h:48
cs_sles_convergence_state_t
Convergence status indicator.
Definition: cs_sles.h:56
double precision, dimension(:,:,:), allocatable v
Definition: atimbr.f90:114
void cs_dot_xx_yy_xy_xz_yz(cs_lnum_t n, const cs_real_t *restrict x, const cs_real_t *restrict y, const cs_real_t *restrict z, double *xx, double *yy, double *xy, double *xz, double *yz)
Return 5 dot products of 3 vectors: x.x, y.y, x.y, x.z, and y.z.
Definition: cs_blas.c:1613
struct _cs_sles_it_convergence_t cs_sles_it_convergence_t
Definition: cs_sles_it.h:90
double precision, save a
Definition: cs_fuel_incl.f90:146
double cs_dot_xx(cs_lnum_t n, const cs_real_t *x)
Return dot products of a vector with itself: x.x.
Definition: cs_blas.c:1445
int cs_lnum_t
local mesh entity id
Definition: cs_defs.h:301
#define END_C_DECLS
Definition: cs_defs.h:496
Definition: cs_timer.h:57
double precision, save b
Definition: cs_fuel_incl.f90:146