36#ifndef _BOUNDARYCONDITIONSCONTAINERIMPLEMENTATION_HPP_
37#define _BOUNDARYCONDITIONSCONTAINERIMPLEMENTATION_HPP_
39#include "BoundaryConditionsContainer.hpp"
40#include "ConstBoundaryCondition.hpp"
41#include "DistributedVector.hpp"
43#include "HeartEventHandler.hpp"
44#include "PetscMatTools.hpp"
45#include "PetscVecTools.hpp"
46#include "ReplicatableVector.hpp"
48template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
54 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
68template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
72 std::set<const AbstractBoundaryCondition<SPACE_DIM>*> deleted_conditions;
73 for (
unsigned i=0; i<PROBLEM_DIM; i++)
76 while (neumann_iterator != mpNeumannMap[i]->end() )
79 if (deleted_conditions.count(neumann_iterator->second) == 0)
81 deleted_conditions.insert(neumann_iterator->second);
83 if (neumann_iterator->second != mpZeroBoundaryCondition)
85 if (this->mDeleteConditions)
87 delete neumann_iterator->second;
93 delete(mpNeumannMap[i]);
94 delete(mpPeriodicBcMap[i]);
97 delete mpZeroBoundaryCondition;
99 if (this->mDeleteConditions)
101 this->DeleteDirichletBoundaryConditions(deleted_conditions);
105template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
108 unsigned indexOfUnknown,
109 bool checkIfBoundaryNode)
111 assert(indexOfUnknown < PROBLEM_DIM);
112 if (checkIfBoundaryNode)
117 (*(this->mpDirichletMap[indexOfUnknown]))[pBoundaryNode] = pBoundaryCondition;
120template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
130 for (
unsigned i=0; i<PROBLEM_DIM; i++)
132 (*(this->mpPeriodicBcMap[i]))[pNode1] = pNode2;
136template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
139 unsigned indexOfUnknown)
141 assert(indexOfUnknown < PROBLEM_DIM);
150 if (p_const_cond->
GetValue(pBoundaryElement->
GetNode(0)->GetPoint()) != 0.0)
152 mAnyNonZeroNeumannConditionsForUnknown[indexOfUnknown] =
true;
157 mAnyNonZeroNeumannConditionsForUnknown[indexOfUnknown] =
true;
160 for (
unsigned unknown=0; unknown<PROBLEM_DIM; unknown++)
162 if (unknown == indexOfUnknown)
164 (*(mpNeumannMap[indexOfUnknown]))[pBoundaryElement] = pBoundaryCondition;
169 if (mpNeumannMap[unknown]->find(pBoundaryElement)==mpNeumannMap[unknown]->end())
172 (*(mpNeumannMap[unknown]))[pBoundaryElement] = mpZeroBoundaryCondition;
178template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
180 unsigned indexOfUnknown)
182 this->DefineConstantDirichletOnMeshBoundary(pMesh, 0.0, indexOfUnknown);
185template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
188 unsigned indexOfUnknown)
190 assert(indexOfUnknown < PROBLEM_DIM);
200 AddDirichletBoundaryCondition(*iter, p_boundary_condition, indexOfUnknown);
205template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
207 unsigned indexOfUnknown)
209 assert(indexOfUnknown < PROBLEM_DIM);
219 AddNeumannBoundaryCondition(*iter, p_zero_boundary_condition, indexOfUnknown);
223 mAnyNonZeroNeumannConditionsForUnknown[indexOfUnknown] =
false;
256template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
260 bool applyToRhsVector)
266 if (!this->HasDirichletBoundaryConditions())
275 if (matrix_is_symmetric)
303 lo = lo_s; hi = hi_s;
306 for (
unsigned i=lo; i<hi; i++)
308 dirichlet_conditions[i] = DBL_MAX;
311 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
313 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
315 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
317 unsigned node_index = this->mDirichIterator->first->GetIndex();
318 double value = this->mDirichIterator->second->GetValue(this->mDirichIterator->first->GetPoint());
319 assert(value != DBL_MAX);
321 unsigned row = PROBLEM_DIM*node_index + index_of_unknown;
322 dirichlet_conditions[row] = value;
324 this->mDirichIterator++;
329 dirichlet_conditions.Replicate(lo, hi);
332 std::vector<unsigned> rows_to_zero;
333 for (
unsigned i=0; i<dirichlet_conditions.GetSize(); i++)
335 if (dirichlet_conditions[i] != DBL_MAX)
337 rows_to_zero.push_back(i);
341 if (matrix_is_symmetric)
344 for (
unsigned i=0; i<rows_to_zero.size(); i++)
346 unsigned col = rows_to_zero[i];
347 double minus_value = -dirichlet_conditions[col];
379 if (matrix_is_symmetric)
389 if (applyToRhsVector)
401 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
403 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
405 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
407 unsigned node_index = this->mDirichIterator->first->GetIndex();
408 double value = this->mDirichIterator->second->GetValue(this->mDirichIterator->first->GetPoint());
410 unsigned row = PROBLEM_DIM*node_index + index_of_unknown;
414 this->mDirichIterator++;
422template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
425 bool applyToRhsVector)
427 bool has_periodic_bcs =
false;
428 for (
unsigned i=0; i<PROBLEM_DIM; i++)
430 if (!mpPeriodicBcMap[i]->empty())
432 has_periodic_bcs =
true;
441 std::vector<unsigned> rows_to_zero;
442 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
445 iter != mpPeriodicBcMap[index_of_unknown]->end();
448 unsigned node_index_1 = iter->first->GetIndex();
449 unsigned row_index_1 = PROBLEM_DIM*node_index_1 + index_of_unknown;
450 rows_to_zero.push_back(row_index_1);
456 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
459 iter != mpPeriodicBcMap[index_of_unknown]->end();
462 unsigned node_index_1 = iter->first->GetIndex();
463 unsigned node_index_2 = iter->second->GetIndex();
465 unsigned mat_index1 = PROBLEM_DIM*node_index_1 + index_of_unknown;
466 unsigned mat_index2 = PROBLEM_DIM*node_index_2 + index_of_unknown;
472 if (applyToRhsVector)
474 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
477 iter != mpPeriodicBcMap[index_of_unknown]->end();
480 unsigned node_index = iter->first->GetIndex();
481 unsigned row_index = PROBLEM_DIM*node_index + index_of_unknown;
488template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
490 const Vec currentSolution,
494 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
496 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
502 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
507 unsigned node_index = this->mDirichIterator->first->GetIndex();
509 double value = this->mDirichIterator->second->GetValue(this->mDirichIterator->first->GetPoint());
513 residual_stripe[node_index]=solution_stripe[node_index] - value;
515 this->mDirichIterator++;
518 residual_distributed.
Restore();
522template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
525 unsigned num_boundary_conditions = 0;
526 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
528 num_boundary_conditions += this->mpDirichletMap[index_of_unknown]->size();
531 std::vector<unsigned> rows_to_zero(num_boundary_conditions);
534 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
536 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
538 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
540 unsigned node_index = this->mDirichIterator->first->GetIndex();
541 rows_to_zero[counter++] = PROBLEM_DIM*node_index + index_of_unknown;
542 this->mDirichIterator++;
549template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
554 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
561 if (!HasNeumannBoundaryCondition(*elt_iter, index_of_unknown))
564 for (
unsigned i=0; i<(*elt_iter)->GetNumNodes(); i++)
566 if (!this->HasDirichletBoundaryCondition((*elt_iter)->GetNode(i)))
578template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
581 unsigned indexOfUnknown)
583 assert(indexOfUnknown < PROBLEM_DIM);
586 if (mLastNeumannCondition[indexOfUnknown] == mpNeumannMap[indexOfUnknown]->end() ||
587 mLastNeumannCondition[indexOfUnknown]->first != pSurfaceElement)
589 mLastNeumannCondition[indexOfUnknown] = mpNeumannMap[indexOfUnknown]->find(pSurfaceElement);
591 if (mLastNeumannCondition[indexOfUnknown] == mpNeumannMap[indexOfUnknown]->end())
598 return mLastNeumannCondition[indexOfUnknown]->second->GetValue(rX);
602template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
604 unsigned indexOfUnknown)
606 assert(indexOfUnknown < PROBLEM_DIM);
608 mLastNeumannCondition[indexOfUnknown] = mpNeumannMap[indexOfUnknown]->find(pSurfaceElement);
610 return (mLastNeumannCondition[indexOfUnknown] != mpNeumannMap[indexOfUnknown]->end());
613template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
617 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
619 if (mAnyNonZeroNeumannConditionsForUnknown[index_of_unknown] ==
true)
627template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
631 return mpNeumannMap[0]->begin();
634template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
638 return mpNeumannMap[0]->end();
#define EXCEPT_IF_NOT(test)
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
BoundaryNodeIterator GetBoundaryNodeIteratorBegin() const
std::vector< Node< SPACE_DIM > * >::const_iterator BoundaryNodeIterator
BoundaryNodeIterator GetBoundaryNodeIteratorEnd() const
unsigned GetNumBoundaryNodes() const
virtual unsigned GetNumBoundaryElements() const
std::vector< BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > * >::const_iterator BoundaryElementIterator
BoundaryElementIterator GetBoundaryElementIteratorBegin() const
BoundaryElementIterator GetBoundaryElementIteratorEnd() const
void ApplyDirichletToNonlinearJacobian(Mat jacobian)
~BoundaryConditionsContainer()
NeumannMapIterator BeginNeumann()
NeumannMapIterator EndNeumann()
bool AnyNonZeroNeumannConditions()
std::map< const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *, const AbstractBoundaryCondition< SPACE_DIM > * > * mpNeumannMap[PROBLEM_DIM]
NeumannMapIterator mLastNeumannCondition[PROBLEM_DIM]
void AddDirichletBoundaryCondition(const Node< SPACE_DIM > *pBoundaryNode, const AbstractBoundaryCondition< SPACE_DIM > *pBoundaryCondition, unsigned indexOfUnknown=0, bool checkIfBoundaryNode=true)
double GetNeumannBCValue(const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *pSurfaceElement, const ChastePoint< SPACE_DIM > &rX, unsigned indexOfUnknown=0)
void ApplyDirichletToLinearProblem(LinearSystem &rLinearSystem, bool applyToMatrix=true, bool applyToRhsVector=true)
void AddPeriodicBoundaryCondition(const Node< SPACE_DIM > *pNode1, const Node< SPACE_DIM > *pNode2)
bool HasNeumannBoundaryCondition(const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *pSurfaceElement, unsigned indexOfUnknown=0)
bool Validate(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh)
void DefineZeroDirichletOnMeshBoundary(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, unsigned indexOfUnknown=0)
std::map< const Node< SPACE_DIM > *, const Node< SPACE_DIM > * > * mpPeriodicBcMap[PROBLEM_DIM]
void ApplyDirichletToNonlinearResidual(const Vec currentSolution, Vec residual, DistributedVectorFactory &rFactory)
void DefineZeroNeumannOnMeshBoundary(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, unsigned indexOfUnknown=0)
std::map< constBoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *, constAbstractBoundaryCondition< SPACE_DIM > * >::const_iterator NeumannMapIterator
BoundaryConditionsContainer(bool deleteConditions=true)
ConstBoundaryCondition< SPACE_DIM > * mpZeroBoundaryCondition
void DefineConstantDirichletOnMeshBoundary(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, double value, unsigned indexOfUnknown=0)
void AddNeumannBoundaryCondition(const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *pBoundaryElement, const AbstractBoundaryCondition< SPACE_DIM > *pBoundaryCondition, unsigned indexOfUnknown=0)
bool mAnyNonZeroNeumannConditionsForUnknown[PROBLEM_DIM]
void ApplyPeriodicBcsToLinearProblem(LinearSystem &rLinearSystem, bool applyToMatrix=true, bool applyToRhsVector=true)
double GetValue(const ChastePoint< SPACE_DIM > &rX) const
DistributedVector CreateDistributedVector(Vec vec, bool readOnly=false)
bool IsGlobalIndexLocal(unsigned globalIndex)
static void BeginEvent(unsigned event)
static void EndEvent(unsigned event)
Vec & rGetDirichletBoundaryConditionsVector()
void AssembleFinalLinearSystem()
void GetOwnershipRange(PetscInt &lo, PetscInt &hi)
void ZeroMatrixRowsWithValueOnDiagonal(std::vector< unsigned > &rRows, double diagonalValue)
void ZeroMatrixRowsAndColumnsWithValueOnDiagonal(std::vector< unsigned > &rRowColIndices, double diagonalValue)
void SetRhsVectorElement(PetscInt row, double value)
Vec GetMatrixRowDistributed(unsigned rowIndex)
bool IsBoundaryNode() const