![]() |
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 STRESSUPDATE_DECLARE 00021 00022 class StressUpdate 00023 { 00024 public: 00025 // callbacks 00026 typedef void (*pDbgFun) (StressUpdate const & SU, void * UserData); 00027 00028 // enum 00029 enum Scheme_t { ME_t, SingleFE_t, RK_t }; 00030 00031 // Constructor & Destructor 00032 StressUpdate (); 00033 ~StressUpdate () { if (ODE!=NULL) delete ODE; if (sta_1!=NULL) delete sta_1; if (sta_ME!=NULL) delete sta_ME; } 00034 00035 // Methods 00036 void SetModel (Model const * TheMdl); 00037 void SetScheme (String const & Name); 00038 void Update (Vec_t const & DEps, State * Sta, Vec_t & DSig); 00039 double Update (double Dt, ATensor2 const & L, ATensor2 & F, State * Sta); 00040 void GetInfo (std::ostream & os, bool Header=false) const; 00041 00042 // Data 00043 Model const * Mdl; 00044 pDbgFun DbgFun; 00045 void * DbgDat; 00046 00047 // ODE solver (if sheme==RK) 00048 Numerical::ODESolver<StressUpdate> * ODE; 00049 00050 // Constants for integration 00051 Scheme_t Scheme; 00052 double STOL; 00053 double dTini; 00054 double mMin; 00055 double mMax; 00056 size_t MaxSS; 00057 bool CDrift; 00058 double Error; 00059 String RKScheme; 00060 double T; 00061 double dT; 00062 size_t SS; 00063 size_t SSs; 00064 size_t DCit; 00065 size_t DCitEl; 00066 size_t ncp; 00067 size_t niv; 00068 size_t neq; 00069 Vec_t dsig; 00070 Vec_t deps; 00071 Vec_t divs; 00072 Vec_t eps0; 00073 EquilibState * sta; 00074 00075 // auxiliary variables 00076 EquilibState * sta_1; // intermediate state 00077 EquilibState * sta_ME; // Modified-Euler state 00078 Vec_t deps_1, dsig_1, divs_1; // intermediate increments 00079 Vec_t dsig_2, divs_2; // ME increments 00080 Vec_t sig_dif; // ME - FE stress difference 00081 00082 // auxiliary variables for large deformation update 00083 ATensor2 mF; 00084 ATensor2 Ia; 00085 ATensor2 DtL; 00086 ATensor2 dtL; 00087 ATensor2 dtL_1; 00088 Vec_t sig_tmp; 00089 Vec_t DEps_in; 00090 Vec_t dsig_out; 00091 bool CorrectObj; 00092 EquilibState * sta_in; 00093 00094 // auxiliary methods 00095 size_t GetMax (size_t PrevMax, size_t NewMax) 00096 { 00097 if (NewMax>PrevMax) return NewMax; 00098 else return PrevMax; 00099 } 00100 00101 private: 00102 // Auxiliary methods 00103 int _RK_fun (double t, double const Y[], double dYdt[]); 00104 void _RK_up_fun (double t, double Y[]); 00105 }; 00106 00107 #endif // STRESSUPDATE_DECLARE 00108 00109 00111 00112 00113 #ifdef STRESSUPDATE_IMPLEMENT 00114 00115 #include <mechsys/numerical/odesolver.h> 00116 00117 inline Model::StressUpdate::StressUpdate () 00118 : Mdl (NULL), 00119 DbgFun (NULL), 00120 DbgDat (NULL), 00121 ODE (NULL), 00122 Scheme (ME_t), 00123 STOL (1.0e-5), 00124 dTini (1.0), 00125 mMin (0.1), 00126 mMax (10.0), 00127 MaxSS (2000), 00128 CDrift (true), 00129 Error (0.0), 00130 RKScheme ("ME"), 00131 T (0.0), 00132 dT (dTini), 00133 SS (0), 00134 SSs (0), 00135 DCit (0), 00136 DCitEl (0), 00137 sta (NULL), 00138 CorrectObj (false) 00139 { 00140 Ia = 1.0,1.0,1.0, 0.0,0.0,0.0, 0.0,0.0,0.0; 00141 } 00142 00143 inline void Model::StressUpdate::SetModel (Model const * TheMdl) 00144 { 00145 Mdl = TheMdl; 00146 ncp = Mdl->NCps; 00147 niv = Mdl->NIvs; 00148 neq = ncp + niv; 00149 ODE = new Numerical::ODESolver<StressUpdate> (this, &StressUpdate::_RK_fun, neq, "ME", STOL, dTini); 00150 ODE->UpFun = &StressUpdate::_RK_up_fun; 00151 ODE->mMin = mMin; 00152 ODE->mMax = mMax; 00153 00154 // auxiliary variables 00155 dsig.change_dim (ncp); 00156 deps.change_dim (ncp); 00157 divs.change_dim (niv); 00158 00159 // ME variables 00160 sta_1 = new EquilibState (Mdl->NDim); 00161 sta_ME = new EquilibState (Mdl->NDim); 00162 deps_1.change_dim(ncp); dsig_1.change_dim(ncp); divs_1.change_dim(niv); 00163 dsig_2.change_dim(ncp); divs_2.change_dim(niv); 00164 sig_dif.change_dim(ncp); 00165 } 00166 00167 inline void Model::StressUpdate::SetScheme (String const & Name) 00168 { 00169 if (Name=="ME") Scheme = ME_t; 00170 else if (Name=="SingleFE") Scheme = SingleFE_t; 00171 else if (Name=="RK") Scheme = RK_t; 00172 else throw new Fatal("StressUpdate::SetScheme: Scheme named %s is invalid",Name.CStr()); 00173 } 00174 00175 inline void Model::StressUpdate::Update (Vec_t const & DEps, State * Sta, Vec_t & DSig) 00176 { 00177 // check 00178 if (Mdl==NULL) throw new Fatal("Model::StressUpdate::Update: SetModel must be called before calling this method"); 00179 00180 // scheme 00181 if (Mdl->Prms.HasKey("newsu")) { if ((int)Mdl->Prms("newsu")) Scheme = RK_t; } 00182 00183 // current state 00184 sta = static_cast<EquilibState*>(Sta); 00185 DSig = sta->Sig; // temporary copy to calculate increment later 00186 00187 if (Scheme==SingleFE_t) // without intersection detection (should be used for linear elasticity only) 00188 { 00189 throw new Fatal("Model::StressUpdate::Update: SingleFE_t is deactivated"); 00190 deps = DEps; 00191 Mdl->TgIncs (sta, deps, dsig, divs); 00192 if (CorrectObj) 00193 { 00194 AddSkewTimesOp1 (DtL, sta->Sig, dsig); 00195 //printf("Model::StressUpdate::Update: Correcting objective stress increment\n"); 00196 } 00197 sta->Eps += deps; 00198 sta->Sig += dsig; 00199 sta->Ivs += divs; 00200 if (DbgFun!=NULL) (*DbgFun) ((*this), DbgDat); 00201 } 00202 else if (Scheme==ME_t) 00203 { 00204 // loading-unloading ? 00205 double aint = -1.0; // no intersection 00206 bool ldg = Mdl->LoadCond (sta, DEps, aint); 00207 00208 // set loading flag 00209 sta -> Ldg = ldg; 00210 sta_1 -> Ldg = ldg; 00211 sta_ME -> Ldg = ldg; 00212 00213 // with intersection ? 00214 if (aint>0.0 && aint<1.0) 00215 { 00216 // update to intersection 00217 deps = aint*DEps; 00218 Mdl->TgIncs (sta, deps, dsig, divs); 00219 if (CorrectObj) { dtL=aint*DtL; AddSkewTimesOp1 (dtL, sta->Sig, dsig); } 00220 sta->Eps += deps; 00221 sta->Sig += dsig; 00222 sta->Ivs += divs; 00223 deps = fabs(1.0-aint)*DEps; // remaining of DEps to be applied 00224 if (CorrectObj) dtL = fabs(1.0-aint)*DtL; 00225 00226 // change loading flag 00227 ldg = true; 00228 sta -> Ldg = ldg; 00229 sta_1 -> Ldg = ldg; 00230 sta_ME -> Ldg = ldg; 00231 00232 // drift correction 00233 //if (DbgFun!=NULL) (*DbgFun) ((*this), DbgDat); 00234 if (CDrift) DCitEl = GetMax (DCitEl, Mdl->CorrectDrift(sta)); 00235 00236 // debug 00237 if (DbgFun!=NULL) (*DbgFun) ((*this), DbgDat); 00238 } 00239 else 00240 { 00241 deps = DEps; // update with full DEps 00242 if (CorrectObj) dtL = DtL; 00243 } 00244 00245 // for each pseudo time T 00246 T = 0.0; 00247 dT = dTini; 00248 SS = 0; 00249 SSs = 0; 00250 DCitEl = 0; 00251 DCit = 0; 00252 for (SS=0; SS<MaxSS; ++SS) 00253 { 00254 // exit point 00255 if (T>=1.0) break; 00256 00257 // FE and ME increments 00258 deps_1 = dT*deps; 00259 Mdl->TgIncs (sta, deps_1, dsig_1, divs_1); 00260 if (CorrectObj) { dtL_1=dT*dtL; AddSkewTimesOp1 (dtL_1, sta->Sig, dsig_1); } 00261 sta_1->Eps = sta->Eps + deps_1; 00262 sta_1->Sig = sta->Sig + dsig_1; 00263 sta_1->Ivs = sta->Ivs + divs_1; 00264 Mdl->TgIncs (sta_1, deps_1, dsig_2, divs_2); 00265 if (CorrectObj) AddSkewTimesOp1 (dtL_1, sta_1->Sig, dsig_2); 00266 sta_ME->Sig = sta->Sig + 0.5*(dsig_1+dsig_2); 00267 sta_ME->Ivs = sta->Ivs + 0.5*(divs_1+divs_2); 00268 00269 // local error estimate 00270 sig_dif = sta_ME->Sig - sta_1->Sig; 00271 double sig_err = Norm(sig_dif)/(1.0+Norm(sta_ME->Sig)); 00272 double ivs_err = 0.0; 00273 for (size_t i=0; i<niv; ++i) ivs_err += fabs(sta_ME->Ivs(i)-sta_1->Ivs(i))/(1.0+fabs(sta_ME->Ivs(i))); 00274 Error = sig_err + ivs_err; 00275 00276 // step multiplier 00277 double m = (Error>0.0 ? 0.9*sqrt(STOL/Error) : mMax); 00278 00279 // update 00280 if (Error<STOL) 00281 { 00282 // update state 00283 SSs++; 00284 T += dT; 00285 sta->Eps = sta_1 -> Eps; 00286 sta->Sig = sta_ME -> Sig; 00287 sta->Ivs = sta_ME -> Ivs; 00288 00289 // drift correction 00290 //if (DbgFun!=NULL) (*DbgFun) ((*this), DbgDat); 00291 if (CDrift) DCit = GetMax (DCit, Mdl->CorrectDrift (sta)); 00292 00293 // update stress path in model 00294 Mdl->UpdatePath (sta, deps_1, Vec_t(0.5*(dsig_1+dsig_2))); 00295 00296 // limit change on stepsize 00297 if (m>mMax) m = mMax; 00298 00299 // debug 00300 if (DbgFun!=NULL) (*DbgFun) ((*this), DbgDat); 00301 } 00302 else if (m<mMin) m = mMin; 00303 00304 // change next step size 00305 dT = m * dT; 00306 00307 // check for last increment 00308 if (dT>1.0-T) dT = 1.0-T; 00309 } 00310 if (SS>=MaxSS) throw new Fatal("StressUpdate::Update: Modified-Euler (local) did not converge after %d substeps",SS); 00311 } 00312 else if (Scheme==RK_t) 00313 { 00314 // initial strain and increment 00315 eps0 = sta->Eps; 00316 deps = DEps; 00317 00318 // loading condition 00319 double aint; 00320 sta->Ldg = Mdl->LoadCond (sta, deps, aint); 00321 00322 // initial state 00323 ODE->t = 0.0; 00324 for (size_t i=0; i<ncp; ++i) ODE->Y[ i] = sta->Sig(i); 00325 for (size_t i=0; i<niv; ++i) ODE->Y[ncp+i] = sta->Ivs(i); 00326 00327 // evolve 00328 ODE->Evolve (1.0); 00329 00330 // final state 00331 for (size_t i=0; i<ncp; ++i) sta->Sig(i) = ODE->Y[ i]; 00332 for (size_t i=0; i<niv; ++i) sta->Ivs(i) = ODE->Y[ncp+i]; 00333 sta->Eps = eps0 + deps; 00334 } 00335 else throw new Fatal("StressUpdate::Update: Scheme is not available yet"); 00336 00337 // return total stress increment 00338 DSig = sta->Sig - DSig; 00339 00340 // debug 00341 if (DbgFun!=NULL) (*DbgFun) ((*this), DbgDat); 00342 } 00343 00344 inline double Model::StressUpdate::Update (double Dt, ATensor2 const & L, ATensor2 & F, State * Sta) 00345 { 00346 // update deformation gradient 00347 mF = Ia + L*Dt; 00348 Dot (mF, F, F); // F = mF*F 00349 00350 // compute strain increment == rate of deformation D*Dt, in which D = Sym(L) 00351 Sym (Dt, L, ncp, DEps_in); // DEps_in = Dt*sym(L) 00352 00353 // stress update 00354 sta_in = static_cast<EquilibState*>(Sta); // cannot use sta_1 or else, because the other Update will re-assign these 00355 sig_tmp = sta_in->Sig; 00356 if (Mdl->UseUpdateSta) 00357 { 00358 Mdl->UpdateSta (F, sta_in); 00359 } 00360 else 00361 { 00362 DtL = Dt*L; 00363 CorrectObj = true; 00364 Update (DEps_in, sta_in, dsig_out); 00365 CorrectObj = false; 00366 } 00367 00368 // Strain energy 00369 return 0.0;//0.5*Dot(sig_tmp+sta_in->Sig, DEps_in); // strain energy / volume 00370 } 00371 00372 inline void Model::StressUpdate::GetInfo (std::ostream & os, bool Header) const 00373 { 00374 String buf; 00375 if (Scheme==ME_t) 00376 { 00377 if (Header) 00378 { 00379 os << "\n" << TERM_BLACK_WHITE << "----------------------------- StressUpdate/Scheme: ME ------------------------------" << TERM_RST << "\n\n"; 00380 os << "STOL = " << STOL << std::endl; 00381 os << "dTini = " << dTini << std::endl; 00382 os << "mMin = " << mMin << std::endl; 00383 os << "mMax = " << mMax << std::endl; 00384 os << "MaxSS = " << MaxSS << std::endl; 00385 os << "CDrift = " << CDrift << std::endl; 00386 buf.Printf("\n%6s %6s %6s %6s %6s %12s %12s %16s\n", "Scheme", "SS", "SSs", "DCitEl", "DCit", "T", "dT", "Error"); 00387 os << buf; 00388 } 00389 buf.Printf("%6s %6zd %6zd %6zd %6zd %12.8f %12.8f %16.8e\n", "ME", SS, SSs, DCitEl, DCit, T, dT, Error); 00390 os << buf; 00391 } 00392 else if (Scheme==SingleFE_t) 00393 { 00394 if (Header) os << "\n" << TERM_BLACK_WHITE << "----------------------------- StressUpdate/Scheme: SingleFE ------------------------" << TERM_RST << "\n\n"; 00395 } 00396 else if (Scheme==RK_t) 00397 { 00398 if (Header) 00399 { 00400 if (ODE==NULL) 00401 { 00402 os << "\n" << TERM_BLACK_WHITE << "----------------------------- StressUpdate/Scheme: RK ----------------------------" << TERM_RST << "\n\n"; 00403 return; 00404 } 00405 os << "\n" << TERM_BLACK_WHITE << "----------------------------- StressUpdate/Scheme: RK(" << ODE->Scheme << ") ----------------------------" << TERM_RST << "\n\n"; 00406 os << "STOL = " << ODE->STOL << std::endl; 00407 os << "dTini = " << ODE->dTini << std::endl; 00408 os << "mMin = " << ODE->mMin << std::endl; 00409 os << "mMax = " << ODE->mMax << std::endl; 00410 os << "MaxSS = " << ODE->MaxSS << std::endl; 00411 os << "CDrift = " << CDrift << std::endl; 00412 buf.Printf("\n%6s %6s %6s %6s %12s %12s\n", "Scheme", "SS", "SSs", "DCit", "T", "dT"); 00413 os << buf; 00414 } 00415 if (ODE==NULL) return; 00416 buf.Printf("%6s %6zd %6zd %6zd %12.8f %12.8f\n", "ME", ODE->SS, ODE->SSs, DCit, ODE->T, ODE->dT); 00417 os << buf; 00418 } 00419 } 00420 00421 inline int Model::StressUpdate::_RK_fun (double t, double const Y[], double dYdt[]) 00422 { 00423 // current strain, stress, and internal values 00424 sta->Eps = eps0 + t*deps; 00425 for (size_t i=0; i<ncp; ++i) sta->Sig(i) = Y[ i]; 00426 for (size_t i=0; i<niv; ++i) sta->Ivs(i) = Y[ncp+i]; 00427 00428 // tangent increments 00429 Mdl->TgIncs (sta, deps, dsig, divs); 00430 for (size_t i=0; i<ncp; ++i) dYdt[ i] = dsig(i); 00431 for (size_t i=0; i<niv; ++i) dYdt[ncp+i] = divs(i); 00432 00433 // return success 00434 return GSL_SUCCESS; 00435 } 00436 00437 inline void Model::StressUpdate::_RK_up_fun (double t, double Y[]) 00438 { 00439 // current strain, stress, and internal values 00440 sta->Eps = eps0 + t*deps; 00441 for (size_t i=0; i<ncp; ++i) sta->Sig(i) = Y[ i]; 00442 for (size_t i=0; i<niv; ++i) sta->Ivs(i) = Y[ncp+i]; 00443 00444 // correct drift 00445 if (CDrift) 00446 { 00447 DCit = GetMax (DCit, Mdl->CorrectDrift (sta)); 00448 for (size_t i=0; i<ncp; ++i) Y[ i] = sta->Sig(i); 00449 for (size_t i=0; i<niv; ++i) Y[ncp+i] = sta->Ivs(i); 00450 } 00451 00452 // debug function 00453 if (DbgFun!=NULL) (*DbgFun) ((*this), DbgDat); 00454 } 00455 00456 #endif // STRESSUPDATE_IMPLEMENT