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"
48 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
54 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
68 template<
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);
105 template<
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;
120 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
130 for (
unsigned i=0; i<PROBLEM_DIM; i++)
132 (*(this->mpPeriodicBcMap[i]))[pNode1] = pNode2;
136 template<
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;
178 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
180 unsigned indexOfUnknown)
182 this->DefineConstantDirichletOnMeshBoundary(pMesh, 0.0, indexOfUnknown);
185 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
188 unsigned indexOfUnknown)
190 assert(indexOfUnknown < PROBLEM_DIM);
200 AddDirichletBoundaryCondition(*iter, p_boundary_condition, indexOfUnknown);
205 template<
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;
256 template<
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];
378 if (matrix_is_symmetric)
388 if (applyToRhsVector)
400 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
402 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
404 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
406 unsigned node_index = this->mDirichIterator->first->GetIndex();
407 double value = this->mDirichIterator->second->GetValue(this->mDirichIterator->first->GetPoint());
409 unsigned row = PROBLEM_DIM*node_index + index_of_unknown;
413 this->mDirichIterator++;
421 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
424 bool applyToRhsVector)
426 bool has_periodic_bcs =
false;
427 for (
unsigned i=0; i<PROBLEM_DIM; i++)
429 if (!mpPeriodicBcMap[i]->empty())
431 has_periodic_bcs =
true;
440 std::vector<unsigned> rows_to_zero;
441 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
444 iter != mpPeriodicBcMap[index_of_unknown]->end();
447 unsigned node_index_1 = iter->first->GetIndex();
448 unsigned row_index_1 = PROBLEM_DIM*node_index_1 + index_of_unknown;
449 rows_to_zero.push_back(row_index_1);
455 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
458 iter != mpPeriodicBcMap[index_of_unknown]->end();
461 unsigned node_index_1 = iter->first->GetIndex();
462 unsigned node_index_2 = iter->second->GetIndex();
464 unsigned mat_index1 = PROBLEM_DIM*node_index_1 + index_of_unknown;
465 unsigned mat_index2 = PROBLEM_DIM*node_index_2 + index_of_unknown;
471 if (applyToRhsVector)
473 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
476 iter != mpPeriodicBcMap[index_of_unknown]->end();
479 unsigned node_index = iter->first->GetIndex();
480 unsigned row_index = PROBLEM_DIM*node_index + index_of_unknown;
487 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
489 const Vec currentSolution,
493 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
495 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
501 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
506 unsigned node_index = this->mDirichIterator->first->GetIndex();
508 double value = this->mDirichIterator->second->GetValue(this->mDirichIterator->first->GetPoint());
512 residual_stripe[node_index]=solution_stripe[node_index] - value;
514 this->mDirichIterator++;
517 residual_distributed.
Restore();
521 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
524 unsigned num_boundary_conditions = 0;
525 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
527 num_boundary_conditions += this->mpDirichletMap[index_of_unknown]->size();
530 std::vector<unsigned> rows_to_zero(num_boundary_conditions);
533 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
535 this->mDirichIterator = this->mpDirichletMap[index_of_unknown]->begin();
537 while (this->mDirichIterator != this->mpDirichletMap[index_of_unknown]->end() )
539 unsigned node_index = this->mDirichIterator->first->GetIndex();
540 rows_to_zero[counter++] = PROBLEM_DIM*node_index + index_of_unknown;
541 this->mDirichIterator++;
548 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
553 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
560 if (!HasNeumannBoundaryCondition(*elt_iter, index_of_unknown))
563 for (
unsigned i=0; i<(*elt_iter)->GetNumNodes(); i++)
565 if (!this->HasDirichletBoundaryCondition((*elt_iter)->GetNode(i)))
577 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
580 unsigned indexOfUnknown)
582 assert(indexOfUnknown < PROBLEM_DIM);
585 if (mLastNeumannCondition[indexOfUnknown] == mpNeumannMap[indexOfUnknown]->end() ||
586 mLastNeumannCondition[indexOfUnknown]->first != pSurfaceElement)
588 mLastNeumannCondition[indexOfUnknown] = mpNeumannMap[indexOfUnknown]->find(pSurfaceElement);
590 if (mLastNeumannCondition[indexOfUnknown] == mpNeumannMap[indexOfUnknown]->end())
597 return mLastNeumannCondition[indexOfUnknown]->second->GetValue(rX);
601 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
603 unsigned indexOfUnknown)
605 assert(indexOfUnknown < PROBLEM_DIM);
607 mLastNeumannCondition[indexOfUnknown] = mpNeumannMap[indexOfUnknown]->find(pSurfaceElement);
609 return (mLastNeumannCondition[indexOfUnknown] != mpNeumannMap[indexOfUnknown]->end());
612 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
616 for (
unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
618 if (mAnyNonZeroNeumannConditionsForUnknown[index_of_unknown] ==
true)
626 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
630 return mpNeumannMap[0]->begin();
633 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
637 return mpNeumannMap[0]->end();
640 #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
#define EXCEPT_IF_NOT(test)
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