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

Generated on Tue Aug 4 16:10:22 2009 for Chaste by  doxygen 1.5.5