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