MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/models/hmstressupdate.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines