37 #include "AbstractBidomainSolver.hpp" 38 #include "TetrahedralMesh.hpp" 39 #include "PetscMatTools.hpp" 40 #include "PetscVecTools.hpp" 42 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
46 assert(this->mpLinearSystem == NULL);
56 std::cout <<
"Using absolute tolerance: " << mpConfig->GetAbsoluteTolerance() <<
"\n";
59 this->mpLinearSystem->SetAbsoluteTolerance(mpConfig->GetAbsoluteTolerance());
66 std::cout <<
"Using relative tolerance: " << mpConfig->GetRelativeTolerance() <<
"\n";
69 this->mpLinearSystem->SetRelativeTolerance(mpConfig->GetRelativeTolerance());
76 assert(std::string(
HeartConfig::Instance()->GetKSPPreconditioner()) != std::string(
"twolevelsblockdiagonal"));
79 if (mRowForAverageOfPhiZeroed == INT_MAX)
82 this->mpLinearSystem->SetMatrixIsSymmetric(
true);
90 this->mpLinearSystem->SetMatrixIsSymmetric(
false);
93 this->mpLinearSystem->SetUseFixedNumberIterations(
98 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
104 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
107 double sqrt_num_nodes = sqrt((
double) this->mpMesh->GetNumNodes());
117 index != dist_null_basis.
End();
120 null_basis_stripe_0[index] = 0.0;
121 null_basis_stripe_1[index] = 1.0/sqrt_num_nodes;
128 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
140 if (!(GetBoundaryConditions()->HasDirichletBoundaryConditions()))
143 CheckCompatibilityCondition();
146 if (mRowForAverageOfPhiZeroed==INT_MAX)
149 if (!mNullSpaceCreated)
152 Vec null_basis[] = {GenerateNullBasis()};
154 this->mpLinearSystem->SetNullBasis(null_basis, 1);
157 mNullSpaceCreated =
true;
165 this->mpLinearSystem->SetKspType(
"gmres");
166 mpConfig->SetKSPSolver(
"gmres",
true);
170 unsigned matrix_size = this->mpLinearSystem->GetSize();
171 if (!this->mMatrixIsAssembled)
175 std::vector<unsigned> row_for_average;
176 row_for_average.push_back(mRowForAverageOfPhiZeroed);
177 this->mpLinearSystem->ZeroMatrixRowsWithValueOnDiagonal(row_for_average, 0.0);
178 for (
unsigned col_index=0; col_index<matrix_size; col_index++)
180 if (col_index%2 == 1)
182 this->mpLinearSystem->SetMatrixElement(mRowForAverageOfPhiZeroed, col_index, 1);
186 this->mpLinearSystem->FinaliseLhsMatrix();
190 this->mpLinearSystem->SetRhsVectorElement(mRowForAverageOfPhiZeroed, 0);
192 this->mpLinearSystem->FinaliseRhsVector();
197 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
200 if (GetBoundaryConditions()->HasDirichletBoundaryConditions() || this->mRowForAverageOfPhiZeroed!=INT_MAX)
207 DistributedVector distributed_rhs=this->mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(this->mpLinearSystem->rGetRhsVector());
212 index!= distributed_rhs.
End();
215 local_sum += distributed_rhs_phi_entries[index];
219 int mpi_ret = MPI_Allreduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
220 assert(mpi_ret == MPI_SUCCESS);
222 if (fabs(global_sum)>1e-6)
227 EXCEPTION(
"Linear system does not satisfy compatibility constraint!");
233 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
240 mBathSimulation(bathSimulation),
241 mpBidomainTissue(pTissue),
242 mpBoundaryConditions(pBoundaryConditions)
244 assert(pTissue != NULL);
245 assert(pBoundaryConditions != NULL);
256 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
261 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
263 std::vector<unsigned> fixedExtracellularPotentialNodes)
265 for (
unsigned i=0; i<fixedExtracellularPotentialNodes.size(); i++)
267 if (fixedExtracellularPotentialNodes[i] >= this->
mpMesh->GetNumNodes() )
269 EXCEPTION(
"Fixed node number must be less than total number nodes");
294 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
300 EXCEPTION(
"Row for applying the constraint 'Average of phi_e = zero' should be odd in C++ like indexing");
306 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
310 PetscBool is_matrix_assembled;
312 assert(is_matrix_assembled == PETSC_TRUE);
333 iter != this->
mpMesh->GetNodeIteratorEnd();
338 int num_equation = 2*iter->GetIndex();
344 if ((local_lo <= (
int)num_equation) && ((
int)num_equation < local_hi))
353 for (
int row=local_lo; row<local_hi; row++)
369 iter != this->
mpMesh->GetNodeIteratorEnd();
374 PetscInt index = 2*iter->GetIndex();
unsigned mRowForAverageOfPhiZeroed
AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > * mpMesh
std::vector< unsigned > mFixedExtracellularPotentialNodes
static bool IsRegionBath(HeartRegionType regionId)
virtual void CheckCompatibilityCondition()
void GetOwnershipRange(PetscInt &lo, PetscInt &hi)
void InitialiseForSolve(Vec initialSolution)
virtual void FinaliseLinearSystem(Vec existingSolution)
DistributedVector CreateDistributedVector(Vec vec, bool readOnly=false)
virtual void InitialiseForSolve(Vec initialSolution=nullptr)
#define EXCEPTION(message)
double GetMatrixElement(PetscInt row, PetscInt col)
void SetFixedExtracellularPotentialNodes(std::vector< unsigned > fixedExtracellularPotentialNodes)
void AddDirichletBoundaryCondition(const Node< SPACE_DIM > *pBoundaryNode, const AbstractBoundaryCondition< SPACE_DIM > *pBoundaryCondition, unsigned indexOfUnknown=0, bool checkIfBoundaryNode=true)
void FinaliseForBath(bool computeMatrix, bool computeVector)
static double GetNextTime()
void PrepareForSetupLinearSystem(Vec existingSolution)
BoundaryConditionsContainer< ELEMENT_DIM, SPACE_DIM, 2 > * GetBoundaryConditions()
AbstractBidomainSolver(bool bathSimulation, AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, BidomainTissue< SPACE_DIM > *pTissue, BoundaryConditionsContainer< ELEMENT_DIM, SPACE_DIM, 2 > *pBoundaryConditions)
void ResetDirichletCommunication()
virtual ~AbstractBidomainSolver()
void SetRowForAverageOfPhiZeroed(unsigned rowMeanPhiEZero)
static HeartConfig * Instance()
LinearSystem * mpLinearSystem
virtual Vec GenerateNullBasis() const