00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef MECHSYS_FEM_AUTOINCME_H
00023 #define MECHSYS_FEM_AUTOINCME_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 "util/string.h"
00034 #include "fem/solver/solver.h"
00035 #include "util/lineparser.h"
00036 #ifdef DO_DEBUG
00037 #include "util/numstreams.h"
00038 #endif
00039
00040 namespace FEM
00041 {
00042
00043 class AutoIncME : public Solver
00044 {
00045 public:
00046 AutoIncME(Array<String> const & SolverCtes, FEM::Data & data, FEM::Output & output, Array<int> & nDiv)
00047 : Solver (data, output, nDiv) ,
00048 _dT_ini (0.001) ,
00049 _m_min (0.01) ,
00050 _m_max (10) ,
00051 _m_sf (0.7) ,
00052 _max_sub_steps (200) ,
00053 _dtol (1.0e-4) ,
00054 _use_resid_correct (false)
00055 {
00056 for (size_t i=0; i<SolverCtes.size(); ++i)
00057 {
00058 LineParser LP(SolverCtes[i]);
00059 LP.ReplaceAllChars('=',' ');
00060 String key; LP>>key;
00061 if (key=="dTini") LP>>_dT_ini;
00062 else if (key=="mMin") LP>>_m_min;
00063 else if (key=="mMax") LP>>_m_max;
00064 else if (key=="mSF") LP>>_m_sf;
00065 else if (key=="maxSSteps") LP>>_max_sub_steps;
00066 else if (key=="DTOL") LP>>_dtol;
00067 else if (key=="correctResid") LP>>_use_resid_correct;
00068 }
00069 }
00070 void _do_solve_for_an_increment(int const increment ,
00071 LinAlg::Vector<REAL> & dF_ext ,
00072 LinAlg::Vector<REAL> & dU_ext ,
00073 REAL const norm_dF_ext ,
00074 LinAlg::Matrix<REAL> & K ,
00075 LinAlg::Vector<REAL> & dF_int ,
00076 LinAlg::Vector<REAL> & R ,
00077 REAL & resid );
00078 private:
00079 REAL _dT_ini;
00080 REAL _m_min;
00081 REAL _m_max;
00082 REAL _m_sf;
00083 int _max_sub_steps;
00084 REAL _dtol;
00085 bool _use_resid_correct;
00086 LinAlg::Vector<REAL> _df_ext;
00087 LinAlg::Vector<REAL> _du_ext;
00088 LinAlg::Vector<REAL> _df_int;
00089 LinAlg::Vector<REAL> _df_1;
00090 LinAlg::Vector<REAL> _df_2;
00091 LinAlg::Vector<REAL> _du_1;
00092 LinAlg::Vector<REAL> _du_2;
00093 LinAlg::Vector<REAL> _du_ME;
00094 LinAlg::Vector<REAL> _Err_f;
00095 LinAlg::Vector<REAL> _Err_u;
00096 };
00097
00098
00100
00101
00102 inline void AutoIncME::_do_solve_for_an_increment(int const increment ,
00103 LinAlg::Vector<REAL> & dF_ext ,
00104 LinAlg::Vector<REAL> & dU_ext ,
00105 REAL const norm_dF_ext ,
00106 LinAlg::Matrix<REAL> & K ,
00107 LinAlg::Vector<REAL> & dF_int ,
00108 LinAlg::Vector<REAL> & R ,
00109 REAL & resid )
00110 {
00111 #ifdef DO_DEBUG // {{{
00112 std::cout << "AutoIncME: Increment # " << increment+1 << std::endl;
00113 #endif // }}}
00114
00115 if (increment==0)
00116 {
00117
00118 int n_tot_dof = dF_ext.Size();
00119 _df_ext.Resize(n_tot_dof);
00120 _du_ext.Resize(n_tot_dof);
00121 _df_int.Resize(n_tot_dof);
00122 _df_1.Resize(n_tot_dof);
00123 _df_2.Resize(n_tot_dof);
00124 _du_1.Resize(n_tot_dof);
00125 _du_2.Resize(n_tot_dof);
00126 _du_ME.Resize(n_tot_dof);
00127 _Err_f.Resize(n_tot_dof);
00128 _Err_u.Resize(n_tot_dof);
00129
00130 #ifdef DO_DEBUG // {{{
00131 std::cout << "Sub-step" << _8s()<< "resid" << "Accep/Reject" << _8s()<< "T" << _8s()<< "m" << _8s()<< "dT" << std::endl;
00132 #endif // }}}
00133 }
00134
00135
00136 REAL T = 0.0;
00137 REAL dT = _dT_ini;
00138 REAL m;
00139
00140
00141 bool DidFinish=false;
00142 for (int k_sub_step=0; k_sub_step<_max_sub_steps; ++k_sub_step)
00143 {
00144
00145 if (T>=1.0) { DidFinish=true; std::cout << std::endl; break; }
00146
00147
00148 LinAlg::CopyScal(dT,dF_ext, _df_ext);
00149 LinAlg::CopyScal(dT,dU_ext, _du_ext);
00150
00151
00152 LinAlg::Copy(_df_ext, _df_1);
00153 LinAlg::Copy(_df_ext, _df_2);
00154
00155
00156 LinAlg::Copy(_du_ext, _du_1);
00157 LinAlg::Copy(_du_ext, _du_2);
00158
00159
00160 _backup_nodes_and_elements_state();
00161
00162
00163 _assemb_K(K);
00164
00165 _inv_K_times_X(K, false, _df_1, _du_1);
00166
00167
00168 _update_nodes_and_elements_state(_du_1, _df_int);
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 _assemb_K(K);
00188
00189 _inv_K_times_X(K, false, _df_2, _du_2);
00190
00191
00192 LinAlg::AddScaled(0.5,_du_1, 0.5,_du_2, _du_ME);
00193
00194
00195
00196
00197
00198 LinAlg::AddScaled(0.5,_df_2, -0.5,_df_1, _Err_f);
00199 LinAlg::AddScaled(0.5,_du_2, -0.5,_du_1, _Err_u);
00200 REAL norm_Err_f = sqrt(LinAlg::Dot(_Err_f,_Err_f))/sqrt(LinAlg::Dot(_df_2,_df_2));
00201 REAL norm_Err_u = sqrt(LinAlg::Dot(_Err_u,_Err_u))/sqrt(LinAlg::Dot(_du_2,_du_2));
00202 REAL err = (norm_Err_f>norm_Err_u ? norm_Err_f : norm_Err_u);
00203
00204
00205 m = _m_sf*sqrt(_dtol/err);
00206
00207
00208 _restore_nodes_and_elements_state();
00209
00210
00211 if (err<=_dtol)
00212 {
00213
00214 T = T + dT;
00215
00216
00217 _update_nodes_and_elements_state(_du_ME, _df_int);
00218
00219
00220 LinAlg::AddScaled(1.0,_df_ext, -1.0,_df_int, R);
00221 resid = sqrt(LinAlg::Dot(R,R))/norm_dF_ext;
00222
00223
00224 if (m>_m_max) m=_m_max;
00225 #ifdef DO_DEBUG // {{{
00226 std::cout << k_sub_step << _8s()<< resid << "Accepted";
00227 #endif // }}}
00228 }
00229 else
00230 {
00231 if (m<_m_min) m=_m_min;
00232 #ifdef DO_DEBUG // {{{
00233 std::cout << k_sub_step << -1 << "Rejected";
00234 #endif // }}}
00235 }
00236
00237
00238 dT = m*dT;
00239 if (dT>1.0-T) dT=1.0-T;
00240
00241 std::cout << _8s()<< T << _8s()<< m << _8s()<< dT << std::endl;
00242
00243
00244 }
00245 if (!DidFinish)
00246 throw new Fatal(_("AutoIncME::_do_solve did not finish with T=1. k_sub_step=<%d>"),_max_sub_steps);
00247 }
00248
00249
00251
00252
00253
00254 Solver * AutoIncMEMaker(Array<String> const & SolverCtes, FEM::Data & data, FEM::Output & output, Array<int> & nDiv)
00255 {
00256 return new AutoIncME(SolverCtes, data, output, nDiv);
00257 }
00258
00259
00260 int AutoIncMERegister()
00261 {
00262 SolverFactory["AutoIncME"] = AutoIncMEMaker;
00263 return 0;
00264 }
00265
00266
00267 int __AutoIncME_dummy_int = AutoIncMERegister();
00268
00269 };
00270
00271 #endif // MECHSYS_FEM_AUTOINCME_H
00272
00273