![]() |
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 #ifndef MECHSYS_STRAINUPDATE_H 00021 #define MECHSYS_STRAINUPDATE_H 00022 00023 // Std Lib 00024 #include <iostream> 00025 00026 // MechSys 00027 #include <mechsys/models/model.h> 00028 #include <mechsys/models/equilibstate.h> 00029 00030 class StrainUpdate 00031 { 00032 public: 00033 // enum 00034 enum Scheme_t { ME_t, SingleFE_t }; 00035 00036 // Constructor 00037 StrainUpdate (Model const * Mdl); 00038 00039 // Methods 00040 void Update (Vec_t const & DSig, State * Sta, Vec_t & DEps) const; 00041 00042 // Data 00043 Model const * Mdl; 00044 00045 // Constants for integration 00046 Scheme_t Scheme; 00047 double STOL; 00048 double dTini; 00049 double mMin; 00050 double mMax; 00051 size_t MaxSS; 00052 bool CDrift; 00053 }; 00054 00055 00057 00058 00059 inline StrainUpdate::StrainUpdate (Model const * TheMdl) 00060 : Mdl (TheMdl), 00061 Scheme (ME_t), 00062 STOL (1.0e-5), 00063 dTini (1.0), 00064 mMin (0.1), 00065 mMax (10.0), 00066 MaxSS (2000), 00067 CDrift (true) 00068 { 00069 } 00070 00071 inline void StrainUpdate::Update (Vec_t const & DSig, State * Sta, Vec_t & DEps) const 00072 { 00073 // current state 00074 EquilibState * sta = static_cast<EquilibState*>(Sta); 00075 DEps = sta->Eps; // temporary copy to calculate increment later 00076 00077 // constants 00078 size_t ncp = size(sta->Sig); // num of stress components 00079 size_t niv = size(sta->Ivs); // num of internal variables 00080 00081 // auxiliar variables 00082 Vec_t dsig(ncp); 00083 Vec_t deps(ncp); 00084 Vec_t divs(niv); 00085 00086 if (Scheme==SingleFE_t) // without intersection detection (should be used for linear elasticity only) 00087 { 00088 dsig = DSig; 00089 Mdl->InvTgIncs (sta, dsig, deps, divs); 00090 sta->Eps += deps; 00091 sta->Sig += dsig; 00092 sta->Ivs += divs; 00093 } 00094 else if (Scheme==ME_t) 00095 { 00096 // auxiliar variables 00097 EquilibState sta_1 (Mdl->NDim); // intermediate state 00098 EquilibState sta_ME(Mdl->NDim); // Modified-Euler state 00099 Vec_t deps_1(ncp), dsig_1(ncp), divs_1(niv); // intermediate increments 00100 Vec_t deps_2(ncp), divs_2(niv); // ME increments 00101 Vec_t eps_dif(ncp); // ME - FE strain difference 00102 00103 // update with full DSig 00104 dsig = DSig; 00105 00106 // for each pseudo time T 00107 double T = 0.0; 00108 double dT = dTini; 00109 size_t k = 0; 00110 for (k=0; k<MaxSS; ++k) 00111 { 00112 // exit point 00113 if (T>=1.0) break; 00114 00115 // FE and ME increments 00116 dsig_1 = dT*dsig; 00117 Mdl->InvTgIncs (sta, dsig_1, deps_1, divs_1); 00118 sta_1.Eps = sta->Eps + deps_1; 00119 sta_1.Sig = sta->Sig + dsig_1; 00120 sta_1.Ivs = sta->Ivs + divs_1; 00121 Mdl->InvTgIncs (&sta_1, dsig_1, deps_2, divs_2); 00122 sta_ME.Eps = sta->Eps + 0.5*(deps_1+deps_2); 00123 sta_ME.Ivs = sta->Ivs + 0.5*(divs_1+divs_2); 00124 00125 // local error estimate 00126 eps_dif = sta_ME.Eps - sta_1.Eps; 00127 double eps_err = Norm(eps_dif)/(1.0+Norm(sta_ME.Eps)); 00128 double ivs_err = 0.0; 00129 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))); 00130 double error = eps_err + ivs_err; 00131 00132 // step multiplier 00133 double m = (error>0.0 ? 0.9*sqrt(STOL/error) : mMax); 00134 00135 // update 00136 if (error<STOL) 00137 { 00138 // update state 00139 T += dT; 00140 sta->Eps = sta_ME.Eps; 00141 sta->Sig = sta_1 .Sig; 00142 sta->Ivs = sta_ME.Ivs; 00143 00144 // drift correction 00145 if (CDrift) Mdl->CorrectDrift (sta); 00146 00147 // update stress path in model 00148 Mdl->UpdatePath (sta, Vec_t(0.5*(deps_1+deps_2)), dsig_1); 00149 00150 // limit change on stepsize 00151 if (m>mMax) m = mMax; 00152 } 00153 else if (m<mMin) m = mMin; 00154 00155 // change next step size 00156 dT = m * dT; 00157 00158 // check for last increment 00159 if (dT>1.0-T) dT = 1.0-T; 00160 } 00161 if (k>=MaxSS) throw new Fatal("StrainUpdate::Update: Modified-Euler (local) did not converge after %d substeps",k); 00162 } 00163 else throw new Fatal("StrainUpdate::Update: Scheme is not available yet"); 00164 00165 // return total stress increment 00166 DEps = sta->Eps - DEps; 00167 } 00168 00169 #endif // MECHSYS_STRAINUPDATE_H