ImplicitCardiacMechanicsSolver.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
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 "ImplicitCardiacMechanicsSolver.hpp"
00030 #include "Kerchoffs2003ContractionModel.hpp"
00031 #include "NhsModelWithBackwardSolver.hpp"
00032 #include "NonPhysiologicalContractionModel.hpp"
00033 
00034 template<class ELASTICITY_SOLVER,unsigned DIM>
00035 ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::ImplicitCardiacMechanicsSolver(
00036                                   ContractionModelName contractionModel,
00037                                   QuadraticMesh<DIM>& rQuadMesh,
00038                                   SolidMechanicsProblemDefinition<DIM>& rProblemDefinition,
00039                                   std::string outputDirectory)
00040     : AbstractCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>(rQuadMesh,
00041                                                             rProblemDefinition,
00042                                                             outputDirectory)
00043 {
00044     InitialiseContractionModels(contractionModel);
00045 
00046     // initialise stores
00047     mStretchesLastTimeStep.resize(this->mTotalQuadPoints, 1.0);
00048 }
00049 
00050 
00051 template<class ELASTICITY_SOLVER,unsigned DIM>
00052 void ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::InitialiseContractionModels(ContractionModelName contractionModel)
00053 {
00054     switch(contractionModel)
00055     {
00056         case NONPHYSIOL1:
00057         case NONPHYSIOL2:
00058         case NONPHYSIOL3:
00059         {
00060             unsigned option = (contractionModel==NONPHYSIOL1 ? 1 : (contractionModel==NONPHYSIOL2? 2 : 3));
00061             for(unsigned i=0; i<this->mTotalQuadPoints; i++)
00062             {
00063                 this->mContractionModelSystems.push_back(new NonPhysiologicalContractionModel(option));
00064             }
00065             break;
00066         }
00067         case NHS:
00068         {
00069             for(unsigned i=0; i<this->mTotalQuadPoints; i++)
00070             {
00071                 this->mContractionModelSystems.push_back(new NhsModelWithBackwardSolver);
00072             }
00073             break;
00074         }
00075         case KERCHOFFS2003: //stretch dependent
00076         {
00077             for(unsigned i=0; i<this->mTotalQuadPoints; i++)
00078             {
00079                 this->mContractionModelSystems.push_back(new Kerchoffs2003ContractionModel());
00080             }
00081             break;
00082         }
00083         default:
00084         {
00085             #define COVERAGE_IGNORE // currently all available contraction models are acceptable for implicit
00086             EXCEPTION("Unknown or disallowed contraction model");
00087             #undef COVERAGE_IGNORE
00088         }
00089     }
00090 }
00091 
00092 template<class ELASTICITY_SOLVER,unsigned DIM>
00093 ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::~ImplicitCardiacMechanicsSolver()
00094 {
00095     for(unsigned i=0; i<this->mContractionModelSystems.size(); i++)
00096     {
00097         delete this->mContractionModelSystems[i];
00098     }
00099 }
00100 
00101 
00102 template<class ELASTICITY_SOLVER,unsigned DIM>
00103 std::vector<double>& ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::rGetFibreStretches()
00104 {
00105     return this->mStretches;
00106 }
00107 
00108 
00109 template<class ELASTICITY_SOLVER,unsigned DIM>
00110 void ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::Solve(double time, double nextTime, double odeTimestep)
00111 {
00112     // set the times, which are used in AssembleOnElement
00113     assert(time < nextTime);
00114     this->mCurrentTime = time;
00115     this->mNextTime = nextTime;
00116     this->mOdeTimestep = odeTimestep;
00117 
00118     // solve
00119     ELASTICITY_SOLVER::Solve();
00120 
00121     // assemble residual again (to solve the cell models implicitly again
00122     // using the correct value of the deformation x (in case this wasn't the
00123     // last thing that was done
00124     if(this->GetNumNewtonIterations() > 0)
00125     {
00126         this->AssembleSystem(true,false);
00127     }
00128 
00129     // now update state variables, and set lambda at last timestep. Note
00130     // lambda was set in AssembleOnElement
00131     for(unsigned i=0; i<this->mContractionModelSystems.size(); i++)
00132     {
00133          this->mContractionModelSystems[i]->UpdateStateVariables();
00134          mStretchesLastTimeStep[i] = this->mStretches[i];
00135     }
00136 }
00137 
00138 
00139 
00140 template<class ELASTICITY_SOLVER,unsigned DIM>
00141 void ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::GetActiveTensionAndTensionDerivs(double currentFibreStretch,
00142                                                                                              unsigned currentQuadPointGlobalIndex,
00143                                                                                              bool assembleJacobian,
00144                                                                                              double& rActiveTension,
00145                                                                                              double& rDerivActiveTensionWrtLambda,
00146                                                                                              double& rDerivActiveTensionWrtDLambdaDt)
00147 {
00148     // save this fibre stretch
00149     this->mStretches[currentQuadPointGlobalIndex] = currentFibreStretch;
00150 
00151     // compute dlam/dt
00152     double dlam_dt = (currentFibreStretch-mStretchesLastTimeStep[currentQuadPointGlobalIndex])/(this->mNextTime-this->mCurrentTime);
00153 
00154     AbstractContractionModel* p_contraction_model = this->mContractionModelSystems[currentQuadPointGlobalIndex];
00155 
00156     // Set this stretch and stretch rate
00157     p_contraction_model->SetStretchAndStretchRate(currentFibreStretch, dlam_dt);
00158 
00159     // Call RunDoNotUpdate() on the contraction model to solve it using this stretch, and get the active tension
00160     try
00161     {
00162         p_contraction_model->RunDoNotUpdate(this->mCurrentTime,this->mNextTime,this->mOdeTimestep);
00163         rActiveTension = p_contraction_model->GetNextActiveTension();
00164     }
00165     catch (Exception& e)
00166     {
00167         #define COVERAGE_IGNORE
00168         // if this failed during assembling the Jacobian this is a fatal error.
00169         if(assembleJacobian)
00170         {
00171             // probably shouldn't be able to get here
00172             EXCEPTION("Failure in solving contraction models using current stretches for assembling Jacobian");
00173         }
00174         // if this failed during assembling the residual, the stretches are too large, so we just
00175         // set the active tension to infinity so that the residual will be infinite
00176         rActiveTension = DBL_MAX;
00177         std::cout << "WARNING: could not solve contraction model with this stretch and stretch rate. "
00178                   << "Setting active tension to infinity (DBL_MAX) so that the residual(-norm) is also infinite\n" << std::flush;
00179         assert(0); // just to see if we ever get here, can be removed..
00180         return;
00181         #undef COVERAGE_IGNORE
00182     }
00183 
00184     // if assembling the Jacobian, numerically evaluate dTa/dlam & dTa/d(lamdot)
00185     if(assembleJacobian)
00186     {
00187         // get active tension for (lam+h,dlamdt)
00188         double h1 = std::max(1e-6, currentFibreStretch/100);
00189         p_contraction_model->SetStretchAndStretchRate(currentFibreStretch+h1, dlam_dt);
00190         p_contraction_model->RunDoNotUpdate(this->mCurrentTime,this->mNextTime,this->mOdeTimestep);
00191         double active_tension_at_lam_plus_h = p_contraction_model->GetNextActiveTension();
00192 
00193         // get active tension for (lam,dlamdt+h)
00194         double h2 = std::max(1e-6, dlam_dt/100);
00195         p_contraction_model->SetStretchAndStretchRate(currentFibreStretch, dlam_dt+h2);
00196         p_contraction_model->RunDoNotUpdate(this->mCurrentTime,this->mNextTime,this->mOdeTimestep);
00197         double active_tension_at_dlamdt_plus_h = p_contraction_model->GetNextActiveTension();
00198 
00199         rDerivActiveTensionWrtLambda = (active_tension_at_lam_plus_h - rActiveTension)/h1;
00200         rDerivActiveTensionWrtDLambdaDt = (active_tension_at_dlamdt_plus_h - rActiveTension)/h2;
00201     }
00202 
00203     // Re-set the stretch and stretch rate and recompute the active tension so that
00204     // if this guess turns out to the solution, we can just update the state variables
00205     //  -- not needed as AssembleSystem(true,false) [ie assemble residual] is
00206     //     called in ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::Solve() above
00207     //     after the solve and before the update.
00208     //  -- The SetActiveTensionInitialGuess() would make this very fast
00209     //     (compared to AssembleSystem(true,false) above), but the NHS class uses the last
00210     //     active tension as the initial guess anyway..
00211     //p_contraction_model->SetStretchAndStretchRate(currentFibreStretch, dlam_dt);
00212     //p_contraction_model->SetActiveTensionInitialGuess(rActiveTension);   // this line would now need a cast
00213     //p_contraction_model->RunDoNotUpdate(this->mCurrentTime,this->mNextTime,this->mOdeTimestep);
00214     //assert( fabs(p_contraction_model->GetNextActiveTension()-rActiveTension)<1e-8);
00215 }
00216 
00217 
00218 
00219 template class ImplicitCardiacMechanicsSolver<IncompressibleNonlinearElasticitySolver<2>,2>;
00220 template class ImplicitCardiacMechanicsSolver<IncompressibleNonlinearElasticitySolver<3>,3>;
00221 template class ImplicitCardiacMechanicsSolver<CompressibleNonlinearElasticitySolver<2>,2>;
00222 template class ImplicitCardiacMechanicsSolver<CompressibleNonlinearElasticitySolver<3>,3>;
00223 
00224 
Generated on Thu Dec 22 13:00:06 2011 for Chaste by  doxygen 1.6.3