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_NEWTON_H
00023 #define MECHSYS_FEM_NEWTON_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 NewtonRaphson : public Solver
00040 {
00041 public:
00042 NewtonRaphson(Array<String> const & SolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output)
00043 : Solver (ID, data, output),
00044 _itol (1.0e-10) ,
00045 _max_it (20) ,
00046 _use_modfied_newton (false) ,
00047 _nSS (1)
00048 {
00049 for (size_t i=0; i<SolverCtes.size(); ++i)
00050 {
00051 LineParser LP(SolverCtes[i]);
00052 LP.ReplaceAllChars('=',' ');
00053 String key; LP>>key;
00054 if (key=="ITOL") LP>>_itol;
00055 else if (key=="maxIt") LP>>_max_it;
00056 else if (key=="modified") LP>>_use_modfied_newton;
00057 else if (key=="nSS") LP>>_nSS;
00058 else throw new Fatal(_("AutoME::AutoME: < %s > is invalid "), key.c_str());
00059 }
00060 if (_nSS<1) throw new Fatal(_("NewtonRaphson::NewtonRaphson: The number of substeps (nSS=%d) must be greater than or equal to 1"), _nSS);
00061 }
00062 void _do_solve_for_an_increment(int const increment,
00063 LinAlg::Vector<REAL> const & DF_ext ,
00064 LinAlg::Vector<REAL> const & DU_ext ,
00065 LinAlg::Matrix<REAL> & K ,
00066 LinAlg::Vector<REAL> & dF_int ,
00067 LinAlg::Vector<REAL> & Rinternal,
00068 IntSolverData & ISD );
00069 private:
00070 REAL _itol;
00071 int _max_it;
00072 bool _use_modfied_newton;
00073 int _nSS;
00074 LinAlg::Vector<REAL> _dU;
00075 };
00076
00077
00079
00080
00081 inline void NewtonRaphson::_do_solve_for_an_increment(int const increment,
00082 LinAlg::Vector<REAL> const & DF_ext ,
00083 LinAlg::Vector<REAL> const & DU_ext ,
00084 LinAlg::Matrix<REAL> & K ,
00085 LinAlg::Vector<REAL> & dF_int ,
00086 LinAlg::Vector<REAL> & Rinternal,
00087 IntSolverData & ISD )
00088
00089 {
00090
00091 int n_tot_dof = DF_ext.Size();
00092 LinAlg::Vector<REAL> dF_ext; dF_ext.Resize(n_tot_dof);
00093 LinAlg::Vector<REAL> dU_ext; dU_ext.Resize(n_tot_dof);
00094 LinAlg::CopyScal(1.0/_nSS,DF_ext, dF_ext);
00095 LinAlg::CopyScal(1.0/_nSS,DU_ext, dU_ext);
00096
00097
00098 for (int i=0; i<_nSS; ++i)
00099 {
00100
00101 if (increment==0)
00102 {
00103
00104 _dU.Resize(dF_ext.Size());
00105 }
00106
00107
00108 LinAlg::Copy(dF_ext, Rinternal);
00109 REAL resid = 1.0+_itol;
00110
00111
00112 LinAlg::Copy(dU_ext, _dU);
00113
00114
00115 if (_use_modfied_newton)
00116 _assemb_K(K);
00117
00118
00119 bool converged=false;
00120 for (int k=0; k<_max_it; ++k)
00121 {
00122
00123 if (resid<=_itol) { converged=true; break;}
00124
00125
00126 if (_use_modfied_newton)
00127 _inv_K_times_X(K, true, Rinternal, _dU);
00128 else
00129 {
00130 _assemb_K(K);
00131 _inv_K_times_X(K, false, Rinternal, _dU);
00132 }
00133
00134
00135 _update_nodes_and_elements_state(_dU, dF_int);
00136
00137
00138 LinAlg::Axpy(-1.0,dF_int, Rinternal);
00139 _dU.SetValues(0.0);
00140
00141
00142 REAL denom = 0.0;
00143 for (int i=0; i<Rinternal.Size(); i++) denom += pow((dF_ext(i)+dF_int(i))/2.0, 2.0);
00144 resid = LinAlg::Norm(Rinternal)/sqrt(denom);
00145 ISD.BE_resid(resid);
00146
00147 }
00148 if (!converged)
00149 throw new Fatal(_("NewtonRaphson::_do_solve did not converge for %d iterations"),_max_it);
00150 }
00151
00152 }
00153
00154
00156
00157
00158
00159 Solver * NewtonRaphsonMaker(Array<String> const & SolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output)
00160 {
00161 return new NewtonRaphson(SolverCtes, ID, data, output);
00162 }
00163
00164
00165 int NewtonRaphsonRegister()
00166 {
00167 SolverFactory["NewtonRaphson"] = NewtonRaphsonMaker;
00168 return 0;
00169 }
00170
00171
00172 int __NewtonRaphson_dummy_int = NewtonRaphsonRegister();
00173
00174 };
00175
00176 #endif // MECHSYS_FEM_NEWTON_H
00177
00178