ImplicitCardiacMechanicsSolver.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, 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 #include "ImplicitCardiacMechanicsSolver.hpp"
00037 
00038 template<class ELASTICITY_SOLVER,unsigned DIM>
00039 ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::ImplicitCardiacMechanicsSolver(
00040                                   QuadraticMesh<DIM>& rQuadMesh,
00041                                   ElectroMechanicsProblemDefinition<DIM>& rProblemDefinition,
00042                                   std::string outputDirectory)
00043     : AbstractCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>(rQuadMesh,
00044                                                             rProblemDefinition,
00045                                                             outputDirectory)
00046 {
00047 
00048 }
00049 
00050 template<class ELASTICITY_SOLVER,unsigned DIM>
00051 ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::~ImplicitCardiacMechanicsSolver()
00052 {
00053 }
00054 
00055 
00056 template<class ELASTICITY_SOLVER,unsigned DIM>
00057 void ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::Solve(double time, double nextTime, double odeTimestep)
00058 {
00059     // set the times, which are used in AssembleOnElement
00060     assert(time < nextTime);
00061     this->mCurrentTime = time;
00062     this->mNextTime = nextTime;
00063     this->mOdeTimestep = odeTimestep;
00064 
00065     // solve
00066     ELASTICITY_SOLVER::Solve();
00067 
00068     // assemble residual again (to solve the cell models implicitly again
00069     // using the correct value of the deformation x (in case this wasn't the
00070     // last thing that was done
00071     if(this->GetNumNewtonIterations() > 0)
00072     {
00073         this->AssembleSystem(true,false);
00074     }
00075 
00076     // now update state variables, and set lambda at last timestep. Note
00077     // stretches were set in AssembleOnElement
00078     for(std::map<unsigned,DataAtQuadraturePoint>::iterator iter = this->mQuadPointToDataAtQuadPointMap.begin();
00079         iter != this->mQuadPointToDataAtQuadPointMap.end();
00080         iter++)
00081     {
00082         AbstractContractionModel* p_contraction_model = iter->second.ContractionModel;
00083         iter->second.StretchLastTimeStep = iter->second.Stretch;
00084         p_contraction_model->UpdateStateVariables();
00085     }
00086 
00087 }
00088 
00089 
00090 
00091 template<class ELASTICITY_SOLVER,unsigned DIM>
00092 void ImplicitCardiacMechanicsSolver<ELASTICITY_SOLVER,DIM>::GetActiveTensionAndTensionDerivs(double currentFibreStretch,
00093                                                                                              unsigned currentQuadPointGlobalIndex,
00094                                                                                              bool assembleJacobian,
00095                                                                                              double& rActiveTension,
00096                                                                                              double& rDerivActiveTensionWrtLambda,
00097                                                                                              double& rDerivActiveTensionWrtDLambdaDt)
00098 {
00099     // The iterator should be pointing to the right place (note: it is incremented at the end of this method)
00100     // This iterator is used so that we don't have to search the map
00101     assert(this->mMapIterator->first==currentQuadPointGlobalIndex);
00102 
00103     DataAtQuadraturePoint& r_data_at_quad_point = this->mMapIterator->second;
00104 
00105     // save this fibre stretch
00106     r_data_at_quad_point.Stretch = currentFibreStretch;
00107 
00108     // compute dlam/dt
00109     double dlam_dt = (currentFibreStretch-r_data_at_quad_point.StretchLastTimeStep)/(this->mNextTime-this->mCurrentTime);
00110 
00111     // Set this stretch and stretch rate on contraction model
00112     AbstractContractionModel* p_contraction_model = r_data_at_quad_point.ContractionModel;
00113     p_contraction_model->SetStretchAndStretchRate(currentFibreStretch, dlam_dt);
00114 
00115     // Call RunDoNotUpdate() on the contraction model to solve it using this stretch, and get the active tension
00116     try
00117     {
00118         p_contraction_model->RunDoNotUpdate(this->mCurrentTime,this->mNextTime,this->mOdeTimestep);
00119         rActiveTension = p_contraction_model->GetNextActiveTension();
00120     }
00121     catch (Exception&)
00122     {
00123         #define COVERAGE_IGNORE
00124         // if this failed during assembling the Jacobian this is a fatal error.
00125         if(assembleJacobian)
00126         {
00127             // probably shouldn't be able to get here
00128             EXCEPTION("Failure in solving contraction models using current stretches for assembling Jacobian");
00129         }
00130         // if this failed during assembling the residual, the stretches are too large, so we just
00131         // set the active tension to infinity so that the residual will be infinite
00132         rActiveTension = DBL_MAX;
00133         std::cout << "WARNING: could not solve contraction model with this stretch and stretch rate. "
00134                   << "Setting active tension to infinity (DBL_MAX) so that the residual(-norm) is also infinite\n" << std::flush;
00135         assert(0); // just to see if we ever get here, can be removed..
00136         return;
00137         #undef COVERAGE_IGNORE
00138     }
00139 
00140     // if assembling the Jacobian, numerically evaluate dTa/dlam & dTa/d(lamdot)
00141     if(assembleJacobian)
00142     {
00143         // get active tension for (lam+h,dlamdt)
00144         double h1 = std::max(1e-6, currentFibreStretch/100);
00145         p_contraction_model->SetStretchAndStretchRate(currentFibreStretch+h1, dlam_dt);
00146         p_contraction_model->RunDoNotUpdate(this->mCurrentTime,this->mNextTime,this->mOdeTimestep);
00147         double active_tension_at_lam_plus_h = p_contraction_model->GetNextActiveTension();
00148 
00149         // get active tension for (lam,dlamdt+h)
00150         double h2 = std::max(1e-6, dlam_dt/100);
00151         p_contraction_model->SetStretchAndStretchRate(currentFibreStretch, dlam_dt+h2);
00152         p_contraction_model->RunDoNotUpdate(this->mCurrentTime,this->mNextTime,this->mOdeTimestep);
00153         double active_tension_at_dlamdt_plus_h = p_contraction_model->GetNextActiveTension();
00154 
00155         rDerivActiveTensionWrtLambda = (active_tension_at_lam_plus_h - rActiveTension)/h1;
00156         rDerivActiveTensionWrtDLambdaDt = (active_tension_at_dlamdt_plus_h - rActiveTension)/h2;
00157     }
00158 
00159     // increment the iterator
00160     this->mMapIterator++;
00161     if(this->mMapIterator==this->mQuadPointToDataAtQuadPointMap.end())
00162     {
00163         this->mMapIterator = this->mQuadPointToDataAtQuadPointMap.begin();
00164     }
00165 
00166 }
00167 
00168 
00169 
00170 template class ImplicitCardiacMechanicsSolver<IncompressibleNonlinearElasticitySolver<2>,2>;
00171 template class ImplicitCardiacMechanicsSolver<IncompressibleNonlinearElasticitySolver<3>,3>;
00172 template class ImplicitCardiacMechanicsSolver<CompressibleNonlinearElasticitySolver<2>,2>;
00173 template class ImplicitCardiacMechanicsSolver<CompressibleNonlinearElasticitySolver<3>,3>;
00174 
00175 

Generated by  doxygen 1.6.2