BoundaryConditionsContainer.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
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     // Save Dirichlet conditions
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     // Save Neumann conditions
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     // Keep track of conditions that might need deleting
00398     std::set<const AbstractBoundaryCondition<SPACE_DIM>*> maybe_unused_bcs;
00399     std::set<const AbstractBoundaryCondition<SPACE_DIM>*> used_bcs;
00400     
00401     // Load Dirichlet conditions
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;  //We know that a Dirichlet is being added, even if not by this process
00412             Node<SPACE_DIM>* p_node;
00413             try
00414             {
00415                 p_node = pMesh->GetNodeFromPrePermutationIndex(node_index);
00416             }
00417             catch (Exception& e)
00418             {
00419                 // It's a distributed mesh and we don't own this node - skip to the next BC
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; // Whether the Dirichlet BCC was empty or not, all processes know the status.
00428 
00429     // Load Neumann conditions
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                 // It's a distributed mesh and we don't own this element - skip to the next BC
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     // Free any unused BCs
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_

Generated on Mon Nov 1 12:35:24 2010 for Chaste by  doxygen 1.5.5