1
2
3
4
5
6
7
8
9
10
11
12 #include "HypreParVector.hpp"
13 #include "HypreParMatrix.hpp"
14
15 #ifdef MOAB_HAVE_MPI
16
17 #include "hypre_parcsr.hpp"
18
19 #include <fstream>
20 #include <iostream>
21 #include <cmath>
22 #include <cstdlib>
23 #include <cassert>
24
25 using namespace std;
26
27 #define MOAB_DEBUG
28
29 namespace moab
30 {
31 #define moab_hypre_assert( a, b ) \
32 { \
33 }
34 #define moab_hypre_assert_t( a, b ) \
35 { \
36 if( !a ) \
37 { \
38 std::cout << "HYPRE Error: " << b << std::endl; \
39 exit( -1 ); \
40 } \
41 }
42
43 template < typename TargetT, typename SourceT >
44 static TargetT* DuplicateAs( const SourceT* array, int size, bool cplusplus = true )
45 {
46 TargetT* target_array = cplusplus ? new TargetT[size]
47
48 : hypre_TAlloc( TargetT, size );
49
50 for( int i = 0; i < size; i++ )
51 {
52 target_array[i] = array[i];
53 }
54
55 return target_array;
56 }
57
58 void HypreParMatrix::Init()
59 {
60 A = NULL;
61 A_parcsr = NULL;
62 ParCSROwner = 1;
63 }
64
65 HypreParMatrix::HypreParMatrix( moab::ParallelComm* p_comm ) : pcomm( p_comm )
66 {
67 Init();
68 height = width = 0;
69 }
70
71
72 HypreParMatrix::HypreParMatrix( moab::ParallelComm* p_comm,
73 HYPRE_Int glob_size,
74 HYPRE_Int* row_starts,
75 HYPRE_Int nnz_pr )
76 : pcomm( p_comm )
77 {
78 Init();
79 resize( glob_size, row_starts, nnz_pr );
80 }
81
82 void HypreParMatrix::resize( HYPRE_Int glob_size,
83 HYPRE_Int* row_starts,
84 HYPRE_Int nnz_pr_diag,
85 HYPRE_Int nnz_pr_offdiag )
86 {
87
90 HYPRE_IJMatrixCreate( pcomm->comm(), row_starts[0], row_starts[1], row_starts[0], row_starts[1], &A );
91
92 HYPRE_IJMatrixSetObjectType( A, HYPRE_PARCSR );
93
94 int locsize = row_starts[1] - row_starts[0] + 1;
95 int num_procs, rank;
96 MPI_Comm_size( pcomm->comm(), &num_procs );
97 MPI_Comm_rank( pcomm->comm(), &rank );
98
99 if( nnz_pr_diag != 0 || nnz_pr_offdiag != 0 )
100 {
101 if( num_procs > 1 )
102 {
103 std::vector< HYPRE_Int > m_nnz_pr_diag( locsize, nnz_pr_diag );
104 std::vector< HYPRE_Int > m_onz_pr_diag( locsize, nnz_pr_offdiag );
105 HYPRE_IJMatrixSetDiagOffdSizes( A, &m_nnz_pr_diag[0], &m_onz_pr_diag[0] );
106 }
107 else
108 {
109 std::vector< HYPRE_Int > m_nnz_pr_diag( locsize, nnz_pr_diag );
110 HYPRE_IJMatrixSetRowSizes( A, &m_nnz_pr_diag[0] );
111 }
112 }
113
114
115 HYPRE_IJMatrixInitialize( A );
116
117 HYPRE_IJMatrixGetObject( A, (void**)&A_parcsr );
118
119
120 HYPRE_MatvecFunctions matvec_fn;
121 interpreter = hypre_CTAlloc( mv_InterfaceInterpreter, 1 );
122 HYPRE_ParCSRSetupInterpreter( interpreter );
123 HYPRE_ParCSRSetupMatvec( &matvec_fn );
124 gnrows = glob_size;
125 gncols = glob_size;
126 height = GetNumRows();
127 width = GetNumCols();
128 }
129
130 void HypreParMatrix::resize( HYPRE_Int global_num_rows,
131 HYPRE_Int global_num_cols,
132 HYPRE_Int* row_starts,
133 HYPRE_Int* col_starts,
134 HYPRE_Int* nnz_pr_diag,
135 HYPRE_Int* onz_pr_diag,
136 HYPRE_Int nnz_pr_offdiag )
137 {
138
141 HYPRE_IJMatrixCreate( pcomm->comm(), row_starts[0], row_starts[1], col_starts[0], col_starts[1], &A );
142
143 HYPRE_IJMatrixSetObjectType( A, HYPRE_PARCSR );
144
145 int num_procs;
146 MPI_Comm_size( pcomm->comm(), &num_procs );
147
148
149 if( num_procs > 1 )
150 {
151 if( nnz_pr_diag == NULL && onz_pr_diag == NULL )
152 {
153 std::cout << "Parameter nnz_pr_diag and onz_pr_diag cannot be NULL.\n";
154 moab_hypre_assert_t( nnz_pr_diag, true );
155 }
156
157 HYPRE_IJMatrixSetDiagOffdSizes( A, nnz_pr_diag, onz_pr_diag );
158 }
159 else
160 {
161 HYPRE_IJMatrixSetRowSizes( A, nnz_pr_diag );
162 }
163
164 if( nnz_pr_offdiag )
165 {
166 HYPRE_IJMatrixSetMaxOffProcElmts( A, nnz_pr_offdiag );
167 }
168
169
170 HYPRE_IJMatrixInitialize( A );
171
172 HYPRE_IJMatrixGetObject( A, (void**)&A_parcsr );
173
174
175 HYPRE_MatvecFunctions matvec_fn;
176 interpreter = hypre_CTAlloc( mv_InterfaceInterpreter, 1 );
177 HYPRE_ParCSRSetupInterpreter( interpreter );
178 HYPRE_ParCSRSetupMatvec( &matvec_fn );
179 gnrows = global_num_rows;
180 gncols = global_num_cols;
181 height = GetNumRows();
182 width = GetNumCols();
183 }
184
185
186 HypreParMatrix::HypreParMatrix( moab::ParallelComm* p_comm,
187 HYPRE_Int global_num_rows,
188 HYPRE_Int global_num_cols,
189 HYPRE_Int* row_starts,
190 HYPRE_Int* col_starts,
191 HYPRE_Int nnz_pr_diag,
192 HYPRE_Int onz_pr_diag,
193 HYPRE_Int nnz_pr_offdiag )
194 : pcomm( p_comm )
195 {
196 Init();
197 std::vector< HYPRE_Int > m_nnz_pr_diag( row_starts[1] - row_starts[0], nnz_pr_diag );
198 std::vector< HYPRE_Int > m_onz_pr_diag( row_starts[1] - row_starts[0], onz_pr_diag );
199 resize( global_num_rows, global_num_cols, row_starts, col_starts, &m_nnz_pr_diag[0], &m_onz_pr_diag[0],
200 nnz_pr_offdiag );
201 }
202
203 void HypreParMatrix::MakeRef( const HypreParMatrix& master )
204 {
205 Destroy();
206 Init();
207 A = master.A;
208 A_parcsr = master.A_parcsr;
209 ParCSROwner = 0;
210 height = master.GetNumRows();
211 width = master.GetNumCols();
212 }
213
214 HYPRE_IJMatrix HypreParMatrix::StealData()
215 {
216
217
218
219 moab_hypre_assert( diagOwner == -1 && offdOwner == -1 && colMapOwner == -1, "" );
220 moab_hypre_assert( ParCSROwner, "" );
221 HYPRE_IJMatrix R = A;
222 A = NULL;
223 ParCSROwner = 0;
224 Destroy();
225 Init();
226 return R;
227 }
228
229 void HypreParMatrix::StealData( HypreParMatrix& X )
230 {
231
232
233
234 moab_hypre_assert( diagOwner == -1 && offdOwner == -1 && colMapOwner == -1, "" );
235 moab_hypre_assert( ParCSROwner, "" );
236 moab_hypre_assert( X.diagOwner == -1 && X.offdOwner == -1 && X.colMapOwner == -1, "" );
237 moab_hypre_assert( X.ParCSROwner, "" );
238 A = X.A;
239 A_parcsr = X.A_parcsr;
240 ParCSROwner = 1;
241 X.A = NULL;
242 X.A_parcsr = NULL;
243 X.ParCSROwner = 0;
244 X.Destroy();
245 X.Init();
246 }
247
248 void HypreParMatrix::GetDiag( Eigen::VectorXd& diag ) const
249 {
250 int size = this->height;
251 diag.resize( size );
252
253 for( int j = 0; j < size; j++ )
254 {
255 diag( j ) = A_parcsr->diag->data[A_parcsr->diag->i[j]];
256 moab_hypre_assert( A_parcsr->diag->j[A_parcsr->diag->i[j]] == j,
257 "the first entry in each row must be the diagonal one" );
258 }
259 }
260
261 static void MakeWrapper( const hypre_CSRMatrix* mat, Eigen::SparseMatrix< double, Eigen::RowMajor >& wrapper )
262 {
263 HYPRE_Int nr = hypre_CSRMatrixNumRows( mat );
264 HYPRE_Int nc = hypre_CSRMatrixNumCols( mat );
265 Eigen::SparseMatrix< double, Eigen::RowMajor > tmp( nr, nc );
266 typedef Eigen::Triplet< double > T;
267 HYPRE_Int nnz = hypre_CSRMatrixNumNonzeros( mat );
268 int *rindx, *cindx;
269 double* dindx;
270 #ifndef HYPRE_BIGINT
271 rindx = hypre_CSRMatrixI( mat );
272 cindx = hypre_CSRMatrixJ( mat );
273 dindx = hypre_CSRMatrixData( mat );
274 #else
275 rindx = DuplicateAs< int >( hypre_CSRMatrixI( mat ), nr + 1 );
276 cindx = DuplicateAs< int >( hypre_CSRMatrixJ( mat ), nnz );
277 dindx = hypre_CSRMatrixData( mat );
278 #endif
279 std::vector< T > tripletList( nnz );
280
281 for( int i = 0; i < nnz; ++i )
282 {
283 tripletList.push_back( T( rindx[i], cindx[i], dindx[i] ) );
284 }
285
286 tmp.setFromTriplets( tripletList.begin(), tripletList.end() );
287 wrapper.swap( tmp );
288 }
289
290 void HypreParMatrix::GetDiag( Eigen::SparseMatrix< double, Eigen::RowMajor >& diag ) const
291 {
292 MakeWrapper( A_parcsr->diag, diag );
293 }
294
295 void HypreParMatrix::GetOffd( Eigen::SparseMatrix< double, Eigen::RowMajor >& offd, HYPRE_Int*& cmap ) const
296 {
297 MakeWrapper( A_parcsr->offd, offd );
298 cmap = A_parcsr->col_map_offd;
299 }
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335 HYPRE_Int HypreParMatrix::Mult( HypreParVector& x, HypreParVector& y, double a, double b )
336 {
337 return hypre_ParCSRMatrixMatvec( a, A_parcsr, x.x_par, b, y.x_par );
338 }
339
340 void HypreParMatrix::Mult( double a, const HypreParVector& x, double b, HypreParVector& y ) const
341 {
342 hypre_ParCSRMatrixMatvec( a, A_parcsr, x.x_par, b, y.x_par );
343 }
344
345 void HypreParMatrix::MultTranspose( double a, const HypreParVector& x, double b, HypreParVector& y ) const
346 {
347 hypre_ParCSRMatrixMatvecT( a, A_parcsr, y.x_par, b, x.x_par );
348 }
349
350 HYPRE_Int HypreParMatrix::Mult( HYPRE_ParVector x, HYPRE_ParVector y, double a, double b )
351 {
352 return hypre_ParCSRMatrixMatvec( a, A_parcsr, (hypre_ParVector*)x, b, (hypre_ParVector*)y );
353 }
354
355 HYPRE_Int HypreParMatrix::MultTranspose( HypreParVector& x, HypreParVector& y, double a, double b )
356 {
357 return hypre_ParCSRMatrixMatvecT( a, A_parcsr, x.x_par, b, y.x_par );
358 }
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438 void HypreParMatrix::ScaleRows( const Eigen::VectorXd& diag )
439 {
440 if( hypre_CSRMatrixNumRows( A_parcsr->diag ) != hypre_CSRMatrixNumRows( A_parcsr->offd ) )
441 {
442 MB_SET_ERR_RET( "Row does not match" );
443 }
444
445 if( hypre_CSRMatrixNumRows( A_parcsr->diag ) != diag.size() )
446 {
447 MB_SET_ERR_RET( "Note the Eigen::VectorXd diag is not of compatible dimensions with A\n" );
448 }
449
450 int size = this->height;
451 double* Adiag_data = hypre_CSRMatrixData( A_parcsr->diag );
452 HYPRE_Int* Adiag_i = hypre_CSRMatrixI( A_parcsr->diag );
453 double* Aoffd_data = hypre_CSRMatrixData( A_parcsr->offd );
454 HYPRE_Int* Aoffd_i = hypre_CSRMatrixI( A_parcsr->offd );
455 double val;
456 HYPRE_Int jj;
457
458 for( int i( 0 ); i < size; ++i )
459 {
460 val = diag[i];
461
462 for( jj = Adiag_i[i]; jj < Adiag_i[i + 1]; ++jj )
463 {
464 Adiag_data[jj] *= val;
465 }
466
467 for( jj = Aoffd_i[i]; jj < Aoffd_i[i + 1]; ++jj )
468 {
469 Aoffd_data[jj] *= val;
470 }
471 }
472 }
473
474 void HypreParMatrix::InvScaleRows( const Eigen::VectorXd& diag )
475 {
476 if( hypre_CSRMatrixNumRows( A_parcsr->diag ) != hypre_CSRMatrixNumRows( A_parcsr->offd ) )
477 {
478 MB_SET_ERR_RET( "Row does not match" );
479 }
480
481 if( hypre_CSRMatrixNumRows( A_parcsr->diag ) != diag.size() )
482 {
483 MB_SET_ERR_RET( "Note the Eigen::VectorXd diag is not of compatible dimensions with A_parcsr\n" );
484 }
485
486 int size = this->height;
487 double* Adiag_data = hypre_CSRMatrixData( A_parcsr->diag );
488 HYPRE_Int* Adiag_i = hypre_CSRMatrixI( A_parcsr->diag );
489 double* Aoffd_data = hypre_CSRMatrixData( A_parcsr->offd );
490 HYPRE_Int* Aoffd_i = hypre_CSRMatrixI( A_parcsr->offd );
491 double val;
492 HYPRE_Int jj;
493
494 for( int i( 0 ); i < size; ++i )
495 {
496 #ifdef MOAB_DEBUG
497
498 if( 0.0 == diag( i ) )
499 {
500 MB_SET_ERR_RET( "HypreParMatrix::InvDiagScale : Division by 0" );
501 }
502
503 #endif
504 val = 1. / diag( i );
505
506 for( jj = Adiag_i[i]; jj < Adiag_i[i + 1]; ++jj )
507 {
508 Adiag_data[jj] *= val;
509 }
510
511 for( jj = Aoffd_i[i]; jj < Aoffd_i[i + 1]; ++jj )
512 {
513 Aoffd_data[jj] *= val;
514 }
515 }
516 }
517
518 void HypreParMatrix::operator*=( double s )
519 {
520 if( hypre_CSRMatrixNumRows( A_parcsr->diag ) != hypre_CSRMatrixNumRows( A_parcsr->offd ) )
521 {
522 MB_SET_ERR_RET( "Row does not match" );
523 }
524
525 HYPRE_Int size = hypre_CSRMatrixNumRows( A_parcsr->diag );
526 HYPRE_Int jj;
527 double* Adiag_data = hypre_CSRMatrixData( A_parcsr->diag );
528 HYPRE_Int* Adiag_i = hypre_CSRMatrixI( A_parcsr->diag );
529
530 for( jj = 0; jj < Adiag_i[size]; ++jj )
531 {
532 Adiag_data[jj] *= s;
533 }
534
535 double* Aoffd_data = hypre_CSRMatrixData( A_parcsr->offd );
536 HYPRE_Int* Aoffd_i = hypre_CSRMatrixI( A_parcsr->offd );
537
538 for( jj = 0; jj < Aoffd_i[size]; ++jj )
539 {
540 Aoffd_data[jj] *= s;
541 }
542 }
543
544 HYPRE_Int HypreParMatrix::GetValues( const HYPRE_Int nrows,
545 HYPRE_Int* ncols,
546 HYPRE_Int* rows,
547 HYPRE_Int* cols,
548 HYPRE_Complex* values )
549 {
550 return HYPRE_IJMatrixGetValues( A, nrows, ncols, rows, cols, values );
551 }
552
553 HYPRE_Int HypreParMatrix::SetValues( const HYPRE_Int nrows,
554 HYPRE_Int* ncols,
555 const HYPRE_Int* rows,
556 const HYPRE_Int* cols,
557 const HYPRE_Complex* values )
558 {
559 return HYPRE_IJMatrixSetValues( A, nrows, ncols, rows, cols, values );
560 }
561
562 HYPRE_Int HypreParMatrix::AddToValues( const HYPRE_Int nrows,
563 HYPRE_Int* ncols,
564 const HYPRE_Int* rows,
565 const HYPRE_Int* cols,
566 const HYPRE_Complex* values )
567 {
568 return HYPRE_IJMatrixAddToValues( A, nrows, ncols, rows, cols, values );
569 }
570
571 HYPRE_Int HypreParMatrix::verbosity( const HYPRE_Int level )
572 {
573 return HYPRE_IJMatrixSetPrintLevel( A, level );
574 }
575
576 HYPRE_Int HypreParMatrix::FinalizeAssembly()
577 {
578 return HYPRE_IJMatrixAssemble( A );
579 }
580
581 static void get_sorted_rows_cols( const std::vector< HYPRE_Int >& rows_cols, std::vector< HYPRE_Int >& hypre_sorted )
582 {
583 hypre_sorted.resize( rows_cols.size() );
584 std::copy( rows_cols.begin(), rows_cols.end(), hypre_sorted.begin() );
585 std::sort( hypre_sorted.begin(), hypre_sorted.end() );
586 }
587
588 void HypreParMatrix::Threshold( double threshold )
589 {
590 int ierr = 0;
591 int num_procs;
592 hypre_CSRMatrix* csr_A;
593 hypre_CSRMatrix* csr_A_wo_z;
594 hypre_ParCSRMatrix* parcsr_A_ptr;
595 int* row_starts = NULL;
596 int* col_starts = NULL;
597 int row_start = -1;
598 int row_end = -1;
599 int col_start = -1;
600 int col_end = -1;
601 MPI_Comm_size( pcomm->comm(), &num_procs );
602 ierr += hypre_ParCSRMatrixGetLocalRange( A_parcsr, &row_start, &row_end, &col_start, &col_end );
603 row_starts = hypre_ParCSRMatrixRowStarts( A_parcsr );
604 col_starts = hypre_ParCSRMatrixColStarts( A_parcsr );
605 parcsr_A_ptr = hypre_ParCSRMatrixCreate( pcomm->comm(), row_starts[num_procs], col_starts[num_procs], row_starts,
606 col_starts, 0, 0, 0 );
607 csr_A = hypre_MergeDiagAndOffd( A_parcsr );
608 csr_A_wo_z = hypre_CSRMatrixDeleteZeros( csr_A, threshold );
609
610
612 if( csr_A_wo_z == NULL )
613 {
614 csr_A_wo_z = csr_A;
615 }
616 else
617 {
618 ierr += hypre_CSRMatrixDestroy( csr_A );
619 }
620
621 ierr += GenerateDiagAndOffd( csr_A_wo_z, parcsr_A_ptr, col_start, col_end );
622 ierr += hypre_CSRMatrixDestroy( csr_A_wo_z );
623 ierr += hypre_ParCSRMatrixDestroy( A_parcsr );
624 hypre_IJMatrixObject( A ) = parcsr_A_ptr;
625
626 HYPRE_IJMatrixGetObject( A, (void**)A_parcsr );
627 }
628
629 void HypreParMatrix::EliminateRowsCols( const std::vector< HYPRE_Int >& rows_cols,
630 const HypreParVector& X,
631 HypreParVector& B )
632 {
633 std::vector< HYPRE_Int > rc_sorted;
634 get_sorted_rows_cols( rows_cols, rc_sorted );
635 internal::hypre_ParCSRMatrixEliminateAXB( A_parcsr, rc_sorted.size(), rc_sorted.data(), X.x_par, B.x_par );
636 }
637
638 HypreParMatrix* HypreParMatrix::EliminateRowsCols( const std::vector< HYPRE_Int >& rows_cols )
639 {
640 std::vector< HYPRE_Int > rc_sorted;
641 get_sorted_rows_cols( rows_cols, rc_sorted );
642 hypre_ParCSRMatrix* Ae;
643 internal::hypre_ParCSRMatrixEliminateAAe( A_parcsr, &Ae, rc_sorted.size(), rc_sorted.data() );
644 HypreParMatrix* tmpMat = new HypreParMatrix( pcomm, M(), N(), RowPart(), ColPart(), 0, 0 );
645 hypre_IJMatrixObject( tmpMat->A ) = Ae;
646
647 HYPRE_IJMatrixGetObject( tmpMat->A, (void**)tmpMat->A_parcsr );
648 return tmpMat;
649 }
650
651 void HypreParMatrix::Print( const char* fname, HYPRE_Int offi, HYPRE_Int offj )
652 {
653 hypre_ParCSRMatrixPrintIJ( A_parcsr, offi, offj, fname );
654 }
655
656 void HypreParMatrix::Read( const char* fname )
657 {
658 Destroy();
659 Init();
660 HYPRE_Int base_i, base_j;
661 hypre_ParCSRMatrixReadIJ( pcomm->comm(), fname, &base_i, &base_j, &A_parcsr );
662 hypre_ParCSRMatrixSetNumNonzeros( A_parcsr );
663 hypre_MatvecCommPkgCreate( A_parcsr );
664 height = GetNumRows();
665 width = GetNumCols();
666 }
667
668 void HypreParMatrix::Destroy()
669 {
670 if( interpreter )
671 {
672 hypre_TFree( interpreter );
673 }
674
675 if( A == NULL )
676 {
677 return;
678 }
679
680 else
681 {
682 HYPRE_IJMatrixDestroy( A );
683 }
684 }
685
686 HypreParMatrix* ParMult( HypreParMatrix* A, HypreParMatrix* B )
687 {
688 hypre_ParCSRMatrix* ab;
689 ab = hypre_ParMatmul( A->A_parcsr, B->A_parcsr );
690 hypre_MatvecCommPkgCreate( ab );
691 HypreParMatrix* tmpMat = new HypreParMatrix( A->pcomm, A->M(), A->N(), A->RowPart(), A->ColPart(), 0, 0 );
692 hypre_IJMatrixObject( tmpMat->A ) = ab;
693
694 HYPRE_IJMatrixGetObject( tmpMat->A, (void**)tmpMat->A_parcsr );
695 return tmpMat;
696 }
697
698 HypreParMatrix* RAP( HypreParMatrix* A, HypreParMatrix* P )
699 {
700 HYPRE_Int P_owns_its_col_starts = hypre_ParCSRMatrixOwnsColStarts( (hypre_ParCSRMatrix*)( P->A_parcsr ) );
701 hypre_ParCSRMatrix* rap;
702 hypre_BoomerAMGBuildCoarseOperator( P->A_parcsr, A->A_parcsr, P->A_parcsr, &rap );
703 hypre_ParCSRMatrixSetNumNonzeros( rap );
704
705
707 hypre_ParCSRMatrixSetRowStartsOwner( rap, 0 );
708 hypre_ParCSRMatrixSetColStartsOwner( rap, 0 );
709
710 if( P_owns_its_col_starts )
711 {
712 hypre_ParCSRMatrixSetColStartsOwner( P->A_parcsr, 1 );
713 }
714
715 HypreParMatrix* tmpMat = new HypreParMatrix( A->pcomm, A->M(), A->N(), A->RowPart(), A->ColPart(), 0, 0 );
716 hypre_IJMatrixObject( tmpMat->A ) = rap;
717
718 HYPRE_IJMatrixGetObject( tmpMat->A, (void**)tmpMat->A_parcsr );
719 return tmpMat;
720 }
721
722 HypreParMatrix* RAP( HypreParMatrix* Rt, HypreParMatrix* A, HypreParMatrix* P )
723 {
724 HYPRE_Int P_owns_its_col_starts = hypre_ParCSRMatrixOwnsColStarts( (hypre_ParCSRMatrix*)( P->A_parcsr ) );
725 HYPRE_Int Rt_owns_its_col_starts = hypre_ParCSRMatrixOwnsColStarts( (hypre_ParCSRMatrix*)( Rt->A_parcsr ) );
726 hypre_ParCSRMatrix* rap;
727 hypre_BoomerAMGBuildCoarseOperator( Rt->A_parcsr, A->A_parcsr, P->A_parcsr, &rap );
728 hypre_ParCSRMatrixSetNumNonzeros( rap );
729
730
731 if( !P_owns_its_col_starts )
732 {
733
735 hypre_ParCSRMatrixSetColStartsOwner( rap, 0 );
736 }
737
738 if( !Rt_owns_its_col_starts )
739 {
740
742 hypre_ParCSRMatrixSetRowStartsOwner( rap, 0 );
743 }
744
745 HypreParMatrix* tmpMat = new HypreParMatrix( A->pcomm, A->M(), A->N(), A->RowPart(), A->ColPart(), 0, 0 );
746 hypre_IJMatrixObject( tmpMat->A ) = rap;
747
748 HYPRE_IJMatrixGetObject( tmpMat->A, (void**)tmpMat->A_parcsr );
749 return tmpMat;
750 }
751
752 void EliminateBC( HypreParMatrix& A,
753 HypreParMatrix& Ae,
754 const std::vector< int >& ess_dof_list,
755 const HypreParVector& X,
756 HypreParVector& B )
757 {
758
759 Ae.Mult( -1.0, X, 1.0, B );
760 hypre_CSRMatrix* A_diag = hypre_ParCSRMatrixDiag( (hypre_ParCSRMatrix*)A.A_parcsr );
761 double* data = hypre_CSRMatrixData( A_diag );
762 HYPRE_Int* I = hypre_CSRMatrixI( A_diag );
763 #ifdef MOAB_DEBUG
764 HYPRE_Int* J = hypre_CSRMatrixJ( A_diag );
765 hypre_CSRMatrix* A_offd = hypre_ParCSRMatrixOffd( (hypre_ParCSRMatrix*)A.A_parcsr );
766 HYPRE_Int* I_offd = hypre_CSRMatrixI( A_offd );
767 double* data_offd = hypre_CSRMatrixData( A_offd );
768 #endif
769 std::vector< HYPRE_Complex > bdata( ess_dof_list.size() ), xdata( ess_dof_list.size() );
770 B.GetValues( ess_dof_list.size(), ess_dof_list.data(), bdata.data() );
771 X.GetValues( ess_dof_list.size(), ess_dof_list.data(), xdata.data() );
772
773 for( size_t i = 0; i < ess_dof_list.size(); i++ )
774 {
775 int r = ess_dof_list[i];
776 bdata[r] = data[I[r]] * xdata[r];
777 #ifdef MOAB_DEBUG
778
779
780
781
782 if( J[I[r]] != r )
783 {
784 MB_SET_ERR_RET( "the diagonal entry must be the first entry in the row!" );
785 }
786
787 for( int j = I[r] + 1; j < I[r + 1]; j++ )
788 {
789 if( data[j] != 0.0 )
790 {
791 MB_SET_ERR_RET( "all off-diagonal entries must be zero!" );
792 }
793 }
794
795 for( int j = I_offd[r]; j < I_offd[r + 1]; j++ )
796 {
797 if( data_offd[j] != 0.0 )
798 {
799 MB_SET_ERR_RET( "all off-diagonal entries must be zero!" );
800 }
801 }
802
803 #endif
804 }
805 }
806
807
808
809
810 int ParCSRRelax_Taubin( hypre_ParCSRMatrix* A,
811 hypre_ParVector* f,
812 double lambda,
813 double mu,
814 int N,
815 double max_eig,
816 hypre_ParVector* u,
817 hypre_ParVector* r
818 )
819 {
820 hypre_CSRMatrix* A_diag = hypre_ParCSRMatrixDiag( A );
821 HYPRE_Int num_rows = hypre_CSRMatrixNumRows( A_diag );
822 double* u_data = hypre_VectorData( hypre_ParVectorLocalVector( u ) );
823 double* r_data = hypre_VectorData( hypre_ParVectorLocalVector( r ) );
824
825 for( int i = 0; i < N; i++ )
826 {
827
828 hypre_ParVectorCopy( f, r );
829 hypre_ParCSRMatrixMatvec( -1.0, A, u, 1.0, r );
830 double coef;
831 ( 0 == ( i % 2 ) ) ? coef = lambda : coef = mu;
832
833 for( HYPRE_Int j = 0; j < num_rows; j++ )
834 {
835 u_data[j] += coef * r_data[j] / max_eig;
836 }
837 }
838
839 return 0;
840 }
841
842
843
844
845 int ParCSRRelax_FIR( hypre_ParCSRMatrix* A,
846 hypre_ParVector* f,
847 double max_eig,
848 int poly_order,
849 double* fir_coeffs,
850 hypre_ParVector* u,
851 hypre_ParVector* x0,
852 hypre_ParVector* x1,
853 hypre_ParVector* x2,
854 hypre_ParVector* x3 )
855
856 {
857 hypre_CSRMatrix* A_diag = hypre_ParCSRMatrixDiag( A );
858 HYPRE_Int num_rows = hypre_CSRMatrixNumRows( A_diag );
859 double* u_data = hypre_VectorData( hypre_ParVectorLocalVector( u ) );
860 double* x0_data = hypre_VectorData( hypre_ParVectorLocalVector( x0 ) );
861 double* x1_data = hypre_VectorData( hypre_ParVectorLocalVector( x1 ) );
862 double* x2_data = hypre_VectorData( hypre_ParVectorLocalVector( x2 ) );
863 double* x3_data = hypre_VectorData( hypre_ParVectorLocalVector( x3 ) );
864 hypre_ParVectorCopy( u, x0 );
865
866 hypre_ParVectorCopy( f, x1 );
867 hypre_ParCSRMatrixMatvec( -1.0, A, x0, 1.0, x1 );
868
869 for( HYPRE_Int i = 0; i < num_rows; i++ )
870 {
871 x1_data[i] /= -max_eig;
872 }
873
874
875 for( HYPRE_Int i = 0; i < num_rows; i++ )
876 {
877 x1_data[i] = x0_data[i] - x1_data[i];
878 }
879
880
881 for( HYPRE_Int i = 0; i < num_rows; i++ )
882 {
883 x3_data[i] = fir_coeffs[0] * x0_data[i] + fir_coeffs[1] * x1_data[i];
884 }
885
886 for( int n = 2; n <= poly_order; n++ )
887 {
888
889 hypre_ParVectorCopy( f, x2 );
890 hypre_ParCSRMatrixMatvec( -1.0, A, x1, 1.0, x2 );
891
892 for( HYPRE_Int i = 0; i < num_rows; i++ )
893 {
894 x2_data[i] /= -max_eig;
895 }
896
897
898
899
900
901
902 for( HYPRE_Int i = 0; i < num_rows; i++ )
903 {
904 x2_data[i] = ( x1_data[i] - x0_data[i] ) + ( x1_data[i] - 2 * x2_data[i] );
905 x3_data[i] += fir_coeffs[n] * x2_data[i];
906 x0_data[i] = x1_data[i];
907 x1_data[i] = x2_data[i];
908 }
909 }
910
911 for( HYPRE_Int i = 0; i < num_rows; i++ )
912 {
913 u_data[i] = x3_data[i];
914 }
915
916 return 0;
917 }
918
919 }
920
921 #endif