Chaste Release::3.1
ExtendedBidomainSolver.cpp
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 
00037 #include "ExtendedBidomainSolver.hpp"
00038 #include "ExtendedBidomainMassMatrixAssembler.hpp"
00039 #include "ExtendedBidomainAssembler.hpp"
00040 
00041 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00042 void ExtendedBidomainSolver<ELEMENT_DIM,SPACE_DIM>::InitialiseForSolve(Vec initialSolution)
00043 {
00044     if (this->mpLinearSystem != NULL)
00045     {
00046         return;
00047     }
00048     AbstractExtendedBidomainSolver<ELEMENT_DIM,SPACE_DIM>::InitialiseForSolve(initialSolution);
00049 
00050     // initialise matrix-based RHS vector and matrix, and use the linear
00051     // system rhs as a template
00052     Vec& r_template = this->mpLinearSystem->rGetRhsVector();
00053     VecDuplicate(r_template, &mVecForConstructingRhs);
00054     PetscInt ownership_range_lo;
00055     PetscInt ownership_range_hi;
00056     VecGetOwnershipRange(r_template, &ownership_range_lo, &ownership_range_hi);
00057     PetscInt local_size = ownership_range_hi - ownership_range_lo;
00058     PetscTools::SetupMat(mMassMatrix, 3*this->mpMesh->GetNumNodes(), 3*this->mpMesh->GetNumNodes(),
00059                          3*this->mpMesh->CalculateMaximumNodeConnectivityPerProcess(),
00060                          local_size, local_size);
00061 }
00062 
00063 
00064 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00065 void ExtendedBidomainSolver<ELEMENT_DIM,SPACE_DIM>::SetupLinearSystem(
00066         Vec currentSolution,
00067         bool computeMatrix)
00068 {
00069     assert(this->mpLinearSystem->rGetLhsMatrix() != NULL);
00070     assert(this->mpLinearSystem->rGetRhsVector() != NULL);
00071     assert(currentSolution != NULL);
00072 
00073 
00075     // set up LHS matrix (and mass matrix)
00077     if(computeMatrix)
00078     {
00079         mpExtendedBidomainAssembler->SetMatrixToAssemble(this->mpLinearSystem->rGetLhsMatrix());
00080         mpExtendedBidomainAssembler->AssembleMatrix();
00081 
00082         // the ExtendedBidomainMassMatrixAssembler deals with the mass matrix
00083         // for both bath and nonbath problems
00084         assert(SPACE_DIM==ELEMENT_DIM);
00085         ExtendedBidomainMassMatrixAssembler<SPACE_DIM> mass_matrix_assembler(this->mpMesh);
00086         mass_matrix_assembler.SetMatrixToAssemble(mMassMatrix);
00087         mass_matrix_assembler.Assemble();
00088 
00089         this->mpLinearSystem->SwitchWriteModeLhsMatrix();
00090         PetscMatTools::Finalise(mMassMatrix);
00091     }
00092 
00093 
00094     HeartEventHandler::BeginEvent(HeartEventHandler::ASSEMBLE_RHS);
00095 
00097     // Set up z in b=Mz
00099     DistributedVectorFactory* p_factory = this->mpMesh->GetDistributedVectorFactory();
00100 
00101     // get bidomain parameters
00102     double Am1 = this->mpExtendedBidomainTissue->GetAmFirstCell();
00103     double Am2 = this->mpExtendedBidomainTissue->GetAmSecondCell();
00104     double AmGap = this->mpExtendedBidomainTissue->GetAmGap();
00105     double Cm1 = this->mpExtendedBidomainTissue->GetCmFirstCell();
00106     double Cm2 = this->mpExtendedBidomainTissue->GetCmSecondCell();
00107 
00108     // dist stripe for the current Voltage
00109     DistributedVector distributed_current_solution = p_factory->CreateDistributedVector(currentSolution);
00110     DistributedVector::Stripe distributed_current_solution_v_first_cell(distributed_current_solution, 0);
00111     DistributedVector::Stripe distributed_current_solution_v_second_cell(distributed_current_solution, 1);
00112     DistributedVector::Stripe distributed_current_solution_phi_e(distributed_current_solution, 2);
00113 
00114     // dist stripe for z
00115     DistributedVector dist_vec_matrix_based = p_factory->CreateDistributedVector(mVecForConstructingRhs);
00116     DistributedVector::Stripe dist_vec_matrix_based_v_first_cell(dist_vec_matrix_based, 0);
00117     DistributedVector::Stripe dist_vec_matrix_based_v_second_cell(dist_vec_matrix_based, 1);
00118     DistributedVector::Stripe dist_vec_matrix_based_phi_e(dist_vec_matrix_based, 2);
00119 
00120     for (DistributedVector::Iterator index = dist_vec_matrix_based.Begin();
00121          index!= dist_vec_matrix_based.End();
00122          ++index)
00123     {
00124         double V_first_cell = distributed_current_solution_v_first_cell[index];
00125         double V_second_Cell = distributed_current_solution_v_second_cell[index];
00126         double Phi_e = distributed_current_solution_phi_e[index];
00127 
00128         double i_ionic_first_cell = this->mpExtendedBidomainTissue->rGetIionicCacheReplicated()[index.Global];
00129         double i_ionic_second_cell = this->mpExtendedBidomainTissue->rGetIionicCacheReplicatedSecondCell()[index.Global];
00130         double intracellular_stimulus_first_cell = this->mpExtendedBidomainTissue->rGetIntracellularStimulusCacheReplicated()[index.Global];
00131         double intracellular_stimulus_second_cell = this->mpExtendedBidomainTissue->rGetIntracellularStimulusCacheReplicatedSecondCell()[index.Global];
00132         double extracellular_stimulus =  this->mpExtendedBidomainTissue->rGetExtracellularStimulusCacheReplicated()[index.Global];
00133         double g_gap = this->mpExtendedBidomainTissue->rGetGgapCacheReplicated()[index.Global];
00134         double delta_t = PdeSimulationTime::GetPdeTimeStep();
00135         dist_vec_matrix_based_v_first_cell[index] = Am1*Cm1*V_first_cell/delta_t - Am1*Cm1*Phi_e/delta_t - Am1*i_ionic_first_cell + AmGap*g_gap*(V_second_Cell - V_first_cell) -  intracellular_stimulus_first_cell;
00136         dist_vec_matrix_based_v_second_cell[index] = Am2*Cm2*V_second_Cell/delta_t- Am2*Cm2*Phi_e/delta_t - Am2*i_ionic_second_cell + AmGap*g_gap*(V_first_cell - V_second_Cell) - intracellular_stimulus_second_cell;
00137 
00138         if (this->mpExtendedBidomainTissue->HasTheUserSuppliedExtracellularStimulus() )
00139         {
00140             assert((fabs(intracellular_stimulus_first_cell) < 1e-12)
00141             && (fabs(intracellular_stimulus_second_cell) < 1e-12));
00142 
00147             dist_vec_matrix_based_phi_e[index] = -extracellular_stimulus;
00148         }
00149         else
00150         {
00151             dist_vec_matrix_based_phi_e[index] = 0.0;
00152         }
00153     }
00154 
00155 
00156     dist_vec_matrix_based.Restore();
00157 
00159     // b = Mz
00161 
00162     MatMult(mMassMatrix, mVecForConstructingRhs, this->mpLinearSystem->rGetRhsVector());
00163 
00164     // assembling RHS is not finished yet, as Neumann bcs are added below, but
00165     // the event will be begun again inside mpExtendedBidomainAssembler->AssembleVector();
00166     HeartEventHandler::EndEvent(HeartEventHandler::ASSEMBLE_RHS);
00167 
00169     // apply Neumann boundary conditions
00171     mpExtendedBidomainNeumannSurfaceTermAssembler->ResetBoundaryConditionsContainer(this->mpBoundaryConditions); // as the BCC can change
00172     mpExtendedBidomainNeumannSurfaceTermAssembler->SetVectorToAssemble(this->mpLinearSystem->rGetRhsVector(), false/*don't zero vector!*/);
00173     mpExtendedBidomainNeumannSurfaceTermAssembler->AssembleVector();
00174 
00175     this->mpLinearSystem->FinaliseRhsVector();
00176 
00177     this->mpBoundaryConditions->ApplyDirichletToLinearProblem(*(this->mpLinearSystem), computeMatrix);
00178 
00179     if(computeMatrix)
00180     {
00181         this->mpLinearSystem->FinaliseLhsMatrix();
00182     }
00183     this->mpLinearSystem->FinaliseRhsVector();
00184 }
00185 
00186 
00187 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00188 ExtendedBidomainSolver<ELEMENT_DIM,SPACE_DIM>::ExtendedBidomainSolver(
00189         bool bathSimulation,
00190         AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00191         ExtendedBidomainTissue<SPACE_DIM>* pTissue,
00192         BoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,3>* pBoundaryConditions,
00193         unsigned numQuadPoints)
00194     : AbstractExtendedBidomainSolver<ELEMENT_DIM,SPACE_DIM>(bathSimulation,pMesh,pTissue,pBoundaryConditions)
00195 {
00196     // Tell Tissue there's no need to replicate ionic caches
00197     pTissue->SetCacheReplication(false);
00198     mVecForConstructingRhs = NULL;
00199 
00200     // create assembler
00201     if(this->mBathSimulation)
00202     {
00203         //this->mpExtendedExtendedBidomainAssembler = new ExtendedExtendedBidomainWithBathAssembler<ELEMENT_DIM,SPACE_DIM>(this->mpMesh,this->mpExtendedExtendedBidomainTissue,this->mDt,this->mNumQuadPoints);
00204         EXCEPTION("Bath simulations are not yet supported for extended bidomain problems");
00205     }
00206     else
00207     {
00208         mpExtendedBidomainAssembler = new ExtendedBidomainAssembler<ELEMENT_DIM,SPACE_DIM>(this->mpMesh,this->mpExtendedBidomainTissue,this->mNumQuadPoints);
00209     }
00210 
00211     mpExtendedBidomainNeumannSurfaceTermAssembler = new ExtendedBidomainNeumannSurfaceTermAssembler<ELEMENT_DIM,SPACE_DIM>(pMesh,pBoundaryConditions);
00212 
00213 }
00214 
00215 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00216 ExtendedBidomainSolver<ELEMENT_DIM,SPACE_DIM>::~ExtendedBidomainSolver()
00217 {
00218     delete mpExtendedBidomainAssembler;
00219     delete mpExtendedBidomainNeumannSurfaceTermAssembler;
00220 
00221     if(mVecForConstructingRhs)
00222     {
00223         PetscTools::Destroy(mVecForConstructingRhs);
00224         PetscTools::Destroy(mMassMatrix);
00225     }
00226 }
00227 
00229 // explicit instantiation
00231 
00232 template class ExtendedBidomainSolver<1,1>;
00233 template class ExtendedBidomainSolver<2,2>;
00234 template class ExtendedBidomainSolver<3,3>;
00235