1 #ifndef __CS_MATRIX_ASSEMBLER_PRIV_H__
2 #define __CS_MATRIX_ASSEMBLER_PRIV_H__
3 
4 /*============================================================================
5  * Incremental or general construction of matrix.
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 /*----------------------------------------------------------------------------
37  * Local headers
38  *----------------------------------------------------------------------------*/
39 
40 #include "cs_defs.h"
41 #include "cs_log.h"
42 #include "cs_rank_neighbors.h"
43 #include "cs_timer.h"
44 
45 #include "cs_matrix.h"
46 
47 /*----------------------------------------------------------------------------
48  *  Header for the current file
49  *----------------------------------------------------------------------------*/
50 
51 /*----------------------------------------------------------------------------*/
52 
53 BEGIN_C_DECLS
54 
55 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
56 
57 /*=============================================================================
58  * Local Macro Definitions
59  *============================================================================*/
60 
61 /*=============================================================================
62  * Local Structure Definitions
63  *============================================================================*/
64 
65 /*----------------------------------------------------------------------------
66  * Structure used to pre-build a matrix
67  *----------------------------------------------------------------------------*/
68 
69 struct _cs_matrix_assembler_t {
70 
71   bool        separate_diag;     /* is diagonal handled separately ? */
72 
73   int         flags;             /* sum (bitwise or) of option constants */
74 
75   cs_gnum_t   l_range[2];        /* local global row range */
76   cs_gnum_t   n_g_rows;          /* global number of rows */
77   cs_lnum_t   n_rows;            /* local number of rows */
78 
79   cs_lnum_t   size;              /* current insertion array size */
80   cs_lnum_t   max_size;          /* maximum insertion array size */
81 
82   const cs_lnum_t  *r_idx;       /* shared main row index (0 to n-1) */
83   const cs_lnum_t  *c_id;        /* shared main column ids (0 to n-1) */
84 
85   cs_lnum_t   *_r_idx;           /* private main row index (0 to n-1) */
86   cs_lnum_t   *_c_id;            /* private main column ids (0 to n-1) */
87 
88   cs_lnum_t   *d_r_idx;          /* distant row index (0 to n-1) */
89   cs_gnum_t   *d_g_c_id;         /* distant global column ids (0 to n-1) */
90 
91   cs_gnum_t   *g_rc_id;          /* global row and column ids
92                                     (local and distant) */
93 
94 #if defined(HAVE_MPI)
95 
96   /* Distant columns associated with local rows */
97 
98   /* Metadata for exchange of matrix coefficient values with other ranks */
99 
100   int           n_coeff_ranks;           /* number of MPI ranks with which
101                                             coefficients are exchanged */
102   int          *coeff_rank;              /* ranks with which coefficients are
103                                             exchanged */
104 
105   cs_lnum_t     coeff_send_size;         /* number of coefficients to send */
106   cs_lnum_t     coeff_recv_size;         /* number of coefficients to receive */
107 
108   cs_lnum_t     coeff_send_n_rows;       /* number of matching rows */
109   cs_lnum_t    *coeff_send_index;        /* index of sent coefficient rows */
110   cs_gnum_t    *coeff_send_row_g_id;     /* global ids matching rows (ordered) */
111   cs_gnum_t    *coeff_send_col_g_id;     /* global ids matching columns
112                                             (ordered) */
113 
114   cs_lnum_t    *coeff_rank_send_index;   /* index of data to send */
115   cs_lnum_t    *coeff_rank_recv_index;   /* index of data to receive */
116 
117   cs_lnum_t    *coeff_recv_row_id;       /* local row ids associated with
118                                             received data; */
119   cs_lnum_t    *coeff_recv_col_idx;      /* local column index associated with
120                                             received data; the column numbering
121                                             implicitely assumes local terms
122                                             first, distant ones second */
123   cs_gnum_t    *coeff_recv_col_g_id;     /* global column id couples
124                                             associated with received data */
125 
126   /* Associated communicator */
127 
128   MPI_Comm     comm;             /* associated MPI communicator */
129 
130   /* Statistics */
131 
132   int          n_ranks_init[2];  /* Number of ranks for initial exchange
133                                     for distant rows then columns */
134 #endif /* HAVE_MPI */
135 
136   /* Associated vector ghost element info */
137 
138   const cs_halo_t  *halo;                /* shared halo for associated vectors */
139   cs_halo_t        *_halo;               /* private halo for associated vectors */
140 
141   cs_lnum_t         n_e_g_ids;           /* number of external global ids */
142   cs_gnum_t        *e_g_id;              /* global ids associated with halo
143                                             elements (size: n_e_g_ids */
144 
145 };
146 
147 /*----------------------------------------------------------------------------
148  * Structure managing matrix coefficient contributions.
149  *----------------------------------------------------------------------------*/
150 
151 struct _cs_matrix_assembler_values_t {
152 
153   const  cs_matrix_assembler_t  *ma;  /* associated matrix assembler */
154 
155   bool        separate_diag;          /* is diagonal handled separately ? */
156   bool        final_assembly;         /* are we ready for final assembly ? */
157 
158   cs_lnum_t   db_size[4];             /* Diag Block size including padding:
159                                          0: useful block size
160                                          1: vector block extents
161                                          2: matrix line extents
162                                          3: matrix line*column extents */
163 
164   cs_lnum_t   eb_size[4];             /* Extradiag block size including padding:
165                                          0: useful block size
166                                          1: vector block extents
167                                          2: matrix line extents
168                                          3: matrix line*column extents */
169 
170   cs_lnum_t  *diag_idx;               /* Local index of diagonal in each row
171                                          when conversion beween separate
172                                          diagonal and included diagonal is
173                                          required */
174 
175   /* Accumulated contributions to distant rows, indexed as per
176      coeff_send_index of the matching assembler structure */
177 
178 #if defined(HAVE_MPI)
179 
180   cs_real_t  *coeff_send;
181 
182 #endif
183 
184   /* Matching structure and function pointers; some function type may not be
185      useful for certain matrix structures or libraries. */
186 
187   void                                 *matrix;          /* pointer to
188                                                             matrix structure */
189 
190   cs_matrix_assembler_values_init_t    *init;
191   cs_matrix_assembler_values_add_t     *add_values;
192   cs_matrix_assembler_values_add_g_t   *add_values_g;
193   cs_matrix_assembler_values_begin_t   *assembly_begin;  /* optional */
194   cs_matrix_assembler_values_end_t     *assembly_end;    /* optional */
195 
196 };
197 
198 /*============================================================================
199  * Public inline function definitions
200  *============================================================================*/
201 
202 /*----------------------------------------------------------------------------*/
203 /*!
204  * \brief Binary search for a given local id in a given array of
205  *        ordered local ids, when the id might not be present
206  *
207  * We assume the id is present in the array.
208  *
209  * \param[in]  l_id_array size  array_size
210  * \param[in]  l_id             local id to search for
211  * \param[in]  l_id_array       ordered unique local ids array
212  *
213  * \return  index of l_id in l_id_array, or -1 if not found
214  */
215 /*----------------------------------------------------------------------------*/
216 
217 static inline cs_lnum_t
_l_id_binary_search(cs_lnum_t l_id_array_size,cs_lnum_t l_id,const cs_lnum_t l_id_array[])218 _l_id_binary_search(cs_lnum_t        l_id_array_size,
219                     cs_lnum_t        l_id,
220                     const cs_lnum_t  l_id_array[])
221 {
222   if (l_id_array_size < 1)
223     return -1;
224 
225   cs_lnum_t start_id = 0;
226   cs_lnum_t end_id = l_id_array_size - 1;
227   cs_lnum_t mid_id = end_id/2;
228   while (start_id < end_id) {
229     if (l_id_array[mid_id] < l_id)
230       start_id = mid_id + 1;
231     else if (l_id_array[mid_id] > l_id)
232       end_id = mid_id - 1;
233     else
234       break;
235     mid_id = start_id + (end_id - start_id)/2;
236   }
237   if (l_id_array[mid_id] != l_id)
238     mid_id = -1;
239 
240   return mid_id;
241 }
242 
243 /*----------------------------------------------------------------------------*/
244 /*!
245  * \brief Binary search for a given global id in a given array of
246  *        ordered global ids, when we know the id is present.
247  *
248  * We assume the id is present in the array.
249  *
250  * \param[in]  g_id_array size  array_size
251  * \param[in]  g_id             global id to search for
252  * \param[in]  g_id_array       ordered unique global ids array
253  *
254  * \return  index of g_id in g_id_array.
255  */
256 /*----------------------------------------------------------------------------*/
257 
258 static inline cs_lnum_t
_g_id_binary_find(cs_lnum_t g_id_array_size,cs_gnum_t g_id,const cs_gnum_t g_id_array[])259 _g_id_binary_find(cs_lnum_t        g_id_array_size,
260                   cs_gnum_t        g_id,
261                   const cs_gnum_t  g_id_array[])
262 {
263   cs_lnum_t start_id = 0;
264   cs_lnum_t end_id = g_id_array_size - 1;
265   cs_lnum_t mid_id = (end_id -start_id) / 2;
266   while (start_id < end_id) {
267     if (g_id_array[mid_id] < g_id)
268       start_id = mid_id + 1;
269     else if (g_id_array[mid_id] > g_id)
270       end_id = mid_id - 1;
271     else
272       break;
273     mid_id = start_id + ((end_id -start_id) / 2);
274   }
275   assert(g_id_array[mid_id] == g_id);
276 
277   return mid_id;
278 }
279 
280 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
281 
282 /*----------------------------------------------------------------------------*/
283 
284 END_C_DECLS
285 
286 #endif /* __CS_MATRIX_ASSEMBLER_PRIV_H__ */
287