00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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;
00071 REAL dT = _dTini;
00072 REAL smult;
00073 REAL error;
00074
00075 xType dx_k;
00076 yType dy_FE;
00077 zType dz_FE;
00078
00079 xType x_FE;
00080 yType y_FE;
00081 zType z_FE;
00082
00083 yType dy_int;
00084 zType dz_int;
00085
00086 yType y_ME;
00087 zType z_ME;
00088
00089 yType E_y;
00090 zType E_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;
00103
00104
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);
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);
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)
00134 {
00135 T = T + dT;
00136 x = x_FE;
00137 y = y_ME;
00138 z = z_ME;
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;
00146 }
00147 else
00148 if (smult<_mMin) smult=_mMin;
00149
00150 dT = smult * dT;
00151 if (dT>1.0-T) dT=1.0-T;
00152 }
00153 return -1;
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 };
00172
00173
00174
00175
00176
00177 #endif // #define MECHSYS_AUTOSTEPME_H