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_MODIFIEDEULER_H
00023 #define MECHSYS_FEM_MODIFIEDEULER_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/solver.h"
00035
00036 namespace FEM
00037 {
00038
00039 class ModifiedEuler : public Solver
00040 {
00041 public:
00042 ModifiedEuler(Array<String> const & SolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output)
00043 : Solver (ID, data, output),
00044 _nSS (1)
00045 {
00046 for (size_t i=0; i<SolverCtes.size(); ++i)
00047 {
00048 LineParser LP(SolverCtes[i]);
00049 LP.ReplaceAllChars('=',' ');
00050 String key; LP>>key;
00051 if (key=="nSS") LP>>_nSS;
00052 else throw new Fatal(_("ModifiedEuler::ModifiedEuler: < %s > is invalid "), key.c_str());
00053 }
00054 if (_nSS<1) throw new Fatal(_("ModifiedEuler::ModifiedEuler: 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 LinAlg::Matrix<REAL> & K ,
00060 LinAlg::Vector<REAL> & dF_int ,
00061 LinAlg::Vector<REAL> & Rinternal,
00062 IntSolverData & ISD );
00063 private:
00064 int _nSS;
00065
00066 LinAlg::Vector<REAL> _dF_2;
00067 LinAlg::Vector<REAL> _dU_2;
00068 LinAlg::Vector<REAL> _dU_ME;
00069 };
00070
00072
00073
00074 inline void ModifiedEuler::_do_solve_for_an_increment(int const increment,
00075 LinAlg::Vector<REAL> const & DF_ext ,
00076 LinAlg::Vector<REAL> const & DU_ext ,
00077 LinAlg::Matrix<REAL> & K ,
00078 LinAlg::Vector<REAL> & dF_int ,
00079 LinAlg::Vector<REAL> & Rinternal,
00080 IntSolverData & ISD )
00081 {
00082
00083 int n_tot_dof = DF_ext.Size();
00084 LinAlg::Vector<REAL> dF_ext; dF_ext.Resize(n_tot_dof);
00085 LinAlg::Vector<REAL> dU_ext; dU_ext.Resize(n_tot_dof);
00086 LinAlg::CopyScal(1.0/_nSS,DF_ext, dF_ext);
00087 LinAlg::CopyScal(1.0/_nSS,DU_ext, dU_ext);
00088
00089
00090 for (int i=0; i<_nSS; ++i)
00091 {
00092
00093 if (increment==0)
00094 {
00095 int n_tot_dof = dF_ext.Size();
00096 _dF_2 .Resize(n_tot_dof);
00097 _dU_2 .Resize(n_tot_dof);
00098 _dU_ME.Resize(n_tot_dof);
00099 }
00100
00101
00102 LinAlg::Copy(dF_ext, _dF_2);
00103 LinAlg::Copy(dU_ext, _dU_2);
00104
00105
00106 _backup_nodes_and_elements_state();
00107
00108
00109 _assemb_K (K);
00110 _inv_K_times_X (K, false, dF_ext, dU_ext);
00111
00112
00113
00114 _update_nodes_and_elements_state(dU_ext, dF_int);
00115
00116
00117 _assemb_K (K);
00118 _inv_K_times_X (K, false, _dF_2, _dU_2);
00119
00120
00121 LinAlg::AddScaled(0.5,dU_ext, 0.5,_dU_2, _dU_ME);
00122
00123
00124 _restore_nodes_and_elements_state();
00125
00126
00127 _update_nodes_and_elements_state(_dU_ME, dF_int);
00128 }
00129
00130 }
00131
00132
00134
00135
00136
00137 Solver * ModifiedEulerMaker(Array<String> const & SolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output)
00138 {
00139 return new ModifiedEuler(SolverCtes, ID, data, output);
00140 }
00141
00142
00143 int ModifiedEulerRegister()
00144 {
00145 SolverFactory["ModifiedEuler"] = ModifiedEulerMaker;
00146 return 0;
00147 }
00148
00149
00150 int __ModifiedEuler_dummy_int = ModifiedEulerRegister();
00151
00152 };
00153
00154 #endif // MECHSYS_FEM_MODIFIEDEULER_H
00155
00156