1 /******************************************************************************
2  * Copyright 1998-2019 Lawrence Livermore National Security, LLC and other
3  * HYPRE Project Developers. See the top-level COPYRIGHT file for details.
4  *
5  * SPDX-License-Identifier: (Apache-2.0 OR MIT)
6  ******************************************************************************/
7 
8 /******************************************************************************
9  *
10  * HYPRE_ParCSRMatrix interface
11  *
12  *****************************************************************************/
13 
14 #include "_hypre_parcsr_mv.h"
15 
16 /*--------------------------------------------------------------------------
17  * HYPRE_ParCSRMatrixCreate
18  *--------------------------------------------------------------------------*/
19 
20 HYPRE_Int
HYPRE_ParCSRMatrixCreate(MPI_Comm comm,HYPRE_BigInt global_num_rows,HYPRE_BigInt global_num_cols,HYPRE_BigInt * row_starts,HYPRE_BigInt * col_starts,HYPRE_Int num_cols_offd,HYPRE_Int num_nonzeros_diag,HYPRE_Int num_nonzeros_offd,HYPRE_ParCSRMatrix * matrix)21 HYPRE_ParCSRMatrixCreate( MPI_Comm            comm,
22                           HYPRE_BigInt        global_num_rows,
23                           HYPRE_BigInt        global_num_cols,
24                           HYPRE_BigInt       *row_starts,
25                           HYPRE_BigInt       *col_starts,
26                           HYPRE_Int           num_cols_offd,
27                           HYPRE_Int           num_nonzeros_diag,
28                           HYPRE_Int           num_nonzeros_offd,
29                           HYPRE_ParCSRMatrix *matrix )
30 {
31    if (!matrix)
32    {
33       hypre_error_in_arg(9);
34       return hypre_error_flag;
35    }
36 
37    *matrix = (HYPRE_ParCSRMatrix)
38       hypre_ParCSRMatrixCreate(comm, global_num_rows, global_num_cols,
39                                row_starts, col_starts, num_cols_offd,
40                                num_nonzeros_diag, num_nonzeros_offd);
41 
42    return hypre_error_flag;
43 }
44 
45 /*--------------------------------------------------------------------------
46  * HYPRE_ParCSRMatrixDestroy
47  *--------------------------------------------------------------------------*/
48 
49 HYPRE_Int
HYPRE_ParCSRMatrixDestroy(HYPRE_ParCSRMatrix matrix)50 HYPRE_ParCSRMatrixDestroy( HYPRE_ParCSRMatrix matrix )
51 {
52    return( hypre_ParCSRMatrixDestroy( (hypre_ParCSRMatrix *) matrix ) );
53 }
54 
55 /*--------------------------------------------------------------------------
56  * HYPRE_ParCSRMatrixInitialize
57  *--------------------------------------------------------------------------*/
58 
59 HYPRE_Int
HYPRE_ParCSRMatrixInitialize(HYPRE_ParCSRMatrix matrix)60 HYPRE_ParCSRMatrixInitialize( HYPRE_ParCSRMatrix matrix )
61 {
62    return ( hypre_ParCSRMatrixInitialize( (hypre_ParCSRMatrix *) matrix ) );
63 }
64 
65 /*--------------------------------------------------------------------------
66  * HYPRE_ParCSRMatrixRead
67  *--------------------------------------------------------------------------*/
68 
69 HYPRE_Int
HYPRE_ParCSRMatrixRead(MPI_Comm comm,const char * file_name,HYPRE_ParCSRMatrix * matrix)70 HYPRE_ParCSRMatrixRead( MPI_Comm            comm,
71                         const char         *file_name,
72                         HYPRE_ParCSRMatrix *matrix)
73 {
74    if (!matrix)
75    {
76       hypre_error_in_arg(3);
77       return hypre_error_flag;
78    }
79    *matrix = (HYPRE_ParCSRMatrix) hypre_ParCSRMatrixRead( comm, file_name );
80    return hypre_error_flag;
81 }
82 
83 /*--------------------------------------------------------------------------
84  * HYPRE_ParCSRMatrixPrint
85  *--------------------------------------------------------------------------*/
86 
87 HYPRE_Int
HYPRE_ParCSRMatrixPrint(HYPRE_ParCSRMatrix matrix,const char * file_name)88 HYPRE_ParCSRMatrixPrint( HYPRE_ParCSRMatrix  matrix,
89                          const char         *file_name )
90 {
91    hypre_ParCSRMatrixPrint( (hypre_ParCSRMatrix *) matrix,
92                             file_name );
93    return hypre_error_flag;
94 }
95 
96 /*--------------------------------------------------------------------------
97  * HYPRE_ParCSRMatrixGetComm
98  *--------------------------------------------------------------------------*/
99 
100 HYPRE_Int
HYPRE_ParCSRMatrixGetComm(HYPRE_ParCSRMatrix matrix,MPI_Comm * comm)101 HYPRE_ParCSRMatrixGetComm( HYPRE_ParCSRMatrix  matrix,
102                            MPI_Comm           *comm )
103 {
104    if (!matrix)
105    {
106       hypre_error_in_arg(1);
107       return hypre_error_flag;
108    }
109    *comm = hypre_ParCSRMatrixComm((hypre_ParCSRMatrix *) matrix);
110 
111    return hypre_error_flag;
112 }
113 /*--------------------------------------------------------------------------
114  * HYPRE_ParCSRMatrixGetDims
115  *--------------------------------------------------------------------------*/
116 
117 HYPRE_Int
HYPRE_ParCSRMatrixGetDims(HYPRE_ParCSRMatrix matrix,HYPRE_BigInt * M,HYPRE_BigInt * N)118 HYPRE_ParCSRMatrixGetDims( HYPRE_ParCSRMatrix  matrix,
119                            HYPRE_BigInt       *M,
120                            HYPRE_BigInt       *N )
121 {
122    if (!matrix)
123    {
124       hypre_error_in_arg(1);
125       return hypre_error_flag;
126    }
127    *M = hypre_ParCSRMatrixGlobalNumRows((hypre_ParCSRMatrix *) matrix);
128    *N = hypre_ParCSRMatrixGlobalNumCols((hypre_ParCSRMatrix *) matrix);
129 
130    return hypre_error_flag;
131 }
132 
133 /*--------------------------------------------------------------------------
134  * HYPRE_ParCSRMatrixGetRowPartitioning
135  *--------------------------------------------------------------------------*/
136 
137 HYPRE_Int
HYPRE_ParCSRMatrixGetRowPartitioning(HYPRE_ParCSRMatrix matrix,HYPRE_BigInt ** row_partitioning_ptr)138 HYPRE_ParCSRMatrixGetRowPartitioning( HYPRE_ParCSRMatrix   matrix,
139                                       HYPRE_BigInt       **row_partitioning_ptr )
140 {
141    HYPRE_BigInt *row_partitioning, *row_starts;
142    HYPRE_Int num_procs, i;
143 
144    if (!matrix)
145    {
146       hypre_error_in_arg(1);
147       return hypre_error_flag;
148    }
149 
150    hypre_MPI_Comm_size(hypre_ParCSRMatrixComm((hypre_ParCSRMatrix *) matrix),
151                        &num_procs);
152    row_starts = hypre_ParCSRMatrixRowStarts((hypre_ParCSRMatrix *) matrix);
153    if (!row_starts) return -1;
154    row_partitioning = hypre_CTAlloc(HYPRE_BigInt,  num_procs+1, HYPRE_MEMORY_HOST);
155    for (i=0; i < num_procs + 1; i++)
156       row_partitioning[i] = row_starts[i];
157 
158    *row_partitioning_ptr = row_partitioning;
159    return hypre_error_flag;
160 }
161 
162 /*--------------------------------------------------------------------------
163  * HYPRE_ParCSRMatrixGetGlobalRowPartitioning
164  *--------------------------------------------------------------------------*/
165 HYPRE_Int
HYPRE_ParCSRMatrixGetGlobalRowPartitioning(HYPRE_ParCSRMatrix matrix,HYPRE_Int all_procs,HYPRE_BigInt ** row_partitioning_ptr)166 HYPRE_ParCSRMatrixGetGlobalRowPartitioning( HYPRE_ParCSRMatrix   matrix,
167                                             HYPRE_Int            all_procs,
168                                             HYPRE_BigInt       **row_partitioning_ptr )
169 {
170    MPI_Comm        comm;
171    HYPRE_Int       my_id;
172    HYPRE_BigInt   *row_partitioning = NULL;
173 
174    if (!matrix)
175    {
176       hypre_error_in_arg(1);
177       return hypre_error_flag;
178    }
179 
180    comm = hypre_ParCSRMatrixComm((hypre_ParCSRMatrix *) matrix);
181    hypre_MPI_Comm_rank(comm, &my_id);
182 
183    HYPRE_Int       num_procs;
184    HYPRE_BigInt    row_start;
185 
186    hypre_MPI_Comm_size(comm, &num_procs);
187    if (my_id == 0 || all_procs)
188    {
189       row_partitioning = hypre_CTAlloc(HYPRE_BigInt, num_procs+1, HYPRE_MEMORY_HOST);
190    }
191 
192    row_start = hypre_ParCSRMatrixFirstRowIndex((hypre_ParCSRMatrix *) matrix);
193    if (all_procs)
194    {
195       hypre_MPI_Allgather(&row_start, 1, HYPRE_MPI_BIG_INT, row_partitioning,
196                           1, HYPRE_MPI_BIG_INT, comm);
197    }
198    else
199    {
200       hypre_MPI_Gather(&row_start, 1, HYPRE_MPI_BIG_INT, row_partitioning,
201                        1, HYPRE_MPI_BIG_INT, 0, comm);
202    }
203 
204    if (my_id == 0 || all_procs)
205    {
206       row_partitioning[num_procs] = hypre_ParCSRMatrixGlobalNumRows((hypre_ParCSRMatrix *) matrix);
207    }
208 
209    *row_partitioning_ptr = row_partitioning;
210 
211    return hypre_error_flag;
212 }
213 
214 /*--------------------------------------------------------------------------
215  * HYPRE_ParCSRMatrixGetColPartitioning
216  *--------------------------------------------------------------------------*/
217 
218 HYPRE_Int
HYPRE_ParCSRMatrixGetColPartitioning(HYPRE_ParCSRMatrix matrix,HYPRE_BigInt ** col_partitioning_ptr)219 HYPRE_ParCSRMatrixGetColPartitioning( HYPRE_ParCSRMatrix   matrix,
220                                       HYPRE_BigInt       **col_partitioning_ptr )
221 {
222    HYPRE_BigInt *col_partitioning, *col_starts;
223    HYPRE_Int num_procs, i;
224 
225    if (!matrix)
226    {
227       hypre_error_in_arg(1);
228       return hypre_error_flag;
229    }
230 
231    hypre_MPI_Comm_size(hypre_ParCSRMatrixComm((hypre_ParCSRMatrix *) matrix),
232                        &num_procs);
233    col_starts = hypre_ParCSRMatrixColStarts((hypre_ParCSRMatrix *) matrix);
234    if (!col_starts) return -1;
235    col_partitioning = hypre_CTAlloc(HYPRE_BigInt,  num_procs+1, HYPRE_MEMORY_HOST);
236    for (i=0; i < num_procs + 1; i++)
237       col_partitioning[i] = col_starts[i];
238 
239    *col_partitioning_ptr = col_partitioning;
240    return hypre_error_flag;
241 }
242 
243 /*--------------------------------------------------------------------------
244  * HYPRE_ParCSRMatrixGetLocalRange
245  *--------------------------------------------------------------------------*/
246 /**
247    Returns range of rows and columns owned by this processor.
248    Not collective.
249 
250    @return integer error code
251    @param HYPRE_ParCSRMatrix matrix [IN]
252    the matrix to be operated on.
253    @param HYPRE_Int *row_start [OUT]
254    the global number of the first row stored on this processor
255    @param HYPRE_Int *row_end [OUT]
256    the global number of the first row stored on this processor
257    @param HYPRE_Int *col_start [OUT]
258    the global number of the first column stored on this processor
259    @param HYPRE_Int *col_end [OUT]
260    the global number of the first column stored on this processor
261 */
262 
263 HYPRE_Int
HYPRE_ParCSRMatrixGetLocalRange(HYPRE_ParCSRMatrix matrix,HYPRE_BigInt * row_start,HYPRE_BigInt * row_end,HYPRE_BigInt * col_start,HYPRE_BigInt * col_end)264 HYPRE_ParCSRMatrixGetLocalRange( HYPRE_ParCSRMatrix  matrix,
265                                  HYPRE_BigInt       *row_start,
266                                  HYPRE_BigInt       *row_end,
267                                  HYPRE_BigInt       *col_start,
268                                  HYPRE_BigInt       *col_end )
269 {
270    if (!matrix)
271    {
272       hypre_error_in_arg(1);
273       return hypre_error_flag;
274    }
275 
276    hypre_ParCSRMatrixGetLocalRange( (hypre_ParCSRMatrix *) matrix,
277                                     row_start, row_end, col_start, col_end );
278    return hypre_error_flag;
279 }
280 
281 /*--------------------------------------------------------------------------
282  * HYPRE_ParCSRMatrixGetRow
283  *--------------------------------------------------------------------------*/
284 
285 HYPRE_Int
HYPRE_ParCSRMatrixGetRow(HYPRE_ParCSRMatrix matrix,HYPRE_BigInt row,HYPRE_Int * size,HYPRE_BigInt ** col_ind,HYPRE_Complex ** values)286 HYPRE_ParCSRMatrixGetRow( HYPRE_ParCSRMatrix  matrix,
287                           HYPRE_BigInt        row,
288                           HYPRE_Int          *size,
289                           HYPRE_BigInt      **col_ind,
290                           HYPRE_Complex     **values )
291 {
292    if (!matrix)
293    {
294       hypre_error_in_arg(1);
295       return hypre_error_flag;
296    }
297 
298    hypre_ParCSRMatrixGetRow( (hypre_ParCSRMatrix *) matrix,
299                              row, size, col_ind, values );
300    return hypre_error_flag;
301 }
302 
303 /*--------------------------------------------------------------------------
304  * HYPRE_ParCSRMatrixRestoreRow
305  *--------------------------------------------------------------------------*/
306 
307 HYPRE_Int
HYPRE_ParCSRMatrixRestoreRow(HYPRE_ParCSRMatrix matrix,HYPRE_BigInt row,HYPRE_Int * size,HYPRE_BigInt ** col_ind,HYPRE_Complex ** values)308 HYPRE_ParCSRMatrixRestoreRow( HYPRE_ParCSRMatrix  matrix,
309                               HYPRE_BigInt        row,
310                               HYPRE_Int          *size,
311                               HYPRE_BigInt      **col_ind,
312                               HYPRE_Complex     **values )
313 {
314    if (!matrix)
315    {
316       hypre_error_in_arg(1);
317       return hypre_error_flag;
318    }
319 
320    hypre_ParCSRMatrixRestoreRow( (hypre_ParCSRMatrix *) matrix,
321                                  row, size, col_ind, values );
322    return hypre_error_flag;
323 }
324 
325 /*--------------------------------------------------------------------------
326  * HYPRE_CSRMatrixToParCSRMatrix
327  * Output argument (fifth argument): a new ParCSRmatrix.
328  * Input arguments: MPI communicator, CSR matrix, and optional partitionings.
329  * If you don't have partitionings, just pass a null pointer for the third
330  * and fourth arguments and they will be computed.
331  * Note that it is not possible to provide a null pointer if this is called
332  * from Fortran code; so you must provide the paritionings from Fortran.
333  *--------------------------------------------------------------------------*/
334 
335 HYPRE_Int
HYPRE_CSRMatrixToParCSRMatrix(MPI_Comm comm,HYPRE_CSRMatrix A_CSR,HYPRE_BigInt * row_partitioning,HYPRE_BigInt * col_partitioning,HYPRE_ParCSRMatrix * matrix)336 HYPRE_CSRMatrixToParCSRMatrix( MPI_Comm            comm,
337                                HYPRE_CSRMatrix     A_CSR,
338                                HYPRE_BigInt       *row_partitioning,
339                                HYPRE_BigInt       *col_partitioning,
340                                HYPRE_ParCSRMatrix *matrix)
341 {
342    if (!matrix)
343    {
344       hypre_error_in_arg(5);
345       return hypre_error_flag;
346    }
347    *matrix = (HYPRE_ParCSRMatrix)
348       hypre_CSRMatrixToParCSRMatrix( comm, (hypre_CSRMatrix *) A_CSR,
349                                      row_partitioning, col_partitioning) ;
350    return hypre_error_flag;
351 }
352 
353 /*--------------------------------------------------------------------------
354  * HYPRE_CSRMatrixToParCSRMatrix_WithNewPartitioning
355  * Output argument (third argument): a new ParCSRmatrix.
356  * Input arguments: MPI communicator, CSR matrix.
357  * Row and column partitionings are computed for the output matrix.
358  *--------------------------------------------------------------------------*/
359 
360 HYPRE_Int
HYPRE_CSRMatrixToParCSRMatrix_WithNewPartitioning(MPI_Comm comm,HYPRE_CSRMatrix A_CSR,HYPRE_ParCSRMatrix * matrix)361 HYPRE_CSRMatrixToParCSRMatrix_WithNewPartitioning(
362    MPI_Comm            comm,
363    HYPRE_CSRMatrix     A_CSR,
364    HYPRE_ParCSRMatrix *matrix )
365 {
366    if (!matrix)
367    {
368       hypre_error_in_arg(3);
369       return hypre_error_flag;
370    }
371    *matrix = (HYPRE_ParCSRMatrix)
372       hypre_CSRMatrixToParCSRMatrix( comm, (hypre_CSRMatrix *) A_CSR, NULL, NULL ) ;
373    return hypre_error_flag;
374 }
375 
376 /*--------------------------------------------------------------------------
377  * HYPRE_ParCSRMatrixMatvec
378  *--------------------------------------------------------------------------*/
379 
380 HYPRE_Int
HYPRE_ParCSRMatrixMatvec(HYPRE_Complex alpha,HYPRE_ParCSRMatrix A,HYPRE_ParVector x,HYPRE_Complex beta,HYPRE_ParVector y)381 HYPRE_ParCSRMatrixMatvec( HYPRE_Complex      alpha,
382                           HYPRE_ParCSRMatrix A,
383                           HYPRE_ParVector    x,
384                           HYPRE_Complex      beta,
385                           HYPRE_ParVector    y )
386 {
387    return ( hypre_ParCSRMatrixMatvec(
388                alpha, (hypre_ParCSRMatrix *) A,
389                (hypre_ParVector *) x, beta, (hypre_ParVector *) y) );
390 }
391 
392 /*--------------------------------------------------------------------------
393  * HYPRE_ParCSRMatrixMatvecT
394  *--------------------------------------------------------------------------*/
395 
396 HYPRE_Int
HYPRE_ParCSRMatrixMatvecT(HYPRE_Complex alpha,HYPRE_ParCSRMatrix A,HYPRE_ParVector x,HYPRE_Complex beta,HYPRE_ParVector y)397 HYPRE_ParCSRMatrixMatvecT( HYPRE_Complex      alpha,
398                            HYPRE_ParCSRMatrix A,
399                            HYPRE_ParVector    x,
400                            HYPRE_Complex      beta,
401                            HYPRE_ParVector    y )
402 {
403    return ( hypre_ParCSRMatrixMatvecT(
404                alpha, (hypre_ParCSRMatrix *) A,
405                (hypre_ParVector *) x, beta, (hypre_ParVector *) y) );
406 }
407