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_CFORWARDEULER_H
00023 #define MECHSYS_FEM_CFORWARDEULER_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 CForwardEuler: public CSolver
00040 {
00041 public:
00042 CForwardEuler(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(_("CForwardEuler::CForwardEuler: < %s > is invalid "), key.c_str());
00053 }
00054 if (_nSS<1) throw new Fatal(_("CForwardEuler::CForwardEuler: 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
00069
00071
00072
00073 inline void CForwardEuler::_do_solve_for_an_increment(int const increment,
00074 LinAlg::Vector<REAL> const & DF_ext ,
00075 LinAlg::Vector<REAL> const & DU_ext ,
00076 REAL const dTime ,
00077 LinAlg::Matrix<REAL> & G ,
00078 LinAlg::Vector<REAL> & hKUn ,
00079 LinAlg::Vector<REAL> & dF_int ,
00080 LinAlg::Vector<REAL> & Rinternal,
00081 IntSolverData & ISD )
00082 {
00083
00084 int n_tot_dof = DF_ext.Size();
00085 LinAlg::Vector<REAL> dF_ext; dF_ext.Resize(n_tot_dof);
00086 LinAlg::Vector<REAL> dU_ext; dU_ext.Resize(n_tot_dof);
00087 LinAlg::CopyScal(1.0/_nSS,DF_ext, dF_ext);
00088 LinAlg::CopyScal(1.0/_nSS,DU_ext, dU_ext);
00089 REAL h = dTime/_nSS;
00090
00091
00092 for (int i=0; i<_nSS; ++i)
00093 {
00094
00095 _assemb_G (G, hKUn, h);
00096 LinAlg::Axpy (-1.0,hKUn, dF_ext);
00097 _inv_K_times_X (G, false, dF_ext, dU_ext);
00098
00099
00100 _update_nodes_and_elements_state(dU_ext, dF_int, h);
00101
00102
00103 LinAlg::Axpy (+1.0,hKUn, dF_ext);
00104 LinAlg::AddScaled (1.0,dF_ext, -1.0,dF_int, Rinternal);
00105 REAL denom = 0.0;
00106 for (int i=0; i<Rinternal.Size(); i++) denom += pow((dF_ext(i)+dF_int(i))/2.0, 2.0);
00107 ISD.FE_resid(LinAlg::Norm(Rinternal)/sqrt(denom));
00108 }
00109
00110 }
00111
00112
00114
00115
00116
00117 CSolver * CForwardEulerMaker(Array<String> const & CSolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output)
00118 {
00119 return new CForwardEuler(CSolverCtes, ID, data, output);
00120 }
00121
00122
00123 int CForwardEulerRegister()
00124 {
00125 CSolverFactory["CForwardEuler"] = CForwardEulerMaker;
00126 return 0;
00127 }
00128
00129
00130 int __CForwardEuler_dummy_int = CForwardEulerRegister();
00131
00132 };
00133
00134 #endif // MECHSYS_FEM_CFORWARDEULER_H
00135
00136