int SolverOperator::Apply ( const vector_Type& X, vector_Type& Y ) const { ASSERT_PRE ( X.Map().SameAs ( M_oper->OperatorDomainMap() ), "X and domain map do no coincide \n" ); ASSERT_PRE ( Y.Map().SameAs ( M_oper->OperatorRangeMap() ) , "Y and range map do no coincide \n" ); return M_oper->Apply ( X, Y ); }
// =================================================== // Methods // =================================================== void FSIExactJacobian::solveJac (vector_Type& _muk, const vector_Type& _res, const Real _linearRelTol) { if (this->isFluid() && this->isLeader() ) { std::cout << " f- "; } if (this->isSolid() && this->isLeader() ) { std::cout << " s- "; } this->displayer().leaderPrint ( "FSI --- solveJac: NormInf res " , _res.normInf(), "\n" ); _muk *= 0.; M_linearSolver.setTolerance ( _linearRelTol ); M_linearSolver.setMaxNumIterations ( 100 ); vector_Type res (_res); M_linearSolver.setOperator (M_epetraOper); this->displayer().leaderPrint ( "FSI --- Solving Jacobian FSI system... " ); M_recomputeShapeDer = true; M_linearSolver.solve (_muk, res); this->displayer().leaderPrint ( "FSI --- Solving the Jacobian FSI system done.\n" ); }
int SolverOperator::ApplyInverse( const vector_Type& X, vector_Type& Y ) const { ASSERT_PRE( Y.Map().SameAs( M_oper->OperatorDomainMap() ), "Y and domain map do no coincide \n" ); ASSERT_PRE( X.Map().SameAs( M_oper->OperatorRangeMap() ) , "X and range map do no coincide \n" ); if ( M_useTranspose ) return -1; int result = doApplyInverse( X, Y ); M_numCumulIterations += M_numIterations; if( M_comm->MyPID() == 0 && M_printSubiterationCount ) { std::cout << "> " << numIterations() << " subiterations" << std::endl; } return result; }
void computeP0pressure (const feSpacePtr_Type& pFESpacePtr, const feSpacePtr_Type& p0FESpacePtr, const feSpacePtr_Type& uFESpacePtr, const vector_Type& velAndPressure, vector_Type& P0pres, Real /*time*/) { int MyPID; MPI_Comm_rank (MPI_COMM_WORLD, &MyPID); UInt offset = 3 * uFESpacePtr->dof().numTotalDof(); std::vector<int> gid0Vec (0); gid0Vec.reserve (p0FESpacePtr->mesh()->numVolumes() ); std::vector<Real> val0Vec (0); val0Vec.reserve (p0FESpacePtr->mesh()->numVolumes() ); for (UInt ivol = 0; ivol < pFESpacePtr->mesh()->numVolumes(); ++ivol) { pFESpacePtr->fe().update ( pFESpacePtr->mesh()->volumeList ( ivol ), UPDATE_DPHI ); p0FESpacePtr->fe().update ( p0FESpacePtr->mesh()->volumeList ( ivol ) ); UInt eleID = pFESpacePtr->fe().currentLocalId(); double tmpsum = 0.; for (UInt iNode = 0; iNode < (UInt) pFESpacePtr->fe().nbFEDof(); iNode++) { int ig = pFESpacePtr->dof().localToGlobalMap ( eleID, iNode ); tmpsum += velAndPressure (ig + offset); gid0Vec.push_back ( p0FESpacePtr->fe().currentId() ); val0Vec.push_back ( tmpsum / (double) pFESpacePtr->fe().nbFEDof() ); } } P0pres.setCoefficients (gid0Vec, val0Vec); P0pres.globalAssemble(); MPI_Barrier (MPI_COMM_WORLD); }
MatrixEpetra<Real> ElectroIonicModel::getJac (const vector_Type& v, Real /*h*/) { matrix_Type J (v.map(), M_numberOfEquations, false); // vector<Real> f1(M_numberOfEquations,0.0); // vector<Real> f2(M_numberOfEquations,0.0); // vector< vector<Real> > df ( M_numberOfEquations, vector<Real> (M_numberOfEquations,0.0) ); // vector<Real> y1(M_numberOfEquations,0.0); // vector<Real> y2(M_numberOfEquations,0.0); // const Int* k = v.blockMap().MyGlobalElements(); // // int* Indices = new int[M_numberOfEquations]; // double* Values = new double[M_numberOfEquations]; // for(int i=0; i<M_numberOfEquations; i++) // Indices[i] = i; // // for(int i=0; i<M_numberOfEquations; i++) // { // for(int j=0; j<M_numberOfEquations; j++) // { // y1[j] = v[ k[j] ] + ((double)(i==j))*h; // y2[j] = v[ k[j] ] - ((double)(i==j))*h; // } // this->computeRhs(y1, f1); // this->computeRhs(y2, f2); // // for(int j=0; j<M_numberOfEquations; j++) // df[j][i] = (f1[j]-f2[j])/(2.0*h); // } // // // for(int i=0; i<M_numberOfEquations; i++) // { // for(int j=0; j<M_numberOfEquations; j++) // Values[j] = df[i][j]; // J.matrixPtr()->InsertGlobalValues (i, M_numberOfEquations, Values, Indices); // } // // J.globalAssemble(); // // delete[] Indices; // delete[] Values; return J; }
int BelosOperator::doApplyInverse ( const vector_Type& X, vector_Type& Y ) const { Teuchos::RCP<vector_Type> Xcopy ( new vector_Type ( X ) ); Y.PutScalar ( 0.0 ); bool set = M_linProblem->setProblem ( Teuchos::rcp ( &Y, false ), Xcopy ); if ( set == false ) { std::cout << std::endl << "SLV- ERROR: Belos::LinearProblem failed to set up correctly!" << std::endl; return -12; } M_solverManager->setProblem ( M_linProblem ); // Solving the system Belos::ReturnType ret = M_solverManager->solve(); // Update the number of performed iterations M_numIterations = M_solverManager->getNumIters(); // Update of the status if ( M_solverManager->isLOADetected() ) { M_lossOfAccuracy = yes; } else { M_lossOfAccuracy = no; } if ( ret == Belos::Converged ) { M_converged = yes; return 0; } else { M_converged = no; return -1; } }
void Heart::computeRhs ( vector_Type& rhs, HeartBidomainSolver< mesh_Type >& electricModel, boost::shared_ptr< HeartIonicSolver< mesh_Type > > ionicModel, HeartBidomainData& data ) { bool verbose = (M_heart_fct->M_comm->MyPID() == 0); if (verbose) { std::cout << " f- Computing Rhs ... " << "\n" << std::flush; } LifeChrono chrono; chrono.start(); //! u, w with repeated map vector_Type uVecRep (electricModel.solutionTransmembranePotential(), Repeated); ionicModel->updateRepeated(); VectorElemental elvec_Iapp ( electricModel.potentialFESpace().fe().nbFEDof(), 2 ), elvec_u ( electricModel.potentialFESpace().fe().nbFEDof(), 1 ), elvec_Iion ( electricModel.potentialFESpace().fe().nbFEDof(), 1 ); for (UInt iVol = 0; iVol < electricModel.potentialFESpace().mesh()->numVolumes(); ++iVol) { electricModel.potentialFESpace().fe().updateJacQuadPt ( electricModel.potentialFESpace().mesh()->volumeList ( iVol ) ); elvec_u.zero(); elvec_Iion.zero(); elvec_Iapp.zero(); UInt eleIDu = electricModel.potentialFESpace().fe().currentLocalId(); UInt nbNode = ( UInt ) electricModel.potentialFESpace().fe().nbFEDof(); for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ ) { Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, iNode ); elvec_u.vec() [ iNode ] = uVecRep[ig]; } UInt eleID = electricModel.potentialFESpace().fe().currentLocalId(); ionicModel->updateElementSolution (eleID); ionicModel->computeIonicCurrent (data.membraneCapacitance(), elvec_Iion, elvec_u, electricModel.potentialFESpace() ); //! Computing Iapp AssemblyElemental::source (M_heart_fct->stimulus(), elvec_Iapp, electricModel.potentialFESpace().fe(), data.time(), 0); AssemblyElemental::source (M_heart_fct->stimulus(), elvec_Iapp, electricModel.potentialFESpace().fe(), data.time(), 1); UInt totalUDof = electricModel.potentialFESpace().map().map (Unique)->NumGlobalElements(); for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ ) { Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, iNode ); rhs.sumIntoGlobalValues (ig, elvec_Iapp.vec() [iNode] + data.volumeSurfaceRatio() * elvec_Iion.vec() [iNode] ); rhs.sumIntoGlobalValues (ig + totalUDof, -elvec_Iapp.vec() [iNode + nbNode] - data.volumeSurfaceRatio() * elvec_Iion.vec() [iNode] ); } } rhs.globalAssemble(); rhs += electricModel.matrMass() * data.volumeSurfaceRatio() * data.membraneCapacitance() * electricModel.BDFIntraExtraPotential().time_der (data.timeStep() ); MPI_Barrier (MPI_COMM_WORLD); chrono.stop(); if (verbose) { std::cout << "done in " << chrono.diff() << " s." << std::endl; } }
void Heart::computeRhs ( vector_Type& rhs, HeartMonodomainSolver< mesh_Type >& electricModel, boost::shared_ptr< HeartIonicSolver< mesh_Type > > ionicModel, HeartMonodomainData& data ) { bool verbose = (M_heart_fct->M_comm->MyPID() == 0); if (verbose) { std::cout << " f- Computing Rhs ... " << "\n" << std::flush; } LifeChrono chrono; chrono.start(); //! u, w with repeated map vector_Type uVecRep (electricModel.solutionTransmembranePotential(), Repeated); ionicModel->updateRepeated(); VectorElemental elvec_Iapp ( electricModel.potentialFESpace().fe().nbFEDof(), 2 ), elvec_u ( electricModel.potentialFESpace().fe().nbFEDof(), 1 ), elvec_Iion ( electricModel.potentialFESpace().fe().nbFEDof(), 1 ); for (UInt iVol = 0; iVol < electricModel.potentialFESpace().mesh()->numVolumes(); ++iVol) { electricModel.potentialFESpace().fe().updateJacQuadPt ( electricModel.potentialFESpace().mesh()->volumeList ( iVol ) ); elvec_Iapp.zero(); elvec_u.zero(); elvec_Iion.zero(); UInt eleIDu = electricModel.potentialFESpace().fe().currentLocalId(); UInt nbNode = ( UInt ) electricModel.potentialFESpace().fe().nbFEDof(); //! Filling local elvec_u with potential values in the nodes for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ ) { Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, iNode ); elvec_u.vec() [ iNode ] = uVecRep[ig]; } ionicModel->updateElementSolution (eleIDu); ionicModel->computeIonicCurrent (data.membraneCapacitance(), elvec_Iion, elvec_u, electricModel.potentialFESpace() ); //! Computing the current source of the righthand side, repeated AssemblyElemental::source (M_heart_fct->stimulus(), elvec_Iapp, electricModel.potentialFESpace().fe(), data.time(), 0); AssemblyElemental::source (M_heart_fct->stimulus(), elvec_Iapp, electricModel.potentialFESpace().fe(), data.time(), 1); //! Assembling the righthand side for ( UInt i = 0 ; i < electricModel.potentialFESpace().fe().nbFEDof() ; i++ ) { Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, i ); rhs.sumIntoGlobalValues (ig, (data.conductivityRatio() * elvec_Iapp.vec() [i] + elvec_Iapp.vec() [i + nbNode]) / (1 + data.conductivityRatio() ) + data.volumeSurfaceRatio() * elvec_Iion.vec() [i] ); } } rhs.globalAssemble(); Real coeff = data.volumeSurfaceRatio() * data.membraneCapacitance() / data.timeStep(); vector_Type tmpvec (electricModel.solutionTransmembranePotential() ); tmpvec *= coeff; rhs += electricModel.massMatrix() * tmpvec; MPI_Barrier (MPI_COMM_WORLD); chrono.stop(); if (verbose) { std::cout << "done in " << chrono.diff() << " s." << std::endl; } }
int AztecooOperator::doApplyInverse( const vector_Type& X, vector_Type& Y ) const { M_numIterations = 0; vector_Type Xcopy( X ); Y.PutScalar( 0.0 ); if( M_tolerance > 0 ) M_pList->sublist( "Trilinos: AztecOO List" ).set( "tol", M_tolerance ); M_linSolver->SetParameters( M_pList->sublist( "Trilinos: AztecOO List" ) ); M_linSolver->SetRHS( &Xcopy ); M_linSolver->SetLHS( &Y ); M_linSolver->SetUserOperator( M_oper.get() ); if( M_prec.get() != 0 ) M_linSolver->SetPrecOperator( (Epetra_Operator*) M_prec.get() ); int maxIter( M_pList->sublist( "Trilinos: AztecOO List" ).get<int>( "max_iter" ) ); double tol( M_pList->sublist( "Trilinos: AztecOO List" ).get<double>( "tol" ) ); // Solving the system int retValue = M_linSolver->Iterate(maxIter, tol); /* try to solve again (reason may be: -2 "Aztec status AZ_breakdown: numerical breakdown" -3 "Aztec status AZ_loss: loss of precision" -4 "Aztec status AZ_ill_cond: GMRES hessenberg ill-conditioned" This method was used in the old AztecOO solver. */ if ( retValue <= -2 ) { M_numIterations += M_linSolver->NumIters(); retValue = M_linSolver->Iterate(maxIter, tol); } // Update the number of performed iterations M_numIterations += M_linSolver->NumIters(); // Update of the status Real status[AZ_STATUS_SIZE]; M_linSolver->GetAllAztecStatus( status ); if ( status[AZ_why] == AZ_normal ) { M_converged = yes; } else { M_converged = no; } if ( status[AZ_why] == AZ_loss ) { M_lossOfAccuracy = yes; } else { M_lossOfAccuracy = no; } return retValue; }
void FSIExactJacobian::evalResidual (vector_Type& res, const vector_Type& disp, const UInt iter) { if (this->isSolid() ) { std::cout << "FSI --- Residual computation g(x_" << iter << " )\n"; } setLambdaSolidOld (disp); eval (disp, iter); res = this->lambdaSolid(); res -= disp; if (this->isSolid() ) { M_solid->updateJacobian (M_solid->displacement() ); } this->displayer().leaderPrint ("FSI --- NormInf res = " , res.normInf(), "\n" ); if (this->isSolid() ) { this->displayer().leaderPrint ("FSI --- NormInf res_d = " , this->solid().residual().normInf(), "\n" ); } }
int FSIExactJacobian::Epetra_ExactJacobian::Apply (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { LifeChrono chronoFluid, chronoSolid, chronoInterface; M_comm->Barrier(); double xnorm = 0.; X.NormInf (&xnorm); Epetra_FEVector dz (Y.Map() ); if (M_ej->isSolid() ) { std::cout << "\n ***** norm (z)= " << xnorm << std::endl << std::endl; } if ( xnorm == 0.0 ) { Y.Scale (0.); dz.Scale (0.); } else { vector_Type const z (X, M_ej->solidInterfaceMap(), Unique); M_ej->displayer().leaderPrint ( "NormInf res " , z.normInf(), "\n" ); //M_ej->solid().residual() *= 0.; //M_ej->transferInterfaceOnSolid(z, M_ej->solid().residual()); //std::cout << "NormInf res_d " << M_ej->solid().residual().NormInf() << std::endl; //if (M_ej->isSolid()) // M_ej->solid().postProcess(); M_ej->setLambdaFluid (z); //M_ej->transferInterfaceOnSolid(z, M_ej->solid().disp()); chronoInterface.start(); vector_Type sigmaFluidUnique (M_ej->sigmaFluid(), Unique); chronoInterface.stop(); M_comm->Barrier(); chronoFluid.start(); if (M_ej->isFluid() ) { //to be used when we correct the other lines if (true || ( !this->M_ej->dataFluid()->isSemiImplicit() /*|| this->M_ej->dataFluid().semiImplicit()==-1*/) ) { M_ej->meshMotion().iterate (*M_ej->BCh_harmonicExtension() ); //std::cout<<" mesh motion iterated!!!"<<std::endl; } M_ej->displayer().leaderPrint ( " norm inf dx = " , M_ej->meshMotion().disp().normInf(), "\n" ); M_ej->solveLinearFluid(); M_ej->transferFluidOnInterface (M_ej->fluid().residual(), sigmaFluidUnique); //M_ej->fluidPostProcess(); } M_comm->Barrier(); chronoFluid.stop(); M_ej->displayer().leaderPrintMax ( "Fluid linear solution: total time : ", chronoFluid.diff() ); chronoInterface.start(); // M_ej->setSigmaFluid(sigmaFluidUnique); M_ej->setSigmaSolid (sigmaFluidUnique); vector_Type lambdaSolidUnique (M_ej->lambdaSolid(), Unique); chronoInterface.stop(); M_comm->Barrier(); chronoFluid.start(); if (M_ej->isSolid() ) { M_ej->solveLinearSolid(); M_ej->transferSolidOnInterface (M_ej->solid().displacement(), lambdaSolidUnique); } M_comm->Barrier(); chronoSolid.stop(); M_ej->displayer().leaderPrintMax ( "Solid linear solution: total time : " , chronoSolid.diff() ); chronoInterface.start(); M_ej->setLambdaSolid (lambdaSolidUnique); chronoInterface.stop(); M_ej->displayer().leaderPrintMax ( "Interface linear transfer: total time : " , chronoInterface.diffCumul() ); dz = lambdaSolidUnique.epetraVector(); } Y = X; Y.Update (1., dz, -1.); double ynorm; Y.NormInf (&ynorm); if (M_ej->isSolid() ) std::cout << "\n\n ***** norm (Jz)= " << ynorm << std::endl << std::endl; return 0; }
void FSIExactJacobian::eval (const vector_Type& _disp, const UInt iter) { LifeChrono chronoFluid, chronoSolid, chronoInterface; bool recomputeMatrices ( iter == 0 || ( !this->M_data->dataFluid()->isSemiImplicit() && ( M_data->updateEvery() > 0 && (iter % M_data->updateEvery() == 0) ) ) ); if (iter == 0) { if (isFluid() ) { this->M_fluid->resetPreconditioner(); } //this->M_solid->resetPrec(); } this->setLambdaFluid (_disp); vector_Type sigmaFluidUnique (this->sigmaFluid(), Unique); M_epetraWorldComm->Barrier(); chronoFluid.start(); if (isFluid() ) { M_meshMotion->iterate (*M_BCh_mesh); // M_meshMotion->updateDispDiff(); // copying displacement to a repeated indeces displacement, otherwise the mesh wont know // the value of the displacement for some points if ( iter == 0 || !this->M_data->dataFluid()->isSemiImplicit() ) { *M_beta *= 0.; if ( iter == 0 ) { M_ALETimeAdvance->updateRHSFirstDerivative (M_data->dataFluid()->dataTime()->timeStep() ); M_ALETimeAdvance->shiftRight (M_meshMotion->disp() ); M_ALETimeAdvance->extrapolation (M_meshMotion->disp() ); //closer initial solution } else { M_ALETimeAdvance->setSolution (M_meshMotion->disp() ); } vector_Type meshDispRepeated ( M_meshMotion->disp(), Repeated ); this->moveMesh (meshDispRepeated); vector_Type vel ( this->M_ALETimeAdvance->firstDerivative( ) ); transferMeshMotionOnFluid ( vel, veloFluidMesh() ); M_fluidTimeAdvance->extrapolation (*M_beta); //explicit *M_beta -= veloFluidMesh();//implicit //the conservative formulation as it is now is of order 1. To have higher order (TODO) we need to store the mass matrices computed at the previous time steps. if (M_data->dataFluid()->conservativeFormulation() ) //*M_rhs = M_fluid->matrixMass()*M_fluidTimeAdvance->rhsContributionFirstDerivative(); { *M_rhs = M_fluidMassTimeAdvance->rhsContributionFirstDerivative(); } if (recomputeMatrices) { double alpha = M_fluidTimeAdvance->coefficientFirstDerivative (0) / M_data->dataFluid()->dataTime()->timeStep(); this->M_fluid->updateSystem ( alpha, *M_beta, *M_rhs ); } else { this->M_fluid->updateRightHandSide ( *M_rhs ); } if (!M_data->dataFluid()->conservativeFormulation() ) { *M_rhs = M_fluid->matrixMass() * M_fluidTimeAdvance->rhsContributionFirstDerivative(); this->M_fluid->updateRightHandSide ( *M_rhs ); } } this->M_fluid->iterate ( *M_BCh_u ); this->transferFluidOnInterface (this->M_fluid->residual(), sigmaFluidUnique); } M_epetraWorldComm->Barrier(); chronoFluid.stop(); this->displayer().leaderPrintMax (" Fluid solution total time: ", chronoFluid.diff() ); if ( false && this->isFluid() ) { vector_Type vel (this->fluid().velocityFESpace().map() ); vector_Type press (this->fluid().pressureFESpace().map() ); vel.subset (*this->M_fluid->solution() ); press.subset (*this->M_fluid->solution(), this->fluid().velocityFESpace().dim() *this->fluid().pressureFESpace().fieldDim() ); std::cout << "norm_inf( vel ) " << vel.normInf() << std::endl; std::cout << "norm_inf( press ) " << press.normInf() << std::endl; //this->M_fluid->postProcess(); } chronoInterface.start(); this->setSigmaFluid ( sigmaFluidUnique ); this->setSigmaSolid ( sigmaFluidUnique ); vector_Type lambdaSolidUnique (this->lambdaSolid(), Unique); vector_Type lambdaDotSolidUnique (this->lambdaDotSolid(), Unique); vector_Type sigmaSolidUnique (this->sigmaSolid(), Unique); chronoInterface.stop(); M_epetraWorldComm->Barrier(); chronoSolid.start(); if (this->isSolid() ) { this->M_solid->iterate ( M_BCh_d ); } M_epetraWorldComm->Barrier(); chronoSolid.stop(); this->displayer().leaderPrintMax (" Solid solution total time: ", chronoSolid.diff() ); chronoInterface.start(); if (this->isSolid() ) { this->transferSolidOnInterface (this->M_solid->displacement(), lambdaSolidUnique); this->transferSolidOnInterface ( this->M_solidTimeAdvance->firstDerivative ( this->M_solid->displacement() ), lambdaDotSolidUnique ); this->transferSolidOnInterface (this->M_solid->residual(), sigmaSolidUnique); } this->setLambdaSolid ( lambdaSolidUnique); this->setLambdaDotSolid ( lambdaDotSolidUnique); this->setSigmaSolid ( sigmaSolidUnique); chronoInterface.stop(); this->displayer().leaderPrintMax (" Interface transfer total time: ", chronoInterface.diffCumul() ); // possibly unsafe when using more cpus, since both has repeated maps this->displayer().leaderPrint (" Norm(disp ) = ", _disp.normInf(), "\n"); this->displayer().leaderPrint (" Norm(dispNew ) = " , this->lambdaSolid().normInf(), "\n" ); this->displayer().leaderPrint (" Norm(velo ) = " , this->lambdaDotSolid().normInf(), "\n" ); this->displayer().leaderPrint (" Max Residual Fluid = " , this->sigmaFluid().normInf(), "\n" ); this->displayer().leaderPrint (" Max Residual Solid = " , this->sigmaSolid().normInf(), "\n" ); if ( this->isFluid() ) { this->displayer().leaderPrint (" Max ResidualF = " , M_fluid->residual().normInf(), "\n" ); } if ( this->isSolid() ) { this->displayer().leaderPrint (" NL2 Diplacement S. = " , M_solid->displacement().norm2(), "\n" ); this->displayer().leaderPrint (" Max Residual Solid = " , M_solid->residual().normInf(), "\n" ); } }