mv.h

来自「C++ source code for book-C++ and Object 」· C头文件 代码 · 共 1,506 行 · 第 1/4 页

H
1,506
字号
    // update the solution x = x0 + sum v[i]*y[i]
    for (int i = 0; i < k; i++) x += (*v[i])*g[i];

    // calculate residual and check for convergence
    r = preconding(b - (*this) * x, pcn);
    beta = r.twonorm();
    if (abs(beta) <= stp ) {    // stop if residual small
      conv = true;
      break;
    }
  }

  eps =  (b - (*this) * x).twonorm();  // get final residual

  // deallocate space for v and h
  for (int i = 0; i <= m; i++ ) delete v[i];
  delete[] v;
  for (int i = 0; i < m; i++) delete[] h[i];
  delete[] h;

  if (conv) return 0;
  else return 1;
}   // end of gmres(m)

// *** definitions for members of class BandMtx

template<class T>
BandMtx<T>::BandMtx(int n, int p, int r, T** t) {
  nrows = n;                      // number of rows
  bwleft = p;                     // left bandwidth
  bwrit = r;                      // right bandwidth
  bdmx = new T* [nrows]; 
  for (int i = 0; i < nrows; i++) {
   bdmx[i] = new T [bwleft + bwrit + 1];
   bdmx[i] += bwleft;                              
  }
  for (int i = 0; i < nrows; i++) 
    for (int j = - bwleft; j <= bwrit; j++) 
      bdmx[i][j] = t[i][j];
}

template<class T>
BandMtx<T>::BandMtx(int n, int p, int r, T t) {
  nrows = n;
  bwleft = p;
  bwrit = r;
  bdmx = new T* [nrows]; 
  for (int i = 0; i < nrows; i++) {
   bdmx[i] = new T [bwleft + bwrit + 1];
   bdmx[i] += bwleft;                              
  }
  for (int i = 0; i < nrows; i++) 
    for (int j = - bwleft; j <= bwrit; j++) bdmx[i][j] = t;
}

template<class T>
BandMtx<T>::BandMtx(const BandMtx & bd) {
  nrows = bd.nrows;
  bwleft = bd.bwleft;
  bwrit = bd.bwrit;
  bdmx = new T* [nrows]; 
  for (int i = 0; i < nrows; i++) {
   bdmx[i] = new T [bwleft + bwrit + 1];
   bdmx[i] += bwleft;                              
  }
  for (int i = 0; i < nrows; i++) 
    for (int j = - bwleft; j <= bwrit; j++) 
      bdmx[i][j] = bd[i][j];
}

template<class T>
BandMtx<T>::BandMtx(int n,int p,int r,const FullMtx<T>& fm){
  nrows = n;                      // fm may be non-symmetric
  bwleft = p;
  bwrit = r;
  bdmx = new T* [nrows]; 
  for (int i = 0; i < nrows; i++) {
   bdmx[i] = new T [bwleft + bwrit + 1];
   bdmx[i] += bwleft;                              
  }
  for (int i = 0; i< nrows; i++) {   
    int ip = max(i-bwleft, 0); 
    int ir = min(i+bwrit, nrows -1); 
    for (int j = ip; j <= ir; j++) bdmx[i][j-i] = fm[i][j];
  }
}

template<class T>
BandMtx<T>& BandMtx<T>::operator=(const BandMtx & bd) {
  if (nrows != bd.nrows || bwleft != bd.bwleft 
                        || bwrit != bd.bwrit) 
    error("bad matrix size in BandMtx assignment");
  for (int j = 0; j < nrows; j++) 
    for (int k = -bwleft; k <= bwrit; k++) 
      bdmx[j][k] = bd[j][k];
  return *this;
}

template<class T>            // matrix vector multiply 
Vcr<T> BandMtx<T>::operator*(const Vcr<T> & vec) const {    
  if (nrows != vec.size()) 
    error("matrix and vector sizes do not match");
  Vcr<T> tm(nrows);
  for (int i = 0; i < nrows; i++) {
    int ip = max(i-bwleft, 0); 
    int ir = min(i+bwrit, nrows - 1);
    for (int j = ip; j <= ir; j++) 
      tm[i] += bdmx[i][j-i]*vec[j]; 
  }
  return tm;
}

template<class T>            // solve Pz = r, return z
Vcr<T> BandMtx<T>::preconding(const Vcr<T>& r,
                              int precn) const {
  if (precn == 0) {          // no preconditioning
    return r;
  } else if (precn == 1) {   // diagonal preconditioning
    Vcr<T> z(nrows);
    for (int i = 0; i < nrows; i++) z[i] = r[i]/bdmx[i][0];
    return z;
  } else if (precn == 2) {   // symmetric SOR preconditioner
    const T omega = 1;       // SSOR parameter for precondit
    Vcr<T> z(nrows);
    for (int i = 0; i < nrows; i++) {
      T sum = 0;
      int ip = max(i-bwleft, 0);
      for (int j = ip; j < i; j++)  
        sum += omega*bdmx[i][j-i]*z[j];
      z[i] = (r[i] - sum)/bdmx[i][0];
    }
    for (int i = nrows -1; i >= 0; i--) {
      T sum = 0;
      int ir = min(i+bwrit, nrows -1); 
      for (int j = i+1; j <= ir; j++) 
        sum += omega*bdmx[i][j-i]*z[j];
      z[i] -= sum/bdmx[i][0];
    }
    return z;
  } else {
    error("specified preconditioner not implemented");
  }
}

// Gauss elim without pivoting
template<class T>
void BandMtx<T>::GaussElim(Vcr<T>& bb) const {
  if (nrows != bb.size()) 
    error("matrix and vector sizes do not match");
  BandMtx<T> tmx = *this;

  // banded LU decomposition without pivoting
  const int nrowsmone = nrows - 1;
  for (int k = 0; k < nrowsmone; k++) {
    if (tmx[k][0] == 0) 
      error("pivot is zero in BandMtx::GaussElim()");
    int kbf = min(nrowsmone - k, bwleft);
    int kbr = min(nrowsmone - k, bwrit);
    for (int i = 1; i <= kbf; i++) {
      int kpi = k+i;
      if (tmx[kpi][-i] != 0) {   
        T dmul = tmx[kpi][-i]/tmx[k][0];
        tmx[kpi][-i] = dmul;  // tmx[k+i][-i] = a[k+i][k]
        for (int j = 1; j <= kbr; j++) 
          tmx[kpi][j-i] -= dmul*tmx[k][j];   
      }                       // a[k+i][k+j] = tmx[k+i][j-i]
    }
  }

  // Forward substitution
  for (int k = 1; k < nrows; k++) {
    int kf = min(k, bwleft);
    for (int j = 1; j <= kf; j++) 
      bb[k] -= tmx[k][-j]*bb[k-j];
  }                           // tmx[k][-j] = a[k][k-j]

  // Backward substitution
  for (int k = nrowsmone; k >= 0; k--) {
    int kbr = min(nrowsmone - k, bwrit);
    for ( int j = 1; j <= kbr; j++) 
      bb[k] -= tmx[k][j]*bb[k+j];
    bb[k] /= tmx[k][0];
  }
} // end GaussElim()

// Band Gauss elimination with partial pivoting
template<class T>
void BandMtx<T>::GaussElimPP(Vcr<T>& bb) const {
  if (nrows != bb.size()) 
    error("matrix-vector sizes not match");

  BandMtx<T> tx(nrows, bwleft,
                       min(nrows-1, bwleft+bwrit));
  for (int i = 0; i < nrows; i++) 
    for (int j = - bwleft; j <= bwrit; j++) 
      tx[i][j] = bdmx[i][j];

  Vcr<int> pvt(nrows);   // store pivoting info

  // LU decomposition with column partial pivoting
  const int nrowsmone = tx.nrows - 1;
  for (int k = 0; k < nrowsmone; k++) {
    int kbrow = min(nrowsmone - k, tx.bwleft); 
    int kbcol = min(nrowsmone - k, tx.bwrit); 

    // find the pivot in the k-th column
    int pc = k;
    double aet = abs(tx[k][0]);
    for (int i = 1; i <= kbrow; i++) {
      if (abs(tx[k+i][-i]) > aet) {
        aet = abs(tx[k+i][-i]);
        pc = k + i;
      }
    }
    if (!aet) error("pivot is zero in GaussElimPP");
    pvt[k] = pc;

    // interchange pivot row and k-th row in U, not in L
    if (pc != k) {
      for (int j = 0; j <= kbcol; j++) 
        swap(tx[pc][k+j-pc], tx[k][j]);
    }

    // now eliminate column entries 
    for (int i = 1; i <= kbrow; i++) { 
      int kpi = k + i;
      if (tx[kpi][-i] != 0) {
        T dmul = tx[kpi][-i]/tx[k][0];
        tx[kpi][-i] = dmul;
        for (int j = 1; j <= kbcol; j++) 
          tx[kpi][j-i] -= dmul*tx[k][j];
      } 
    }
  }

  // Forward substitution LY = b
  for (int k = 0; k < nrowsmone; k++) {
    int kbrow = min(nrowsmone - k, tx.bwleft); 
    int pvtk = pvt[k];
    T sb = bb[pvtk];
    if (k != pvtk) swap(bb[k], bb[pvtk]);
    for (int j = 1; j <= kbrow; j++) 
      bb[k+j] -= tx[k+j][-j]*sb;
  }

  // Backward substitution U x = y
  for (int k = nrowsmone; k>= 0; k--) {
    int kb = min(nrowsmone -k, tx.bwrit); 
    for (int j = 1; j <= kb; j++) bb[k] -= tx[k][j]*bb[k+j];
    bb[k] /= tx[k][0];
  }
} // end GaussElimPP()

// *** definitions for members of class SparseMtx

template<class T>
SparseMtx<T>::SparseMtx(int n,int m,T* et,int* cn,int* da) {
  nrows = n;
  lenth = m;
  sra = new T [lenth];
  clm = new int [lenth];
  fnz = new int [nrows +1];

  for (int i =0; i< lenth; i++) {
    sra[i] = et[i];
    clm[i] = cn[i];
  }
  for (int i = 0; i <= nrows; i++)  fnz[i] = da[i];
}

template<class T>
SparseMtx<T>::SparseMtx(int n, int m) {
  nrows = n;
  lenth = m;
  sra = new T [lenth];
  clm = new int [lenth];
  fnz = new int [nrows +1];

  for (int i =0; i< lenth; i++)  {
    sra[i] = 0;
    clm[i] = 0;
  }
  for (int i =0; i <= nrows; i++)  fnz[i] = 0;
}

template<class T>           // copy constructor
SparseMtx<T>::SparseMtx(const SparseMtx& mat) {
  nrows = mat.nrows;
  lenth = mat.lenth;
  sra = new T [lenth]; 
  clm = new int [lenth]; 
  fnz = new int [nrows +1]; 
  for (int i = 0; i < lenth; i++) {
    sra[i] = mat[i]; 
    clm[i] = mat.clm[i]; 
  }
  for (int i =  0; i <= nrows; i++) fnz[i] = mat.fnz[i];
}

template<class T>
SparseMtx<T>& SparseMtx<T>::operator=(const SparseMtx& ssm) {
  if(nrows != ssm.nrows || lenth != ssm.lenth) 
    error("bad matrix sizes in SparseMtx::operator=()");
  for (int i = 0; i < lenth; i++) {
    sra[i]  = ssm[i];
    clm[i]  = ssm.clm[i];
  }
  for (int i = 0; i <= nrows; i++) fnz[i] = ssm.fnz[i]; 
  return *this;
}

template<class T>
Vcr<T> SparseMtx<T>::operator*(const Vcr<T>& vec) const {
  if (nrows != vec.size()) 
    error("matrix and vector sizes do not match");
  Vcr<T> tm(nrows);
  for (int i = 0; i < nrows; i++)  
    for (int j = fnz[i]; j < fnz[i +1]; j++) 
      tm[i] += sra[j]*vec[clm[j]];
  return tm;
}

template<class T>    // solve preconditioned Pz = r, return z
Vcr<T> SparseMtx<T>::preconding(const Vcr<T>& r, 
                                int precn) const {
  if (precn == 0) {             // no preconditioning
    return r;
  } else if (precn == 1) {      // diagonal preconditioning
    Vcr<T> diag(nrows);         // find diagonal entries
    for (int i = 0; i < nrows; i++) { 
      for (int j = fnz[i]; j < fnz[i+1]; j++) 
        diag[i] += sra[j]*sra[j];  // geom. average, stable
      diag[i] = sqrt(diag[i]); 
    }

    Vcr<T> z(nrows);
    for (int i = 0; i < nrows; i++) z[i] = r[i]/diag[i];
    return z;
  } else if (precn == 2) {      // SSOR preconditioning
    const T omega = 1;          // SOR parameter

    Vcr<T> diag(nrows);         // find diagonal entries
    for (int i = 0; i < nrows; i++) {        
      for (int j = fnz[i]; j < fnz[i+1]; j++) {
        if (clm[j] == i) diag[i] += sra[j]*sra[j];   
        else diag[i] += omega*omega*sra[j]*sra[j];  
      }          // averaging is used, it is more stable
      diag[i] = sqrt(diag[i]);
    }

    Vcr<T> z(nrows);
    for (int i = 0; i < nrows; i++) {  
      T sum = 0;        // solve lower triangular system
      for (int j = fnz[i]; j < fnz[i+1]; j++) {
        if (clm[j] < i) sum += omega*sra[j]*z[clm[j]];
      }
      z[i] = (r[i] - sum)/diag[i];
    }
    for (int i = nrows -1; i >= 0; i--) {
      T sum = 0;        // solve upper triangular system
      for (int j = fnz[i]; j < fnz[i+1]; j++) {
        if (clm[j] > i) sum += omega*sra[j]*z[clm[j]];
      }
      z[i] -= sum/diag[i];
    }
    return z;
  } else {
    error("specified preconditioner not implemented");
  } 
} // end SparseMtx::preconding()

#endif

//****** end mv.h  ***************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?