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_FORWARDEULER_H
00023 #define MECHSYS_FEM_FORWARDEULER_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 ForwardEuler: public Solver
00040 {
00041 public:
00042 ForwardEuler(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(_("ForwardEuler::ForwardEuler: < %s > is invalid "), key.c_str());
00053 }
00054 if (_nSS<1) throw new Fatal(_("ForwardEuler::ForwardEuler: 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
00067
00069
00070
00071 inline void ForwardEuler::_do_solve_for_an_increment(int const increment,
00072 LinAlg::Vector<REAL> const & DF_ext ,
00073 LinAlg::Vector<REAL> const & DU_ext ,
00074 LinAlg::Matrix<REAL> & K ,
00075 LinAlg::Vector<REAL> & dF_int ,
00076 LinAlg::Vector<REAL> & Rinternal,
00077 IntSolverData & ISD )
00078 {
00079
00080 int n_tot_dof = DF_ext.Size();
00081 LinAlg::Vector<REAL> dF_ext; dF_ext.Resize(n_tot_dof);
00082 LinAlg::Vector<REAL> dU_ext; dU_ext.Resize(n_tot_dof);
00083 LinAlg::CopyScal(1.0/_nSS,DF_ext, dF_ext);
00084 LinAlg::CopyScal(1.0/_nSS,DU_ext, dU_ext);
00085
00086
00087 for (int i=0; i<_nSS; ++i)
00088 {
00089
00090 _assemb_K (K);
00091 _inv_K_times_X (K, false, dF_ext, dU_ext);
00092
00093
00094 _update_nodes_and_elements_state(dU_ext, dF_int);
00095
00096
00097 LinAlg::AddScaled (1.0,dF_ext, -1.0,dF_int, Rinternal);
00098 REAL denom = 0.0;
00099 for (int i=0; i<Rinternal.Size(); i++) denom += pow((dF_ext(i)+dF_int(i))/2.0, 2.0);
00100 ISD.FE_resid(LinAlg::Norm(Rinternal)/sqrt(denom));
00101 }
00102
00103 }
00104
00105
00107
00108
00109
00110 Solver * ForwardEulerMaker(Array<String> const & SolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output)
00111 {
00112 return new ForwardEuler(SolverCtes, ID, data, output);
00113 }
00114
00115
00116 int ForwardEulerRegister()
00117 {
00118 SolverFactory["ForwardEuler"] = ForwardEulerMaker;
00119 return 0;
00120 }
00121
00122
00123 int __ForwardEuler_dummy_int = ForwardEulerRegister();
00124
00125 };
00126
00127 #endif // MECHSYS_FEM_FORWARDEULER_H
00128
00129