![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand * 00004 * Copyright (C) 2009 Sergio Galindo * 00005 * * 00006 * This program is free software: you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation, either version 3 of the License, or * 00009 * any later version. * 00010 * * 00011 * This program is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00018 ************************************************************************/ 00019 00020 #ifdef HMSTRESSUPDATE_DECLARE 00021 00022 class HMStressUpdate 00023 { 00024 public: 00025 // callbacks 00026 typedef void (*pDbgFun) (HMStressUpdate const & SU, void * UserData); 00027 00028 // Constructor & Destructor 00029 HMStressUpdate (); 00030 ~HMStressUpdate () { if (ODE!=NULL) delete ODE; } 00031 00032 // Methods 00033 void SetModel (Model const * TheMdl, UnsatFlow const * TheFMdl); 00034 void Update (Vec_t const & DEps, double Dpw, State * Sta, UnsatFlowState * FSta, Vec_t & DSig); 00035 void GetInfo (std::ostream & os, bool Header=false) const; 00036 00037 // Data 00038 Model const * Mdl; 00039 UnsatFlow const * FMdl; 00040 pDbgFun DbgFun; 00041 void * DbgDat; 00042 00043 // ODE solver 00044 Numerical::ODESolver<HMStressUpdate> * ODE; 00045 00046 // Constants for integration 00047 double STOL; 00048 double dTini; 00049 double mMin; 00050 double mMax; 00051 size_t MaxSS; 00052 bool CDrift; 00053 String RKScheme; 00054 size_t SS; 00055 size_t SSs; 00056 size_t DCit; 00057 size_t DCitEl; 00058 size_t ncp; 00059 size_t niv; 00060 size_t neq; 00061 Vec_t dsig; 00062 Vec_t deps; 00063 Vec_t divs; 00064 Vec_t eps0; 00065 double pc0; 00066 double n0; 00067 double dpc; 00068 double dev; 00069 00070 // State 00071 EquilibState * sta; 00072 UnsatFlowState * fsta; 00073 00074 // auxiliary methods 00075 size_t GetMax (size_t PrevMax, size_t NewMax) 00076 { 00077 if (NewMax>PrevMax) return NewMax; 00078 else return PrevMax; 00079 } 00080 00081 private: 00082 // Auxiliary methods 00083 int _RK_fun (double t, double const Y[], double dYdt[]); 00084 void _RK_up_fun (double t, double Y[]); 00085 }; 00086 00087 #endif // HMSTRESSUPDATE_DECLARE 00088 00089 00091 00092 00093 #ifdef HMSTRESSUPDATE_IMPLEMENT 00094 00095 #include <mechsys/numerical/odesolver.h> 00096 00097 inline UnsatFlow::HMStressUpdate::HMStressUpdate () 00098 : Mdl (NULL), 00099 FMdl (NULL), 00100 DbgFun (NULL), 00101 DbgDat (NULL), 00102 ODE (NULL), 00103 STOL (1.0e-5), 00104 dTini (1.0), 00105 mMin (0.1), 00106 mMax (10.0), 00107 MaxSS (2000), 00108 CDrift (true), 00109 RKScheme ("ME"), 00110 SS (0), 00111 SSs (0), 00112 DCit (0), 00113 DCitEl (0), 00114 ncp (0), 00115 niv (0), 00116 neq (0), 00117 sta (NULL), 00118 fsta (NULL) 00119 { 00120 } 00121 00122 inline void UnsatFlow::HMStressUpdate::SetModel (Model const * TheMdl, UnsatFlow const * TheFMdl) 00123 { 00124 // model 00125 Mdl = TheMdl; 00126 FMdl = TheFMdl; 00127 00128 // constants 00129 if (Mdl!=NULL) 00130 { 00131 ncp = Mdl->NCps; 00132 niv = Mdl->NIvs; 00133 neq = ncp + niv + 1; // +1 => Sw 00134 00135 dsig.change_dim (ncp); 00136 deps.change_dim (ncp); 00137 divs.change_dim (niv); 00138 00139 } 00140 else neq = 1; // Sw 00141 00142 // ODE 00143 ODE = new Numerical::ODESolver<HMStressUpdate> (this, &HMStressUpdate::_RK_fun, neq, "ME", STOL, dTini); 00144 ODE->UpFun = &HMStressUpdate::_RK_up_fun; 00145 ODE->mMin = mMin; 00146 ODE->mMax = mMax; 00147 ODE->MaxSS = MaxSS; 00148 } 00149 00150 inline void UnsatFlow::HMStressUpdate::Update (Vec_t const & DEps, double Dpw, State * Sta, UnsatFlowState * FSta, Vec_t & DSig) 00151 { 00152 // check 00153 if (Mdl ==NULL) throw new Fatal("UnsatFlow::HMStressUpdate::Update: SetModel must be called before calling this method (equilib mdl is null)"); 00154 if (FMdl==NULL) throw new Fatal("UnsatFlow::HMStressUpdate::Update: SetModel must be called before calling this method (unsatflow mdl is null)"); 00155 00156 // current state 00157 sta = static_cast<EquilibState*>(Sta); 00158 fsta = FSta; 00159 DSig = sta->Sig; // temporary copy to calculate increment later 00160 00161 // driving increments 00162 eps0 = sta->Eps; 00163 deps = DEps; 00164 pc0 = FSta->pc; 00165 n0 = FSta->n; 00166 dpc = (-Dpw); 00167 dev = Calc_ev(deps); 00168 00169 // loading condition 00170 fsta->Drying = (dpc>0.0); 00171 double aint; 00172 if (Mdl->HMCoup) sta->Ldg = Mdl->LoadCond (sta, -pc0, deps, Dpw); 00173 else sta->Ldg = Mdl->LoadCond (sta, deps, aint); 00174 00175 // initial state 00176 ODE->t = 0.0; 00177 for (size_t i=0; i<ncp; ++i) ODE->Y[ i] = sta->Sig(i); 00178 for (size_t i=0; i<niv; ++i) ODE->Y[ncp+i] = sta->Ivs(i); 00179 ODE->Y[ncp+niv] = FSta->Sw; 00180 00181 // evolve 00182 ODE->Evolve (1.0); 00183 00184 // return total stress increment 00185 DSig = sta->Sig - DSig; 00186 00187 // debug 00188 if (DbgFun!=NULL) (*DbgFun) ((*this), DbgDat); 00189 } 00190 00191 inline void UnsatFlow::HMStressUpdate::GetInfo (std::ostream & os, bool Header) const 00192 { 00193 String buf; 00194 if (Header) 00195 { 00196 if (ODE==NULL) 00197 { 00198 os << "\n" << TERM_BLACK_WHITE << "----------------------------- HMStressUpdate/Scheme: RK ----------------------------" << TERM_RST << "\n\n"; 00199 return; 00200 } 00201 os << "\n" << TERM_BLACK_WHITE << "----------------------------- HMStressUpdate/Scheme: RK(" << ODE->Scheme << ") ----------------------------" << TERM_RST << "\n\n"; 00202 os << "STOL = " << ODE->STOL << std::endl; 00203 os << "dTini = " << ODE->dTini << std::endl; 00204 os << "mMin = " << ODE->mMin << std::endl; 00205 os << "mMax = " << ODE->mMax << std::endl; 00206 os << "MaxSS = " << ODE->MaxSS << std::endl; 00207 os << "CDrift = " << CDrift << std::endl; 00208 buf.Printf("\n%6s %6s %6s %6s %12s %12s\n", "Scheme", "SS", "SSs", "DCit", "T", "dT"); 00209 os << buf; 00210 } 00211 if (ODE==NULL) return; 00212 buf.Printf("%6s %6zd %6zd %6zd %12.8f %12.8f\n", "ME", ODE->SS, ODE->SSs, DCit, ODE->T, ODE->dT); 00213 os << buf; 00214 } 00215 00216 inline int UnsatFlow::HMStressUpdate::_RK_fun (double t, double const Y[], double dYdt[]) 00217 { 00218 // current strain, stress, and internal values 00219 sta->Eps = eps0 + t*deps; 00220 fsta->pc = pc0 + t*dpc; 00221 fsta->n = n0 + t*dev; 00222 for (size_t i=0; i<ncp; ++i) sta->Sig(i) = Y[ i]; 00223 for (size_t i=0; i<niv; ++i) sta->Ivs(i) = Y[ncp+i]; 00224 fsta->Sw = Y[ncp+niv]; 00225 00226 // dSw and dchi 00227 double dpw = -dpc; 00228 double dSw, dchi; 00229 FMdl->TgIncs (fsta, dpw, dev, dSw, dchi); 00230 00231 // tangent increments 00232 double pw = -fsta->pc; 00233 if (Mdl->HMCoup) 00234 { 00235 // the model expects TOTAL stresses and returns TOTAL stress increments 00236 Mdl->TgIncs (sta, pw, deps, dpw, dsig, divs); 00237 } 00238 else 00239 { 00240 // the model expects EFFECTIVE stresses and returns EFFECTIVE stress increments 00241 sta->Sig += (FMdl->chi*pw)*Model::I; 00242 Mdl->TgIncs (sta, deps, dsig, divs); 00243 dsig -= (FMdl->chi*dpw + pw*dchi)*Model::I; // total stress increments 00244 } 00245 00246 // rate 00247 for (size_t i=0; i<ncp; ++i) dYdt[ i] = dsig(i); 00248 for (size_t i=0; i<niv; ++i) dYdt[ncp+i] = divs(i); 00249 dYdt[ncp+niv] = dSw; 00250 00251 // return success 00252 return GSL_SUCCESS; 00253 } 00254 00255 inline void UnsatFlow::HMStressUpdate::_RK_up_fun (double t, double Y[]) 00256 { 00257 // current strain, stress, and internal values 00258 sta->Eps = eps0 + t*deps; 00259 fsta->pc = pc0 + t*dpc; 00260 fsta->n = n0 + t*dev; 00261 for (size_t i=0; i<ncp; ++i) sta->Sig(i) = Y[ i]; 00262 for (size_t i=0; i<niv; ++i) sta->Ivs(i) = Y[ncp+i]; 00263 fsta->Sw = Y[ncp+niv]; 00264 00265 // correct drift 00266 if (CDrift) 00267 { 00268 double pw = -fsta->pc; 00269 if (Mdl->HMCoup) DCit = GetMax (DCit, Mdl->CorrectDrift (sta, pw)); 00270 else DCit = GetMax (DCit, Mdl->CorrectDrift (sta)); 00271 for (size_t i=0; i<ncp; ++i) Y[ i] = sta->Sig(i); 00272 for (size_t i=0; i<niv; ++i) Y[ncp+i] = sta->Ivs(i); 00273 // TODO: should set corrected pw here 00274 } 00275 00276 // debug function 00277 if (DbgFun!=NULL) (*DbgFun) ((*this), DbgDat); 00278 } 00279 00280 #endif // HMSTRESSUPDATE_IMPLEMENT