void BidomainSolver<ELEMENT_DIM,SPACE_DIM>::SetupLinearSystem( Vec currentSolution, bool computeMatrix) { assert(this->mpLinearSystem->rGetLhsMatrix() != NULL); assert(this->mpLinearSystem->rGetRhsVector() != NULL); assert(currentSolution != NULL); ///////////////////////////////////////// // set up LHS matrix (and mass matrix) ///////////////////////////////////////// if (computeMatrix) { mpBidomainAssembler->SetMatrixToAssemble(this->mpLinearSystem->rGetLhsMatrix()); mpBidomainAssembler->AssembleMatrix(); // the BidomainMassMatrixAssembler deals with the mass matrix // for both bath and nonbath problems assert(SPACE_DIM==ELEMENT_DIM); BidomainMassMatrixAssembler<SPACE_DIM> mass_matrix_assembler(this->mpMesh); mass_matrix_assembler.SetMatrixToAssemble(mMassMatrix); mass_matrix_assembler.Assemble(); this->mpLinearSystem->SwitchWriteModeLhsMatrix(); PetscMatTools::Finalise(mMassMatrix); } HeartEventHandler::BeginEvent(HeartEventHandler::ASSEMBLE_RHS); ////////////////////////////////////////// // Set up z in b=Mz ////////////////////////////////////////// DistributedVectorFactory* p_factory = this->mpMesh->GetDistributedVectorFactory(); // dist stripe for the current Voltage DistributedVector distributed_current_solution = p_factory->CreateDistributedVector(currentSolution); DistributedVector::Stripe distributed_current_solution_vm(distributed_current_solution, 0); // dist stripe for z DistributedVector dist_vec_matrix_based = p_factory->CreateDistributedVector(mVecForConstructingRhs); DistributedVector::Stripe dist_vec_matrix_based_vm(dist_vec_matrix_based, 0); DistributedVector::Stripe dist_vec_matrix_based_phie(dist_vec_matrix_based, 1); double Am = HeartConfig::Instance()->GetSurfaceAreaToVolumeRatio(); double Cm = HeartConfig::Instance()->GetCapacitance(); if(!(this->mBathSimulation)) { for (DistributedVector::Iterator index = dist_vec_matrix_based.Begin(); index!= dist_vec_matrix_based.End(); ++index) { double V = distributed_current_solution_vm[index]; double F = - Am*this->mpBidomainTissue->rGetIionicCacheReplicated()[index.Global] - this->mpBidomainTissue->rGetIntracellularStimulusCacheReplicated()[index.Global]; dist_vec_matrix_based_vm[index] = Am*Cm*V*PdeSimulationTime::GetPdeTimeStepInverse() + F; dist_vec_matrix_based_phie[index] = 0.0; } } else { for (DistributedVector::Iterator index = dist_vec_matrix_based.Begin(); index!= dist_vec_matrix_based.End(); ++index) { if ( !HeartRegionCode::IsRegionBath( this->mpMesh->GetNode(index.Global)->GetRegion() )) { double V = distributed_current_solution_vm[index]; double F = - Am*this->mpBidomainTissue->rGetIionicCacheReplicated()[index.Global] - this->mpBidomainTissue->rGetIntracellularStimulusCacheReplicated()[index.Global]; dist_vec_matrix_based_vm[index] = Am*Cm*V*PdeSimulationTime::GetPdeTimeStepInverse() + F; } else { dist_vec_matrix_based_vm[index] = 0.0; } dist_vec_matrix_based_phie[index] = 0.0; } } dist_vec_matrix_based.Restore(); ////////////////////////////////////////// // b = Mz ////////////////////////////////////////// MatMult(mMassMatrix, mVecForConstructingRhs, this->mpLinearSystem->rGetRhsVector()); // assembling RHS is not finished yet, as Neumann bcs are added below, but // the event will be begun again inside mpBidomainAssembler->AssembleVector(); HeartEventHandler::EndEvent(HeartEventHandler::ASSEMBLE_RHS); ///////////////////////////////////////// // apply Neumann boundary conditions ///////////////////////////////////////// mpBidomainNeumannSurfaceTermAssembler->ResetBoundaryConditionsContainer(this->mpBoundaryConditions); // as the BCC can change mpBidomainNeumannSurfaceTermAssembler->SetVectorToAssemble(this->mpLinearSystem->rGetRhsVector(), false/*don't zero vector!*/); mpBidomainNeumannSurfaceTermAssembler->AssembleVector(); ///////////////////////////////////////// // apply correction term ///////////////////////////////////////// if(mpBidomainCorrectionTermAssembler) { mpBidomainCorrectionTermAssembler->SetVectorToAssemble(this->mpLinearSystem->rGetRhsVector(), false/*don't zero vector!*/); // don't need to set current solution mpBidomainCorrectionTermAssembler->AssembleVector(); } this->mpLinearSystem->FinaliseRhsVector(); this->mpBoundaryConditions->ApplyDirichletToLinearProblem(*(this->mpLinearSystem), computeMatrix); if(this->mBathSimulation) { this->mpLinearSystem->FinaliseLhsMatrix(); this->FinaliseForBath(computeMatrix,true); } if(computeMatrix) { this->mpLinearSystem->FinaliseLhsMatrix(); } this->mpLinearSystem->FinaliseRhsVector(); }
void ExtendedBidomainSolver<ELEMENT_DIM,SPACE_DIM>::SetupLinearSystem( Vec currentSolution, bool computeMatrix) { assert(this->mpLinearSystem->rGetLhsMatrix() != NULL); assert(this->mpLinearSystem->rGetRhsVector() != NULL); assert(currentSolution != NULL); ///////////////////////////////////////// // set up LHS matrix (and mass matrix) ///////////////////////////////////////// if(computeMatrix) { mpExtendedBidomainAssembler->SetMatrixToAssemble(this->mpLinearSystem->rGetLhsMatrix()); mpExtendedBidomainAssembler->AssembleMatrix(); // the ExtendedBidomainMassMatrixAssembler deals with the mass matrix // for both bath and nonbath problems assert(SPACE_DIM==ELEMENT_DIM); ExtendedBidomainMassMatrixAssembler<SPACE_DIM> mass_matrix_assembler(this->mpMesh); mass_matrix_assembler.SetMatrixToAssemble(mMassMatrix); mass_matrix_assembler.Assemble(); this->mpLinearSystem->SwitchWriteModeLhsMatrix(); PetscMatTools::Finalise(mMassMatrix); } HeartEventHandler::BeginEvent(HeartEventHandler::ASSEMBLE_RHS); ////////////////////////////////////////// // Set up z in b=Mz ////////////////////////////////////////// DistributedVectorFactory* p_factory = this->mpMesh->GetDistributedVectorFactory(); // get bidomain parameters double Am1 = this->mpExtendedBidomainTissue->GetAmFirstCell(); double Am2 = this->mpExtendedBidomainTissue->GetAmSecondCell(); double AmGap = this->mpExtendedBidomainTissue->GetAmGap(); double Cm1 = this->mpExtendedBidomainTissue->GetCmFirstCell(); double Cm2 = this->mpExtendedBidomainTissue->GetCmSecondCell(); // dist stripe for the current Voltage DistributedVector distributed_current_solution = p_factory->CreateDistributedVector(currentSolution); DistributedVector::Stripe distributed_current_solution_v_first_cell(distributed_current_solution, 0); DistributedVector::Stripe distributed_current_solution_v_second_cell(distributed_current_solution, 1); DistributedVector::Stripe distributed_current_solution_phi_e(distributed_current_solution, 2); // dist stripe for z DistributedVector dist_vec_matrix_based = p_factory->CreateDistributedVector(mVecForConstructingRhs); DistributedVector::Stripe dist_vec_matrix_based_v_first_cell(dist_vec_matrix_based, 0); DistributedVector::Stripe dist_vec_matrix_based_v_second_cell(dist_vec_matrix_based, 1); DistributedVector::Stripe dist_vec_matrix_based_phi_e(dist_vec_matrix_based, 2); for (DistributedVector::Iterator index = dist_vec_matrix_based.Begin(); index!= dist_vec_matrix_based.End(); ++index) { double V_first_cell = distributed_current_solution_v_first_cell[index]; double V_second_Cell = distributed_current_solution_v_second_cell[index]; double i_ionic_first_cell = this->mpExtendedBidomainTissue->rGetIionicCacheReplicated()[index.Global]; double i_ionic_second_cell = this->mpExtendedBidomainTissue->rGetIionicCacheReplicatedSecondCell()[index.Global]; double intracellular_stimulus_first_cell = this->mpExtendedBidomainTissue->rGetIntracellularStimulusCacheReplicated()[index.Global]; double intracellular_stimulus_second_cell = this->mpExtendedBidomainTissue->rGetIntracellularStimulusCacheReplicatedSecondCell()[index.Global]; double extracellular_stimulus = this->mpExtendedBidomainTissue->rGetExtracellularStimulusCacheReplicated()[index.Global]; double g_gap = this->mpExtendedBidomainTissue->rGetGgapCacheReplicated()[index.Global]; double delta_t = PdeSimulationTime::GetPdeTimeStep(); dist_vec_matrix_based_v_first_cell[index] = Am1*Cm1*V_first_cell/delta_t - Am1*i_ionic_first_cell + AmGap*g_gap*(V_second_Cell - V_first_cell) - intracellular_stimulus_first_cell; dist_vec_matrix_based_v_second_cell[index] = Am2*Cm2*V_second_Cell/delta_t - Am2*i_ionic_second_cell + AmGap*g_gap*(V_first_cell - V_second_Cell) - intracellular_stimulus_second_cell; if (this->mpExtendedBidomainTissue->HasTheUserSuppliedExtracellularStimulus() ) { assert((fabs(intracellular_stimulus_first_cell) < 1e-12) && (fabs(intracellular_stimulus_second_cell) < 1e-12));///\todo turn these into exceptions somewhere else /** * The following line should also have * - intracellular_stimulus_first_cell - intracellular_stimulus_second_cell in the summation, * but they are zero... */ dist_vec_matrix_based_phi_e[index] = -extracellular_stimulus; } else { dist_vec_matrix_based_phi_e[index] = 0.0; } } dist_vec_matrix_based.Restore(); ////////////////////////////////////////// // b = Mz ////////////////////////////////////////// MatMult(mMassMatrix, mVecForConstructingRhs, this->mpLinearSystem->rGetRhsVector()); // assembling RHS is not finished yet, as Neumann bcs are added below, but // the event will be begun again inside mpExtendedBidomainAssembler->AssembleVector(); HeartEventHandler::EndEvent(HeartEventHandler::ASSEMBLE_RHS); ///////////////////////////////////////// // apply Neumann boundary conditions ///////////////////////////////////////// mpExtendedBidomainNeumannSurfaceTermAssembler->ResetBoundaryConditionsContainer(this->mpBoundaryConditions); // as the BCC can change mpExtendedBidomainNeumannSurfaceTermAssembler->SetVectorToAssemble(this->mpLinearSystem->rGetRhsVector(), false/*don't zero vector!*/); mpExtendedBidomainNeumannSurfaceTermAssembler->AssembleVector(); this->mpLinearSystem->FinaliseRhsVector(); this->mpBoundaryConditions->ApplyDirichletToLinearProblem(*(this->mpLinearSystem), computeMatrix); if(computeMatrix) { this->mpLinearSystem->FinaliseLhsMatrix(); } this->mpLinearSystem->FinaliseRhsVector(); }
void OperatorSplittingMonodomainSolver<ELEMENT_DIM,SPACE_DIM>::SetupLinearSystem(Vec currentSolution, bool computeMatrix) { assert(this->mpLinearSystem->rGetLhsMatrix() != NULL); assert(this->mpLinearSystem->rGetRhsVector() != NULL); ///////////////////////////////////////// // set up LHS matrix (and mass matrix) ///////////////////////////////////////// if(computeMatrix) { mpMonodomainAssembler->SetMatrixToAssemble(this->mpLinearSystem->rGetLhsMatrix()); mpMonodomainAssembler->AssembleMatrix(); MassMatrixAssembler<ELEMENT_DIM,SPACE_DIM> mass_matrix_assembler(this->mpMesh, HeartConfig::Instance()->GetUseMassLumping()); mass_matrix_assembler.SetMatrixToAssemble(mMassMatrix); mass_matrix_assembler.Assemble(); this->mpLinearSystem->FinaliseLhsMatrix(); PetscMatTools::Finalise(mMassMatrix); } HeartEventHandler::BeginEvent(HeartEventHandler::ASSEMBLE_RHS); ////////////////////////////////////////// // Set up z in b=Mz ////////////////////////////////////////// DistributedVectorFactory* p_factory = this->mpMesh->GetDistributedVectorFactory(); // dist stripe for the current Voltage DistributedVector distributed_current_solution = p_factory->CreateDistributedVector(currentSolution); // dist stripe for z (return value) DistributedVector dist_vec_matrix_based = p_factory->CreateDistributedVector(mVecForConstructingRhs); double Am = HeartConfig::Instance()->GetSurfaceAreaToVolumeRatio(); double Cm = HeartConfig::Instance()->GetCapacitance(); for (DistributedVector::Iterator index = dist_vec_matrix_based.Begin(); index!= dist_vec_matrix_based.End(); ++index) { double V = distributed_current_solution[index]; // in the main solver, the nodal ionic current and stimuli is computed and used. // However in operator splitting, this part of the solve is diffusion only, no reaction terms //double F = - Am*this->mpMonodomainTissue->rGetIionicCacheReplicated()[index.Global] // - this->mpMonodomainTissue->rGetIntracellularStimulusCacheReplicated()[index.Global]; dist_vec_matrix_based[index] = Am*Cm*V*PdeSimulationTime::GetPdeTimeStepInverse(); } dist_vec_matrix_based.Restore(); ////////////////////////////////////////// // b = Mz ////////////////////////////////////////// MatMult(mMassMatrix, mVecForConstructingRhs, this->mpLinearSystem->rGetRhsVector()); // assembling RHS is not finished yet, as Neumann bcs are added below, but // the event will be begun again inside mpMonodomainAssembler->AssembleVector(); HeartEventHandler::EndEvent(HeartEventHandler::ASSEMBLE_RHS); ///////////////////////////////////////// // apply Neumann boundary conditions ///////////////////////////////////////// mpNeumannSurfaceTermsAssembler->SetVectorToAssemble(this->mpLinearSystem->rGetRhsVector(), false/*don't zero vector!*/); mpNeumannSurfaceTermsAssembler->AssembleVector(); // finalise this->mpLinearSystem->FinaliseRhsVector(); }