cautome.h

00001 /*************************************************************************************
00002  * MechSys - A C++ library to simulate (Continuum) Mechanical Systems                *
00003  * Copyright (C) 2005 Dorival de Moraes Pedroso <dorival.pedroso at gmail.com>       *
00004  * Copyright (C) 2005 Raul Dario Durand Farfan  <raul.durand at gmail.com>           *
00005  *                                                                                   *
00006  * This file is part of MechSys.                                                     *
00007  *                                                                                   *
00008  * MechSys is free software; you can redistribute it and/or modify it under the      *
00009  * terms of the GNU General Public License as published by the Free Software         *
00010  * Foundation; either version 2 of the License, or (at your option) any later        *
00011  * version.                                                                          *
00012  *                                                                                   *
00013  * MechSys is distributed in the hope that it will be useful, but WITHOUT ANY        *
00014  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A   *
00015  * PARTICULAR PURPOSE. See the GNU General Public License for more details.          *
00016  *                                                                                   *
00017  * You should have received a copy of the GNU General Public License along with      *
00018  * MechSys; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, *
00019  * Fifth Floor, Boston, MA 02110-1301, USA                                           *
00020  *************************************************************************************/
00021 
00022 #ifndef MECHSYS_FEM_CAUTOME_H
00023 #define MECHSYS_FEM_CAUTOME_H
00024 
00025 #ifdef HAVE_CONFIG_H
00026   #include "config.h"
00027 #else
00028   #ifndef REAL
00029     #define REAL double
00030   #endif
00031 #endif
00032 
00033 // MechSys
00034 #include "util/string.h"
00035 #include "util/lineparser.h"
00036 #include "fem/solver/csolver.h"
00037 
00038 namespace FEM
00039 {
00040 
00041 class CAutoME: public CSolver
00042 {
00043 public:
00044     CAutoME(Array<String> const & CSolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output)
00045         : CSolver (ID, data, output),
00046           _maxSS (200)   ,
00047           _STOL  (1.0e-2),
00048           _dTini (0.001) ,
00049           _mMin  (0.01)  ,
00050           _mMax  (10)    ,
00051           _mCoef (0.7)   ,
00052           _ZTOL  (1e-5)  ,
00053           _check_convergence (true)
00054     {
00055         for (size_t i=0; i<CSolverCtes.size(); ++i)
00056         {
00057             LineParser LP(CSolverCtes[i]);
00058             LP.ReplaceAllChars('=',' ');
00059             String key;            LP>>key;
00060                  if (key=="maxSS") LP>>_maxSS;
00061             else if (key=="STOL")  LP>>_STOL;
00062             else if (key=="dTini") LP>>_dTini;
00063             else if (key=="mMin")  LP>>_mMin;
00064             else if (key=="mMax")  LP>>_mMax;
00065             else if (key=="mCoef") LP>>_mCoef;
00066             else if (key=="ZTOL")  LP>>_ZTOL;
00067             else if (key=="checkConvergence") LP>>_check_convergence;
00068             else throw new Fatal(_("CAutoME::CAutoME: < %s > is invalid "), key.c_str());
00069         }
00070     }
00071     void _do_solve_for_an_increment(int                  const   increment,  // In
00072                                     LinAlg::Vector<REAL> const & DF_ext   ,  // In
00073                                     LinAlg::Vector<REAL> const & DU_ext   ,  // In
00074                                     REAL                 const   dTime    ,  // In
00075                                     LinAlg::Matrix<REAL>       & G        ,  // (no needed outside)
00076                                     LinAlg::Vector<REAL>       & hKUn     ,  // (no needed outside)
00077                                     LinAlg::Vector<REAL>       & dF_int   ,  // (no needed outside)
00078                                     LinAlg::Vector<REAL>       & Rinternal,  // (no needed outside)
00079                                     IntSolverData              & ISD      ); // Out
00080 private:
00081     int  _maxSS;
00082     REAL _STOL;
00083     REAL _dTini;
00084     REAL _mMin;
00085     REAL _mMax;
00086     REAL _mCoef;
00087     REAL _ZTOL;
00088     bool _check_convergence;
00089 
00090     LinAlg::Vector<REAL> _dF_1;
00091     LinAlg::Vector<REAL> _dU_1;
00092     LinAlg::Vector<REAL> _dF_2;
00093     LinAlg::Vector<REAL> _dU_2;
00094     LinAlg::Vector<REAL> _dU_ME;
00095     LinAlg::Vector<REAL> _Err_U;
00096     LinAlg::Vector<REAL> _Err_F;
00097 }; // class CAutoME
00098 
00099 
00101 
00102 
00103 inline void CAutoME::_do_solve_for_an_increment(int                  const   increment,  // In // {{{
00104                                                 LinAlg::Vector<REAL> const & DF_ext   ,  // In (may be changed)
00105                                                 LinAlg::Vector<REAL> const & DU_ext   ,  // In (may be changed)
00106                                                 REAL                 const   dTime    ,  // In
00107                                                 LinAlg::Matrix<REAL>       & G        ,  // (no needed outside)
00108                                                 LinAlg::Vector<REAL>       & hKUn     ,  // (no needed outside)
00109                                                 LinAlg::Vector<REAL>       & dF_int   ,  // (no needed outside)
00110                                                 LinAlg::Vector<REAL>       & Rinternal,  // (no needed outside)
00111                                                 IntSolverData              & ISD      )  // Out
00112 {
00113     // Allocate and fill dF_ext and dU_ext
00114     int n_tot_dof = DF_ext.Size();
00115     LinAlg::Vector<REAL> dF_ext; dF_ext.Resize(n_tot_dof);
00116     LinAlg::Vector<REAL> dU_ext; dU_ext.Resize(n_tot_dof);
00117     LinAlg::Copy(DF_ext, dF_ext);
00118     LinAlg::Copy(DU_ext, dU_ext);
00119 
00120     // Allocate auxiliar vectors
00121     if (increment==0)
00122     {
00123         _dF_1 .Resize(n_tot_dof);
00124         _dU_1 .Resize(n_tot_dof);
00125         _dF_2 .Resize(n_tot_dof);
00126         _dU_2 .Resize(n_tot_dof);
00127         _dU_ME.Resize(n_tot_dof);
00128         _Err_U.Resize(n_tot_dof);
00129         _Err_F.Resize(n_tot_dof);
00130     }
00131 
00132     // Start substeps
00133     REAL  T = 0.0;
00134     REAL dT = _dTini;
00135     for (int k=0; k<_maxSS; ++k)
00136     {
00137         if (T>=1.0) return;
00138 
00139         // Sub-divide timestep
00140         REAL h = dT*dTime;
00141 
00142         // Calculate scaled increment vectors for this sub-step
00143         LinAlg::CopyScal(dT,dF_ext, _dF_1); // _dF_1 <- dT*dF_ext
00144         LinAlg::CopyScal(dT,dU_ext, _dU_1); // _dU_1 <- dT*dU_ext;
00145         LinAlg::CopyScal(dT,dF_ext, _dF_2); // _dF_2 <- dT*dF_ext
00146         LinAlg::CopyScal(dT,dU_ext, _dU_2); // _dU_2 <- dT*dU_ext;
00147 
00148         // Backup element state (needed when updating disp. state for a ME increment)
00149         _backup_nodes_and_elements_state();
00150 
00151         // Forward-Euler: Assemble G matrix and calculate _dU_1
00152         _assemb_G      (G, hKUn, h);             // G <- C + h*alpha*K
00153         LinAlg::Axpy   (-1.0,hKUn, _dF_1);       // _dF_1 <- _dF_1 - hKUn
00154         _inv_K_times_X (G, false, _dF_1, _dU_1); // _dU_1 <- inv(G)*(dF_ext - hKUn)
00155     
00156         // Forward-Euler: update nodes and elements state
00157         _update_nodes_and_elements_state(_dU_1, dF_int, h);
00158 
00159         // Modified-Euler: Assemble G matrix and calculate dU_2
00160         _assemb_G      (G, hKUn, h);             // G <- C + h*alpha*K
00161         LinAlg::Axpy   (-1.0,hKUn, _dF_2);       // _dF_2 <- _dF_2 - hKUn
00162         _inv_K_times_X (G, false, _dF_2, _dU_2); // _dU_2 <- inv(G)*(dF_ext - hKun)
00163     
00164         // Save the norm of essential and natural vectors
00165         REAL normU = _norm_essential_vector(); // (%)
00166         REAL normF = _norm_natural_vector();
00167 
00168         // Calculate local error
00169         if (normF<=_ZTOL) throw new Message(_("CAutoME::_do_solve_for_an_increment: k=%d: normF=%e cannot be equal to ZTOL (%e)"),k,normF,_ZTOL);
00170         LinAlg::AddScaled(0.5,_dU_2, -0.5,_dU_1, _Err_U); // Error on U (%)
00171         LinAlg::AddScaled(0.5,_dF_2, -0.5,_dF_1, _Err_F); // Error on F
00172         REAL Rerr_U = LinAlg::Norm(_Err_U)/(1.0+normU);   // (R)elative error on U
00173         REAL Rerr_F = LinAlg::Norm(_Err_F)/normF;         // (R)elative error on F
00174         REAL   Rerr = (Rerr_U>Rerr_F ? Rerr_U : Rerr_F);  // (R)elative error
00175         REAL      m = _mCoef*sqrt(_STOL/Rerr);
00176 
00177         // Restore nodes and element for initial disp. state given at the start of the increment
00178         _restore_nodes_and_elements_state();
00179 
00180         if (Rerr<=_STOL)
00181         {
00182             // Calculate Modified-Euler displacement increment vector
00183             LinAlg::AddScaled(0.5,_dU_1, 0.5,_dU_2, _dU_ME);
00184 
00185             // Update nodes and elements state for a Modified-Euler evaluation of displacements
00186             _update_nodes_and_elements_state(_dU_ME, dF_int, h);
00187 
00188             // Next pseudo time
00189             T = T + dT;
00190             if (m>_mMax) m=_mMax;
00191         }
00192         else
00193             if (m<_mMin) m=_mMin;
00194 
00195         // Next substep size
00196         dT = m*dT;
00197         if (dT>1.0-T) dT=1.0-T;
00198 
00199         // IntSolverData
00200         ISD.ME_Rerr(Rerr).ME_T(T).ME_dT(dT).ME_m(m);
00201     }
00202     if (_check_convergence)
00203         throw new Fatal(_("CAutoME::_do_solve_for_an_increment: did not converge for %d substeps"), _maxSS);
00204 
00205 } // }}}
00206 
00207 
00209 
00210 
00211 // Allocate a new CAutoME solver
00212 CSolver * CAutoMEMaker(Array<String> const & CSolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output) // {{{
00213 {
00214     return new CAutoME(CSolverCtes, ID, data, output);
00215 } // }}}
00216 
00217 // Register an CAutoME solver into CSolverFactory array map
00218 int CAutoMERegister() // {{{
00219 {
00220     CSolverFactory["CAutoME"] = CAutoMEMaker;
00221     return 0;
00222 } // }}}
00223 
00224 // Execute the autoregistration
00225 int __CAutoME_dummy_int = CAutoMERegister();
00226 
00227 }; // namespace FEM
00228 
00229 #endif // MECHSYS_FEM_CAUTOME_H
00230 
00231 // vim:fdm=marker

Generated on Wed Jan 24 15:56:25 2007 for MechSys by  doxygen 1.4.7