MFEM v2.0
hypre.cpp
Go to the documentation of this file.
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
00003 // reserved. See file COPYRIGHT for details.
00004 //
00005 // This file is part of the MFEM library. For more information and source code
00006 // availability see http://mfem.googlecode.com.
00007 //
00008 // MFEM is free software; you can redistribute it and/or modify it under the
00009 // terms of the GNU Lesser General Public License (as published by the Free
00010 // Software Foundation) version 2.1 dated February 1999.
00011 
00012 #ifdef MFEM_USE_MPI
00013 
00014 #include <iostream>
00015 #include <fstream>
00016 #include <iomanip>
00017 #include <math.h>
00018 #include <stdlib.h>
00019 
00020 #include "linalg.hpp"
00021 #include "../fem/fem.hpp"
00022 
00023 HypreParVector::HypreParVector(int glob_size, int *col) : Vector()
00024 {
00025    x = hypre_ParVectorCreate(MPI_COMM_WORLD,glob_size,col);
00026    hypre_ParVectorInitialize(x);
00027    hypre_ParVectorSetPartitioningOwner(x,0);
00028    // The data will be destroyed by hypre (this is the default)
00029    hypre_ParVectorSetDataOwner(x,1);
00030    hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(x),1);
00031    SetDataAndSize(hypre_VectorData(hypre_ParVectorLocalVector(x)),
00032                   hypre_VectorSize(hypre_ParVectorLocalVector(x)));
00033    own_ParVector = 1;
00034 }
00035 
00036 HypreParVector::HypreParVector(int glob_size, double *_data, int *col)
00037    : Vector()
00038 {
00039    x = hypre_ParVectorCreate(MPI_COMM_WORLD,glob_size,col);
00040    hypre_ParVectorSetDataOwner(x,1); // owns the seq vector
00041    hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(x),0);
00042    hypre_ParVectorSetPartitioningOwner(x,0);
00043    hypre_VectorData(hypre_ParVectorLocalVector(x)) = _data;
00044    // If hypre_ParVectorLocalVector(x) is non-NULL, hypre_ParVectorInitialize(x)
00045    // does not allocate memory!
00046    hypre_ParVectorInitialize(x);
00047    SetDataAndSize(hypre_VectorData(hypre_ParVectorLocalVector(x)),
00048                   hypre_VectorSize(hypre_ParVectorLocalVector(x)));
00049    own_ParVector = 1;
00050 }
00051 
00052 HypreParVector::HypreParVector(const HypreParVector &y) : Vector()
00053 {
00054    x = hypre_ParVectorCreate(MPI_COMM_WORLD, y.x -> global_size,
00055                              y.x -> partitioning);
00056    hypre_ParVectorInitialize(x);
00057    hypre_ParVectorSetPartitioningOwner(x,0);
00058    hypre_ParVectorSetDataOwner(x,1);
00059    hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(x),1);
00060    SetDataAndSize(hypre_VectorData(hypre_ParVectorLocalVector(x)),
00061                   hypre_VectorSize(hypre_ParVectorLocalVector(x)));
00062    own_ParVector = 1;
00063 }
00064 
00065 HypreParVector::HypreParVector(HYPRE_ParVector y) : Vector()
00066 {
00067    x = (hypre_ParVector *) y;
00068    SetDataAndSize(hypre_VectorData(hypre_ParVectorLocalVector(x)),
00069                   hypre_VectorSize(hypre_ParVectorLocalVector(x)));
00070    own_ParVector = 0;
00071 }
00072 
00073 HypreParVector::operator hypre_ParVector*() const
00074 {
00075    return x;
00076 }
00077 
00078 HypreParVector::operator HYPRE_ParVector() const
00079 {
00080    return (HYPRE_ParVector) x;
00081 }
00082 
00083 Vector * HypreParVector::GlobalVector()
00084 {
00085    hypre_Vector *hv = hypre_ParVectorToVectorAll(*this);
00086    Vector *v = new Vector(hv->data, hv->size);
00087    v->MakeDataOwner();
00088    hypre_SeqVectorSetDataOwner(hv,0);
00089    hypre_SeqVectorDestroy(hv);
00090    return v;
00091 }
00092 
00093 HypreParVector& HypreParVector::operator=(double d)
00094 {
00095    hypre_ParVectorSetConstantValues(x,d);
00096    return *this;
00097 }
00098 
00099 HypreParVector& HypreParVector::operator=(const HypreParVector &y)
00100 {
00101 #ifdef MFEM_DEBUG
00102    if (size != y.Size())
00103       mfem_error("HypreParVector::operator=");
00104 #endif
00105 
00106    for (int i = 0; i < size; i++)
00107       data[i] = y.data[i];
00108    return *this;
00109 }
00110 
00111 void HypreParVector::SetData(double *_data)
00112 {
00113    Vector::data = hypre_VectorData(hypre_ParVectorLocalVector(x)) = _data;
00114 }
00115 
00116 int HypreParVector::Randomize(int seed)
00117 {
00118    return hypre_ParVectorSetRandomValues(x,seed);
00119 }
00120 
00121 void HypreParVector::Print(const char *fname)
00122 {
00123    hypre_ParVectorPrint(x,fname);
00124 }
00125 
00126 HypreParVector::~HypreParVector()
00127 {
00128    if (own_ParVector)
00129       hypre_ParVectorDestroy(x);
00130 }
00131 
00132 
00133 double InnerProduct(HypreParVector *x, HypreParVector *y)
00134 {
00135    return hypre_ParVectorInnerProd(*x, *y);
00136 }
00137 
00138 double InnerProduct(HypreParVector &x, HypreParVector &y)
00139 {
00140    return hypre_ParVectorInnerProd(x, y);
00141 }
00142 
00143 
00144 HypreParMatrix::HypreParMatrix(int size, int *row, SparseMatrix *diag)
00145    : Operator(size)
00146 {
00147    A = hypre_ParCSRMatrixCreate(MPI_COMM_WORLD, size, size, row, row,
00148                                 0, diag->NumNonZeroElems(), 0);
00149    hypre_ParCSRMatrixSetDataOwner(A,0);
00150    hypre_ParCSRMatrixSetRowStartsOwner(A,0);
00151    hypre_ParCSRMatrixSetColStartsOwner(A,0);
00152 
00153    hypre_CSRMatrixSetDataOwner(A->diag,0);
00154    hypre_CSRMatrixI(A->diag)    = diag->GetI();
00155    hypre_CSRMatrixJ(A->diag)    = diag->GetJ();
00156    hypre_CSRMatrixData(A->diag) = diag->GetData();
00157    hypre_CSRMatrixSetRownnz(A->diag);
00158 
00159    hypre_CSRMatrixSetDataOwner(A->offd,1);
00160    hypre_CSRMatrixI(A->offd)    = hypre_CTAlloc(HYPRE_Int, diag->Size()+1);
00161 
00162    /* Don't need to call these, since they allocate memory only
00163       if it was not already allocated */
00164    // hypre_CSRMatrixInitialize(A->diag);
00165    // hypre_ParCSRMatrixInitialize(A);
00166 
00167    hypre_ParCSRMatrixSetNumNonzeros(A);
00168 
00169    hypre_MatvecCommPkgCreate(A);
00170 
00171    CommPkg = NULL;
00172    X = Y = NULL;
00173 }
00174 
00175 
00176 HypreParMatrix::HypreParMatrix(int M, int N, int *row, int *col,
00177                                SparseMatrix *diag)
00178 {
00179    A = hypre_ParCSRMatrixCreate(MPI_COMM_WORLD, M, N, row, col,
00180                                 0, diag->NumNonZeroElems(), 0);
00181    hypre_ParCSRMatrixSetDataOwner(A,0);
00182    hypre_ParCSRMatrixSetRowStartsOwner(A,0);
00183    hypre_ParCSRMatrixSetColStartsOwner(A,0);
00184 
00185    hypre_CSRMatrixSetDataOwner(A->diag,0);
00186    hypre_CSRMatrixI(A->diag)    = diag->GetI();
00187    hypre_CSRMatrixJ(A->diag)    = diag->GetJ();
00188    hypre_CSRMatrixData(A->diag) = diag->GetData();
00189    hypre_CSRMatrixSetRownnz(A->diag);
00190 
00191    hypre_CSRMatrixSetDataOwner(A->offd,1);
00192    hypre_CSRMatrixI(A->offd) = hypre_CTAlloc(HYPRE_Int, diag->Size()+1);
00193 
00194    hypre_ParCSRMatrixSetNumNonzeros(A);
00195 
00196    hypre_MatvecCommPkgCreate(A);
00197 
00198    CommPkg = NULL;
00199    X = Y = NULL;
00200 
00201    size = GetNumRows();
00202 }
00203 
00204 HypreParMatrix::HypreParMatrix(int M, int N, int *row, int *col,
00205                                SparseMatrix *diag, SparseMatrix *offd,
00206                                int *cmap)
00207 {
00208    A = hypre_ParCSRMatrixCreate(MPI_COMM_WORLD, M, N, row, col,
00209                                 offd->Width(), diag->NumNonZeroElems(),
00210                                 offd->NumNonZeroElems());
00211    hypre_ParCSRMatrixSetDataOwner(A,0);
00212    hypre_ParCSRMatrixSetRowStartsOwner(A,0);
00213    hypre_ParCSRMatrixSetColStartsOwner(A,0);
00214 
00215    hypre_CSRMatrixSetDataOwner(A->diag,0);
00216    hypre_CSRMatrixI(A->diag)    = diag->GetI();
00217    hypre_CSRMatrixJ(A->diag)    = diag->GetJ();
00218    hypre_CSRMatrixData(A->diag) = diag->GetData();
00219    hypre_CSRMatrixSetRownnz(A->diag);
00220 
00221    hypre_CSRMatrixSetDataOwner(A->offd,0);
00222    hypre_CSRMatrixI(A->offd)    = offd->GetI();
00223    hypre_CSRMatrixJ(A->offd)    = offd->GetJ();
00224    hypre_CSRMatrixData(A->offd) = offd->GetData();
00225    hypre_CSRMatrixSetRownnz(A->offd);
00226 
00227    hypre_ParCSRMatrixColMapOffd(A) = cmap;
00228 
00229    hypre_ParCSRMatrixSetNumNonzeros(A);
00230 
00231    hypre_MatvecCommPkgCreate(A);
00232 
00233    CommPkg = NULL;
00234    X = Y = NULL;
00235 
00236    size = GetNumRows();
00237 }
00238 
00239 HypreParMatrix::HypreParMatrix(int *row, int *col, SparseMatrix *sm_a)
00240 {
00241 #ifdef MFEM_DEBUG
00242    if (sm_a == NULL)
00243       mfem_error("HypreParMatrix::HypreParMatrix: sm_a==NULL");
00244 #endif
00245 
00246    hypre_CSRMatrix *csr_a;
00247 
00248    csr_a = hypre_CSRMatrixCreate(sm_a -> Size(), sm_a -> Width(),
00249                                  sm_a -> NumNonZeroElems());
00250 
00251    hypre_CSRMatrixSetDataOwner(csr_a,0);
00252    hypre_CSRMatrixI(csr_a)    = sm_a -> GetI();
00253    hypre_CSRMatrixJ(csr_a)    = sm_a -> GetJ();
00254    hypre_CSRMatrixData(csr_a) = sm_a -> GetData();
00255    hypre_CSRMatrixSetRownnz(csr_a);
00256 
00257    A = hypre_CSRMatrixToParCSRMatrix(MPI_COMM_WORLD,csr_a,row,col);
00258 
00259    CommPkg = NULL;
00260    X = Y = NULL;
00261 
00262    size = GetNumRows();
00263 
00264    hypre_MatvecCommPkgCreate(A);
00265 }
00266 
00267 HypreParMatrix::HypreParMatrix(int M, int N, int *row, int *col,
00268                                Table *diag)
00269 {
00270    int nnz = diag->Size_of_connections();
00271    A = hypre_ParCSRMatrixCreate(MPI_COMM_WORLD, M, N, row, col,
00272                                 0, nnz, 0);
00273    hypre_ParCSRMatrixSetDataOwner(A,1);
00274    hypre_ParCSRMatrixSetRowStartsOwner(A,0);
00275    hypre_ParCSRMatrixSetColStartsOwner(A,0);
00276 
00277    hypre_CSRMatrixSetDataOwner(A->diag,1);
00278    hypre_CSRMatrixI(A->diag)    = diag->GetI();
00279    hypre_CSRMatrixJ(A->diag)    = diag->GetJ();
00280 
00281    hypre_CSRMatrixData(A->diag) = hypre_TAlloc(double, nnz);
00282    for (int k = 0; k < nnz; k++)
00283       (hypre_CSRMatrixData(A->diag))[k] = 1.0;
00284 
00285    hypre_CSRMatrixSetRownnz(A->diag);
00286 
00287    hypre_CSRMatrixSetDataOwner(A->offd,1);
00288    hypre_CSRMatrixI(A->offd) = hypre_CTAlloc(HYPRE_Int, diag->Size()+1);
00289 
00290    hypre_ParCSRMatrixSetNumNonzeros(A);
00291 
00292    hypre_MatvecCommPkgCreate(A);
00293 
00294    CommPkg = NULL;
00295    X = Y = NULL;
00296 
00297    size = GetNumRows();
00298 }
00299 
00300 HypreParMatrix::HypreParMatrix(MPI_Comm comm, int id, int np,
00301                                int *row, int *col,
00302                                int *i_diag, int *j_diag,
00303                                int *i_offd, int *j_offd,
00304                                int *cmap, int cmap_size)
00305 {
00306    int diag_col, offd_col;
00307 
00308    if (HYPRE_AssumedPartitionCheck())
00309    {
00310       diag_col = i_diag[row[1]-row[0]];
00311       offd_col = i_offd[row[1]-row[0]];
00312 
00313       A = hypre_ParCSRMatrixCreate(comm, row[2], col[2], row, col,
00314                                    cmap_size, diag_col, offd_col);
00315    }
00316    else
00317    {
00318       diag_col = i_diag[row[id+1]-row[id]];
00319       offd_col = i_offd[row[id+1]-row[id]];
00320 
00321       A = hypre_ParCSRMatrixCreate(comm, row[np], col[np], row, col,
00322                                    cmap_size, diag_col, offd_col);
00323    }
00324 
00325    hypre_ParCSRMatrixSetDataOwner(A,1);
00326    hypre_ParCSRMatrixSetRowStartsOwner(A,0);
00327    hypre_ParCSRMatrixSetColStartsOwner(A,0);
00328 
00329    int i;
00330 
00331    double *a_diag = hypre_TAlloc(double, diag_col);
00332    for (i = 0; i < diag_col; i++)
00333       a_diag[i] = 1.0;
00334 
00335    double *a_offd = hypre_TAlloc(double, offd_col);
00336    for (i = 0; i < offd_col; i++)
00337       a_offd[i] = 1.0;
00338 
00339    hypre_CSRMatrixSetDataOwner(A->diag,1);
00340    hypre_CSRMatrixI(A->diag)    = i_diag;
00341    hypre_CSRMatrixJ(A->diag)    = j_diag;
00342    hypre_CSRMatrixData(A->diag) = a_diag;
00343    hypre_CSRMatrixSetRownnz(A->diag);
00344 
00345    hypre_CSRMatrixSetDataOwner(A->offd,1);
00346    hypre_CSRMatrixI(A->offd)    = i_offd;
00347    hypre_CSRMatrixJ(A->offd)    = j_offd;
00348    hypre_CSRMatrixData(A->offd) = a_offd;
00349    hypre_CSRMatrixSetRownnz(A->offd);
00350 
00351    hypre_ParCSRMatrixColMapOffd(A) = cmap;
00352 
00353    hypre_ParCSRMatrixSetNumNonzeros(A);
00354 
00355    hypre_MatvecCommPkgCreate(A);
00356 
00357    CommPkg = NULL;
00358    X = Y = NULL;
00359 
00360    size = GetNumRows();
00361 }
00362 
00363 HypreParMatrix::HypreParMatrix(MPI_Comm comm, int nrows, int glob_nrows,
00364                                int glob_ncols, int *I, int *J, double *data,
00365                                int *rows, int *cols)
00366 {
00367    // construct the local CSR matrix
00368    int nnz = I[nrows];
00369    hypre_CSRMatrix *local = hypre_CSRMatrixCreate(nrows, glob_ncols, nnz);
00370    hypre_CSRMatrixI(local) = I;
00371    hypre_CSRMatrixJ(local) = J;
00372    hypre_CSRMatrixData(local) = data;
00373    hypre_CSRMatrixRownnz(local) = NULL;
00374    hypre_CSRMatrixOwnsData(local) = 1;
00375    hypre_CSRMatrixNumRownnz(local) = nrows;
00376 
00377    int part_size, myid;
00378    if (HYPRE_AssumedPartitionCheck())
00379    {
00380       myid = 0;
00381       part_size = 2;
00382    }
00383    else
00384    {
00385       MPI_Comm_rank(comm, &myid);
00386       MPI_Comm_size(comm, &part_size);
00387       part_size++;
00388    }
00389 
00390    // copy in the row and column partitionings
00391    HYPRE_Int *row_starts = hypre_TAlloc(HYPRE_Int, part_size);
00392    HYPRE_Int *col_starts = hypre_TAlloc(HYPRE_Int, part_size);
00393    for (int i = 0; i < part_size; i++)
00394    {
00395       row_starts[i] = rows[i];
00396       col_starts[i] = cols[i];
00397    }
00398 
00399    // construct the global ParCSR matrix
00400    A = hypre_ParCSRMatrixCreate(comm, glob_nrows, glob_ncols,
00401                                 row_starts, col_starts, 0, 0, 0);
00402    hypre_ParCSRMatrixOwnsRowStarts(A) = 1;
00403    hypre_ParCSRMatrixOwnsColStarts(A) = 1;
00404    GenerateDiagAndOffd(local, A, col_starts[myid], col_starts[myid+1]-1);
00405    hypre_ParCSRMatrixSetNumNonzeros(A);
00406    hypre_MatvecCommPkgCreate(A);
00407 
00408    // delete the local CSR matrix
00409    hypre_CSRMatrixI(local) = NULL;
00410    hypre_CSRMatrixJ(local) = NULL;
00411    hypre_CSRMatrixData(local) = NULL;
00412    hypre_CSRMatrixDestroy(local);
00413 
00414    CommPkg = NULL;
00415    X = Y = NULL;
00416    size = GetNumRows();
00417 }
00418 
00419 void HypreParMatrix::SetCommPkg(hypre_ParCSRCommPkg *comm_pkg)
00420 {
00421    CommPkg = comm_pkg;
00422 
00423    if (hypre_ParCSRMatrixCommPkg(A))
00424       hypre_MatvecCommPkgDestroy(hypre_ParCSRMatrixCommPkg(A));
00425 
00426    hypre_ParCSRMatrixCommPkg(A) = comm_pkg;
00427 }
00428 
00429 void HypreParMatrix::CheckCommPkg()
00430 {
00431 #ifdef MFEM_DEBUG
00432    if (CommPkg == NULL || CommPkg != hypre_ParCSRMatrixCommPkg(A))
00433       mfem_error("\nHypreParMatrix::CheckCommPkg()");
00434 #endif
00435 }
00436 
00437 void HypreParMatrix::DestroyCommPkg()
00438 {
00439    if (CommPkg == NULL)
00440       return;
00441    hypre_TFree(CommPkg->send_procs);
00442    hypre_TFree(CommPkg->send_map_starts);
00443    hypre_TFree(CommPkg->send_map_elmts);
00444    hypre_TFree(CommPkg->recv_procs);
00445    hypre_TFree(CommPkg->recv_vec_starts);
00446    if (CommPkg->send_mpi_types)
00447       hypre_TFree(CommPkg->send_mpi_types);
00448    if (CommPkg->recv_mpi_types)
00449       hypre_TFree(CommPkg->recv_mpi_types);
00450    if (hypre_ParCSRMatrixCommPkg(A) == CommPkg)
00451       hypre_ParCSRMatrixCommPkg(A) = NULL;
00452    delete CommPkg;
00453    CommPkg = NULL;
00454 }
00455 
00456 HypreParMatrix::operator hypre_ParCSRMatrix*()
00457 {
00458    return (this) ? A : NULL;
00459 }
00460 
00461 HypreParMatrix::operator HYPRE_ParCSRMatrix()
00462 {
00463    return (this) ? (HYPRE_ParCSRMatrix) A : (HYPRE_ParCSRMatrix) NULL;
00464 }
00465 
00466 hypre_ParCSRMatrix* HypreParMatrix::StealData()
00467 {
00468    hypre_ParCSRMatrix *R = A;
00469    A = NULL;
00470    return R;
00471 }
00472 
00473 void HypreParMatrix::GetDiag(Vector &diag)
00474 {
00475    int size=hypre_CSRMatrixNumRows(A->diag);
00476    diag.SetSize(size);
00477    for (int j = 0; j < size; j++)
00478    {
00479       diag(j) = A->diag->data[A->diag->i[j]];
00480 #ifdef MFEM_DEBUG
00481       if (A->diag->j[A->diag->i[j]] != j)
00482          mfem_error("HypreParMatrix::GetDiag");
00483 #endif
00484    }
00485 }
00486 
00487 
00488 HypreParMatrix * HypreParMatrix::Transpose()
00489 {
00490    hypre_ParCSRMatrix * At;
00491    hypre_ParCSRMatrixTranspose(A, &At, 1);
00492    hypre_ParCSRMatrixSetNumNonzeros(At);
00493 
00494    hypre_MatvecCommPkgCreate(At);
00495 
00496    return new HypreParMatrix(At);
00497 }
00498 
00499 int HypreParMatrix::Mult(HypreParVector &x, HypreParVector &y,
00500                          double a, double b)
00501 {
00502    return hypre_ParCSRMatrixMatvec(a, A, x, b, y);
00503 }
00504 
00505 void HypreParMatrix::Mult(const Vector &x, Vector &y) const
00506 {
00507    if (X == NULL)
00508    {
00509       X = new HypreParVector(GetGlobalNumCols(),
00510                              x.GetData(),
00511                              GetColStarts());
00512       Y = new HypreParVector(GetGlobalNumRows(),
00513                              y.GetData(),
00514                              GetRowStarts());
00515    }
00516    else
00517    {
00518       X -> SetData(x.GetData());
00519       Y -> SetData(y.GetData());
00520    }
00521 
00522    hypre_ParCSRMatrixMatvec(1.0, A, *X, 0.0, *Y);
00523 }
00524 
00525 void HypreParMatrix::MultTranspose(const Vector &x, Vector &y) const
00526 {
00527    if (X == NULL)
00528    {
00529       X = new HypreParVector(GetGlobalNumCols(),
00530                              x.GetData(),
00531                              GetColStarts());
00532       Y = new HypreParVector(GetGlobalNumRows(),
00533                              y.GetData(),
00534                              GetRowStarts());
00535    }
00536    else
00537    {
00538       X -> SetData(x.GetData());
00539       Y -> SetData(y.GetData());
00540    }
00541 
00542    hypre_ParCSRMatrixMatvecT(1.0, A, *X, 0.0, *Y);
00543 }
00544 
00545 int HypreParMatrix::Mult(HYPRE_ParVector x, HYPRE_ParVector y,
00546                          double a, double b)
00547 {
00548    return hypre_ParCSRMatrixMatvec(a,A,(hypre_ParVector *)x,b,(hypre_ParVector *)y);
00549 }
00550 
00551 int HypreParMatrix::MultTranspose(HypreParVector & x, HypreParVector & y,
00552                                   double a, double b)
00553 {
00554    return hypre_ParCSRMatrixMatvecT(a,A,x,b,y);
00555 }
00556 
00557 void HypreParMatrix::Print(const char *fname, int offi, int offj)
00558 {
00559    hypre_ParCSRMatrixPrintIJ(A,offi,offj,fname);
00560 }
00561 
00562 void HypreParMatrix::Read(const char *fname)
00563 {
00564    if (A) hypre_ParCSRMatrixDestroy(A);
00565    int io,jo;
00566    hypre_ParCSRMatrixReadIJ(MPI_COMM_WORLD, fname, &io, &jo, &A);
00567    hypre_ParCSRMatrixSetNumNonzeros(A);
00568 
00569    hypre_MatvecCommPkgCreate(A);
00570 }
00571 
00572 HypreParMatrix::~HypreParMatrix()
00573 {
00574    DestroyCommPkg();
00575 
00576    if (A)
00577    {
00578       if (hypre_ParCSRMatrixCommPkg(A))
00579          hypre_MatvecCommPkgDestroy(hypre_ParCSRMatrixCommPkg(A));
00580       hypre_ParCSRMatrixCommPkg(A) = NULL;
00581 
00582       if (hypre_CSRMatrixOwnsData(A->diag))
00583       {
00584          hypre_CSRMatrixDestroy(A->diag);
00585          A->diag = NULL;
00586       }
00587       else
00588       {
00589          if (hypre_CSRMatrixRownnz(A->diag))
00590             hypre_TFree(hypre_CSRMatrixRownnz(A->diag));
00591          hypre_TFree(A->diag);
00592          A->diag = NULL;
00593       }
00594 
00595       if (hypre_CSRMatrixOwnsData(A->offd))
00596       {
00597          hypre_CSRMatrixDestroy(A->offd);
00598          A->offd = NULL;
00599       }
00600       else
00601       {
00602          if (hypre_CSRMatrixRownnz(A->offd))
00603             hypre_TFree(hypre_CSRMatrixRownnz(A->offd));
00604       }
00605       hypre_ParCSRMatrixDestroy(A);
00606    }
00607 
00608    delete X;
00609    delete Y;
00610 }
00611 
00612 HypreParMatrix * ParMult(HypreParMatrix *A, HypreParMatrix *B)
00613 {
00614    hypre_ParCSRMatrix * ab;
00615    ab = hypre_ParMatmul(*A,*B);
00616 
00617    hypre_MatvecCommPkgCreate(ab);
00618 
00619    return new HypreParMatrix(ab);
00620 }
00621 
00622 HypreParMatrix * RAP(HypreParMatrix *A, HypreParMatrix *P)
00623 {
00624    int P_owns_its_col_starts =
00625       hypre_ParCSRMatrixOwnsColStarts((hypre_ParCSRMatrix*)(*P));
00626    hypre_ParCSRMatrix * rap;
00627    hypre_BoomerAMGBuildCoarseOperator(*P,*A,*P,&rap);
00628 
00629    hypre_ParCSRMatrixSetNumNonzeros(rap);
00630    // hypre_MatvecCommPkgCreate(rap);
00631    if (!P_owns_its_col_starts)
00632    {
00633       /* Warning: hypre_BoomerAMGBuildCoarseOperator steals the col_starts
00634          from P (even if it does not own them)! */
00635       hypre_ParCSRMatrixSetRowStartsOwner(rap,0);
00636       hypre_ParCSRMatrixSetColStartsOwner(rap,0);
00637    }
00638    return new HypreParMatrix(rap);
00639 }
00640 
00641 void EliminateBC(HypreParMatrix &A, HypreParMatrix &Ae,
00642                  Array<int> &ess_dof_list,
00643                  HypreParVector &x, HypreParVector &b)
00644 {
00645    // b -= Ae*x
00646    Ae.Mult(x, b, -1.0, 1.0);
00647 
00648    hypre_CSRMatrix *A_diag = hypre_ParCSRMatrixDiag((hypre_ParCSRMatrix *)A);
00649    double *data = hypre_CSRMatrixData(A_diag);
00650    int    *I    = hypre_CSRMatrixI(A_diag);
00651 #ifdef MFEM_DEBUG
00652    int    *J    = hypre_CSRMatrixJ(A_diag);
00653    int *I_offd  =
00654       hypre_CSRMatrixI(hypre_ParCSRMatrixOffd((hypre_ParCSRMatrix *)A));
00655 #endif
00656 
00657    for (int i = 0; i < ess_dof_list.Size(); i++)
00658    {
00659       int r = ess_dof_list[i];
00660       b(r) = data[I[r]] * x(r);
00661 #ifdef MFEM_DEBUG
00662       // Check that in the rows specified by the ess_dof_list, the matrix A has
00663       // only one entry -- the diagonal.
00664       if (I[r+1] != I[r]+1 || J[I[r]] != r || I_offd[r] != I_offd[r+1])
00665          mfem_error("EliminateBC (hypre.cpp)");
00666 #endif
00667    }
00668 }
00669 
00670 
00671 HypreSolver::HypreSolver()
00672 {
00673    size = 0;
00674 
00675    A = NULL;
00676    setup_called = 0;
00677    B = X = NULL;
00678 }
00679 
00680 HypreSolver::HypreSolver(HypreParMatrix *_A)
00681 {
00682    size = _A -> GetNumRows();
00683 
00684    A = _A;
00685    setup_called = 0;
00686    B = X = NULL;
00687 }
00688 
00689 void HypreSolver::Mult(const HypreParVector &b, HypreParVector &x) const
00690 {
00691    if (A == NULL)
00692    {
00693       mfem_error("HypreSolver::Mult (...) : HypreParMatrix A is missing");
00694       return;
00695    }
00696    if (!setup_called)
00697    {
00698       SetupFcn()(*this, *A, b, x);
00699       setup_called = 1;
00700    }
00701 
00702    SolveFcn()(*this, *A, b, x);
00703 }
00704 
00705 void HypreSolver::Mult(const Vector &b, Vector &x) const
00706 {
00707    if (A == NULL)
00708    {
00709       mfem_error("HypreSolver::Mult (...) : HypreParMatrix A is missing");
00710       return;
00711    }
00712    if (B == NULL)
00713    {
00714       B = new HypreParVector(A -> GetGlobalNumRows(),
00715                              b.GetData(),
00716                              A -> GetRowStarts());
00717       X = new HypreParVector(A -> GetGlobalNumCols(),
00718                              x.GetData(),
00719                              A -> GetColStarts());
00720    }
00721    else
00722    {
00723       B -> SetData(b.GetData());
00724       X -> SetData(x.GetData());
00725    }
00726 
00727    Mult(*B, *X);
00728 }
00729 
00730 HypreSolver::~HypreSolver()
00731 {
00732    if (B) delete B;
00733    if (X) delete X;
00734 }
00735 
00736 
00737 HyprePCG::HyprePCG(HypreParMatrix &_A) : HypreSolver(&_A)
00738 {
00739    MPI_Comm comm;
00740 
00741    print_level = 0;
00742    use_zero_initial_iterate = 0;
00743 
00744    HYPRE_ParCSRMatrixGetComm(*A, &comm);
00745 
00746    HYPRE_ParCSRPCGCreate(comm, &pcg_solver);
00747 }
00748 
00749 void HyprePCG::SetTol(double tol)
00750 {
00751    HYPRE_ParCSRPCGSetTol(pcg_solver, tol);
00752 }
00753 
00754 void HyprePCG::SetMaxIter(int max_iter)
00755 {
00756    HYPRE_ParCSRPCGSetMaxIter(pcg_solver, max_iter);
00757 }
00758 
00759 void HyprePCG::SetLogging(int logging)
00760 {
00761    HYPRE_ParCSRPCGSetLogging(pcg_solver, logging);
00762 }
00763 
00764 void HyprePCG::SetPrintLevel(int print_lvl)
00765 {
00766    print_level = print_lvl;
00767    HYPRE_ParCSRPCGSetPrintLevel(pcg_solver, print_level);
00768 }
00769 
00770 void HyprePCG::SetPreconditioner(HypreSolver &precond)
00771 {
00772    HYPRE_ParCSRPCGSetPrecond(pcg_solver,
00773                              precond.SolveFcn(),
00774                              precond.SetupFcn(),
00775                              precond);
00776 }
00777 
00778 void HyprePCG::SetResidualConvergenceOptions(int res_frequency, double rtol)
00779 {
00780    HYPRE_PCGSetTwoNorm(pcg_solver, 1);
00781    if (res_frequency > 0)
00782       HYPRE_PCGSetRecomputeResidualP(pcg_solver, res_frequency);
00783    if (rtol > 0.0)
00784       HYPRE_PCGSetResidualTol(pcg_solver, rtol);
00785 }
00786 
00787 void HyprePCG::Mult(const HypreParVector &b, HypreParVector &x) const
00788 {
00789    int myid;
00790    int time_index;
00791    int num_iterations;
00792    double final_res_norm;
00793    MPI_Comm comm;
00794 
00795    HYPRE_ParCSRMatrixGetComm(*A, &comm);
00796 
00797    if (!setup_called)
00798    {
00799       if (print_level > 0)
00800       {
00801          time_index = hypre_InitializeTiming("PCG Setup");
00802          hypre_BeginTiming(time_index);
00803       }
00804 
00805       HYPRE_ParCSRPCGSetup(pcg_solver, *A, b, x);
00806       setup_called = 1;
00807 
00808       if (print_level > 0)
00809       {
00810          hypre_EndTiming(time_index);
00811          hypre_PrintTiming("Setup phase times", comm);
00812          hypre_FinalizeTiming(time_index);
00813          hypre_ClearTiming();
00814       }
00815    }
00816 
00817    if (print_level > 0)
00818    {
00819       time_index = hypre_InitializeTiming("PCG Solve");
00820       hypre_BeginTiming(time_index);
00821    }
00822 
00823    if (use_zero_initial_iterate)
00824       x = 0.0;
00825 
00826    HYPRE_ParCSRPCGSolve(pcg_solver, *A, b, x);
00827 
00828    if (print_level > 0)
00829    {
00830       hypre_EndTiming(time_index);
00831       hypre_PrintTiming("Solve phase times", comm);
00832       hypre_FinalizeTiming(time_index);
00833       hypre_ClearTiming();
00834 
00835       HYPRE_ParCSRPCGGetNumIterations(pcg_solver, &num_iterations);
00836       HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(pcg_solver,
00837                                                   &final_res_norm);
00838 
00839       MPI_Comm_rank(comm, &myid);
00840 
00841       if (myid == 0)
00842       {
00843          cout << "PCG Iterations = " << num_iterations << endl
00844               << "Final PCG Relative Residual Norm = " << final_res_norm
00845               << endl;
00846       }
00847    }
00848 }
00849 
00850 HyprePCG::~HyprePCG()
00851 {
00852    HYPRE_ParCSRPCGDestroy(pcg_solver);
00853 }
00854 
00855 
00856 HypreGMRES::HypreGMRES(HypreParMatrix &_A) : HypreSolver(&_A)
00857 {
00858    MPI_Comm comm;
00859 
00860    int k_dim    = 50;
00861    int max_iter = 100;
00862    double tol   = 1e-6;
00863 
00864    print_level = 0;
00865    use_zero_initial_iterate = 0;
00866 
00867    HYPRE_ParCSRMatrixGetComm(*A, &comm);
00868 
00869    HYPRE_ParCSRGMRESCreate(comm, &gmres_solver);
00870    HYPRE_ParCSRGMRESSetKDim(gmres_solver, k_dim);
00871    HYPRE_ParCSRGMRESSetMaxIter(gmres_solver, max_iter);
00872    HYPRE_ParCSRGMRESSetTol(gmres_solver, tol);
00873 }
00874 
00875 void HypreGMRES::SetTol(double tol)
00876 {
00877    HYPRE_ParCSRGMRESSetTol(gmres_solver, tol);
00878 }
00879 
00880 void HypreGMRES::SetMaxIter(int max_iter)
00881 {
00882    HYPRE_ParCSRGMRESSetMaxIter(gmres_solver, max_iter);
00883 }
00884 
00885 void HypreGMRES::SetKDim(int k_dim)
00886 {
00887    HYPRE_ParCSRGMRESSetKDim(gmres_solver, k_dim);
00888 }
00889 
00890 void HypreGMRES::SetLogging(int logging)
00891 {
00892    HYPRE_ParCSRGMRESSetLogging(gmres_solver, logging);
00893 }
00894 
00895 void HypreGMRES::SetPrintLevel(int print_lvl)
00896 {
00897    print_level = print_lvl;
00898    HYPRE_ParCSRGMRESSetPrintLevel(gmres_solver, print_level);
00899 }
00900 
00901 void HypreGMRES::SetPreconditioner(HypreSolver &precond)
00902 {
00903    HYPRE_ParCSRGMRESSetPrecond(gmres_solver,
00904                                precond.SolveFcn(),
00905                                precond.SetupFcn(),
00906                                precond);
00907 }
00908 
00909 void HypreGMRES::Mult(const HypreParVector &b, HypreParVector &x) const
00910 {
00911    int myid;
00912    int time_index;
00913    int num_iterations;
00914    double final_res_norm;
00915    MPI_Comm comm;
00916 
00917    HYPRE_ParCSRMatrixGetComm(*A, &comm);
00918 
00919    if (!setup_called)
00920    {
00921       if (print_level > 0)
00922       {
00923          time_index = hypre_InitializeTiming("GMRES Setup");
00924          hypre_BeginTiming(time_index);
00925       }
00926 
00927       HYPRE_ParCSRGMRESSetup(gmres_solver, *A, b, x);
00928       setup_called = 1;
00929 
00930       if (print_level > 0)
00931       {
00932          hypre_EndTiming(time_index);
00933          hypre_PrintTiming("Setup phase times", comm);
00934          hypre_FinalizeTiming(time_index);
00935          hypre_ClearTiming();
00936       }
00937    }
00938 
00939    if (print_level > 0)
00940    {
00941       time_index = hypre_InitializeTiming("GMRES Solve");
00942       hypre_BeginTiming(time_index);
00943    }
00944 
00945    if (use_zero_initial_iterate)
00946       x = 0.0;
00947 
00948    HYPRE_ParCSRGMRESSolve(gmres_solver, *A, b, x);
00949 
00950    if (print_level > 0)
00951    {
00952       hypre_EndTiming(time_index);
00953       hypre_PrintTiming("Solve phase times", comm);
00954       hypre_FinalizeTiming(time_index);
00955       hypre_ClearTiming();
00956 
00957       HYPRE_ParCSRGMRESGetNumIterations(gmres_solver, &num_iterations);
00958       HYPRE_ParCSRGMRESGetFinalRelativeResidualNorm(gmres_solver,
00959                                                     &final_res_norm);
00960 
00961       MPI_Comm_rank(comm, &myid);
00962 
00963       if (myid == 0)
00964       {
00965          cout << "GMRES Iterations = " << num_iterations << endl
00966               << "Final GMRES Relative Residual Norm = " << final_res_norm
00967               << endl;
00968       }
00969    }
00970 }
00971 
00972 HypreGMRES::~HypreGMRES()
00973 {
00974    HYPRE_ParCSRGMRESDestroy(gmres_solver);
00975 }
00976 
00977 
00978 HypreParaSails::HypreParaSails(HypreParMatrix &A) : HypreSolver(&A)
00979 {
00980    MPI_Comm comm;
00981 
00982    int    sai_max_levels = 1;
00983    double sai_threshold  = 0.1;
00984    double sai_filter     = 0.1;
00985    int    sai_sym        = 0;
00986    double sai_loadbal    = 0.0;
00987    int    sai_reuse      = 0;
00988    int    sai_logging    = 1;
00989 
00990    HYPRE_ParCSRMatrixGetComm(A, &comm);
00991 
00992    HYPRE_ParaSailsCreate(comm, &sai_precond);
00993    HYPRE_ParaSailsSetParams(sai_precond, sai_threshold, sai_max_levels);
00994    HYPRE_ParaSailsSetFilter(sai_precond, sai_filter);
00995    HYPRE_ParaSailsSetSym(sai_precond, sai_sym);
00996    HYPRE_ParaSailsSetLoadbal(sai_precond, sai_loadbal);
00997    HYPRE_ParaSailsSetReuse(sai_precond, sai_reuse);
00998    HYPRE_ParaSailsSetLogging(sai_precond, sai_logging);
00999 }
01000 
01001 void HypreParaSails::SetSymmetry(int sym)
01002 {
01003    HYPRE_ParaSailsSetSym(sai_precond, sym);
01004 }
01005 
01006 HypreParaSails::~HypreParaSails()
01007 {
01008    HYPRE_ParaSailsDestroy(sai_precond);
01009 }
01010 
01011 
01012 HypreBoomerAMG::HypreBoomerAMG(HypreParMatrix &A) : HypreSolver(&A)
01013 {
01014    int coarsen_type = 10;
01015    int agg_levels   = 1;
01016    int relax_type   = 8;
01017    int relax_sweeps = 1;
01018    double theta     = 0.25;
01019    int interp_type  = 6;
01020    int Pmax         = 4;
01021    int print_level  = 1;
01022 
01023    HYPRE_BoomerAMGCreate(&amg_precond);
01024 
01025    HYPRE_BoomerAMGSetCoarsenType(amg_precond, coarsen_type);
01026    HYPRE_BoomerAMGSetAggNumLevels(amg_precond, agg_levels);
01027    HYPRE_BoomerAMGSetRelaxType(amg_precond, relax_type);
01028    HYPRE_BoomerAMGSetNumSweeps(amg_precond, relax_sweeps);
01029    HYPRE_BoomerAMGSetMaxLevels(amg_precond, 25);
01030    HYPRE_BoomerAMGSetTol(amg_precond, 0.0);
01031    HYPRE_BoomerAMGSetMaxIter(amg_precond, 1); // one V-cycle
01032    HYPRE_BoomerAMGSetStrongThreshold(amg_precond, theta);
01033    HYPRE_BoomerAMGSetInterpType(amg_precond, interp_type);
01034    HYPRE_BoomerAMGSetPMaxElmts(amg_precond, Pmax);
01035    HYPRE_BoomerAMGSetPrintLevel(amg_precond, print_level);
01036 }
01037 
01038 void HypreBoomerAMG::SetSystemsOptions(int dim)
01039 {
01040    HYPRE_BoomerAMGSetNumFunctions(amg_precond, dim);
01041 
01042    // More robust options with respect to convergence
01043    HYPRE_BoomerAMGSetAggNumLevels(amg_precond, 0);
01044    HYPRE_BoomerAMGSetStrongThreshold(amg_precond, 0.5);
01045 }
01046 
01047 HypreBoomerAMG::~HypreBoomerAMG()
01048 {
01049    HYPRE_BoomerAMGDestroy(amg_precond);
01050 }
01051 
01052 
01053 HypreAMS::HypreAMS(HypreParMatrix &A, ParFiniteElementSpace *edge_fespace)
01054    : HypreSolver(&A)
01055 {
01056    int cycle_type       = 13;
01057    int rlx_type         = 2;
01058    int rlx_sweeps       = 1;
01059    double rlx_weight    = 1.0;
01060    double rlx_omega     = 1.0;
01061    int amg_coarsen_type = 10;
01062    int amg_agg_levels   = 1;
01063    int amg_rlx_type     = 8;
01064    double theta         = 0.25;
01065    int amg_interp_type  = 6;
01066    int amg_Pmax         = 4;
01067 
01068    int p = edge_fespace->GetOrder(0);
01069    int dim = edge_fespace->GetMesh()->Dimension();
01070 
01071    HYPRE_AMSCreate(&ams);
01072 
01073    HYPRE_AMSSetDimension(ams, dim); // 2D H(div) and 3D H(curl) problems
01074    HYPRE_AMSSetTol(ams, 0.0);
01075    HYPRE_AMSSetMaxIter(ams, 1); // use as a preconditioner
01076    HYPRE_AMSSetCycleType(ams, cycle_type);
01077    HYPRE_AMSSetPrintLevel(ams, 1);
01078 
01079    // define the nodal linear finite element space associated with edge_fespace
01080    ParMesh *pmesh = (ParMesh *) edge_fespace->GetMesh();
01081    FiniteElementCollection *vert_fec = new H1_FECollection(p, dim);
01082    ParFiniteElementSpace *vert_fespace = new ParFiniteElementSpace(pmesh, vert_fec);
01083 
01084    // generate and set the vertex coordinates
01085    if (p == 1)
01086    {
01087       ParGridFunction x_coord(vert_fespace);
01088       ParGridFunction y_coord(vert_fespace);
01089       ParGridFunction z_coord(vert_fespace);
01090       double *coord;
01091       for (int i = 0; i < pmesh->GetNV(); i++)
01092       {
01093          coord = pmesh -> GetVertex(i);
01094          x_coord(i) = coord[0];
01095          y_coord(i) = coord[1];
01096          if (dim == 3)
01097             z_coord(i) = coord[2];
01098       }
01099       x = x_coord.ParallelAverage();
01100       y = y_coord.ParallelAverage();
01101       if (dim == 2)
01102       {
01103          z = NULL;
01104          HYPRE_AMSSetCoordinateVectors(ams, *x, *y, NULL);
01105       }
01106       else
01107       {
01108          z = z_coord.ParallelAverage();
01109          HYPRE_AMSSetCoordinateVectors(ams, *x, *y, *z);
01110       }
01111    }
01112    else
01113    {
01114       x = NULL;
01115       y = NULL;
01116       z = NULL;
01117    }
01118 
01119    // generate and set the discrete gradient
01120    ParDiscreteLinearOperator *grad;
01121    grad = new ParDiscreteLinearOperator(vert_fespace, edge_fespace);
01122    grad->AddDomainInterpolator(new GradientInterpolator);
01123    grad->Assemble();
01124    grad->Finalize();
01125    G = grad->ParallelAssemble();
01126    HYPRE_AMSSetDiscreteGradient(ams, *G);
01127    delete grad;
01128 
01129    // generate and set the Nedelec interpolation matrices
01130    Pi = Pix = Piy = Piz = NULL;
01131    if (p > 1)
01132    {
01133       ParFiniteElementSpace *vert_fespace_d;
01134       if (cycle_type < 10)
01135          vert_fespace_d = new ParFiniteElementSpace(pmesh, vert_fec, dim,
01136                                                     Ordering::byVDIM);
01137       else
01138          vert_fespace_d = new ParFiniteElementSpace(pmesh, vert_fec, dim,
01139                                                     Ordering::byNODES);
01140 
01141       ParDiscreteLinearOperator *id_ND;
01142       id_ND = new ParDiscreteLinearOperator(vert_fespace_d, edge_fespace);
01143       id_ND->AddDomainInterpolator(new IdentityInterpolator);
01144       id_ND->Assemble();
01145 
01146       if (cycle_type < 10)
01147       {
01148          id_ND->Finalize();
01149          Pi = id_ND->ParallelAssemble();
01150       }
01151       else
01152       {
01153          Array2D<HypreParMatrix *> Pi_blocks;
01154          id_ND->GetParBlocks(Pi_blocks);
01155          Pix = Pi_blocks(0,0);
01156          Piy = Pi_blocks(0,1);
01157          if (dim == 3)
01158             Piz = Pi_blocks(0,2);
01159       }
01160 
01161       HYPRE_AMSSetInterpolations(ams, *Pi, *Pix, *Piy, *Piz);
01162 
01163       delete vert_fespace_d;
01164    }
01165 
01166    delete vert_fespace;
01167    delete vert_fec;
01168 
01169    // set additional AMS options
01170    HYPRE_AMSSetSmoothingOptions(ams, rlx_type, rlx_sweeps, rlx_weight, rlx_omega);
01171    HYPRE_AMSSetAlphaAMGOptions(ams, amg_coarsen_type, amg_agg_levels, amg_rlx_type,
01172                                theta, amg_interp_type, amg_Pmax);
01173    HYPRE_AMSSetBetaAMGOptions(ams, amg_coarsen_type, amg_agg_levels, amg_rlx_type,
01174                               theta, amg_interp_type, amg_Pmax);
01175 }
01176 
01177 HypreAMS::~HypreAMS()
01178 {
01179    HYPRE_AMSDestroy(ams);
01180 
01181    delete x;
01182    delete y;
01183    delete z;
01184 
01185    delete G;
01186    delete Pi;
01187    delete Pix;
01188    delete Piy;
01189    delete Piz;
01190 }
01191 
01192 HypreADS::HypreADS(HypreParMatrix &A, ParFiniteElementSpace *face_fespace)
01193    : HypreSolver(&A)
01194 {
01195    int cycle_type       = 11;
01196    int rlx_type         = 2;
01197    int rlx_sweeps       = 1;
01198    double rlx_weight    = 1.0;
01199    double rlx_omega     = 1.0;
01200    int amg_coarsen_type = 10;
01201    int amg_agg_levels   = 1;
01202    int amg_rlx_type     = 6;
01203    double theta         = 0.25;
01204    int amg_interp_type  = 6;
01205    int amg_Pmax         = 4;
01206    int ams_cycle_type   = 14;
01207 
01208    int p = face_fespace->GetOrder(0);
01209 
01210    HYPRE_ADSCreate(&ads);
01211 
01212    HYPRE_ADSSetTol(ads, 0.0);
01213    HYPRE_ADSSetMaxIter(ads, 1); // use as a preconditioner
01214    HYPRE_ADSSetCycleType(ads, cycle_type);
01215    HYPRE_ADSSetPrintLevel(ads, 1);
01216 
01217    // define the nodal and edge finite element spaces associated with face_fespace
01218    ParMesh *pmesh = (ParMesh *) face_fespace->GetMesh();
01219    FiniteElementCollection *vert_fec   = new H1_FECollection(p, 3);
01220    ParFiniteElementSpace *vert_fespace = new ParFiniteElementSpace(pmesh, vert_fec);
01221    FiniteElementCollection *edge_fec   = new ND_FECollection(p, 3);
01222    ParFiniteElementSpace *edge_fespace = new ParFiniteElementSpace(pmesh, edge_fec);
01223 
01224    // generate and set the vertex coordinates
01225    if (p == 1)
01226    {
01227       ParGridFunction x_coord(vert_fespace);
01228       ParGridFunction y_coord(vert_fespace);
01229       ParGridFunction z_coord(vert_fespace);
01230       double *coord;
01231       for (int i = 0; i < pmesh->GetNV(); i++)
01232       {
01233          coord = pmesh -> GetVertex(i);
01234          x_coord(i) = coord[0];
01235          y_coord(i) = coord[1];
01236          z_coord(i) = coord[2];
01237       }
01238       x = x_coord.ParallelAverage();
01239       y = y_coord.ParallelAverage();
01240       z = z_coord.ParallelAverage();
01241       HYPRE_ADSSetCoordinateVectors(ads, *x, *y, *z);
01242    }
01243    else
01244    {
01245       x = NULL;
01246       y = NULL;
01247       z = NULL;
01248    }
01249 
01250    // generate and set the discrete curl
01251    ParDiscreteLinearOperator *curl;
01252    curl = new ParDiscreteLinearOperator(edge_fespace, face_fespace);
01253    curl->AddDomainInterpolator(new CurlInterpolator);
01254    curl->Assemble();
01255    curl->Finalize();
01256    C = curl->ParallelAssemble();
01257    HYPRE_ADSSetDiscreteCurl(ads, *C);
01258    delete curl;
01259 
01260    // generate and set the discrete gradient
01261    ParDiscreteLinearOperator *grad;
01262    grad = new ParDiscreteLinearOperator(vert_fespace, edge_fespace);
01263    grad->AddDomainInterpolator(new GradientInterpolator);
01264    grad->Assemble();
01265    grad->Finalize();
01266    G = grad->ParallelAssemble();
01267    HYPRE_ADSSetDiscreteGradient(ads, *G);
01268    delete grad;
01269 
01270    // generate and set the Nedelec and Raviart-Thomas interpolation matrices
01271    RT_Pi = RT_Pix = RT_Piy = RT_Piz = NULL;
01272    ND_Pi = ND_Pix = ND_Piy = ND_Piz = NULL;
01273    if (p > 1)
01274    {
01275       ParFiniteElementSpace *vert_fespace_d;
01276 
01277       if (ams_cycle_type < 10)
01278          vert_fespace_d = new ParFiniteElementSpace(pmesh, vert_fec, 3,
01279                                                     Ordering::byVDIM);
01280       else
01281          vert_fespace_d = new ParFiniteElementSpace(pmesh, vert_fec, 3,
01282                                                     Ordering::byNODES);
01283 
01284       ParDiscreteLinearOperator *id_ND;
01285       id_ND = new ParDiscreteLinearOperator(vert_fespace_d, edge_fespace);
01286       id_ND->AddDomainInterpolator(new IdentityInterpolator);
01287       id_ND->Assemble();
01288 
01289       if (ams_cycle_type < 10)
01290       {
01291          id_ND->Finalize();
01292          ND_Pi = id_ND->ParallelAssemble();
01293       }
01294       else
01295       {
01296          Array2D<HypreParMatrix *> ND_Pi_blocks;
01297          id_ND->GetParBlocks(ND_Pi_blocks);
01298          ND_Pix = ND_Pi_blocks(0,0);
01299          ND_Piy = ND_Pi_blocks(0,1);
01300          ND_Piz = ND_Pi_blocks(0,2);
01301       }
01302 
01303       if (cycle_type < 10 && ams_cycle_type > 10)
01304       {
01305          delete vert_fespace_d;
01306          vert_fespace_d = new ParFiniteElementSpace(pmesh, vert_fec, 3,
01307                                                     Ordering::byVDIM);
01308       }
01309       else if (cycle_type > 10 && ams_cycle_type < 10)
01310       {
01311          delete vert_fespace_d;
01312          vert_fespace_d = new ParFiniteElementSpace(pmesh, vert_fec, 3,
01313                                                     Ordering::byNODES);
01314       }
01315 
01316       ParDiscreteLinearOperator *id_RT;
01317       id_RT = new ParDiscreteLinearOperator(vert_fespace_d, face_fespace);
01318       id_RT->AddDomainInterpolator(new IdentityInterpolator);
01319       id_RT->Assemble();
01320 
01321       if (cycle_type < 10)
01322       {
01323          id_RT->Finalize();
01324          RT_Pi = id_RT->ParallelAssemble();
01325       }
01326       else
01327       {
01328          Array2D<HypreParMatrix *> RT_Pi_blocks;
01329          id_RT->GetParBlocks(RT_Pi_blocks);
01330          RT_Pix = RT_Pi_blocks(0,0);
01331          RT_Piy = RT_Pi_blocks(0,1);
01332          RT_Piz = RT_Pi_blocks(0,2);
01333       }
01334 
01335       HYPRE_ADSSetInterpolations(ads,
01336                                  *RT_Pi, *RT_Pix, *RT_Piy, *RT_Piz,
01337                                  *ND_Pi, *ND_Pix, *ND_Piy, *ND_Piz);
01338 
01339       delete vert_fespace_d;
01340    }
01341 
01342    delete vert_fec;
01343    delete vert_fespace;
01344    delete edge_fec;
01345    delete edge_fespace;
01346 
01347    // set additional ADS options
01348    HYPRE_ADSSetSmoothingOptions(ads, rlx_type, rlx_sweeps, rlx_weight, rlx_omega);
01349    HYPRE_ADSSetAMGOptions(ads, amg_coarsen_type, amg_agg_levels, amg_rlx_type,
01350                           theta, amg_interp_type, amg_Pmax);
01351    HYPRE_ADSSetAMSOptions(ads, ams_cycle_type, amg_coarsen_type, amg_agg_levels,
01352                           amg_rlx_type, theta, amg_interp_type, amg_Pmax);
01353 }
01354 
01355 HypreADS::~HypreADS()
01356 {
01357    HYPRE_ADSDestroy(ads);
01358 
01359    delete x;
01360    delete y;
01361    delete z;
01362 
01363    delete G;
01364    delete C;
01365 
01366    delete RT_Pi;
01367    delete RT_Pix;
01368    delete RT_Piy;
01369    delete RT_Piz;
01370 
01371    delete ND_Pi;
01372    delete ND_Pix;
01373    delete ND_Piy;
01374    delete ND_Piz;
01375 }
01376 
01377 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines