36 #ifndef _BOUNDARYCONDITIONSCONTAINERIMPLEMENTATION_HPP_
37 #define _BOUNDARYCONDITIONSCONTAINERIMPLEMENTATION_HPP_
39 #include "PetscVecTools.hpp"
40 #include "PetscMatTools.hpp"
41 #include "BoundaryConditionsContainer.hpp"
42 #include "DistributedVector.hpp"
43 #include "ReplicatableVector.hpp"
44 #include "ConstBoundaryCondition.hpp"
45 #include "HeartEventHandler.hpp"
46 #include "PetscMatTools.hpp"
49 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
55 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
69 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
73 std::set<const AbstractBoundaryCondition<SPACE_DIM>*> deleted_conditions;
74 for (
unsigned i=0; i<PROBLEM_DIM; i++)
77 while (neumann_iterator != mpNeumannMap[i]->end() )
80 if (deleted_conditions.count(neumann_iterator->second) == 0)
82 deleted_conditions.insert(neumann_iterator->second);
84 if (neumann_iterator->second != mpZeroBoundaryCondition)
86 if (this->mDeleteConditions)
88 delete neumann_iterator->second;
94 delete(mpNeumannMap[i]);
95 delete(mpPeriodicBcMap[i]);
98 delete mpZeroBoundaryCondition;
100 if (this->mDeleteConditions)
102 this->DeleteDirichletBoundaryConditions(deleted_conditions);
106 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
109 unsigned indexOfUnknown,
110 bool checkIfBoundaryNode)
112 assert(indexOfUnknown < PROBLEM_DIM);
113 if (checkIfBoundaryNode)
118 (*(this->mpDirichletMap[indexOfUnknown]))[pBoundaryNode] = pBoundaryCondition;
121 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
131 for(
unsigned i=0; i<PROBLEM_DIM; i++)
133 (*(this->mpPeriodicBcMap[i]))[pNode1] = pNode2;
138 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
141 unsigned indexOfUnknown)
143 assert(indexOfUnknown < PROBLEM_DIM);
152 if (p_const_cond->
GetValue(pBoundaryElement->
GetNode(0)->GetPoint()) != 0.0)
154 mAnyNonZeroNeumannConditionsForUnknown[indexOfUnknown] =
true;
159 mAnyNonZeroNeumannConditionsForUnknown[indexOfUnknown] =
true;
162 for (
unsigned unknown=0; unknown<PROBLEM_DIM; unknown++)
164 if (unknown==indexOfUnknown)
166 (*(mpNeumannMap[indexOfUnknown]))[pBoundaryElement] = pBoundaryCondition;
171 if ( mpNeumannMap[unknown]->find(pBoundaryElement)==mpNeumannMap[unknown]->end() )
174 (*(mpNeumannMap[unknown]))[pBoundaryElement] = mpZeroBoundaryCondition;
180 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
182 unsigned indexOfUnknown)
184 this->DefineConstantDirichletOnMeshBoundary(pMesh, 0.0, indexOfUnknown);
187 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
190 unsigned indexOfUnknown)
192 assert(indexOfUnknown < PROBLEM_DIM);
202 AddDirichletBoundaryCondition(*iter, p_boundary_condition, indexOfUnknown);
207 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
209 unsigned indexOfUnknown)
211 assert(indexOfUnknown < PROBLEM_DIM);
221 AddNeumannBoundaryCondition(*iter, p_zero_boundary_condition, indexOfUnknown);
225 mAnyNonZeroNeumannConditionsForUnknown[indexOfUnknown] =
false;
258 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
262 bool applyToRhsVector)
268 if (!this->HasDirichletBoundaryConditions())
277 if (matrix_is_symmetric)
305 lo = lo_s; hi = hi_s;
308 for (
unsigned i=lo; i<hi; i++)
310 dirichlet_conditions[i] = DBL_MAX;
313 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
315 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
317 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
319 unsigned node_index = this->mDirichIterator->first->GetIndex();
320 double value = this->mDirichIterator->second->GetValue(this->mDirichIterator->first->GetPoint());
321 assert(value != DBL_MAX);
323 unsigned row = PROBLEM_DIM*node_index + index_of_unknown;
324 dirichlet_conditions[row] = value;
326 this->mDirichIterator++;
331 dirichlet_conditions.Replicate(lo, hi);
334 std::vector<unsigned> rows_to_zero;
335 for (
unsigned i=0; i<dirichlet_conditions.GetSize(); i++)
337 if (dirichlet_conditions[i] != DBL_MAX)
339 rows_to_zero.push_back(i);
343 if (matrix_is_symmetric)
346 for (
unsigned i=0; i<rows_to_zero.size(); i++)
348 unsigned col = rows_to_zero[i];
349 double minus_value = -dirichlet_conditions[col];
380 if (matrix_is_symmetric)
390 if (applyToRhsVector)
402 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
404 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
406 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
408 unsigned node_index = this->mDirichIterator->first->GetIndex();
409 double value = this->mDirichIterator->second->GetValue(this->mDirichIterator->first->GetPoint());
411 unsigned row = PROBLEM_DIM*node_index + index_of_unknown;
415 this->mDirichIterator++;
425 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
428 bool applyToRhsVector)
430 bool has_periodic_bcs =
false;
431 for (
unsigned i=0; i<PROBLEM_DIM; i++)
433 if (!mpPeriodicBcMap[i]->empty())
435 has_periodic_bcs =
true;
440 if(!has_periodic_bcs)
447 std::vector<unsigned> rows_to_zero;
448 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
451 iter != mpPeriodicBcMap[index_of_unknown]->end();
454 unsigned node_index_1 = iter->first->GetIndex();
455 unsigned row_index_1 = PROBLEM_DIM*node_index_1 + index_of_unknown;
456 rows_to_zero.push_back(row_index_1);
462 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
465 iter != mpPeriodicBcMap[index_of_unknown]->end();
468 unsigned node_index_1 = iter->first->GetIndex();
469 unsigned node_index_2 = iter->second->GetIndex();
471 unsigned mat_index1 = PROBLEM_DIM*node_index_1 + index_of_unknown;
472 unsigned mat_index2 = PROBLEM_DIM*node_index_2 + index_of_unknown;
480 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
483 iter != mpPeriodicBcMap[index_of_unknown]->end();
486 unsigned node_index = iter->first->GetIndex();
487 unsigned row_index = PROBLEM_DIM*node_index + index_of_unknown;
495 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
497 const Vec currentSolution,
501 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
503 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
509 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
514 unsigned node_index = this->mDirichIterator->first->GetIndex();
516 double value = this->mDirichIterator->second->GetValue(this->mDirichIterator->first->GetPoint());
520 residual_stripe[node_index]=solution_stripe[node_index] - value;
522 this->mDirichIterator++;
525 residual_distributed.
Restore();
529 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
532 unsigned num_boundary_conditions = 0;
533 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
535 num_boundary_conditions += this->mpDirichletMap[index_of_unknown]->size();
538 std::vector<unsigned> rows_to_zero(num_boundary_conditions);
541 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
543 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
545 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
547 unsigned node_index = this->mDirichIterator->first->GetIndex();
548 rows_to_zero[counter++] = PROBLEM_DIM*node_index + index_of_unknown;
549 this->mDirichIterator++;
556 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
561 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
568 if (!HasNeumannBoundaryCondition(*elt_iter, index_of_unknown))
571 for (
unsigned i=0; i<(*elt_iter)->GetNumNodes(); i++)
573 if (!this->HasDirichletBoundaryCondition((*elt_iter)->GetNode(i)))
585 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
588 unsigned indexOfUnknown)
590 assert(indexOfUnknown < PROBLEM_DIM);
593 if (mLastNeumannCondition[indexOfUnknown] == mpNeumannMap[indexOfUnknown]->end() ||
594 mLastNeumannCondition[indexOfUnknown]->first != pSurfaceElement)
596 mLastNeumannCondition[indexOfUnknown] = mpNeumannMap[indexOfUnknown]->find(pSurfaceElement);
598 if (mLastNeumannCondition[indexOfUnknown] == mpNeumannMap[indexOfUnknown]->end())
605 return mLastNeumannCondition[indexOfUnknown]->second->GetValue(rX);
609 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
611 unsigned indexOfUnknown)
613 assert(indexOfUnknown < PROBLEM_DIM);
615 mLastNeumannCondition[indexOfUnknown] = mpNeumannMap[indexOfUnknown]->find(pSurfaceElement);
617 return (mLastNeumannCondition[indexOfUnknown] != mpNeumannMap[indexOfUnknown]->end());
620 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
624 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
626 if (mAnyNonZeroNeumannConditionsForUnknown[index_of_unknown] ==
true)
634 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
638 return mpNeumannMap[0]->begin();
641 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
645 return mpNeumannMap[0]->end();
648 #endif // _BOUNDARYCONDITIONSCONTAINERIMPLEMENTATION_HPP_
void AssembleFinalLinearSystem()
virtual unsigned GetNumBoundaryElements() const
void AddPeriodicBoundaryCondition(const Node< SPACE_DIM > *pNode1, const Node< SPACE_DIM > *pNode2)
void GetOwnershipRange(PetscInt &lo, PetscInt &hi)
BoundaryElementIterator GetBoundaryElementIteratorBegin() const
void ApplyDirichletToNonlinearResidual(const Vec currentSolution, Vec residual, DistributedVectorFactory &rFactory)
void ZeroMatrixRowsWithValueOnDiagonal(std::vector< unsigned > &rRows, double diagonalValue)
DistributedVector CreateDistributedVector(Vec vec, bool readOnly=false)
NeumannMapIterator mLastNeumannCondition[PROBLEM_DIM]
void DefineZeroDirichletOnMeshBoundary(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, unsigned indexOfUnknown=0)
bool IsBoundaryNode() const
static void BeginEvent(unsigned event)
void AddNeumannBoundaryCondition(const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *pBoundaryElement, const AbstractBoundaryCondition< SPACE_DIM > *pBoundaryCondition, unsigned indexOfUnknown=0)
Vec & rGetDirichletBoundaryConditionsVector()
std::map< const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *, const AbstractBoundaryCondition< SPACE_DIM > * >::const_iterator NeumannMapIterator
void ZeroMatrixRowsAndColumnsWithValueOnDiagonal(std::vector< unsigned > &rRowColIndices, double diagonalValue)
bool IsGlobalIndexLocal(unsigned globalIndex)
BoundaryNodeIterator GetBoundaryNodeIteratorBegin() const
void ApplyDirichletToLinearProblem(LinearSystem &rLinearSystem, bool applyToMatrix=true, bool applyToRhsVector=true)
double GetNeumannBCValue(const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *pSurfaceElement, const ChastePoint< SPACE_DIM > &rX, unsigned indexOfUnknown=0)
void ApplyPeriodicBcsToLinearProblem(LinearSystem &rLinearSystem, bool applyToMatrix=true, bool applyToRhsVector=true)
void AddDirichletBoundaryCondition(const Node< SPACE_DIM > *pBoundaryNode, const AbstractBoundaryCondition< SPACE_DIM > *pBoundaryCondition, unsigned indexOfUnknown=0, bool checkIfBoundaryNode=true)
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
std::map< const Node< SPACE_DIM > *, const Node< SPACE_DIM > * > * mpPeriodicBcMap[PROBLEM_DIM]
~BoundaryConditionsContainer()
unsigned GetNumBoundaryNodes() const
bool Validate(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh)
std::vector< Node< SPACE_DIM > * >::const_iterator BoundaryNodeIterator
ConstBoundaryCondition< SPACE_DIM > * mpZeroBoundaryCondition
bool AnyNonZeroNeumannConditions()
void SetRhsVectorElement(PetscInt row, double value)
BoundaryConditionsContainer(bool deleteConditions=true)
std::map< const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *, const AbstractBoundaryCondition< SPACE_DIM > * > * mpNeumannMap[PROBLEM_DIM]
void DefineConstantDirichletOnMeshBoundary(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, double value, unsigned indexOfUnknown=0)
void ApplyDirichletToNonlinearJacobian(Mat jacobian)
void DefineZeroNeumannOnMeshBoundary(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, unsigned indexOfUnknown=0)
BoundaryNodeIterator GetBoundaryNodeIteratorEnd() const
NeumannMapIterator EndNeumann()
static void EndEvent(unsigned event)
std::vector< BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > * >::const_iterator BoundaryElementIterator
NeumannMapIterator BeginNeumann()
double GetValue(const ChastePoint< SPACE_DIM > &rX) const
bool HasNeumannBoundaryCondition(const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *pSurfaceElement, unsigned indexOfUnknown=0)
bool mAnyNonZeroNeumannConditionsForUnknown[PROBLEM_DIM]
Vec GetMatrixRowDistributed(unsigned rowIndex)
BoundaryElementIterator GetBoundaryElementIteratorEnd() const