00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef _BOUNDARYCONDITIONSCONTAINER_HPP_
00037 #define _BOUNDARYCONDITIONSCONTAINER_HPP_
00038
00039 #include <map>
00040 #include "ChasteSerialization.hpp"
00041 #include <boost/serialization/split_member.hpp>
00042 #include <boost/serialization/map.hpp>
00043
00044 #include "AbstractBoundaryConditionsContainer.hpp"
00045 #include "AbstractBoundaryCondition.hpp"
00046 #include "AbstractTetrahedralMesh.hpp"
00047 #include "BoundaryElement.hpp"
00048 #include "Node.hpp"
00049 #include "LinearSystem.hpp"
00050 #include "PetscException.hpp"
00051 #include "ChastePoint.hpp"
00052 #include "ConstBoundaryCondition.hpp"
00053 #include "DistributedVectorFactory.hpp"
00054
00066 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00067 class BoundaryConditionsContainer : public AbstractBoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>
00068 {
00069 public:
00070
00072 typedef typename std::map< const BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>*, const AbstractBoundaryCondition<SPACE_DIM>* >::const_iterator
00073 NeumannMapIterator;
00074
00076 typedef AbstractBoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM> BaseClassType;
00077
00078 private:
00079
00080 std::map< const BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *, const AbstractBoundaryCondition<SPACE_DIM>* >*
00081 mpNeumannMap[PROBLEM_DIM];
00084 std::map< const Node<SPACE_DIM> *, const Node<SPACE_DIM> * >* mpPeriodicBcMap[PROBLEM_DIM];
00085
00089 NeumannMapIterator mLastNeumannCondition[PROBLEM_DIM];
00090
00094 bool mAnyNonZeroNeumannConditionsForUnknown[PROBLEM_DIM];
00095
00097 ConstBoundaryCondition<SPACE_DIM>* mpZeroBoundaryCondition;
00098
00100 bool mLoadedFromArchive;
00101
00102 public:
00103
00110 BoundaryConditionsContainer(bool deleteConditions=true);
00111
00116 ~BoundaryConditionsContainer();
00117
00130 void AddDirichletBoundaryCondition(const Node<SPACE_DIM>* pBoundaryNode,
00131 const AbstractBoundaryCondition<SPACE_DIM>* pBoundaryCondition,
00132 unsigned indexOfUnknown = 0,
00133 bool checkIfBoundaryNode = true);
00134
00153 void AddNeumannBoundaryCondition(const BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* pBoundaryElement,
00154 const AbstractBoundaryCondition<SPACE_DIM>* pBoundaryCondition,
00155 unsigned indexOfUnknown = 0);
00156
00157
00165 void AddPeriodicBoundaryCondition(const Node<SPACE_DIM>* pNode1,
00166 const Node<SPACE_DIM>* pNode2);
00167
00168
00176 void DefineZeroDirichletOnMeshBoundary(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00177 unsigned indexOfUnknown = 0);
00178
00187 void DefineConstantDirichletOnMeshBoundary(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00188 double value,
00189 unsigned indexOfUnknown = 0);
00190
00198 void DefineZeroNeumannOnMeshBoundary(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00199 unsigned indexOfUnknown = 0);
00200
00215 void ApplyDirichletToLinearProblem(LinearSystem& rLinearSystem,
00216 bool applyToMatrix = true,
00217 bool applyToRhsVector = true);
00218
00219
00220
00240 void ApplyPeriodicBcsToLinearProblem(LinearSystem& rLinearSystem,
00241 bool applyToMatrix = true,
00242 bool applyToRhsVector = true);
00243
00256 void ApplyDirichletToNonlinearResidual(const Vec currentSolution, Vec residual,
00257 DistributedVectorFactory& rFactory);
00258
00269 void ApplyDirichletToNonlinearJacobian(Mat jacobian);
00270
00281 bool Validate(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00282
00292 double GetNeumannBCValue(const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>* pSurfaceElement,
00293 const ChastePoint<SPACE_DIM>& rX,
00294 unsigned indexOfUnknown = 0);
00295
00305 bool HasNeumannBoundaryCondition(const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>* pSurfaceElement,
00306 unsigned indexOfUnknown = 0);
00307
00311 bool AnyNonZeroNeumannConditions();
00312
00316 NeumannMapIterator BeginNeumann();
00317
00321 NeumannMapIterator EndNeumann();
00322
00336 template <class Archive>
00337 void LoadFromArchive(Archive & archive, AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00338 {
00339 if (mLoadedFromArchive)
00340 {
00341 return;
00342 }
00343
00344 MergeFromArchive(archive, pMesh);
00345 }
00346
00356 template <class Archive>
00357 void MergeFromArchive(Archive & archive, AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00358
00359 private:
00360
00362 friend class boost::serialization::access;
00363
00370 template<class Archive>
00371 void save(Archive & archive, const unsigned int version) const;
00372
00390 template<class Archive>
00391 void load(Archive & archive, const unsigned int version)
00392 {
00393 }
00394
00395 BOOST_SERIALIZATION_SPLIT_MEMBER()
00396 };
00397
00398 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00399 template<class Archive>
00400 void BoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::save(
00401 Archive & archive, const unsigned int version) const
00402 {
00403 typedef typename std::map<unsigned, const AbstractBoundaryCondition<SPACE_DIM> *> archive_map_type;
00404
00405
00406 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00407 {
00408 archive_map_type bc_map;
00409 typename BaseClassType::DirichletIteratorType it = this->mpDirichletMap[index_of_unknown]->begin();
00410 while (it != this->mpDirichletMap[index_of_unknown]->end() )
00411 {
00412 unsigned node_index = it->first->GetIndex();
00413 const AbstractBoundaryCondition<SPACE_DIM> * p_cond = it->second;
00414 bc_map[node_index] = p_cond;
00415
00416 it++;
00417 }
00418 archive & bc_map;
00419 }
00420
00421
00422 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00423 {
00424 archive_map_type bc_map;
00425 for (NeumannMapIterator it = mpNeumannMap[index_of_unknown]->begin();
00426 it != mpNeumannMap[index_of_unknown]->end();
00427 ++it)
00428 {
00429 unsigned elem_index = it->first->GetIndex();
00430 const AbstractBoundaryCondition<SPACE_DIM>* p_cond = it->second;
00431 bc_map[elem_index] = p_cond;
00432 }
00433 archive & bc_map;
00434 }
00435 }
00436
00437 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00438 template<class Archive>
00439 void BoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::MergeFromArchive(
00440 Archive & archive, AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00441 {
00442 mLoadedFromArchive = true;
00443
00444 typedef typename std::map<unsigned, AbstractBoundaryCondition<SPACE_DIM>*> archive_map_type;
00445
00446
00447 std::set<const AbstractBoundaryCondition<SPACE_DIM>*> maybe_unused_bcs;
00448 std::set<const AbstractBoundaryCondition<SPACE_DIM>*> used_bcs;
00449
00450
00451 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00452 {
00453 archive_map_type bc_map;
00454 archive & bc_map;
00455 for (typename archive_map_type::iterator it = bc_map.begin();
00456 it != bc_map.end();
00457 ++it)
00458 {
00459 unsigned node_index = it->first;
00460 this->mHasDirichletBCs=true;
00461 Node<SPACE_DIM>* p_node;
00462 try
00463 {
00464 p_node = pMesh->GetNodeFromPrePermutationIndex(node_index);
00465 }
00466 catch (Exception&)
00467 {
00468
00469 maybe_unused_bcs.insert(it->second);
00470 continue;
00471 }
00472 AddDirichletBoundaryCondition(p_node, it->second, index_of_unknown, false);
00473 used_bcs.insert(it->second);
00474 }
00475 }
00476 this->mCheckedAndCommunicatedIfDirichletBcs=true;
00477
00478
00479 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00480 {
00481 archive_map_type bc_map;
00482 archive & bc_map;
00483 for (typename archive_map_type::iterator it = bc_map.begin();
00484 it != bc_map.end();
00485 ++it)
00486 {
00487 unsigned boundary_element_index = it->first;
00488 BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* p_boundary_element;
00489 try
00490 {
00491 p_boundary_element = pMesh->GetBoundaryElement(boundary_element_index);
00492 }
00493 catch (Exception&)
00494 {
00495
00496 maybe_unused_bcs.insert(it->second);
00497 continue;
00498 }
00499 AddNeumannBoundaryCondition(p_boundary_element, it->second, index_of_unknown);
00500 used_bcs.insert(it->second);
00501 }
00502 }
00503
00504
00505 for (typename std::set<const AbstractBoundaryCondition<SPACE_DIM>*>::iterator it=maybe_unused_bcs.begin();
00506 it != maybe_unused_bcs.end();
00507 ++it)
00508 {
00509 typename std::set<const AbstractBoundaryCondition<SPACE_DIM>*>::iterator used = used_bcs.find(*it);
00510 if (used == used_bcs.end())
00511 {
00512 delete (*it);
00513 }
00514 }
00515 }
00516
00517 #endif //_BOUNDARYCONDITIONSCONTAINER_HPP_