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); }
void CSysSolve::SetExternalSolve(CSysMatrix & Jacobian, CSysVector & LinSysRes, CSysVector & LinSysSol, CGeometry *geometry, CConfig *config){ #ifdef CODI_REVERSE_TYPE unsigned long size = LinSysRes.GetLocSize(); unsigned long i, nBlk = LinSysRes.GetNBlk(), nVar = LinSysRes.GetNVar(), nBlkDomain = LinSysRes.GetNBlkDomain(); /*--- Arrays to store the indices of the input/output of the linear solver. * Note: They will be deleted in the CSysSolve_b::Delete_b routine. ---*/ int *LinSysRes_Indices = new int[size]; int *LinSysSol_Indices = new int[size]; for (i = 0; i < size; i++){ /*--- Register the solution of the linear system (could already be registered when using multigrid) ---*/ if (LinSysSol[i].getGradientData() == 0){ AD::globalTape.registerInput(LinSysSol[i]); } /*--- Store the indices ---*/ LinSysRes_Indices[i] = LinSysRes[i].getGradientData(); LinSysSol_Indices[i] = LinSysSol[i].getGradientData(); } /*--- Push the data to the checkpoint handler for access in the reverse sweep ---*/ AD::CheckpointHandler* dataHandler = new AD::CheckpointHandler; dataHandler->addData(LinSysRes_Indices); dataHandler->addData(LinSysSol_Indices); dataHandler->addData(size); dataHandler->addData(nBlk); dataHandler->addData(nVar); dataHandler->addData(nBlkDomain); dataHandler->addData(&Jacobian); dataHandler->addData(geometry); dataHandler->addData(config); /*--- Build preconditioner for the transposed Jacobian ---*/ switch(config->GetKind_DiscAdj_Linear_Prec()){ case ILU: Jacobian.BuildILUPreconditioner(true); break; case JACOBI: Jacobian.BuildJacobiPreconditioner(true); break; default: cout << "The specified preconditioner is not yet implemented for the discrete adjoint method." << endl; exit(EXIT_FAILURE); } /*--- Push the external function to the AD tape ---*/ AD::globalTape.pushExternalFunction(&CSysSolve_b::Solve_b, dataHandler, &CSysSolve_b::Delete_b); #endif }