autostepme.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_AUTOSTEPME_H
00023 #define MECHSYS_AUTOSTEPME_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 #include <cmath>
00034 #ifdef DO_DEBUG
00035     #include <sstream>
00036     #include <string>
00037     #include <iomanip>
00038 #endif
00039 
00040 // MechSys
00041 #include "numerical/integschemesctes.h"
00042 
00044 template<typename xType, typename yType, typename zType, typename Instance>
00045 class AutoStepME
00046 {
00047 public:
00048 
00049     typedef int (Instance::*pTgDyDz) (xType const &  x, yType const &  y, zType const &  z,
00050                                       xType const & dx, yType       & dy, zType       & dz) const;
00051 
00052     typedef REAL (Instance::*pCalcErr) (yType const & Ey, yType const & y_high,
00053                                         zType const & Ez, zType const & z_high) const;
00054 
00055     AutoStepME(IntegSchemesCtes const & ISC)
00056         : _maxSS (ISC.ME_maxSS()),
00057           _STOL  (ISC.ME_STOL ()),
00058           _dTini (ISC.ME_dTini()),
00059           _mMin  (ISC.ME_mMin ()),
00060           _mMax  (ISC.ME_mMax ())
00061     {}
00062 
00064 
00066     int Solve(Instance const * p2Inst, pTgDyDz tg_dy_dz, pCalcErr calc_error,
00067               xType       &  x,  yType &  y,  zType &  z,
00068               xType const & Dx)
00069     {
00070         REAL  T = 0.0;    // Pseudo time
00071         REAL dT = _dTini; // First increment of pseudo time
00072         REAL  smult;      // Multiplier for step-size
00073         REAL  error;      // Error estimative
00074 
00075         xType dx_k;  // "driver" increment
00076         yType dy_FE; // Forward Euler increment
00077         zType dz_FE; // Forward Euler increment
00078 
00079         xType x_FE; // FE "state"
00080         yType y_FE; // FE "state"
00081         zType z_FE; // FE "state" 
00082 
00083         yType dy_int; // Intermediary increment evaluate with a tangent given for the FE "state"
00084         zType dz_int; // Intermediary increment evaluate with a tangent given for the FE "state"
00085 
00086         yType y_ME; // Modified Euler "state" (high order)
00087         zType z_ME; // Modified Euler "state" (high order)
00088 
00089         yType E_y; // Estimated error on y
00090         zType E_z; // Estimated error on z
00091 
00092 #ifdef DO_DEBUG
00093         _results << std::setw(15) << "T";
00094         _results << std::setw(15) << "x";
00095         _results << std::setw(15) << "y";
00096         _results << std::setw(15) << "z" << std::endl;
00097         _results << std::setw(15) << T;
00098         _results << std::setw(15) << x;
00099         _results << std::setw(15) << y;
00100         _results << std::setw(15) << z << std::endl;
00101 #endif
00102         int Flag; // Flag received from tg_dy_dz: -1 => failed
00103                   //                               0 => continue
00104                   //                               1 => stop
00105 
00106         for (int k=1; k<=_maxSS; ++k)
00107         {
00108             if (T>=1.0) return k;
00109 
00110             dx_k = Dx * dT;
00111 
00112             Flag = (p2Inst->*tg_dy_dz)(x, y, z, dx_k, dy_FE, dz_FE); // Out: dy_FE and dz_FE
00113             if      (Flag==-1) return -1;
00114             else if (Flag==1)  return -2;
00115 
00116             x_FE = x + dx_k;
00117             y_FE = y + dy_FE;
00118             z_FE = z + dz_FE;
00119 
00120             Flag = (p2Inst->*tg_dy_dz)(x_FE, y_FE, z_FE, dx_k, dy_int, dz_int); // Out: dy_int and dz_int
00121             if      (Flag==-1) return -1;
00122             else if (Flag==1)  return -2;
00123 
00124             y_ME = y + 0.5*( dy_FE + dy_int );
00125             z_ME = z + 0.5*( dz_FE + dz_int );
00126 
00127             E_y = y_ME - y_FE;
00128             E_z = z_ME - z_FE;
00129 
00130             error = (p2Inst->*calc_error)(E_y, y_ME, E_z, z_ME);
00131             smult = 0.9*sqrt(_STOL/error);
00132             
00133             if (error<=_STOL) // Step accepted
00134             {
00135                 T = T + dT; // Actualize "pseudo-time"
00136                 x = x_FE; // Next x
00137                 y = y_ME; // Next y
00138                 z = z_ME; // Next z
00139 #ifdef DO_DEBUG
00140             _results << std::setw(15) << T;
00141             _results << std::setw(15) << x;
00142             _results << std::setw(15) << y;
00143             _results << std::setw(15) << z << std::endl;
00144 #endif
00145                 if (smult>_mMax) smult=_mMax; // Upper bound step size
00146             }
00147             else // Step rejected
00148                 if (smult<_mMin) smult=_mMin; // Lower bound step size
00149 
00150             dT = smult * dT;        // Update step size
00151             if (dT>1.0-T) dT=1.0-T; // Last step
00152         }
00153         return -1; // ERROR: ME did not converge!
00154     }
00155 
00156 #ifdef DO_DEBUG
00157     std::string Results() { return _results.str(); }
00158 #endif
00159 
00160 private:
00161     int  _maxSS; 
00162     REAL _STOL;  
00163     REAL _dTini; 
00164     REAL _mMin;  
00165     REAL _mMax;  
00166 
00167 #ifdef DO_DEBUG
00168     std::ostringstream _results;
00169 #endif
00170 
00171 }; // AutoStepME
00172 
00173 // \cond implementation
00174 
00175 // \endcond implementation
00176 
00177 #endif // #define MECHSYS_AUTOSTEPME_H

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