Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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 // Save Dirichlet conditions 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 // Save Neumann conditions 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 // Keep track of conditions that might need deleting 00447 std::set<const AbstractBoundaryCondition<SPACE_DIM>*> maybe_unused_bcs; 00448 std::set<const AbstractBoundaryCondition<SPACE_DIM>*> used_bcs; 00449 00450 // Load Dirichlet conditions 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; //We know that a Dirichlet is being added, even if not by this process 00461 Node<SPACE_DIM>* p_node; 00462 try 00463 { 00464 p_node = pMesh->GetNodeFromPrePermutationIndex(node_index); 00465 } 00466 catch (Exception& e) 00467 { 00468 // It's a distributed mesh and we don't own this node - skip to the next BC 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; // Whether the Dirichlet BCC was empty or not, all processes know the status. 00477 00478 // Load Neumann conditions 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& e) 00494 { 00495 // It's a distributed mesh and we don't own this element - skip to the next BC 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 // Free any unused BCs 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_