19 #if MFEM_HYPRE_VERSION < 21400
21 #define mfem_hypre_TAlloc(type, size) hypre_TAlloc(type, size)
22 #define mfem_hypre_CTAlloc(type, size) hypre_CTAlloc(type, size)
23 #define mfem_hypre_TFree(ptr) hypre_TFree(ptr)
25 #else // MFEM_HYPRE_VERSION >= 21400
28 #define mfem_hypre_TAlloc(type, size) \
29 hypre_TAlloc(type, size, HYPRE_MEMORY_HOST)
30 #define mfem_hypre_CTAlloc(type, size) \
31 hypre_CTAlloc(type, size, HYPRE_MEMORY_HOST)
32 #define mfem_hypre_TFree(ptr) hypre_TFree(ptr, HYPRE_MEMORY_HOST)
34 #endif // #if MFEM_HYPRE_VERSION < 21400
40 bool ownReal,
bool ownImag,
42 :
Operator(2*((Op_Real)?Op_Real->Height():Op_Imag->Height()),
43 2*((Op_Real)?Op_Real->Width():Op_Imag->Width()))
48 , convention_(convention)
49 , x_r_(NULL, width / 2)
50 , x_i_(NULL, width / 2)
51 , y_r_(NULL, height / 2)
52 , y_i_(NULL, height / 2)
67 MFEM_ASSERT(
Op_Real_,
"ComplexOperator has no real part!");
73 MFEM_ASSERT(
Op_Imag_,
"ComplexOperator has no imaginary part!");
79 MFEM_ASSERT(
Op_Real_,
"ComplexOperator has no real part!");
85 MFEM_ASSERT(
Op_Imag_,
"ComplexOperator has no imaginary part!");
172 MFEM_ASSERT(
Op_Real_,
"ComplexSparseMatrix has no real part!");
178 MFEM_ASSERT(
Op_Imag_,
"ComplexSparseMatrix has no imaginary part!");
184 MFEM_ASSERT(
Op_Real_,
"ComplexSparseMatrix has no real part!");
190 MFEM_ASSERT(
Op_Imag_,
"ComplexSparseMatrix has no imaginary part!");
199 const int nrows_r = (A_r)?A_r->
Height():0;
200 const int nrows_i = (A_i)?A_i->
Height():0;
201 const int nrows = std::max(nrows_r, nrows_i);
203 const int *I_r = (A_r)?A_r->
GetI():NULL;
204 const int *I_i = (A_i)?A_i->
GetI():NULL;
206 const int *J_r = (A_r)?A_r->
GetJ():NULL;
207 const int *J_i = (A_i)?A_i->
GetJ():NULL;
209 const double *D_r = (A_r)?A_r->
GetData():NULL;
210 const double *D_i = (A_i)?A_i->
GetData():NULL;
212 const int nnz_r = (I_r)?I_r[nrows]:0;
213 const int nnz_i = (I_i)?I_i[nrows]:0;
214 const int nnz = 2 * (nnz_r + nnz_i);
223 I[nrows] = nnz_r + nnz_i;
224 for (
int i=0; i<nrows; i++)
226 I[i + 1] = ((I_r)?I_r[i+1]:0) + ((I_i)?I_i[i+1]:0);
227 I[i + nrows + 1] = I[i+1] + nnz_r + nnz_i;
231 const int off_i = (I_i)?(I_i[i+1] - I_i[i]):0;
232 for (
int j=0; j<I_r[i+1] - I_r[i]; j++)
234 J[I[i] + j] = J_r[I_r[i] + j];
235 D[I[i] + j] = D_r[I_r[i] + j];
237 J[I[i+nrows] + off_i + j] = J_r[I_r[i] + j] + nrows;
238 D[I[i+nrows] + off_i + j] = factor*D_r[I_r[i] + j];
243 const int off_r = (I_r)?(I_r[i+1] - I_r[i]):0;
244 for (
int j=0; j<I_i[i+1] - I_i[i]; j++)
246 J[I[i] + off_r + j] = J_i[I_i[i] + j] + nrows;
247 D[I[i] + off_r + j] = -D_i[I_i[i] + j];
249 J[I[i+nrows] + j] = J_i[I_i[i] + j];
250 D[I[i+nrows] + j] = factor*D_i[I_i[i] + j];
262 bool ownReal,
bool ownImag,
266 comm_ = (A_Real) ? A_Real->
GetComm() :
267 ((A_Imag) ? A_Imag->
GetComm() : MPI_COMM_WORLD);
269 MPI_Comm_rank(comm_, &myid_);
270 MPI_Comm_size(comm_, &nranks_);
275 MFEM_ASSERT(
Op_Real_,
"ComplexHypreParMatrix has no real part!");
281 MFEM_ASSERT(
Op_Imag_,
"ComplexHypreParMatrix has no imaginary part!");
287 MFEM_ASSERT(
Op_Real_,
"ComplexHypreParMatrix has no real part!");
293 MFEM_ASSERT(
Op_Imag_,
"ComplexHypreParMatrix has no imaginary part!");
302 if ( A_r == NULL && A_i == NULL ) {
return NULL; }
306 HYPRE_Int global_num_rows = std::max(global_num_rows_r, global_num_rows_i);
310 HYPRE_Int global_num_cols = std::max(global_num_cols_r, global_num_cols_i);
312 int row_starts_size = (HYPRE_AssumedPartitionCheck()) ? 2 : nranks_ + 1;
313 HYPRE_Int * row_starts = mfem_hypre_CTAlloc(HYPRE_Int, row_starts_size);
314 HYPRE_Int * col_starts = mfem_hypre_CTAlloc(HYPRE_Int, row_starts_size);
316 const HYPRE_Int * row_starts_z = (A_r) ? A_r->
RowPart() :
317 ((A_i) ? A_i->
RowPart() : NULL);
318 const HYPRE_Int * col_starts_z = (A_r) ? A_r->
ColPart() :
319 ((A_i) ? A_i->
ColPart() : NULL);
321 for (
int i = 0; i < row_starts_size; i++)
323 row_starts[i] = 2 * row_starts_z[i];
324 col_starts[i] = 2 * col_starts_z[i];
328 HYPRE_Int * cmap_r, * cmap_i;
330 int nrows_r = 0, nrows_i = 0, ncols_r = 0, ncols_i = 0;
331 int ncols_offd_r = 0, ncols_offd_i = 0;
336 nrows_r = diag_r.
Height();
337 ncols_r = diag_r.
Width();
338 ncols_offd_r = offd_r.
Width();
344 nrows_i = diag_i.
Height();
345 ncols_i = diag_i.
Width();
346 ncols_offd_i = offd_i.
Width();
348 int nrows = std::max(nrows_r, nrows_i);
349 int ncols = std::max(ncols_r, ncols_i);
353 for (
int i=0; i<ncols_offd_r; i++)
355 cset.insert(cmap_r[i]);
357 for (
int i=0; i<ncols_offd_i; i++)
359 cset.insert(cmap_i[i]);
361 int num_cols_offd = (int)cset.size();
364 const int * diag_r_I = (A_r) ? diag_r.
GetI() : NULL;
365 const int * diag_i_I = (A_i) ? diag_i.
GetI() : NULL;
367 const int * diag_r_J = (A_r) ? diag_r.
GetJ() : NULL;
368 const int * diag_i_J = (A_i) ? diag_i.
GetJ() : NULL;
370 const double * diag_r_D = (A_r) ? diag_r.
GetData() : NULL;
371 const double * diag_i_D = (A_i) ? diag_i.
GetData() : NULL;
373 int diag_r_nnz = (diag_r_I) ? diag_r_I[nrows] : 0;
374 int diag_i_nnz = (diag_i_I) ? diag_i_I[nrows] : 0;
375 int diag_nnz = 2 * (diag_r_nnz + diag_i_nnz);
378 const int * offd_r_I = (A_r) ? offd_r.
GetI() : NULL;
379 const int * offd_i_I = (A_i) ? offd_i.
GetI() : NULL;
381 const int * offd_r_J = (A_r) ? offd_r.
GetJ() : NULL;
382 const int * offd_i_J = (A_i) ? offd_i.
GetJ() : NULL;
384 const double * offd_r_D = (A_r) ? offd_r.
GetData() : NULL;
385 const double * offd_i_D = (A_i) ? offd_i.
GetData() : NULL;
387 int offd_r_nnz = (offd_r_I) ? offd_r_I[nrows] : 0;
388 int offd_i_nnz = (offd_i_I) ? offd_i_I[nrows] : 0;
389 int offd_nnz = 2 * (offd_r_nnz + offd_i_nnz);
392 HYPRE_Int * diag_I = mfem_hypre_CTAlloc(HYPRE_Int, 2 * nrows + 1);
393 HYPRE_Int * diag_J = mfem_hypre_CTAlloc(HYPRE_Int, diag_nnz);
394 double * diag_D = mfem_hypre_CTAlloc(
double, diag_nnz);
396 HYPRE_Int * offd_I = mfem_hypre_CTAlloc(HYPRE_Int, 2 * nrows + 1);
397 HYPRE_Int * offd_J = mfem_hypre_CTAlloc(HYPRE_Int, offd_nnz);
398 double * offd_D = mfem_hypre_CTAlloc(
double, offd_nnz);
399 HYPRE_Int * cmap = mfem_hypre_CTAlloc(HYPRE_Int, 2 * num_cols_offd);
405 diag_I[nrows] = diag_r_nnz + diag_i_nnz;
406 for (
int i=0; i<nrows; i++)
408 diag_I[i + 1] = ((diag_r_I)?diag_r_I[i+1]:0) +
409 ((diag_i_I)?diag_i_I[i+1]:0);
410 diag_I[i + nrows + 1] = diag_I[i+1] + diag_r_nnz + diag_i_nnz;
414 for (
int j=0; j<diag_r_I[i+1] - diag_r_I[i]; j++)
416 diag_J[diag_I[i] + j] = diag_r_J[diag_r_I[i] + j];
417 diag_D[diag_I[i] + j] = diag_r_D[diag_r_I[i] + j];
419 diag_J[diag_I[i+nrows] + j] =
420 diag_r_J[diag_r_I[i] + j] + ncols;
421 diag_D[diag_I[i+nrows] + j] =
422 factor * diag_r_D[diag_r_I[i] + j];
427 const int off_r = (diag_r_I)?(diag_r_I[i+1] - diag_r_I[i]):0;
428 for (
int j=0; j<diag_i_I[i+1] - diag_i_I[i]; j++)
430 diag_J[diag_I[i] + off_r + j] = diag_i_J[diag_i_I[i] + j] + ncols;
431 diag_D[diag_I[i] + off_r + j] = -diag_i_D[diag_i_I[i] + j];
433 diag_J[diag_I[i+nrows] + off_r + j] = diag_i_J[diag_i_I[i] + j];
434 diag_D[diag_I[i+nrows] + off_r + j] =
435 factor * diag_i_D[diag_i_I[i] + j];
441 int num_recv_procs = 0;
442 HYPRE_Int * offd_col_start_stop = NULL;
443 this->getColStartStop(A_r, A_i, num_recv_procs, offd_col_start_stop);
445 std::set<int>::iterator sit;
446 std::map<int,int> cmapa, cmapb, cinvmap;
447 for (sit=cset.begin(); sit!=cset.end(); sit++)
452 for (
int i=0; i<num_recv_procs; i++)
454 if (offd_col_start_stop[2*i] <= col_orig &&
455 col_orig < offd_col_start_stop[2*i+1])
457 col_2x2 = offd_col_start_stop[2*i] + col_orig;
458 col_size = offd_col_start_stop[2*i+1] - offd_col_start_stop[2*i];
462 cmapa[*sit] = col_2x2;
463 cmapb[*sit] = col_2x2 + col_size;
464 cinvmap[col_2x2] = -1;
465 cinvmap[col_2x2 + col_size] = -1;
467 delete [] offd_col_start_stop;
469 std::map<int, int>::iterator mit;
471 for (mit=cinvmap.begin(); mit!=cinvmap.end(); mit++, i++)
474 cmap[i] = mit->first;
479 offd_I[nrows] = offd_r_nnz + offd_i_nnz;
480 for (
int i=0; i<nrows; i++)
482 offd_I[i + 1] = ((offd_r_I)?offd_r_I[i+1]:0) +
483 ((offd_i_I)?offd_i_I[i+1]:0);
484 offd_I[i + nrows + 1] = offd_I[i+1] + offd_r_nnz + offd_i_nnz;
488 const int off_i = (offd_i_I)?(offd_i_I[i+1] - offd_i_I[i]):0;
489 for (
int j=0; j<offd_r_I[i+1] - offd_r_I[i]; j++)
491 offd_J[offd_I[i] + j] =
492 cinvmap[cmapa[cmap_r[offd_r_J[offd_r_I[i] + j]]]];
493 offd_D[offd_I[i] + j] = offd_r_D[offd_r_I[i] + j];
495 offd_J[offd_I[i+nrows] + off_i + j] =
496 cinvmap[cmapb[cmap_r[offd_r_J[offd_r_I[i] + j]]]];
497 offd_D[offd_I[i+nrows] + off_i + j] =
498 factor * offd_r_D[offd_r_I[i] + j];
503 const int off_r = (offd_r_I)?(offd_r_I[i+1] - offd_r_I[i]):0;
504 for (
int j=0; j<offd_i_I[i+1] - offd_i_I[i]; j++)
506 offd_J[offd_I[i] + off_r + j] =
507 cinvmap[cmapb[cmap_i[offd_i_J[offd_i_I[i] + j]]]];
508 offd_D[offd_I[i] + off_r + j] = -offd_i_D[offd_i_I[i] + j];
510 offd_J[offd_I[i+nrows] + j] =
511 cinvmap[cmapa[cmap_i[offd_i_J[offd_i_I[i] + j]]]];
512 offd_D[offd_I[i+nrows] + j] = factor * offd_i_D[offd_i_I[i] + j];
521 row_starts, col_starts,
522 diag_I, diag_J, diag_D,
523 offd_I, offd_J, offd_D,
524 2 * num_cols_offd, cmap);
528 hypre_CSRMatrixSetDataOwner(((hypre_ParCSRMatrix*)(*A))->diag,1);
529 hypre_CSRMatrixSetDataOwner(((hypre_ParCSRMatrix*)(*A))->offd,1);
530 hypre_ParCSRMatrixSetRowStartsOwner((hypre_ParCSRMatrix*)(*A),1);
531 hypre_ParCSRMatrixSetColStartsOwner((hypre_ParCSRMatrix*)(*A),1);
537 ComplexHypreParMatrix::getColStartStop(
const HypreParMatrix * A_r,
539 int & num_recv_procs,
540 HYPRE_Int *& offd_col_start_stop)
const
542 hypre_ParCSRCommPkg * comm_pkg_r =
543 (A_r) ? hypre_ParCSRMatrixCommPkg((hypre_ParCSRMatrix*)(*A_r)) : NULL;
544 hypre_ParCSRCommPkg * comm_pkg_i =
545 (A_i) ? hypre_ParCSRMatrixCommPkg((hypre_ParCSRMatrix*)(*A_i)) : NULL;
547 std::set<HYPRE_Int> send_procs, recv_procs;
550 for (HYPRE_Int i=0; i<comm_pkg_r->num_sends; i++)
552 send_procs.insert(comm_pkg_r->send_procs[i]);
554 for (HYPRE_Int i=0; i<comm_pkg_r->num_recvs; i++)
556 recv_procs.insert(comm_pkg_r->recv_procs[i]);
561 for (HYPRE_Int i=0; i<comm_pkg_i->num_sends; i++)
563 send_procs.insert(comm_pkg_i->send_procs[i]);
565 for (HYPRE_Int i=0; i<comm_pkg_i->num_recvs; i++)
567 recv_procs.insert(comm_pkg_i->recv_procs[i]);
571 num_recv_procs = (int)recv_procs.size();
573 HYPRE_Int loc_start_stop[2];
574 offd_col_start_stop =
new HYPRE_Int[2 * num_recv_procs];
576 const HYPRE_Int * row_part = (A_r) ? A_r->
RowPart() :
577 ((A_i) ? A_i->
RowPart() : NULL);
579 int row_part_ind = (HYPRE_AssumedPartitionCheck()) ? 0 : myid_;
580 loc_start_stop[0] = row_part[row_part_ind];
581 loc_start_stop[1] = row_part[row_part_ind+1];
583 MPI_Request * req =
new MPI_Request[send_procs.size()+recv_procs.size()];
584 MPI_Status * stat =
new MPI_Status[send_procs.size()+recv_procs.size()];
589 std::set<HYPRE_Int>::iterator sit;
590 for (sit=send_procs.begin(); sit!=send_procs.end(); sit++)
592 MPI_Isend(loc_start_stop, 2, HYPRE_MPI_INT,
593 *sit, tag, comm_, &req[send_count]);
596 for (sit=recv_procs.begin(); sit!=recv_procs.end(); sit++)
598 MPI_Irecv(&offd_col_start_stop[2*recv_count], 2, HYPRE_MPI_INT,
599 *sit, tag, comm_, &req[send_count+recv_count]);
603 MPI_Waitall(send_count+recv_count, req, stat);
609 #endif // MFEM_USE_MPI
MPI_Comm GetComm() const
MPI communicator.
virtual Operator & real()
Real or imaginary part accessor methods.
virtual ~ComplexOperator()
ComplexHypreParMatrix(HypreParMatrix *A_Real, HypreParMatrix *A_Imag, bool ownReal, bool ownImag, Convention convention=HERMITIAN)
HYPRE_Int * ColPart()
Returns the column partitioning.
Mimic the action of a complex operator using two real operators.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
int * GetJ()
Return the array J.
int * GetI()
Return the array I.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
Alternate convention for damping operators.
double * GetData() const
Return a pointer to the beginning of the Vector data.
ComplexOperator(Operator *Op_Real, Operator *Op_Imag, bool ownReal, bool ownImag, Convention convention=HERMITIAN)
Constructs complex operator object.
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
double * GetData()
Return the element data, i.e. the array A.
HYPRE_Int GetGlobalNumRows() const
Return the global number of rows.
HYPRE_Int GetGlobalNumCols() const
Return the global number of columns.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
void SetOwnerFlags(signed char diag, signed char offd, signed char colmap)
Explicitly set the three ownership flags, see docs for diagOwner etc.
void GetDiag(Vector &diag) const
Get the local diagonal of the matrix.
virtual SparseMatrix & real()
Real or imaginary part accessor methods.
HYPRE_Int * RowPart()
Returns the row partitioning.
SparseMatrix * GetSystemMatrix() const
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
virtual Operator & imag()
int height
Dimension of the output / number of rows in the matrix.
Vector & Add(const double a, const Vector &Va)
(*this) += a * Va
virtual SparseMatrix & imag()
Native convention for Hermitian operators.
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
void GetOffd(SparseMatrix &offd, HYPRE_Int *&cmap) const
Get the local off-diagonal block. NOTE: 'offd' will not own any data.
HypreParMatrix * GetSystemMatrix() const
virtual HypreParMatrix & imag()
Wrapper for hypre's ParCSR matrix class.
virtual HypreParMatrix & real()
Real or imaginary part accessor methods.
int width
Dimension of the input / number of columns in the matrix.