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 #ifndef _BOUNDARYCONDITIONSCONTAINER_HPP_
00029 #define _BOUNDARYCONDITIONSCONTAINER_HPP_
00030
00031 #include <map>
00032 #include "ChasteSerialization.hpp"
00033 #include <boost/serialization/split_member.hpp>
00034 #include <boost/serialization/map.hpp>
00035
00036 #include "AbstractBoundaryConditionsContainer.hpp"
00037 #include "AbstractBoundaryCondition.hpp"
00038 #include "AbstractTetrahedralMesh.hpp"
00039 #include "BoundaryElement.hpp"
00040 #include "Node.hpp"
00041 #include "LinearSystem.hpp"
00042 #include "PetscException.hpp"
00043 #include "ChastePoint.hpp"
00044 #include "ConstBoundaryCondition.hpp"
00045 #include "DistributedVectorFactory.hpp"
00046
00047
00059 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00060 class BoundaryConditionsContainer : public AbstractBoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>
00061 {
00062 public:
00063
00065 typedef typename std::map< const BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>*, const AbstractBoundaryCondition<SPACE_DIM>* >::const_iterator
00066 NeumannMapIterator;
00067
00069 typedef AbstractBoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM> BaseClassType;
00070
00071 private:
00072
00073 std::map< const BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *, const AbstractBoundaryCondition<SPACE_DIM>* >*
00074 mpNeumannMap[PROBLEM_DIM];
00079 NeumannMapIterator mLastNeumannCondition[PROBLEM_DIM];
00080
00084 bool mAnyNonZeroNeumannConditionsForUnknown[PROBLEM_DIM];
00085
00087 ConstBoundaryCondition<SPACE_DIM>* mpZeroBoundaryCondition;
00088
00090 bool mLoadedFromArchive;
00091
00092 public:
00093
00098 BoundaryConditionsContainer();
00099
00104 ~BoundaryConditionsContainer();
00105
00118 void AddDirichletBoundaryCondition(const Node<SPACE_DIM>* pBoundaryNode,
00119 const AbstractBoundaryCondition<SPACE_DIM>* pBoundaryCondition,
00120 unsigned indexOfUnknown = 0,
00121 bool checkIfBoundaryNode = true);
00122
00141 void AddNeumannBoundaryCondition(const BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* pBoundaryElement,
00142 const AbstractBoundaryCondition<SPACE_DIM>* pBoundaryCondition,
00143 unsigned indexOfUnknown = 0);
00144
00152 void DefineZeroDirichletOnMeshBoundary(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00153 unsigned indexOfUnknown = 0);
00154
00163 void DefineConstantDirichletOnMeshBoundary(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00164 double value,
00165 unsigned indexOfUnknown = 0);
00166
00174 void DefineZeroNeumannOnMeshBoundary(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00175 unsigned indexOfUnknown = 0);
00176
00191 void ApplyDirichletToLinearProblem(LinearSystem& rLinearSystem,
00192 bool applyToMatrix = true,
00193 bool applyToRhsVector = true);
00194
00207 void ApplyDirichletToNonlinearResidual(const Vec currentSolution, Vec residual,
00208 DistributedVectorFactory& rFactory);
00209
00220 void ApplyDirichletToNonlinearJacobian(Mat jacobian);
00221
00232 bool Validate(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00233
00243 double GetNeumannBCValue(const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>* pSurfaceElement,
00244 const ChastePoint<SPACE_DIM>& rX,
00245 unsigned indexOfUnknown = 0);
00246
00256 bool HasNeumannBoundaryCondition(const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>* pSurfaceElement,
00257 unsigned indexOfUnknown = 0);
00258
00262 bool AnyNonZeroNeumannConditions();
00263
00267 NeumannMapIterator BeginNeumann();
00268
00272 NeumannMapIterator EndNeumann();
00273
00287 template <class Archive>
00288 void LoadFromArchive(Archive & archive, AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00289 {
00290 if (mLoadedFromArchive)
00291 {
00292 return;
00293 }
00294
00295 MergeFromArchive(archive, pMesh);
00296 }
00297
00307 template <class Archive>
00308 void MergeFromArchive(Archive & archive, AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00309
00310 private:
00312 friend class boost::serialization::access;
00313
00320 template<class Archive>
00321 void save(Archive & archive, const unsigned int version) const;
00322
00340 template<class Archive>
00341 void load(Archive & archive, const unsigned int version)
00342 {
00343 }
00344
00345 BOOST_SERIALIZATION_SPLIT_MEMBER()
00346
00347 };
00348
00349
00350 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00351 template<class Archive>
00352 void BoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::save(
00353 Archive & archive, const unsigned int version) const
00354 {
00355 typedef typename std::map<unsigned, const AbstractBoundaryCondition<SPACE_DIM> *> archive_map_type;
00356
00357 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00358 {
00359 archive_map_type bc_map;
00360 typename BaseClassType::DirichletIteratorType it = this->mpDirichletMap[index_of_unknown]->begin();
00361 while (it != this->mpDirichletMap[index_of_unknown]->end() )
00362 {
00363 unsigned node_index = it->first->GetIndex();
00364 const AbstractBoundaryCondition<SPACE_DIM> * p_cond = it->second;
00365 bc_map[node_index] = p_cond;
00366
00367 it++;
00368 }
00369 archive & bc_map;
00370 }
00371
00372
00373 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00374 {
00375 archive_map_type bc_map;
00376 for (NeumannMapIterator it = mpNeumannMap[index_of_unknown]->begin();
00377 it != mpNeumannMap[index_of_unknown]->end();
00378 ++it)
00379 {
00380 unsigned elem_index = it->first->GetIndex();
00381 const AbstractBoundaryCondition<SPACE_DIM>* p_cond = it->second;
00382 bc_map[elem_index] = p_cond;
00383 }
00384 archive & bc_map;
00385 }
00386 }
00387
00388
00389 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00390 template<class Archive>
00391 void BoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::MergeFromArchive(
00392 Archive & archive, AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00393 {
00394 mLoadedFromArchive = true;
00395
00396 typedef typename std::map<unsigned, AbstractBoundaryCondition<SPACE_DIM>*> archive_map_type;
00397
00398 std::set<const AbstractBoundaryCondition<SPACE_DIM>*> maybe_unused_bcs;
00399 std::set<const AbstractBoundaryCondition<SPACE_DIM>*> used_bcs;
00400
00401
00402 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00403 {
00404 archive_map_type bc_map;
00405 archive & bc_map;
00406 for (typename archive_map_type::iterator it = bc_map.begin();
00407 it != bc_map.end();
00408 ++it)
00409 {
00410 unsigned node_index = it->first;
00411 this->mHasDirichletBCs=true;
00412 Node<SPACE_DIM>* p_node;
00413 try
00414 {
00415 p_node = pMesh->GetNodeFromPrePermutationIndex(node_index);
00416 }
00417 catch (Exception& e)
00418 {
00419
00420 maybe_unused_bcs.insert(it->second);
00421 continue;
00422 }
00423 AddDirichletBoundaryCondition(p_node, it->second, index_of_unknown, false);
00424 used_bcs.insert(it->second);
00425 }
00426 }
00427 this->mCheckedAndCommunicatedIfDirichletBcs=true;
00428
00429
00430 for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++)
00431 {
00432 archive_map_type bc_map;
00433 archive & bc_map;
00434 for (typename archive_map_type::iterator it = bc_map.begin();
00435 it != bc_map.end();
00436 ++it)
00437 {
00438 unsigned boundary_element_index = it->first;
00439 BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* p_boundary_element;
00440 try
00441 {
00442 p_boundary_element = pMesh->GetBoundaryElement(boundary_element_index);
00443 }
00444 catch (Exception& e)
00445 {
00446
00447 maybe_unused_bcs.insert(it->second);
00448 continue;
00449 }
00450 AddNeumannBoundaryCondition(p_boundary_element, it->second, index_of_unknown);
00451 used_bcs.insert(it->second);
00452 }
00453 }
00454
00455
00456 for (typename std::set<const AbstractBoundaryCondition<SPACE_DIM>*>::iterator it=maybe_unused_bcs.begin();
00457 it != maybe_unused_bcs.end();
00458 ++it)
00459 {
00460 typename std::set<const AbstractBoundaryCondition<SPACE_DIM>*>::iterator used = used_bcs.find(*it);
00461 if (used == used_bcs.end())
00462 {
00463 delete (*it);
00464 }
00465 }
00466 }
00467
00468 #endif //_BOUNDARYCONDITIONSCONTAINER_HPP_