Ejemplo n.º 1
0
void CSysMatrix::MatrixVectorProduct(const CSysVector & vec, CSysVector & prod, CGeometry *geometry, CConfig *config) {
  
  unsigned long prod_begin, vec_begin, mat_begin, index, iVar, jVar, row_i;
  
  /*--- Some checks for consistency between CSysMatrix and the CSysVectors ---*/
  if ( (nVar != vec.GetNVar()) || (nVar != prod.GetNVar()) ) {
    cerr << "CSysMatrix::MatrixVectorProduct(const CSysVector&, CSysVector): "
    << "nVar values incompatible." << endl;
    throw(-1);
  }
  if ( (nPoint != vec.GetNBlk()) || (nPoint != prod.GetNBlk()) ) {
    cerr << "CSysMatrix::MatrixVectorProduct(const CSysVector&, CSysVector): "
    << "nPoint and nBlk values incompatible." << endl;
    throw(-1);
  }
  
  prod = 0.0; // set all entries of prod to zero
  for (row_i = 0; row_i < nPointDomain; row_i++) {
    prod_begin = row_i*nVar; // offset to beginning of block row_i
    for (index = row_ptr[row_i]; index < row_ptr[row_i+1]; index++) {
      vec_begin = col_ind[index]*nVar; // offset to beginning of block col_ind[index]
      mat_begin = (index*nVar*nVar); // offset to beginning of matrix block[row_i][col_ind[indx]]
      for (iVar = 0; iVar < nVar; iVar++) {
        for (jVar = 0; jVar < nVar; jVar++) {
          prod[(const unsigned int)(prod_begin+iVar)] += matrix[(const unsigned int)(mat_begin+iVar*nVar+jVar)]*vec[(const unsigned int)(vec_begin+jVar)];
        }
      }
    }
  }
  
  /*--- MPI Parallelization ---*/
  SendReceive_Solution(prod, geometry, config);
  
}
Ejemplo n.º 2
0
void CSysMatrix::ComputeLU_SGSPreconditioner(const CSysVector & vec, CSysVector & prod, CGeometry *geometry, CConfig *config) {
  unsigned long iPoint, iVar;
  
  /*--- There are two approaches to the parallelization (AIAA-2000-0927):
   1. Use a special scheduling algorithm which enables data parallelism by regrouping edges. This method has the advantage of 
   producing exactly the same result as the single processor case, but it suffers from severe overhead penalties for parallel 
   loop initiation, heavy interprocessor communications and poor load balance.
   2. Split the computational domain into several nonoverlapping regions according to the number of processors, and apply the 
   SGS method inside of each region with (or without) some special interprocessor boundary treatment. This approach may suffer 
   from convergence degradation but takes advantage of minimal parallelization overhead and good load balance. ---*/
  
  /*--- First part of the symmetric iteration: (D+L).x* = b ---*/
  
  for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
    LowerProduct(prod, iPoint);                                        // Compute L.x*
    for (iVar = 0; iVar < nVar; iVar++)
      aux_vector[iVar] = vec[iPoint*nVar+iVar] - prod_row_vector[iVar]; // Compute aux_vector = b - L.x*
    Gauss_Elimination(iPoint, aux_vector);                            // Solve D.x* = aux_vector
    for (iVar = 0; iVar < nVar; iVar++)
      prod[iPoint*nVar+iVar] = aux_vector[iVar];                       // Assesing x* = solution
  }
  
  /*--- Inner send-receive operation the solution vector ---*/
  
  SendReceive_Solution(prod, geometry, config);
  
  /*--- Second part of the symmetric iteration: (D+U).x_(1) = D.x* ---*/
  
  for (iPoint = nPointDomain-1; (int)iPoint >= 0; iPoint--) {
    DiagonalProduct(prod, iPoint);                 // Compute D.x*
    for (iVar = 0; iVar < nVar; iVar++)
      aux_vector[iVar] = prod_row_vector[iVar];   // Compute aux_vector = D.x*
    UpperProduct(prod, iPoint);                    // Compute U.x_(n+1)
    for (iVar = 0; iVar < nVar; iVar++)
      aux_vector[iVar] -= prod_row_vector[iVar];  // Compute aux_vector = D.x*-U.x_(n+1)
    Gauss_Elimination(iPoint, aux_vector);        // Solve D.x* = aux_vector
    for (iVar = 0; iVar < nVar; iVar++)
      prod[iPoint*nVar + iVar] = aux_vector[iVar]; // Assesing x_(1) = solution
  }
  
  /*--- Final send-receive operation the solution vector (redundant in CFD simulations) ---*/
  
  SendReceive_Solution(prod, geometry, config);
  
}
Ejemplo n.º 3
0
void CSysMatrix::ComputeLU_SGSPreconditioner(const CSysVector & vec, CSysVector & prod, CGeometry *geometry, CConfig *config) {
  unsigned long iPoint, iVar;
  
  /*--- First part of the symmetric iteration: (D+L).x* = b ---*/
  
  for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
    LowerProduct(prod, iPoint);                                        // Compute L.x*
    for (iVar = 0; iVar < nVar; iVar++)
      aux_vector[iVar] = vec[iPoint*nVar+iVar] - prod_row_vector[iVar]; // Compute aux_vector = b - L.x*
    Gauss_Elimination(iPoint, aux_vector);                            // Solve D.x* = aux_vector
    for (iVar = 0; iVar < nVar; iVar++)
      prod[iPoint*nVar+iVar] = aux_vector[iVar];                       // Assesing x* = solution
  }
  
  /*--- MPI Parallelization ---*/
  
  SendReceive_Solution(prod, geometry, config);

  /*--- Second part of the symmetric iteration: (D+U).x_(1) = D.x* ---*/
  
  for (iPoint = nPointDomain-1; (int)iPoint >= 0; iPoint--) {
    DiagonalProduct(prod, iPoint);                 // Compute D.x*
    for (iVar = 0; iVar < nVar; iVar++)
      aux_vector[iVar] = prod_row_vector[iVar];   // Compute aux_vector = D.x*
    UpperProduct(prod, iPoint);                    // Compute U.x_(n+1)
    for (iVar = 0; iVar < nVar; iVar++)
      aux_vector[iVar] -= prod_row_vector[iVar];  // Compute aux_vector = D.x*-U.x_(n+1)
    Gauss_Elimination(iPoint, aux_vector);        // Solve D.x* = aux_vector
    for (iVar = 0; iVar < nVar; iVar++)
      prod[iPoint*nVar + iVar] = aux_vector[iVar]; // Assesing x_(1) = solution
  }

  /*--- MPI Parallelization ---*/
  
  SendReceive_Solution(prod, geometry, config);
  
}
Ejemplo n.º 4
0
void CSysMatrix::ComputeIdentityPreconditioner(const CSysVector & vec, CSysVector & prod, CGeometry *geometry, CConfig *config) {
  
  unsigned long iPoint, iVar;
  
  for (iPoint = 0; iPoint < nPoint; iPoint++) {
    for (iVar = 0; iVar < nVar; iVar++) {
      prod[(const unsigned int)(iPoint*nVar+iVar)] = vec[(const unsigned int)(iPoint*nVar+iVar)];
    }
  }
  
  /*--- MPI Parallelization ---*/
  
  SendReceive_Solution(prod, geometry, config);
  
}
Ejemplo n.º 5
0
void CSysMatrix::ComputeLineletPreconditioner(const CSysVector & vec, CSysVector & prod,
                                              CGeometry *geometry, CConfig *config) {
  
  unsigned long iVar, jVar, nElem = 0, iLinelet, im1Point, iPoint, ip1Point, iElem;
  long iElemLoop;
  double *block;
  
  /*--- Jacobi preconditioning if there is no linelet ---*/
  
  for (iPoint = 0; iPoint < nPoint; iPoint++) {
    if (!LineletBool[iPoint]) {
      for (iVar = 0; iVar < nVar; iVar++) {
        prod[(const unsigned int)(iPoint*nVar+iVar)] = 0.0;
        for (jVar = 0; jVar < nVar; jVar++)
          prod[(const unsigned int)(iPoint*nVar+iVar)] +=
          invM[(const unsigned int)(iPoint*nVar*nVar+iVar*nVar+jVar)]*vec[(const unsigned int)(iPoint*nVar+jVar)];
      }
    }
  }
  
  /*--- Solve linelet using a Thomas' algorithm ---*/
  
  for (iLinelet = 0; iLinelet < nLinelet; iLinelet++) {
    
    nElem = LineletPoint[iLinelet].size();
    
    /*--- Copy vec vector to the new structure ---*/
    
    for (iElem = 0; iElem < nElem; iElem++) {
      iPoint = LineletPoint[iLinelet][iElem];
      for (iVar = 0; iVar < nVar; iVar++)
        rVector[iElem][iVar] = vec[(const unsigned int)(iPoint*nVar+iVar)];
    }
    
    /*--- Initialization (iElem = 0) ---*/
    
    iPoint = LineletPoint[iLinelet][0];
    block = GetBlock(iPoint, iPoint);
    for (iVar = 0; iVar < nVar; iVar++) {
      yVector[0][iVar] = rVector[0][iVar];
      for (jVar = 0; jVar < nVar; jVar++)
        UBlock[0][iVar*nVar+jVar] = block[iVar*nVar+jVar];
    }
    
    /*--- Main loop (without iElem = 0) ---*/
    
    for (iElem = 1; iElem < nElem; iElem++) {
      
      im1Point = LineletPoint[iLinelet][iElem-1];
      iPoint = LineletPoint[iLinelet][iElem];
      
      InverseBlock(UBlock[iElem-1], invUBlock[iElem-1]);
      block = GetBlock(iPoint, im1Point); GetMultBlockBlock(LBlock[iElem], block, invUBlock[iElem-1]);
      block = GetBlock(im1Point, iPoint); GetMultBlockBlock(LFBlock, LBlock[iElem], block);
      block = GetBlock(iPoint, iPoint); GetSubsBlock(UBlock[iElem], block, LFBlock);
      
      /*--- Forward substituton ---*/
      
      GetMultBlockVector(LyVector, LBlock[iElem], yVector[iElem-1]);
      GetSubsVector(yVector[iElem], rVector[iElem], LyVector);
      
    }
    
    /*--- Backward substituton ---*/
    
    im1Point = LineletPoint[iLinelet][nElem-1];
    InverseBlock(UBlock[nElem-1], invUBlock[nElem-1]);
    GetMultBlockVector(zVector[nElem-1], invUBlock[nElem-1], yVector[nElem-1]);
    
    for (iElemLoop = nElem-2; iElemLoop >= 0; iElemLoop--) {
      iPoint = LineletPoint[iLinelet][iElemLoop];
      ip1Point = LineletPoint[iLinelet][iElemLoop+1];
      block = GetBlock(iPoint, ip1Point); GetMultBlockVector(FzVector, block, zVector[iElemLoop+1]);
      GetSubsVector(AuxVector, yVector[iElemLoop], FzVector);
      GetMultBlockVector(zVector[iElemLoop], invUBlock[iElemLoop], AuxVector);
    }
    
    /*--- Copy zVector to the prod vector ---*/
    
    for (iElem = 0; iElem < nElem; iElem++) {
      iPoint = LineletPoint[iLinelet][iElem];
      for (iVar = 0; iVar < nVar; iVar++)
        prod[(const unsigned int)(iPoint*nVar+iVar)] = zVector[iElem][iVar];
    }
    
  }
  
  /*--- MPI Parallelization ---*/
  
  SendReceive_Solution(prod, geometry, config);
  
}
Ejemplo n.º 6
0
void CSysMatrix::ComputeILUPreconditioner(const CSysVector & vec, CSysVector & prod, CGeometry *geometry, CConfig *config) {
  
  unsigned long index, index_;
  double *Block_ij, *Block_jk;
  long iPoint, jPoint, kPoint;
  unsigned short iVar;
  
  /*--- Copy block matrix, note that the original matrix
   is modified by the algorithm---*/
  
  for (iPoint = 0; iPoint < nPoint; iPoint++) {
    for (index = row_ptr[iPoint]; index < row_ptr[iPoint+1]; index++) {
      jPoint = col_ind[index];
      Block_ij = GetBlock(iPoint, jPoint);
      SetBlock_ILUMatrix(iPoint, jPoint, Block_ij);
    }
    for (iVar = 0; iVar < nVar; iVar++) {
      prod[iPoint*nVar+iVar] = vec[iPoint*nVar+iVar];
    }
  }
  
  /*--- Transform system in Upper Matrix ---*/
  
  for (iPoint = 1; iPoint < nPoint; iPoint++) {
    
    for (index = row_ptr[iPoint]; index < row_ptr[iPoint+1]; index++) {
      
      jPoint = col_ind[index];
      
      if (jPoint < iPoint) {
        
        Block_ij = GetBlock_ILUMatrix(iPoint, jPoint);
        InverseDiagonalBlock_ILUMatrix(jPoint, block_inverse);
        MatrixMatrixProduct(Block_ij, block_inverse, block_weight);
        
        for (index_ = row_ptr[jPoint]; index_ < row_ptr[jPoint+1]; index_++) {
          kPoint = col_ind[index_];
          Block_jk = GetBlock_ILUMatrix(jPoint, kPoint);
          if (kPoint >= jPoint) {
            MatrixMatrixProduct(Block_jk, block_weight, block);
            SubtractBlock_ILUMatrix(iPoint, kPoint, block);
          }
        }
        
        MatrixVectorProduct(block_weight, &prod[jPoint*nVar], aux_vector);
        
        for (iVar = 0; iVar < nVar; iVar++)
          prod[iPoint*nVar+iVar] -= aux_vector[iVar];
        
      }
      
    }
  }
  
  /*--- MPI Parallelization ---*/
  
  SendReceive_Solution(prod, geometry, config);
  
  /*--- Backwards substitution ---*/
  
  InverseDiagonalBlock_ILUMatrix((nPoint-1), block_inverse);
  MatrixVectorProduct(block_inverse, &prod[(nPoint-1)*nVar], aux_vector);
  
  for (iVar = 0; iVar < nVar; iVar++)
    prod[ (nPoint-1)*nVar + iVar] = aux_vector[iVar];
  
  for (iPoint = nPoint-2; iPoint >= 0; iPoint--) {
    
    for (iVar = 0; iVar < nVar; iVar++) sum_vector[iVar] = 0.0;
    
    for (index = row_ptr[iPoint]; index < row_ptr[iPoint+1]; index++) {
      
      jPoint = col_ind[index];
      
      
      Block_ij = GetBlock_ILUMatrix(iPoint, jPoint);
      
      if (jPoint >= iPoint+1) {
        
        MatrixVectorProduct(Block_ij, &prod[jPoint*nVar], aux_vector);
        
        for (iVar = 0; iVar < nVar; iVar++) sum_vector[iVar] += aux_vector[iVar];
        
      }
      
    }
    
    for (iVar = 0; iVar < nVar; iVar++) prod[iPoint*nVar+iVar] = (prod[iPoint*nVar+iVar]-sum_vector[iVar]);
    
    InverseDiagonalBlock_ILUMatrix(iPoint, block_inverse);
    MatrixVectorProduct(block_inverse, &prod[iPoint*nVar], aux_vector);
    
    for (iVar = 0; iVar < nVar; iVar++) prod[iPoint*nVar+iVar] = aux_vector[iVar];
    
    if (iPoint == 0) break;
    
  }
  
  /*--- MPI Parallelization ---*/
  
  SendReceive_Solution(prod, geometry, config);
  
}