AbstractCardiacPde.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
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 
00029 #include "AbstractCardiacPde.hpp"
00030 
00031 #include "DistributedVector.hpp"
00032 #include "AxisymmetricConductivityTensors.hpp"
00033 #include "OrthotropicConductivityTensors.hpp"
00034 #include "ChastePoint.hpp"
00035 #include "ChasteCuboid.hpp"
00036 #include "HeartEventHandler.hpp"
00037 #include "PetscTools.hpp"
00038 #include "FakeBathCell.hpp"
00039 
00040 
00041 template <unsigned SPACE_DIM>
00042 AbstractCardiacPde<SPACE_DIM>::AbstractCardiacPde(
00043             AbstractCardiacCellFactory<SPACE_DIM>* pCellFactory,
00044             const unsigned stride)
00045     : mStride(stride),
00046       mDoCacheReplication(true),
00047       mDoOneCacheReplication(true)
00048 {
00049     //This constructor is called from the Initialise() method of the CardiacProblem class
00050     assert(pCellFactory!=NULL);
00051     assert(pCellFactory->GetMesh()!=NULL);
00052 
00053     std::vector<unsigned>& r_nodes_per_processor = pCellFactory->GetMesh()->rGetNodesPerProcessor();        
00054 
00055     // check number of processor agrees with definition in mesh
00056     if((r_nodes_per_processor.size() != 0) && (r_nodes_per_processor.size() != PetscTools::NumProcs()) )
00057     {
00058         EXCEPTION("Number of processors defined in mesh class not equal to number of processors used");
00059     }
00060 
00061     if(r_nodes_per_processor.size() != 0)
00062     {
00063         unsigned num_local_nodes = r_nodes_per_processor[ PetscTools::GetMyRank() ];
00064         DistributedVector::SetProblemSizePerProcessor(pCellFactory->GetMesh()->GetNumNodes(), num_local_nodes);
00065     }
00066     else
00067     {
00068         DistributedVector::SetProblemSize(pCellFactory->GetMesh()->GetNumNodes());
00069     }
00070 
00071     mCellsDistributed.resize(DistributedVector::End().Global-DistributedVector::Begin().Global);
00072 
00073     for (DistributedVector::Iterator index = DistributedVector::Begin();
00074          index != DistributedVector::End();
00075          ++index)
00076     {
00077         mCellsDistributed[index.Local] = pCellFactory->CreateCardiacCellForNode(index.Global);
00078     }
00079     pCellFactory->FinaliseCellCreation(&mCellsDistributed,
00080                                        DistributedVector::Begin().Global,
00081                                        DistributedVector::End().Global);
00082 
00083 
00084     mIionicCacheReplicated.resize( pCellFactory->GetNumberOfCells() );
00085     mIntracellularStimulusCacheReplicated.resize( pCellFactory->GetNumberOfCells() );
00086     
00087     mpConfig = HeartConfig::Instance();
00088 
00089     if (mpConfig->GetIsMeshProvided() && mpConfig->GetLoadMesh())
00090     {
00091         switch (mpConfig->GetConductivityMedia())
00092         {
00093             case media_type::Orthotropic:
00094                 mpIntracellularConductivityTensors =  new OrthotropicConductivityTensors<SPACE_DIM>;
00095                 mpIntracellularConductivityTensors->SetFibreOrientationFile(mpConfig->GetMeshName() + ".ortho");                
00096                 break;
00097                 
00098             case media_type::Axisymmetric:
00099                 mpIntracellularConductivityTensors =  new AxisymmetricConductivityTensors<SPACE_DIM>;
00100                 mpIntracellularConductivityTensors->SetFibreOrientationFile(mpConfig->GetMeshName() + ".axi");
00101                 break;
00102 
00103             case media_type::NoFibreOrientation:
00105                 mpIntracellularConductivityTensors =  new OrthotropicConductivityTensors<SPACE_DIM>;                
00106                 break;
00107                 
00108             default :
00109                 NEVER_REACHED;                              
00110         }           
00111     }
00112     else // Slab defined in config file or SetMesh() called; no fibre orientation assumed
00113     {
00114         // See previous todo.
00115     mpIntracellularConductivityTensors =  new OrthotropicConductivityTensors<SPACE_DIM>;        
00116     }
00117 
00118     c_vector<double, SPACE_DIM> intra_conductivities;           
00119     mpConfig->GetIntracellularConductivities(intra_conductivities);         
00120 
00121     // this definition must be here (and not inside the if statement) because SetNonConstantConductivities() will keep 
00122     // a pointer to it and we don't want it to go out of scope before Init() is called
00123     unsigned num_elements = pCellFactory->GetMesh()->GetNumElements();                      
00124     std::vector<c_vector<double, SPACE_DIM> > hetero_intra_conductivities(num_elements); 
00125             
00126     if (mpConfig->GetConductivityHeterogeneitiesProvided())
00127     {
00128         std::vector<ChasteCuboid> conductivities_heterogeneity_areas;
00129         std::vector< c_vector<double,3> > intra_h_conductivities;
00130         std::vector< c_vector<double,3> > extra_h_conductivities;
00131         HeartConfig::Instance()->GetConductivityHeterogeneities(conductivities_heterogeneity_areas,
00132                                                                 intra_h_conductivities,
00133                                                                 extra_h_conductivities);
00134 
00135         for (unsigned element_index=0; element_index<num_elements; element_index++)
00136         {
00137             for (unsigned region_index=0; region_index< conductivities_heterogeneity_areas.size(); region_index++)
00138             {
00139                 // if element centroid is contained in the region
00140                 ChastePoint<SPACE_DIM> element_centroid(pCellFactory->GetMesh()->GetElement(element_index)->CalculateCentroid());
00141                 if ( conductivities_heterogeneity_areas[region_index].DoesContain(element_centroid) )
00142                 {
00143                     hetero_intra_conductivities[element_index] = intra_h_conductivities[region_index];
00144                 }
00145                 else
00146                 {
00147                     hetero_intra_conductivities[element_index] = intra_conductivities;                      
00148                 }
00149             }
00150         }
00151 
00152         mpIntracellularConductivityTensors->SetNonConstantConductivities(&hetero_intra_conductivities);
00153     }
00154     else
00155     {               
00156         mpIntracellularConductivityTensors->SetConstantConductivities(intra_conductivities);
00157     }
00158 
00159     mpIntracellularConductivityTensors->Init();        
00160 }
00161 
00162 template <unsigned SPACE_DIM>
00163 AbstractCardiacPde<SPACE_DIM>::~AbstractCardiacPde()
00164 {
00165     for (DistributedVector::Iterator index = DistributedVector::Begin();
00166          index != DistributedVector::End();
00167          ++index)
00168     {
00169         // Only delete real cells
00170         FakeBathCell* p_fake = dynamic_cast<FakeBathCell*>(mCellsDistributed[index.Local]);
00171         if (p_fake == NULL)
00172         {
00173             delete mCellsDistributed[index.Local];
00174         }
00175     }
00176 
00177     delete mpIntracellularConductivityTensors;
00178 }
00179 
00180 template <unsigned SPACE_DIM>
00181 void AbstractCardiacPde<SPACE_DIM>::SetCacheReplication(bool doCacheReplication)
00182 {
00183     mDoCacheReplication = doCacheReplication;
00184 }
00185 
00186 template <unsigned SPACE_DIM>
00187 const c_matrix<double, SPACE_DIM, SPACE_DIM>& AbstractCardiacPde<SPACE_DIM>::rGetIntracellularConductivityTensor(unsigned elementIndex)
00188 {
00189     assert( mpIntracellularConductivityTensors);
00190     return (*mpIntracellularConductivityTensors)[elementIndex];
00191 }
00192 
00193 template <unsigned SPACE_DIM>
00194 AbstractCardiacCell* AbstractCardiacPde<SPACE_DIM>::GetCardiacCell( unsigned globalIndex )
00195 {
00196     assert(DistributedVector::Begin().Global <= globalIndex &&
00197            globalIndex < DistributedVector::End().Global);
00198     return mCellsDistributed[globalIndex - DistributedVector::Begin().Global];
00199 }
00200 
00201 
00202 template <unsigned SPACE_DIM>
00203 void AbstractCardiacPde<SPACE_DIM>::SolveCellSystems(Vec currentSolution, double currentTime, double nextTime)
00204 {
00205     HeartEventHandler::BeginEvent(HeartEventHandler::SOLVE_ODES);
00206 
00207     DistributedVector dist_solution(currentSolution);
00208     DistributedVector::Stripe voltage(dist_solution, 0);
00209     for (DistributedVector::Iterator index = DistributedVector::Begin();
00210          index != DistributedVector::End();
00211          ++index)
00212     {
00213         // overwrite the voltage with the input value
00214         mCellsDistributed[index.Local]->SetVoltage( voltage[index] );
00215         try
00216         {
00217             // solve
00218             // Note: Voltage should not be updated. GetIIonic will be called later
00219             // and needs the old voltage. The voltage will be updated from the pde.
00220             mCellsDistributed[index.Local]->ComputeExceptVoltage(currentTime, nextTime);
00221         }
00222         catch (Exception &e)
00223         {
00224             PetscTools::ReplicateException(true);
00225             throw e;
00226         }
00227 
00228         // update the Iionic and stimulus caches
00229         UpdateCaches(index.Global, index.Local, nextTime);
00230     }
00231     HeartEventHandler::EndEvent(HeartEventHandler::SOLVE_ODES);
00232 
00233     PetscTools::ReplicateException(false);
00234 
00235     HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00236     if ((mDoCacheReplication)||mDoOneCacheReplication)
00237     {
00238         ReplicateCaches();
00239         mDoOneCacheReplication=false;
00240     }
00241     HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00242 }
00243 
00244 template <unsigned SPACE_DIM>
00245 ReplicatableVector& AbstractCardiacPde<SPACE_DIM>::rGetIionicCacheReplicated()
00246 {
00247     return mIionicCacheReplicated;
00248 }
00249 
00250 template <unsigned SPACE_DIM>
00251 ReplicatableVector& AbstractCardiacPde<SPACE_DIM>::rGetIntracellularStimulusCacheReplicated()
00252 {
00253     return mIntracellularStimulusCacheReplicated;
00254 }
00255 
00256 template <unsigned SPACE_DIM>
00257 void AbstractCardiacPde<SPACE_DIM>::UpdateCaches(unsigned globalIndex, unsigned localIndex, double nextTime)
00258 {
00259     mIionicCacheReplicated[globalIndex] = mCellsDistributed[localIndex]->GetIIonic();
00260     mIntracellularStimulusCacheReplicated[globalIndex] = mCellsDistributed[localIndex]->GetIntracellularStimulus(nextTime);
00261 }
00262 
00263 template <unsigned SPACE_DIM>
00264 void AbstractCardiacPde<SPACE_DIM>::ReplicateCaches()
00265 {
00266     mIionicCacheReplicated.Replicate(DistributedVector::Begin().Global, DistributedVector::End().Global);
00267     mIntracellularStimulusCacheReplicated.Replicate(DistributedVector::Begin().Global, DistributedVector::End().Global);
00268 }
00269 
00271 // Explicit instantiation
00273 
00274 template class AbstractCardiacPde<1>;
00275 template class AbstractCardiacPde<2>;
00276 template class AbstractCardiacPde<3>;

Generated on Wed Mar 18 12:51:51 2009 for Chaste by  doxygen 1.5.5