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_CMODIFIEDEULER_H
00023 #define MECHSYS_FEM_CMODIFIEDEULER_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
00034 #include "fem/solver/csolver.h"
00035
00036 namespace FEM
00037 {
00038
00039 class CModifiedEuler: public CSolver
00040 {
00041 public:
00042 CModifiedEuler(Array<String> const & CSolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output)
00043 : CSolver (ID, data, output),
00044 _nSS (1)
00045 {
00046 for (size_t i=0; i<CSolverCtes.size(); ++i)
00047 {
00048 LineParser LP(CSolverCtes[i]);
00049 LP.ReplaceAllChars('=',' ');
00050 String key; LP>>key;
00051 if (key=="nSS") LP>>_nSS;
00052 else throw new Fatal(_("CModifiedEuler::CModifiedEuler: < %s > is invalid "), key.c_str());
00053 }
00054 if (_nSS<1) throw new Fatal(_("CModifiedEuler::CModifiedEuler: The number of substeps (nSS=%d) must be greater than or equal to 1"), _nSS);
00055 }
00056 void _do_solve_for_an_increment(int const increment,
00057 LinAlg::Vector<REAL> const & DF_ext ,
00058 LinAlg::Vector<REAL> const & DU_ext ,
00059 REAL const dTime ,
00060 LinAlg::Matrix<REAL> & G ,
00061 LinAlg::Vector<REAL> & hKUn ,
00062 LinAlg::Vector<REAL> & dF_int ,
00063 LinAlg::Vector<REAL> & Rinternal,
00064 IntSolverData & ISD );
00065 private:
00066 int _nSS;
00067
00068 LinAlg::Vector<REAL> _dF_2;
00069 LinAlg::Vector<REAL> _dU_2;
00070 LinAlg::Vector<REAL> _dU_ME;
00071 };
00072
00073
00075
00076
00077 inline void CModifiedEuler::_do_solve_for_an_increment(int const increment,
00078 LinAlg::Vector<REAL> const & DF_ext ,
00079 LinAlg::Vector<REAL> const & DU_ext ,
00080 REAL const dTime ,
00081 LinAlg::Matrix<REAL> & G ,
00082 LinAlg::Vector<REAL> & hKUn ,
00083 LinAlg::Vector<REAL> & dF_int ,
00084 LinAlg::Vector<REAL> & Rinternal,
00085 IntSolverData & ISD )
00086 {
00087
00088 int n_tot_dof = DF_ext.Size();
00089 LinAlg::Vector<REAL> dF_ext; dF_ext.Resize(n_tot_dof);
00090 LinAlg::Vector<REAL> dU_ext; dU_ext.Resize(n_tot_dof);
00091 LinAlg::CopyScal(1.0/_nSS,DF_ext, dF_ext);
00092 LinAlg::CopyScal(1.0/_nSS,DU_ext, dU_ext);
00093 REAL h = dTime/_nSS;
00094
00095
00096 for (int i=0; i<_nSS; ++i)
00097 {
00098
00099 if (increment==0)
00100 {
00101 int n_tot_dof = dF_ext.Size();
00102 _dF_2 .Resize(n_tot_dof);
00103 _dU_2 .Resize(n_tot_dof);
00104 _dU_ME.Resize(n_tot_dof);
00105 }
00106
00107
00108 LinAlg::Copy(dF_ext, _dF_2);
00109 LinAlg::Copy(dU_ext, _dU_2);
00110
00111
00112 _backup_nodes_and_elements_state();
00113
00114
00115 _assemb_G (G, hKUn, h);
00116 LinAlg::Axpy (-1.0,hKUn, dF_ext);
00117 _inv_K_times_X (G, false, dF_ext, dU_ext);
00118
00119
00120 _update_nodes_and_elements_state(dU_ext, dF_int, h);
00121
00122
00123 _assemb_G (G, hKUn, h);
00124 LinAlg::Axpy (-1.0,hKUn, _dF_2);
00125 _inv_K_times_X (G, false, _dF_2, _dU_2);
00126
00127
00128 LinAlg::AddScaled(0.5,dU_ext, 0.5,_dU_2, _dU_ME);
00129
00130
00131 _restore_nodes_and_elements_state();
00132
00133
00134 _update_nodes_and_elements_state(_dU_ME, dF_int, h);
00135 }
00136
00137 }
00138
00139
00141
00142
00143
00144 CSolver * CModifiedEulerMaker(Array<String> const & CSolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output)
00145 {
00146 return new CModifiedEuler(CSolverCtes, ID, data, output);
00147 }
00148
00149
00150 int CModifiedEulerRegister()
00151 {
00152 CSolverFactory["CModifiedEuler"] = CModifiedEulerMaker;
00153 return 0;
00154 }
00155
00156
00157 int __CModifiedEuler_dummy_int = CModifiedEulerRegister();
00158
00159 };
00160
00161 #endif // MECHSYS_FEM_CMODIFIEDEULER_H
00162
00163