MFEM v2.0
sparsemat.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 // Implementation of sparse matrix
00013 
00014 #include <iostream>
00015 #include <iomanip>
00016 #include <math.h>
00017 
00018 #include "linalg.hpp"
00019 #include "../general/table.hpp"
00020 
00021 SparseMatrix::SparseMatrix(int nrows, int ncols)
00022    : Matrix(nrows)
00023 {
00024    I = NULL;
00025    J = NULL;
00026    A = NULL;
00027 
00028    Rows = new RowNode *[nrows];
00029    width = (ncols) ? (ncols) : (nrows);
00030    for (int i = 0; i < nrows; i++)
00031       Rows[i] = NULL;
00032    ColPtr.Node = NULL;
00033 }
00034 
00035 int SparseMatrix::RowSize(int i)
00036 {
00037    if (I)
00038       return I[i+1]-I[i];
00039 
00040    int s = 0;
00041    RowNode *row = Rows[i];
00042    for ( ; row != NULL; row = row->Prev)
00043       if (row->Value != 0.0)
00044          s++;
00045    return s;
00046 }
00047 
00048 double &SparseMatrix::Elem(int i, int j)
00049 {
00050    return operator()(i,j);
00051 }
00052 
00053 const double &SparseMatrix::Elem(int i, int j) const
00054 {
00055    return operator()(i,j);
00056 }
00057 
00058 double &SparseMatrix::operator()(int i, int j)
00059 {
00060    int k, end;
00061 
00062 #ifdef MFEM_DEBUG
00063    if (i >= size || i < 0 || j >= width || j < 0)
00064       mfem_error("SparseMatrix::operator() #1");
00065 #endif
00066 
00067    if (A == NULL)
00068       mfem_error("SparseMatrix::operator() #2");
00069 
00070    end = I[i+1];
00071    for (k = I[i]; k < end; k++)
00072       if (J[k] == j)
00073          return A[k];
00074 
00075    mfem_error("SparseMatrix::operator() #3");
00076    return A[0];
00077 }
00078 
00079 const double &SparseMatrix::operator()(int i, int j) const
00080 {
00081    int k, end;
00082    static const double zero = 0.0;
00083 
00084 #ifdef MFEM_DEBUG
00085    if (i >= size || i < 0 || j >= width || j < 0)
00086       mfem_error("SparseMatrix::operator() const #1");
00087 #endif
00088 
00089    if (A == NULL)
00090       mfem_error("SparseMatrix::operator() const #2");
00091    end = I[i+1];
00092    for (k = I[i]; k < end; k++)
00093       if (J[k] == j)
00094          return A[k];
00095 
00096    return zero;
00097 }
00098 
00099 void SparseMatrix::Mult(const Vector &x, Vector &y) const
00100 {
00101    y = 0.0;
00102    AddMult(x, y);
00103 }
00104 
00105 void SparseMatrix::AddMult(const Vector &x, Vector &y, const double a) const
00106 {
00107 #ifdef MFEM_DEBUG
00108    if (( width != x.Size() ) || ( size != y.Size() ))
00109       mfem_error("SparseMatrix::AddMult() #1");
00110 #endif
00111 
00112    int i, j, end;
00113    double *Ap = A, *yp = y.GetData();
00114    const double *xp = x.GetData();
00115 
00116    if (Ap == NULL)
00117    {
00118       //  The matrix is not finalized, but multiplication is still possible
00119       for (i = 0; i < size; i++)
00120       {
00121          RowNode *row = Rows[i];
00122          double b = 0.0;
00123          for ( ; row != NULL; row = row->Prev)
00124             b += row->Value * xp[row->Column];
00125          *yp += a * b;
00126          yp++;
00127       }
00128       return;
00129    }
00130 
00131    int *Jp = J, *Ip = I;
00132 
00133    j = *Ip;
00134    if (a == 1.0)
00135    {
00136 #ifndef MFEM_USE_OPENMP
00137       for (i = 0; i < size; i++)
00138       {
00139          double d = 0.0;
00140          Ip++;
00141          end = (*Ip);
00142          for ( ; j < end; j++)
00143          {
00144             d += (*Ap) * xp[*Jp];
00145             Ap++;
00146             Jp++;
00147          }
00148          *yp += d;
00149          yp++;
00150       }
00151 #else
00152 #pragma omp parallel for private(j,end)
00153       for (i = 0; i < size; i++)
00154       {
00155          double d = 0.0;
00156          for (j = Ip[i], end = Ip[i+1]; j < end; j++)
00157          {
00158             d += Ap[j] * xp[Jp[j]];
00159          }
00160          yp[i] += d;
00161       }
00162 #endif
00163    }
00164    else
00165       for (i = 0; i < size; i++)
00166       {
00167          double d = 0.0;
00168          Ip++;
00169          end = (*Ip);
00170          for ( ; j < end; j++)
00171          {
00172             d += (*Ap) * xp[*Jp];
00173             Ap++;
00174             Jp++;
00175          }
00176          *yp += a * d;
00177          yp++;
00178       }
00179 }
00180 
00181 void SparseMatrix::MultTranspose(const Vector &x, Vector &y) const
00182 {
00183    y = 0.0;
00184    AddMultTranspose(x, y);
00185 }
00186 
00187 void SparseMatrix::AddMultTranspose(const Vector &x, Vector &y,
00188                                     const double a) const
00189 {
00190 #ifdef MFEM_DEBUG
00191    if (( size != x.Size() ) || ( width != y.Size() ))
00192       mfem_error("SparseMatrix::AddMultTranspose() #1");
00193 #endif
00194 
00195    int i, j, end;
00196    double *yp = y.GetData();
00197 
00198    if (A == NULL)
00199    {
00200       // The matrix is not finalized, but multiplication is still possible
00201       for (i = 0; i < size; i++)
00202       {
00203          RowNode *row = Rows[i];
00204          double b = a * x(i);
00205          for ( ; row != NULL; row = row->Prev)
00206             yp[row->Column] += row->Value * b;
00207       }
00208       return;
00209    }
00210 
00211    for (i = 0; i < size; i++)
00212    {
00213       double xi = a * x(i);
00214       end = I[i+1];
00215       for(j = I[i]; j < end; j++)
00216       {
00217          yp[J[j]] += A[j]*xi;
00218       }
00219    }
00220 }
00221 
00222 void SparseMatrix::PartMult(
00223    const Array<int> &rows, const Vector &x, Vector &y)
00224 {
00225    if (A)
00226    {
00227       for (int i = 0; i < rows.Size(); i++)
00228       {
00229          int r = rows[i];
00230          int end = I[r+1];
00231          double a = 0.0;
00232          for (int j = I[r]; j < end; j++)
00233             a += A[j] * x(J[j]);
00234          y(r) = a;
00235       }
00236    }
00237    else
00238    {
00239       mfem_error("SparseMatrix::PartMult");
00240    }
00241 }
00242 
00243 double SparseMatrix::InnerProduct(const Vector &x, const Vector &y) const
00244 {
00245    double prod = 0.0;
00246    for (int i = 0; i < size; i++)
00247    {
00248       double a = 0.0;
00249       if (A)
00250          for (int j = I[i], end = I[i+1]; j < end; j++)
00251             a += A[j] * x(J[j]);
00252       else
00253          for (RowNode *np = Rows[i]; np != NULL; np = np->Prev)
00254             a += np->Value * x(np->Column);
00255       prod += a * y(i);
00256    }
00257 
00258    return prod;
00259 }
00260 
00261 void SparseMatrix::GetRowSums(Vector &x) const
00262 {
00263    for (int i = 0; i < size; i++)
00264    {
00265       double a = 0.0;
00266       if (A)
00267          for (int j = I[i], end = I[i+1]; j < end; j++)
00268             a += A[j];
00269       else
00270          for (RowNode *np = Rows[i]; np != NULL; np = np->Prev)
00271             a += np->Value;
00272       x(i) = a;
00273    }
00274 }
00275 
00276 void SparseMatrix::Finalize(int skip_zeros)
00277 {
00278    int i, j, nr, nz;
00279    RowNode *aux;
00280 
00281    delete [] ColPtr.Node;
00282    ColPtr.J = NULL;
00283 
00284    I = new int[size+1];
00285    I[0] = 0;
00286    for (i = 1; i <= size; i++)
00287    {
00288       nr = 0;
00289       for (aux = Rows[i-1]; aux != NULL; aux = aux->Prev)
00290          if (!skip_zeros || aux->Value != 0.0)
00291             nr++;
00292       I[i] = I[i-1] + nr;
00293    }
00294    nz = I[size];
00295    J = new int[nz];
00296    A = new double[nz];
00297    for (j = i = 0; i < size; i++)
00298       for (aux = Rows[i]; aux != NULL; aux = aux->Prev)
00299          if (!skip_zeros || aux->Value != 0.0)
00300          {
00301             J[j] = aux->Column;
00302             A[j] = aux->Value;
00303             j++;
00304          }
00305 #ifdef MFEM_USE_MEMALLOC
00306    NodesMem.Clear();
00307 #else
00308    for (i = 0; i < size; i++)
00309    {
00310       RowNode *node_p = Rows[i];
00311       while (node_p != NULL)
00312       {
00313          aux = node_p;
00314          node_p = node_p->Prev;
00315          delete aux;
00316       }
00317    }
00318 #endif
00319    delete [] Rows;
00320    Rows = NULL;
00321 }
00322 
00323 void SparseMatrix::GetBlocks(Array2D<SparseMatrix *> &blocks) const
00324 {
00325    if (A)
00326       mfem_error("SparseMatrix::GetBlocks : matrix is finalized!");
00327 
00328    int br = blocks.NumRows(), bc = blocks.NumCols();
00329    int nr = (size + br - 1)/br, nc = (width + bc - 1)/bc;
00330 
00331    for (int j = 0; j < bc; j++)
00332       for (int i = 0; i < br; i++)
00333       {
00334          int *bI = new int[nr + 1];
00335          for (int k = 0; k <= nr; k++)
00336             bI[k] = 0;
00337          blocks(i,j) = new SparseMatrix(bI, NULL, NULL, nr, nc);
00338       }
00339 
00340    for (int gr = 0; gr < size; gr++)
00341    {
00342       int bi = gr/nr, i = gr%nr + 1;
00343       for (RowNode *n_p = Rows[gr]; n_p != NULL; n_p = n_p->Prev)
00344          if (n_p->Value != 0.0)
00345             blocks(bi,n_p->Column/nc)->I[i]++;
00346    }
00347 
00348    for (int j = 0; j < bc; j++)
00349       for (int i = 0; i < br; i++)
00350       {
00351          SparseMatrix &b = *blocks(i,j);
00352          int nnz = 0, rs;
00353          for (int k = 1; k <= nr; k++)
00354             rs = b.I[k], b.I[k] = nnz, nnz += rs;
00355          b.J = new int[nnz];
00356          b.A = new double[nnz];
00357       }
00358 
00359    for (int gr = 0; gr < size; gr++)
00360    {
00361       int bi = gr/nr, i = gr%nr + 1;
00362       for (RowNode *n_p = Rows[gr]; n_p != NULL; n_p = n_p->Prev)
00363          if (n_p->Value != 0.0)
00364          {
00365             SparseMatrix &b = *blocks(bi,n_p->Column/nc);
00366             b.J[b.I[i]] = n_p->Column % nc;
00367             b.A[b.I[i]] = n_p->Value;
00368             b.I[i]++;
00369          }
00370    }
00371 }
00372 
00373 double SparseMatrix::IsSymmetric() const
00374 {
00375    if (A == NULL)
00376       mfem_error("SparseMatrix::IsSymmetric()");
00377 
00378    int i, j;
00379    double a, max;
00380 
00381    max = 0.0;
00382    for (i = 1; i < size; i++)
00383       for (j = I[i]; j < I[i+1]; j++)
00384          if (J[j] < i)
00385          {
00386             a = fabs ( A[j] - (*this)(J[j],i) );
00387             if (max < a)
00388                max = a;
00389          }
00390 
00391    return max;
00392 }
00393 
00394 void SparseMatrix::Symmetrize()
00395 {
00396    if (A == NULL)
00397       mfem_error("SparseMatrix::Symmetrize()");
00398 
00399    int i, j;
00400    for (i = 1; i < size; i++)
00401       for (j = I[i]; j < I[i+1]; j++)
00402          if (J[j] < i)
00403          {
00404             A[j] += (*this)(J[j],i);
00405             A[j] *= 0.5;
00406             (*this)(J[j],i) = A[j];
00407          }
00408 }
00409 
00410 int SparseMatrix::NumNonZeroElems() const
00411 {
00412    if (A != NULL)  //  matrix is finalized
00413    {
00414       return I[size];
00415    }
00416    else
00417    {
00418       int nnz = 0;
00419 
00420       for (int i = 0; i < size; i++)
00421          for (RowNode *node_p = Rows[i]; node_p != NULL; node_p = node_p->Prev)
00422             nnz++;
00423 
00424       return nnz;
00425    }
00426 }
00427 
00428 double SparseMatrix::MaxNorm() const
00429 {
00430    double m = 0.0;
00431 
00432    if (A)
00433    {
00434       int nnz = I[size];
00435       for (int j = 0; j < nnz; j++)
00436          m = fmax(m, fabs(A[j]));
00437    }
00438    else
00439    {
00440       for (int i = 0; i < size; i++)
00441          for (RowNode *n_p = Rows[i]; n_p != NULL; n_p = n_p->Prev)
00442             m = fmax(m, fabs(n_p->Value));
00443    }
00444    return m;
00445 }
00446 
00447 int SparseMatrix::CountSmallElems(double tol)
00448 {
00449    int i, counter = 0;
00450 
00451    if (A)
00452    {
00453       int nz = I[size];
00454       double *Ap = A;
00455 
00456       for (i = 0; i < nz; i++)
00457          if (fabs(Ap[i]) < tol)
00458             counter++;
00459    }
00460    else
00461    {
00462       RowNode *aux;
00463 
00464       for (i = 0; i < size; i++)
00465          for (aux = Rows[i]; aux != NULL; aux = aux->Prev)
00466             if (fabs(aux -> Value) < tol)
00467                counter++;
00468    }
00469 
00470    return counter;
00471 }
00472 
00473 MatrixInverse *SparseMatrix::Inverse() const
00474 {
00475    return NULL;
00476 }
00477 
00478 void SparseMatrix::EliminateRow(int row, const double sol, Vector &rhs)
00479 {
00480    RowNode *aux;
00481 
00482 #ifdef MFEM_DEBUG
00483    if ( row >= size || row < 0 )
00484       mfem_error("SparseMatrix::EliminateRow () #1");
00485 #endif
00486 
00487    if (Rows == NULL)
00488       mfem_error("SparseMatrix::EliminateRow () #2");
00489 
00490    for (aux = Rows[row]; aux != NULL; aux = aux->Prev)
00491    {
00492       rhs(aux->Column) -= sol * aux->Value;
00493       aux->Value = 0.0;
00494    }
00495 }
00496 
00497 void SparseMatrix::EliminateRow(int row)
00498 {
00499    RowNode *aux;
00500 
00501 #ifdef MFEM_DEBUG
00502    if ( row >= size || row < 0 )
00503       mfem_error("SparseMatrix::EliminateRow () #1");
00504 #endif
00505 
00506    if (Rows == NULL)
00507       mfem_error("SparseMatrix::EliminateRow () #2");
00508 
00509    for (aux = Rows[row]; aux != NULL; aux = aux->Prev)
00510       aux->Value = 0.0;
00511 }
00512 
00513 void SparseMatrix::EliminateCol(int col)
00514 {
00515    RowNode *aux;
00516 
00517    if (Rows == NULL)
00518       mfem_error("SparseMatrix::EliminateCol () #1");
00519 
00520    for (int i = 0; i < size; i++)
00521       for (aux = Rows[i]; aux != NULL; aux = aux->Prev)
00522          if (aux -> Column == col)
00523             aux->Value = 0.0;
00524 }
00525 
00526 void SparseMatrix::EliminateCols(Array<int> &cols, Vector *x, Vector *b)
00527 {
00528    RowNode *aux;
00529 
00530    if (Rows == NULL)
00531       mfem_error("SparseMatrix::EliminateCols () #1");
00532 
00533    for (int i = 0; i < size; i++)
00534       for (aux = Rows[i]; aux != NULL; aux = aux->Prev)
00535          if (cols[aux -> Column])
00536          {
00537             if (x && b)
00538                (*b)(i) -= aux -> Value * (*x)(aux -> Column);
00539             aux->Value = 0.0;
00540          }
00541 }
00542 
00543 void SparseMatrix::EliminateRowCol(int rc, const double sol, Vector &rhs,
00544                                    int d)
00545 {
00546    int col;
00547 
00548 #ifdef MFEM_DEBUG
00549    if ( rc >= size || rc < 0 )
00550       mfem_error("SparseMatrix::EliminateRowCol () #1");
00551 #endif
00552 
00553    if (Rows == NULL)
00554       for (int j = I[rc]; j < I[rc+1]; j++)
00555          if ((col = J[j]) == rc)
00556             if (d)
00557             {
00558                rhs(rc) = A[j] * sol;
00559             }
00560             else
00561             {
00562                A[j] = 1.0;
00563                rhs(rc) = sol;
00564             }
00565          else
00566          {
00567             A[j] = 0.0;
00568             for (int k = I[col]; 1; k++)
00569                if (k == I[col+1])
00570                {
00571                   mfem_error("SparseMatrix::EliminateRowCol () #2");
00572                }
00573                else if (J[k] == rc)
00574                {
00575                   rhs(col) -= sol * A[k];
00576                   A[k] = 0.0;
00577                   break;
00578                }
00579          }
00580    else
00581       for (RowNode *aux = Rows[rc]; aux != NULL; aux = aux->Prev)
00582          if ((col = aux->Column) == rc)
00583             if (d)
00584             {
00585                rhs(rc) = aux->Value * sol;
00586             }
00587             else
00588             {
00589                aux->Value = 1.0;
00590                rhs(rc) = sol;
00591             }
00592          else
00593          {
00594             aux->Value = 0.0;
00595             for (RowNode *node = Rows[col]; 1; node = node->Prev)
00596                if (node == NULL)
00597                {
00598                   mfem_error("SparseMatrix::EliminateRowCol () #3");
00599                }
00600                else if (node->Column == rc)
00601                {
00602                   rhs(col) -= sol * node->Value;
00603                   node->Value = 0.0;
00604                   break;
00605                }
00606          }
00607 }
00608 
00609 void SparseMatrix::EliminateRowColMultipleRHS(int rc, const Vector &sol,
00610                                               DenseMatrix &rhs, int d)
00611 {
00612    int col;
00613    int num_rhs = rhs.Width();
00614 
00615 #ifdef MFEM_DEBUG
00616    if (rc >= size || rc < 0)
00617       mfem_error("SparseMatrix::EliminateRowColMultipleRHS() #1");
00618    if (sol.Size() != num_rhs)
00619       mfem_error("SparseMatrix::EliminateRowColMultipleRHS() #2");
00620 #endif
00621 
00622    if (Rows == NULL)
00623       for (int j = I[rc]; j < I[rc+1]; j++)
00624          if ((col = J[j]) == rc)
00625             if (d)
00626             {
00627                for (int r = 0; r < num_rhs; r++)
00628                   rhs(rc,r) = A[j] * sol(r);
00629             }
00630             else
00631             {
00632                A[j] = 1.0;
00633                for (int r = 0; r < num_rhs; r++)
00634                   rhs(rc,r) = sol(r);
00635             }
00636          else
00637          {
00638             A[j] = 0.0;
00639             for (int k = I[col]; 1; k++)
00640                if (k == I[col+1])
00641                {
00642                   mfem_error("SparseMatrix::EliminateRowColMultipleRHS() #3");
00643                }
00644                else if (J[k] == rc)
00645                {
00646                   for (int r = 0; r < num_rhs; r++)
00647                      rhs(col,r) -= sol(r) * A[k];
00648                   A[k] = 0.0;
00649                   break;
00650                }
00651          }
00652    else
00653       for (RowNode *aux = Rows[rc]; aux != NULL; aux = aux->Prev)
00654          if ((col = aux->Column) == rc)
00655             if (d)
00656             {
00657                for (int r = 0; r < num_rhs; r++)
00658                   rhs(rc,r) = aux->Value * sol(r);
00659             }
00660             else
00661             {
00662                aux->Value = 1.0;
00663                for (int r = 0; r < num_rhs; r++)
00664                   rhs(rc,r) = sol(r);
00665             }
00666          else
00667          {
00668             aux->Value = 0.0;
00669             for (RowNode *node = Rows[col]; 1; node = node->Prev)
00670                if (node == NULL)
00671                {
00672                   mfem_error("SparseMatrix::EliminateRowColMultipleRHS() #4");
00673                }
00674                else if (node->Column == rc)
00675                {
00676                   for (int r = 0; r < num_rhs; r++)
00677                      rhs(col,r) -= sol(r) * node->Value;
00678                   node->Value = 0.0;
00679                   break;
00680                }
00681          }
00682 }
00683 
00684 void SparseMatrix::EliminateRowCol(int rc, int d)
00685 {
00686    int col;
00687    RowNode *aux, *node;
00688 
00689 #ifdef MFEM_DEBUG
00690    if ( rc >= size || rc < 0 )
00691       mfem_error("SparseMatrix::EliminateRowCol () #1");
00692 #endif
00693 
00694    if (Rows == NULL)
00695       mfem_error("SparseMatrix::EliminateRowCol () #2");
00696 
00697    for (aux = Rows[rc]; aux != NULL; aux = aux->Prev)
00698    {
00699       if ((col = aux->Column) == rc)
00700       {
00701          if (d == 0)
00702             aux->Value = 1.0;
00703       }
00704       else
00705       {
00706          aux->Value = 0.0;
00707          for (node = Rows[col]; 1; node = node->Prev)
00708             if (node == NULL)
00709             {
00710                mfem_error("SparseMatrix::EliminateRowCol () #3");
00711             }
00712             else if (node->Column == rc)
00713             {
00714                node->Value = 0.0;
00715                break;
00716             }
00717       }
00718    }
00719 }
00720 
00721 void SparseMatrix::EliminateRowCol(int rc, SparseMatrix &Ae, int d)
00722 {
00723    int col;
00724 
00725    if (Rows)
00726    {
00727       RowNode *nd, *nd2;
00728       for (nd = Rows[rc]; nd != NULL; nd = nd->Prev)
00729       {
00730          if ((col = nd->Column) == rc)
00731          {
00732             if (d == 0)
00733             {
00734                Ae.Add(rc, rc, nd->Value - 1.0);
00735                nd->Value = 1.0;
00736             }
00737          }
00738          else
00739          {
00740             Ae.Add(rc, col, nd->Value);
00741             nd->Value = 0.0;
00742             for (nd2 = Rows[col]; 1; nd2 = nd2->Prev)
00743             {
00744                if (nd2 == NULL)
00745                {
00746                   mfem_error("SparseMatrix::EliminateRowCol");
00747                }
00748                else if (nd2->Column == rc)
00749                {
00750                   Ae.Add(col, rc, nd2->Value);
00751                   nd2->Value = 0.0;
00752                   break;
00753                }
00754             }
00755          }
00756       }
00757    }
00758    else
00759    {
00760       for (int j = I[rc]; j < I[rc+1]; j++)
00761          if ((col = J[j]) == rc)
00762          {
00763             if (d == 0)
00764             {
00765                Ae.Add(rc, rc, A[j] - 1.0);
00766                A[j] = 1.0;
00767             }
00768          }
00769          else
00770          {
00771             Ae.Add(rc, col, A[j]);
00772             A[j] = 0.0;
00773             for (int k = I[col]; true; k++)
00774                if (k == I[col+1])
00775                {
00776                   mfem_error("SparseMatrix::EliminateRowCol");
00777                }
00778                else if (J[k] == rc)
00779                {
00780                   Ae.Add(col, rc, A[k]);
00781                   A[k] = 0.0;
00782                   break;
00783                }
00784          }
00785    }
00786 }
00787 
00788 void SparseMatrix::SetDiagIdentity()
00789 {
00790    for (int i = 0; i < size; i++)
00791       if (I[i+1] == I[i]+1 && fabs(A[I[i]]) < 1e-16)
00792          A[I[i]] = 1.0;
00793 }
00794 
00795 void SparseMatrix::EliminateZeroRows()
00796 {
00797    int i, j;
00798    double zero;
00799 
00800    for (i = 0; i < size; i++) {
00801       zero = 0.0;
00802       for (j = I[i]; j < I[i+1]; j++)
00803          zero += fabs(A[j]);
00804       if (zero < 1e-12) {
00805          for (j = I[i]; j < I[i+1]; j++)
00806             if (J[j] == i)
00807                A[j] = 1.0;
00808             else
00809                A[j] = 0.0;
00810       }
00811    }
00812 }
00813 
00814 void SparseMatrix::Gauss_Seidel_forw(const Vector &x, Vector &y) const
00815 {
00816    int c, i, s = size;
00817    double sum, *yp = y.GetData();
00818    const double *xp = x.GetData();
00819 
00820    if (A == NULL)
00821    {
00822       RowNode *diag_p, *n_p, **R = Rows;
00823 
00824       for (i = 0; i < s; i++)
00825       {
00826          sum = 0.0;
00827          diag_p = NULL;
00828          for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
00829             if ((c = n_p->Column) == i)
00830                diag_p = n_p;
00831             else
00832                sum += n_p->Value * yp[c];
00833 
00834          if (diag_p != NULL && diag_p->Value != 0.0)
00835             yp[i] = (xp[i] - sum) / diag_p->Value;
00836          else
00837             if (xp[i] == sum)
00838                yp[i] = sum;
00839             else
00840                mfem_error("SparseMatrix::Gauss_Seidel_forw()");
00841       }
00842    }
00843    else
00844    {
00845       int j, end, d, *Ip = I, *Jp = J;
00846       double *Ap = A;
00847 
00848       j = Ip[0];
00849       for (i = 0; i < s; i++)
00850       {
00851          end = Ip[i+1];
00852          sum = 0.0;
00853          d = -1;
00854          for ( ; j < end; j++)
00855             if ((c = Jp[j]) == i)
00856                d = j;
00857             else
00858                sum += Ap[j] * yp[c];
00859 
00860          if (d >= 0 && Ap[d] != 0.0)
00861             yp[i] = (xp[i] - sum) / Ap[d];
00862          else
00863             if (xp[i] == sum)
00864                yp[i] = sum;
00865             else
00866                mfem_error("SparseMatrix::Gauss_Seidel_forw(...) #2");
00867       }
00868    }
00869 }
00870 
00871 void SparseMatrix::Gauss_Seidel_back(const Vector &x, Vector &y) const
00872 {
00873    int i, c;
00874    double sum, *yp = y.GetData();
00875    const double *xp = x.GetData();
00876 
00877    if (A == NULL)
00878    {
00879       RowNode *diag_p, *n_p, **R = Rows;
00880 
00881       for (i = size-1; i >= 0; i--)
00882       {
00883          sum = 0.;
00884          diag_p = NULL;
00885          for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
00886             if ((c = n_p->Column) == i)
00887                diag_p = n_p;
00888             else
00889                sum += n_p->Value * yp[c];
00890 
00891          if (diag_p != NULL && diag_p->Value != 0.0)
00892             yp[i] = (xp[i] - sum) / diag_p->Value;
00893          else
00894             if (xp[i] == sum)
00895                yp[i] = sum;
00896             else
00897                mfem_error("SparseMatrix::Gauss_Seidel_back()");
00898       }
00899    }
00900    else
00901    {
00902       int j, beg, d, *Ip = I, *Jp = J;
00903       double *Ap = A;
00904 
00905       j = Ip[size]-1;
00906       for (i = size-1; i >= 0; i--)
00907       {
00908          beg = Ip[i];
00909          sum = 0.;
00910          d = -1;
00911          for( ; j >= beg; j--)
00912             if ((c = Jp[j]) == i)
00913                d = j;
00914             else
00915                sum += Ap[j] * yp[c];
00916 
00917          if (d >= 0 && Ap[d] != 0.0)
00918             yp[i] = (xp[i] - sum) / Ap[d];
00919          else
00920             if (xp[i] == sum)
00921                yp[i] = sum;
00922             else
00923                mfem_error("SparseMatrix::Gauss_Seidel_back(...) #2");
00924       }
00925    }
00926 }
00927 
00928 double SparseMatrix::GetJacobiScaling() const
00929 {
00930    if (A == NULL)
00931       mfem_error("SparseMatrix::GetJacobiScaling()");
00932 
00933    double sc = 1.0;
00934    for (int i = 0; i < size; i++)
00935    {
00936       int d = -1;
00937       double norm = 0.0;
00938       for (int j = I[i]; j < I[i+1]; j++)
00939       {
00940          if (J[j] == i)
00941             d = j;
00942          norm += fabs(A[j]);
00943       }
00944       if (d >= 0 && A[d] != 0.0)
00945       {
00946          double a = 1.8 * fabs(A[d]) / norm;
00947          if (a < sc)
00948             sc = a;
00949       }
00950       else
00951          mfem_error("SparseMatrix::GetJacobiScaling() #2");
00952    }
00953    return sc;
00954 }
00955 
00956 void SparseMatrix::Jacobi(const Vector &b, const Vector &x0, Vector &x1,
00957                           double sc) const
00958 {
00959    if (A == NULL)
00960       mfem_error("SparseMatrix::Jacobi(...)");
00961 
00962    for (int i = 0; i < size; i++)
00963    {
00964       int d = -1;
00965       double sum = b(i);
00966       for (int j = I[i]; j < I[i+1]; j++)
00967       {
00968          if (J[j] == i)
00969             d = j;
00970          else
00971             sum -= A[j] * x0(J[j]);
00972       }
00973       if (d >= 0 && A[d] != 0.0)
00974          x1(i) = sc * (sum / A[d]) + (1.0 - sc) * x0(i);
00975       else
00976          mfem_error("SparseMatrix::Jacobi(...) #2");
00977    }
00978 }
00979 
00980 void SparseMatrix::Jacobi2(const Vector &b, const Vector &x0, Vector &x1,
00981                            double sc) const
00982 {
00983    if (A == NULL)
00984       mfem_error("SparseMatrix::Jacobi2(...)");
00985 
00986    for (int i = 0; i < size; i++)
00987    {
00988       double resi = b(i), norm = 0.0;
00989       for (int j = I[i]; j < I[i+1]; j++)
00990       {
00991          resi -= A[j] * x0(J[j]);
00992          norm += fabs(A[j]);
00993       }
00994       if (norm > 0.0)
00995          x1(i) = x0(i) + sc * resi / norm;
00996       else
00997          mfem_error("SparseMatrix::Jacobi2(...) #2");
00998    }
00999 }
01000 
01001 void SparseMatrix::AddSubMatrix(const Array<int> &rows, const Array<int> &cols,
01002                                 const DenseMatrix &subm, int skip_zeros)
01003 {
01004    int i, j, gi, gj, s, t;
01005    double a;
01006 
01007    for (i = 0; i < rows.Size(); i++)
01008    {
01009       if ((gi=rows[i]) < 0) gi = -1-gi, s = -1; else s = 1;
01010 #ifdef MFEM_DEBUG
01011       if (gi >= size)
01012          mfem_error("SparseMatrix::AddSubMatrix(...) #1");
01013 #endif
01014       SetColPtr(gi);
01015       for (j = 0; j < cols.Size(); j++)
01016       {
01017          if ((gj=cols[j]) < 0) gj = -1-gj, t = -s; else t = s;
01018 #ifdef MFEM_DEBUG
01019          if (gj >= width)
01020             mfem_error("SparseMatrix::AddSubMatrix(...) #2");
01021 #endif
01022          a = subm(i, j);
01023          if (skip_zeros && a == 0.0)
01024          {
01025             // if the element is zero do not assemble it unless this breaks
01026             // the symmetric structure
01027             if (&rows != &cols || subm(j, i) == 0.0)
01028                continue;
01029          }
01030          if (t < 0)  a = -a;
01031          _Add_(gj, a);
01032       }
01033       ClearColPtr();
01034    }
01035 }
01036 
01037 void SparseMatrix::Set(const int i, const int j, const double A)
01038 {
01039    double a = A;
01040    int gi, gj, s, t;
01041 
01042    if ((gi=i) < 0) gi = -1-gi, s = -1; else s = 1;
01043 #ifdef MFEM_DEBUG
01044    if (gi >= size)
01045       mfem_error("SparseMatrix::Set (...) #1");
01046 #endif
01047    if ((gj=j) < 0) gj = -1-gj, t = -s; else t = s;
01048 #ifdef MFEM_DEBUG
01049    if (gj >= width)
01050       mfem_error("SparseMatrix::Set (...) #2");
01051 #endif
01052    if (t < 0)  a = -a;
01053    _Set_(gi, gj, a);
01054 }
01055 
01056 void SparseMatrix::Add(const int i, const int j, const double A)
01057 {
01058    int gi, gj, s, t;
01059    double a = A;
01060 
01061    if ((gi=i) < 0) gi = -1-gi, s = -1; else s = 1;
01062 #ifdef MFEM_DEBUG
01063    if (gi >= size)
01064       mfem_error("SparseMatrix::Add (...) #1");
01065 #endif
01066    if ((gj=j) < 0) gj = -1-gj, t = -s; else t = s;
01067 #ifdef MFEM_DEBUG
01068    if (gj >= width)
01069       mfem_error("SparseMatrix::Add (...) #2");
01070 #endif
01071    if (t < 0)  a = -a;
01072    _Add_(gi, gj, a);
01073 }
01074 
01075 void SparseMatrix::SetSubMatrix(const Array<int> &rows, const Array<int> &cols,
01076                                 const DenseMatrix &subm, int skip_zeros)
01077 {
01078    int i, j, gi, gj, s, t;
01079    double a;
01080 
01081    for (i = 0; i < rows.Size(); i++)
01082    {
01083       if ((gi=rows[i]) < 0) gi = -1-gi, s = -1; else s = 1;
01084 #ifdef MFEM_DEBUG
01085       if (gi >= size)
01086          mfem_error("SparseMatrix::SetSubMatrix(...) #1");
01087 #endif
01088       SetColPtr(gi);
01089       for (j = 0; j < cols.Size(); j++)
01090       {
01091          a = subm(i, j);
01092          if (skip_zeros && a == 0.0)
01093             continue;
01094          if ((gj=cols[j]) < 0) gj = -1-gj, t = -s; else t = s;
01095 #ifdef MFEM_DEBUG
01096          if (gj >= width)
01097             mfem_error("SparseMatrix::SetSubMatrix(...) #2");
01098 #endif
01099          if (t < 0)  a = -a;
01100          _Set_(gj, a);
01101       }
01102       ClearColPtr();
01103    }
01104 }
01105 
01106 void SparseMatrix::SetSubMatrixTranspose(const Array<int> &rows,
01107                                          const Array<int> &cols,
01108                                          const DenseMatrix &subm,
01109                                          int skip_zeros)
01110 {
01111    int i, j, gi, gj, s, t;
01112    double a;
01113 
01114    for (i = 0; i < rows.Size(); i++)
01115    {
01116       if ((gi=rows[i]) < 0) gi = -1-gi, s = -1; else s = 1;
01117 #ifdef MFEM_DEBUG
01118       if (gi >= size)
01119          mfem_error("SparseMatrix::SetSubMatrixTranspose (...) #1");
01120 #endif
01121       SetColPtr(gi);
01122       for (j = 0; j < cols.Size(); j++)
01123       {
01124          a = subm(j, i);
01125          if (skip_zeros && a == 0.0)
01126             continue;
01127          if ((gj=cols[j]) < 0) gj = -1-gj, t = -s; else t = s;
01128 #ifdef MFEM_DEBUG
01129          if (gj >= width)
01130             mfem_error("SparseMatrix::SetSubMatrixTranspose (...) #2");
01131 #endif
01132          if (t < 0)  a = -a;
01133          _Set_(gj, a);
01134       }
01135       ClearColPtr();
01136    }
01137 }
01138 
01139 void SparseMatrix::GetSubMatrix(const Array<int> &rows, const Array<int> &cols,
01140                                 DenseMatrix &subm)
01141 {
01142    int i, j, gi, gj, s, t;
01143    double a;
01144 
01145    for (i = 0; i < rows.Size(); i++)
01146    {
01147       if ((gi=rows[i]) < 0) gi = -1-gi, s = -1; else s = 1;
01148 #ifdef MFEM_DEBUG
01149       if (gi >= size)
01150          mfem_error("SparseMatrix::GetSubMatrix(...) #1");
01151 #endif
01152       SetColPtr(gi);
01153       for (j = 0; j < cols.Size(); j++)
01154       {
01155          if ((gj=cols[j]) < 0) gj = -1-gj, t = -s; else t = s;
01156 #ifdef MFEM_DEBUG
01157          if (gj >= width)
01158             mfem_error("SparseMatrix::GetSubMatrix(...) #2");
01159 #endif
01160          a = _Get_(gj);
01161          subm(i, j) = (t < 0) ? (-a) : (a);
01162       }
01163       ClearColPtr();
01164    }
01165 }
01166 
01167 void SparseMatrix::AddRow(const int row, const Array<int> &cols,
01168                           const Vector &srow)
01169 {
01170    int j, gi, gj, s, t;
01171    double a;
01172 
01173    if (Rows == NULL)
01174       mfem_error("SparseMatrix::AddRow(...) #0");
01175 
01176    if ((gi=row) < 0) gi = -1-gi, s = -1; else s = 1;
01177 #ifdef MFEM_DEBUG
01178    if (gi >= size)
01179       mfem_error("SparseMatrix::AddRow(...) #1");
01180 #endif
01181    SetColPtr(gi);
01182    for (j = 0; j < cols.Size(); j++)
01183    {
01184       if ((gj=cols[j]) < 0) gj = -1-gj, t = -s; else t = s;
01185 #ifdef MFEM_DEBUG
01186       if (gj >= width)
01187          mfem_error("SparseMatrix::AddRow(...) #2");
01188 #endif
01189       a = srow(j);
01190       if (a == 0.0)
01191          continue;
01192       if (t < 0)  a = -a;
01193       _Add_(gj, a);
01194    }
01195    ClearColPtr();
01196 }
01197 
01198 void SparseMatrix::ScaleRow(const int row, const double scale)
01199 {
01200    int i;
01201 
01202    if ((i=row) < 0)
01203       i = -1-i;
01204    if (Rows != NULL)
01205    {
01206       RowNode *aux;
01207 
01208       for (aux = Rows[i]; aux != NULL; aux = aux -> Prev)
01209          aux -> Value *= scale;
01210    }
01211    else
01212    {
01213       int j, end = I[i+1];
01214 
01215       for (j = I[i]; j < end; j++)
01216          A[j] *= scale;
01217    }
01218 }
01219 
01220 SparseMatrix &SparseMatrix::operator+=(SparseMatrix &B)
01221 {
01222    int i;
01223    RowNode *aux;
01224 
01225    if (Rows == NULL || B.Rows == NULL)
01226       mfem_error("SparseMatrix::operator+=(...) #0");
01227 #ifdef MFEM_DEBUG
01228    if (size != B.size || width != B.width)
01229       mfem_error("SparseMatrix::operator+=(...) #1");
01230 #endif
01231 
01232    for (i = 0; i < size; i++)
01233    {
01234       SetColPtr(i);
01235       for (aux = B.Rows[i]; aux != NULL; aux = aux->Prev)
01236       {
01237          _Add_(aux->Column, aux->Value);
01238       }
01239       ClearColPtr();
01240    }
01241 
01242    return (*this);
01243 }
01244 
01245 SparseMatrix &SparseMatrix::operator=(double a)
01246 {
01247    if (Rows == NULL)
01248       for (int i = 0, nnz = I[size]; i < nnz; i++)
01249          A[i] = a;
01250    else
01251       for (int i = 0; i < size; i++)
01252          for (RowNode *node_p = Rows[i]; node_p != NULL;
01253               node_p = node_p -> Prev)
01254             node_p -> Value = a;
01255 
01256    return (*this);
01257 }
01258 
01259 void SparseMatrix::Print(ostream & out, int _width) const
01260 {
01261    int i, j;
01262 
01263    if (A == NULL)
01264       mfem_error("SparseMatrix::Print()");
01265 
01266    for (i = 0; i < size; i++)
01267    {
01268       out << "[row " << i << "]\n";
01269       for (j = I[i]; j < I[i+1]; j++)
01270       {
01271          out << " (" << J[j] << ","<< A[j] << ")";
01272          if ( !((j+1-I[i]) % _width) )
01273             out << '\n';
01274       }
01275       if ((j-I[i]) % _width)
01276          out << '\n';
01277    }
01278 }
01279 
01280 void SparseMatrix::PrintMatlab(ostream & out) const
01281 {
01282    int i, j;
01283    ios::fmtflags old_fmt = out.setf(ios::scientific);
01284    int old_prec = out.precision(14);
01285 
01286    for(i = 0; i < size; i++)
01287       for (j = I[i]; j < I[i+1]; j++)
01288          out << i+1 << " " << J[j]+1 << " " << A[j] << endl;
01289    out.precision(old_prec);
01290    out.setf(old_fmt);
01291 }
01292 
01293 void SparseMatrix::PrintMM(ostream & out) const
01294 {
01295    int i, j;
01296    ios::fmtflags old_fmt = out.setf(ios::scientific);
01297    int old_prec = out.precision(14);
01298 
01299    out << "%%MatrixMarket matrix coordinate real general" << endl
01300        << "% Generated by MFEM" << endl;
01301 
01302    out << size << " " << width << " " << NumNonZeroElems() << endl;
01303    for(i = 0; i < size; i++)
01304       for (j = I[i]; j < I[i+1]; j++)
01305          out << i+1 << " " << J[j]+1 << " " << A[j] << endl;
01306    out.precision(old_prec);
01307    out.setf(old_fmt);
01308 }
01309 
01310 void SparseMatrix::PrintCSR(ostream & out) const
01311 {
01312    if (A == NULL)
01313       mfem_error("SparseMatrix::PrintCSR()");
01314 
01315    int i;
01316 
01317    out << size << '\n';  // number of rows
01318 
01319    for (i = 0; i <= size; i++)
01320       out << I[i]+1 << '\n';
01321 
01322    for (i = 0; i < I[size]; i++)
01323       out << J[i]+1 << '\n';
01324 
01325    for (i = 0; i < I[size]; i++)
01326       out << A[i] << '\n';
01327 }
01328 
01329 void SparseMatrix::PrintCSR2(ostream & out) const
01330 {
01331    if (A == NULL)
01332       mfem_error("SparseMatrix::PrintCSR2()");
01333 
01334    int i;
01335 
01336    out << size << '\n';  // number of rows
01337    out << width << '\n';  // number of columns
01338 
01339    for (i = 0; i <= size; i++)
01340       out << I[i] << '\n';
01341 
01342    for (i = 0; i < I[size]; i++)
01343       out << J[i] << '\n';
01344 
01345    for (i = 0; i < I[size]; i++)
01346       out << A[i] << '\n';
01347 }
01348 
01349 SparseMatrix::~SparseMatrix ()
01350 {
01351    if (Rows != NULL)
01352    {
01353       delete [] ColPtr.Node;
01354 #ifdef MFEM_USE_MEMALLOC
01355       // NodesMem.Clear();  // this is done implicitly
01356 #else
01357       for (int i = 0; i < size; i++)
01358       {
01359          RowNode *aux, *node_p = Rows[i];
01360          while (node_p != NULL)
01361          {
01362             aux = node_p;
01363             node_p = node_p->Prev;
01364             delete aux;
01365          }
01366       }
01367 #endif
01368       delete [] Rows;
01369    }
01370    if (A != NULL)
01371    {
01372       delete [] ColPtr.J;
01373       delete [] I;
01374       delete [] J;
01375       delete [] A;
01376    }
01377 }
01378 
01379 void SparseMatrixFunction (SparseMatrix & S, double (*f)(double))
01380 {
01381    int n = S.NumNonZeroElems();
01382    double * s = S.GetData();
01383 
01384    for (int i = 0; i < n; i++)
01385       s[i] = f(s[i]);
01386 }
01387 
01388 SparseMatrix *Transpose (SparseMatrix &A)
01389 {
01390    int i, j, end;
01391    int m, n, nnz, *A_i, *A_j, *At_i, *At_j;
01392    double *A_data, *At_data;
01393 
01394    m      = A.Size();   // number of rows of A
01395    n      = A.Width();  // number of columns of A
01396    nnz    = A.NumNonZeroElems();
01397    A_i    = A.GetI();
01398    A_j    = A.GetJ();
01399    A_data = A.GetData();
01400 
01401    At_i = new int[n+1];
01402    At_j = new int[nnz];
01403    At_data = new double[nnz];
01404 
01405    for (i = 0; i <= n; i++)
01406       At_i[i] = 0;
01407    for (i = 0; i < nnz; i++)
01408       At_i[A_j[i]+1]++;
01409    for (i = 1; i < n; i++)
01410       At_i[i+1] += At_i[i];
01411 
01412    for (i = j = 0; i < m; i++)
01413    {
01414       end = A_i[i+1];
01415       for ( ; j < end; j++)
01416       {
01417          At_j[At_i[A_j[j]]] = i;
01418          At_data[At_i[A_j[j]]] = A_data[j];
01419          At_i[A_j[j]]++;
01420       }
01421    }
01422 
01423    for (i = n; i > 0; i--)
01424       At_i[i] = At_i[i-1];
01425    At_i[0] = 0;
01426 
01427    return  new SparseMatrix (At_i, At_j, At_data, n, m);
01428 }
01429 
01430 SparseMatrix *Mult (SparseMatrix &A, SparseMatrix &B,
01431                     SparseMatrix *OAB)
01432 {
01433    int nrowsA, ncolsA, nrowsB, ncolsB;
01434    int *A_i, *A_j, *B_i, *B_j, *C_i, *C_j, *B_marker;
01435    double *A_data, *B_data, *C_data;
01436    int ia, ib, ic, ja, jb, num_nonzeros;
01437    int row_start, counter;
01438    double a_entry, b_entry;
01439    SparseMatrix *C;
01440 
01441    nrowsA = A.Size();
01442    ncolsA = A.Width();
01443    nrowsB = B.Size();
01444    ncolsB = B.Width();
01445 
01446    if (ncolsA != nrowsB)
01447       mfem_error("Sparse matrix multiplication, Mult (...) #1");
01448 
01449    A_i    = A.GetI();
01450    A_j    = A.GetJ();
01451    A_data = A.GetData();
01452    B_i    = B.GetI();
01453    B_j    = B.GetJ();
01454    B_data = B.GetData();
01455 
01456    B_marker = new int[ncolsB];
01457 
01458    for (ib = 0; ib < ncolsB; ib++)
01459       B_marker[ib] = -1;
01460 
01461    if (OAB == NULL)
01462    {
01463       C_i = new int[nrowsA+1];
01464 
01465       C_i[0] = num_nonzeros = 0;
01466       for (ic = 0; ic < nrowsA; ic++)
01467       {
01468          for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
01469          {
01470             ja = A_j[ia];
01471             for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
01472             {
01473                jb = B_j[ib];
01474                if (B_marker[jb] != ic)
01475                {
01476                   B_marker[jb] = ic;
01477                   num_nonzeros++;
01478                }
01479             }
01480          }
01481          C_i[ic+1] = num_nonzeros;
01482       }
01483 
01484       C_j    = new int[num_nonzeros];
01485       C_data = new double[num_nonzeros];
01486 
01487       C = new SparseMatrix (C_i, C_j, C_data, nrowsA, ncolsB);
01488 
01489       for (ib = 0; ib < ncolsB; ib++)
01490          B_marker[ib] = -1;
01491    }
01492    else
01493    {
01494       C = OAB;
01495 
01496       if (nrowsA != C -> Size() || ncolsB != C -> Width())
01497          mfem_error("Sparse matrix multiplication, Mult (...) #2");
01498 
01499       C_i    = C -> GetI();
01500       C_j    = C -> GetJ();
01501       C_data = C -> GetData();
01502    }
01503 
01504    counter = 0;
01505    for (ic = 0; ic < nrowsA; ic++)
01506    {
01507       // row_start = C_i[ic];
01508       row_start = counter;
01509       for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
01510       {
01511          ja = A_j[ia];
01512          a_entry = A_data[ia];
01513          for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
01514          {
01515             jb = B_j[ib];
01516             b_entry = B_data[ib];
01517             if (B_marker[jb] < row_start)
01518             {
01519                B_marker[jb] = counter;
01520                if (OAB == NULL)
01521                   C_j[counter] = jb;
01522                C_data[counter] = a_entry*b_entry;
01523                counter++;
01524             }
01525             else
01526                C_data[B_marker[jb]] += a_entry*b_entry;
01527          }
01528       }
01529    }
01530 
01531    if (OAB != NULL && counter != OAB -> NumNonZeroElems())
01532       mfem_error("Sparse matrix multiplication, Mult (...) #3");
01533 
01534    delete [] B_marker;
01535 
01536    return C;
01537 }
01538 
01539 SparseMatrix *RAP (SparseMatrix &A, SparseMatrix &R,
01540                    SparseMatrix *ORAP)
01541 {
01542    SparseMatrix *P  = Transpose (R);
01543    SparseMatrix *AP = Mult (A, *P);
01544    delete P;
01545    SparseMatrix *_RAP = Mult (R, *AP, ORAP);
01546    delete AP;
01547    return _RAP;
01548 }
01549 
01550 SparseMatrix *Mult_AtDA (SparseMatrix &A, Vector &D,
01551                          SparseMatrix *OAtDA)
01552 {
01553    int i, At_nnz, *At_j;
01554    double *At_data;
01555 
01556    SparseMatrix *At = Transpose (A);
01557    At_nnz  = At -> NumNonZeroElems();
01558    At_j    = At -> GetJ();
01559    At_data = At -> GetData();
01560    for (i = 0; i < At_nnz; i++)
01561       At_data[i] *= D(At_j[i]);
01562    SparseMatrix *AtDA = Mult (*At, A, OAtDA);
01563    delete At;
01564    return AtDA;
01565 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines