37 #include "AbstractBidomainSolver.hpp"
38 #include "TetrahedralMesh.hpp"
39 #include "PetscMatTools.hpp"
40 #include "PetscVecTools.hpp"
42 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
45 if (this->mpLinearSystem != NULL)
58 std::cout <<
"Using absolute tolerance: " << mpConfig->GetAbsoluteTolerance() <<
"\n";
61 this->mpLinearSystem->SetAbsoluteTolerance(mpConfig->GetAbsoluteTolerance());
68 std::cout <<
"Using relative tolerance: " << mpConfig->GetRelativeTolerance() <<
"\n";
71 this->mpLinearSystem->SetRelativeTolerance(mpConfig->GetRelativeTolerance());
77 if(std::string(
"twolevelsblockdiagonal") == std::string(
HeartConfig::Instance()->GetKSPPreconditioner()))
83 boost::shared_ptr<std::vector<PetscInt> > p_bath_nodes(
new std::vector<PetscInt>());
85 for(
unsigned node_index=0; node_index<this->mpMesh->GetNumNodes(); node_index++)
89 p_bath_nodes->push_back(node_index);
97 TERMINATE(
"Two levels block diagonal only works with TetrahedralMesh and p=1");
105 if (mRowForAverageOfPhiZeroed==INT_MAX)
108 this->mpLinearSystem->SetMatrixIsSymmetric(
true);
116 this->mpLinearSystem->SetMatrixIsSymmetric(
false);
124 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
130 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
133 double sqrt_num_nodes = sqrt((
double) this->mpMesh->GetNumNodes());
143 index != dist_null_basis.
End();
146 null_basis_stripe_0[index] = 0.0;
147 null_basis_stripe_1[index] = 1.0/sqrt_num_nodes;
155 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
167 if (!(GetBoundaryConditions()->HasDirichletBoundaryConditions()))
170 CheckCompatibilityCondition();
173 if (mRowForAverageOfPhiZeroed==INT_MAX)
176 if (!mNullSpaceCreated)
179 Vec null_basis[] = {GenerateNullBasis()};
181 this->mpLinearSystem->SetNullBasis(null_basis, 1);
184 mNullSpaceCreated =
true;
192 this->mpLinearSystem->SetKspType(
"gmres");
193 mpConfig->SetKSPSolver(
"gmres",
true);
197 unsigned matrix_size = this->mpLinearSystem->GetSize();
198 if (!this->mMatrixIsAssembled)
202 std::vector<unsigned> row_for_average;
203 row_for_average.push_back(mRowForAverageOfPhiZeroed);
204 this->mpLinearSystem->ZeroMatrixRowsWithValueOnDiagonal(row_for_average, 0.0);
205 for (
unsigned col_index=0; col_index<matrix_size; col_index++)
207 if (col_index%2 == 1)
209 this->mpLinearSystem->SetMatrixElement(mRowForAverageOfPhiZeroed, col_index, 1);
213 this->mpLinearSystem->FinaliseLhsMatrix();
217 this->mpLinearSystem->SetRhsVectorElement(mRowForAverageOfPhiZeroed, 0);
219 this->mpLinearSystem->FinaliseRhsVector();
224 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
227 if (GetBoundaryConditions()->HasDirichletBoundaryConditions() || this->mRowForAverageOfPhiZeroed!=INT_MAX)
234 DistributedVector distributed_rhs=this->mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(this->mpLinearSystem->rGetRhsVector());
239 index!= distributed_rhs.
End();
242 local_sum += distributed_rhs_phi_entries[index];
246 int mpi_ret = MPI_Allreduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
247 assert(mpi_ret == MPI_SUCCESS);
249 if(fabs(global_sum)>1e-6)
251 #define COVERAGE_IGNORE
254 EXCEPTION(
"Linear system does not satisfy compatibility constraint!");
255 #undef COVERAGE_IGNORE
261 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
268 mBathSimulation(bathSimulation),
269 mpBidomainTissue(pTissue),
270 mpBoundaryConditions(pBoundaryConditions)
272 assert(pTissue != NULL);
273 assert(pBoundaryConditions != NULL);
284 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
289 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
291 std::vector<unsigned> fixedExtracellularPotentialNodes)
293 for (
unsigned i=0; i<fixedExtracellularPotentialNodes.size(); i++)
295 if (fixedExtracellularPotentialNodes[i] >= this->mpMesh->GetNumNodes() )
297 EXCEPTION(
"Fixed node number must be less than total number nodes");
301 mFixedExtracellularPotentialNodes = fixedExtracellularPotentialNodes;
304 GetBoundaryConditions()->ResetDirichletCommunication();
306 for (
unsigned i=0; i<mFixedExtracellularPotentialNodes.size(); i++)
308 if (this->mpMesh->GetDistributedVectorFactory()->IsGlobalIndexLocal(mFixedExtracellularPotentialNodes[i]))
314 Node<SPACE_DIM>* p_node = this->mpMesh->GetNode(mFixedExtracellularPotentialNodes[i]);
316 GetBoundaryConditions()->AddDirichletBoundaryCondition(p_node, p_boundary_condition, 1);
322 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
328 EXCEPTION(
"Row for applying the constraint 'Average of phi_e = zero' should be odd in C++ like indexing");
331 mRowForAverageOfPhiZeroed = row;
334 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
337 assert(mBathSimulation);
338 PetscBool is_matrix_assembled;
339 MatAssembled(this->mpLinearSystem->GetLhsMatrix(), &is_matrix_assembled);
340 assert(is_matrix_assembled == PETSC_TRUE);
361 iter != this->mpMesh->GetNodeIteratorEnd();
366 int num_equation = 2*iter->GetIndex();
369 this->mpLinearSystem->GetOwnershipRange(local_lo, local_hi);
372 if ((local_lo <= (
int)num_equation) && ((
int)num_equation < local_hi))
374 for (
unsigned column=0; column < this->mpLinearSystem->GetSize(); column++)
376 assert(this->mpLinearSystem->GetMatrixElement(num_equation, column)==0.0);
381 for (
int row=local_lo; row<local_hi; row++)
383 assert(this->mpLinearSystem->GetMatrixElement(row, num_equation)==0);
397 iter != this->mpMesh->GetNodeIteratorEnd();
402 PetscInt index = 2*iter->GetIndex();
unsigned mRowForAverageOfPhiZeroed
static bool IsRegionBath(HeartRegionType regionId)
virtual void CheckCompatibilityCondition()
virtual void InitialiseForSolve(Vec initialSolution=NULL)
void InitialiseForSolve(Vec initialSolution)
virtual void FinaliseLinearSystem(Vec existingSolution)
DistributedVector CreateDistributedVector(Vec vec, bool readOnly=false)
#define EXCEPTION(message)
#define TERMINATE(message)
void SetFixedExtracellularPotentialNodes(std::vector< unsigned > fixedExtracellularPotentialNodes)
void FinaliseForBath(bool computeMatrix, bool computeVector)
static double GetNextTime()
void PrepareForSetupLinearSystem(Vec existingSolution)
AbstractBidomainSolver(bool bathSimulation, AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, BidomainTissue< SPACE_DIM > *pTissue, BoundaryConditionsContainer< ELEMENT_DIM, SPACE_DIM, 2 > *pBoundaryConditions)
virtual ~AbstractBidomainSolver()
void SetRowForAverageOfPhiZeroed(unsigned rowMeanPhiEZero)
static HeartConfig * Instance()
virtual Vec GenerateNullBasis() const