![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso * 00004 * * 00005 * This program is free software: you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation, either version 3 of the License, or * 00008 * any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00017 ************************************************************************/ 00018 00019 /* MPoints2D - Copyright (C) 2007 Dorival de Moraes Pedroso */ 00020 00021 #ifndef MPM_MPOINTS2D_H 00022 #define MPM_MPOINTS2D_H 00023 00024 // STL 00025 #include <cmath> // for sqrt, pow, etc. 00026 #include <cfloat> // for DBL_EPSILON 00027 00028 // MechSys 00029 #include <mechsys/util/array.h> 00030 #include <mechsys/models/model.h> 00031 #include <mechsys/models/equilibstate.h> 00032 00033 // Local 00034 #include <mechsys/mpm/defs.h> 00035 #include <mechsys/mpm/grid2d.h> 00036 #include <mechsys/mpm/tensors.h> 00037 00039 namespace MPM { 00040 00041 class MPoints2D 00042 { 00043 public: 00044 static const int NDIM = 2; 00045 typedef std::map<int,Model*> Models_t; 00046 00048 MPoints2D (size_t nPcell, Grid2D * G, 00049 ptIsPointInGeom pIsPointInGeom, 00050 ptDensity pDensity, 00051 ptModelData pModelData, 00052 ptIniVelocity pIniVelocity, 00053 ptHasTraction pHasTraction, 00054 ptHasAppDisp pHasAppDisp, 00055 ptAppDisp pAppDisp=NULL); 00056 00057 // Destructor 00058 ~MPoints2D (); 00059 00060 // Methods 00061 size_t nPoints () const { return _p.Size(); } 00062 size_t nPointsOnBry () const { return _ipbry.Size(); } 00063 void SetGrid (Grid2D * G) { _g = G; } 00064 void ReInit () { _initialize_points(); } 00065 00066 // Update method 00067 bool TimeUpdate (bool FwEuler, double Dt, ptB pB, ptLdM pLdM, double & t, double & DsE); 00068 00069 // Set Methods 00070 void SetCPDI (bool UseCPDI=true) { _cpdi = UseCPDI; } 00071 void SetMPM (bool UseMPM=true) { _mpm = UseMPM; } 00072 void SetUSF (bool DoUSF =true) { _usf = DoUSF; } 00073 00074 // Access methods 00075 Array<ATensor2> const & Fs () const { return _F; } 00076 Array<Vector3D> const & Ps () const { return _p; } 00077 Array<Vector3D> const & v () const { return _v; } 00078 Array<Vector3D> const & u () const { return _u; } 00079 Vector3D const & P (size_t i) const { return _p[i]; } 00080 Vector3D const & B (size_t i) const { return _p[_ipbry[i]]; } 00081 double const & m (size_t i) const { return _m[i]; } 00082 Vector3D const & f (size_t i) const { return _f[i]; } 00083 Vector3D const & t (size_t i) const { return _t[i]; } 00084 Vector3D const & fu (size_t i) const { return _fu[i]; } 00085 Vector3D const & u (size_t i) const { return _u[i]; } 00086 Vector3D const & v (size_t i) const { return _v[i]; } 00087 Vec_t const & s (size_t i) const { return _sta[i]->Sig; } 00088 Vec_t const & e (size_t i) const { return _sta[i]->Eps; } 00089 bool HasT (size_t i) const { return _has_t[i]; } 00090 bool HasU (size_t i) const { return _has_fu[i]; } 00091 int Clr (size_t i) const { return _clr[i]; } 00092 Array<EquilibState*> const & Sta () const { return _sta; } 00093 00094 // Access corners 00095 mutable Array<Vector3D> C; 00096 void CalcC (size_t p) const 00097 { 00098 if (NRVEC==2) 00099 { 00100 C[0] = _p[p] - _sg[p].R[0] - _sg[p].R[1]; 00101 C[1] = _p[p] + _sg[p].R[0] - _sg[p].R[1]; 00102 C[2] = _p[p] + _sg[p].R[0] + _sg[p].R[1]; 00103 C[3] = _p[p] - _sg[p].R[0] + _sg[p].R[1]; 00104 } 00105 else for (size_t i=0; i<4; ++i) C[i] = _p[p] + _sg[p].R[i]; 00106 } 00107 00108 // Limit methods 00109 void MinMaxS (int iComp, double & MinS, double & MaxS) const; 00110 void MinMaxE (int iComp, double & MinE, double & MaxE) const; 00111 void MinMaxCamp (double & Minp, double & Maxp) const; 00112 void MinMaxCamq (double & Minq, double & Maxq) const; 00113 void MinMaxVelN (double & MinNv, double & MaxNv) const; 00114 00115 // Constants 00116 double MINMASS; 00117 00118 // Data 00119 Models_t Mdls; 00120 00121 private: 00122 // Data 00123 bool _cpdi; 00124 bool _mpm; 00125 bool _usf; 00126 size_t _npcell; 00127 Grid2D * _g; 00128 ptIsPointInGeom _is_point_in_geom; 00129 ptDensity _density; 00130 ptModelData _model_data; 00131 ptIniVelocity _ini_velocity; 00132 ptHasTraction _has_traction; 00133 ptHasAppDisp _has_app_disp; 00134 ptAppDisp _app_disp; 00135 00136 // Geometry 00137 Array<Vector3D> _p; 00138 Array<int> _ipbry; 00139 00140 // Data (size == _np) 00141 Array<Vector3D> _p0; 00142 Array<double> _V0; 00143 Array<double> _V; 00144 Array<double> _m; 00145 Array<Vector3D> _f; 00146 Array<Vector3D> _u; 00147 Array<Vector3D> _v; 00148 Array<ATensor2> _F; 00149 Array<EquilibState*> _sta; 00150 Array<ShapeAndGrads2D> _sg; 00151 Array<Model*> _mdl; 00152 Array<int> _clr; 00153 00154 // Boundary conditions (size == np) 00155 Array<bool> _has_t; 00156 Array<bool> _has_fu; 00157 Array<Vector3D> _t; 00158 Array<Vector3D> _fu; 00159 00160 // Scratch pad 00161 mutable STensor2 _sp0; 00162 mutable Vector3D _vn; 00163 mutable ATensor2 _Lp; 00164 mutable ATensor2 _DF; 00165 00166 // Update functions 00167 void _initialize_points (); 00168 void _calc_veloc_grad (size_t p); 00169 void _stress_update (double Dt, double & DsE); 00170 bool _explicit_update (double Dt, Vector3D const & B, double LdM, Array<Vector3D> * DqDt, double & DsE); 00171 00172 // Interpolation functions 00173 double _mpm_snp (int n, int p, int icomp) const; 00174 double _mpm_gnp (int n, int p, int icomp) const; 00175 double _gmpm_snp (int n, int p, int icomp) const; 00176 double _gmpm_gnp (int n, int p, int icomp) const; 00177 void _Nnp (int n, int p, double & N) const; 00178 double _S (int n, Vector3D const & X) const; 00179 void _Snp (int n, int p, double & S) const; 00180 void _Gnp (int n, int p, Vector3D & G) const; 00181 }; 00182 00183 00185 00186 00187 /* public */ 00188 00189 inline MPoints2D::MPoints2D(size_t nPcell, Grid2D * G, ptIsPointInGeom pIsPointInGeom, ptDensity pDensity, ptModelData pModelData, ptIniVelocity pIniVelocity, ptHasTraction pHasTraction, ptHasAppDisp pHasAppDisp, ptAppDisp pAppDisp) 00190 : MINMASS (DBL_EPSILON*10.0), 00191 _cpdi (true), 00192 _mpm (false), 00193 _usf (true), 00194 _npcell (nPcell), 00195 _g (G), 00196 _is_point_in_geom (pIsPointInGeom), 00197 _density (pDensity), 00198 _model_data (pModelData), 00199 _ini_velocity (pIniVelocity), 00200 _has_traction (pHasTraction), 00201 _has_app_disp (pHasAppDisp), 00202 _app_disp (pAppDisp) 00203 { 00204 C.Resize(4); 00205 _initialize_points(); 00206 } 00207 00208 inline MPoints2D::~MPoints2D () 00209 { 00210 for (size_t i=0; i<_sta.Size(); ++i) if (_sta[i]!=NULL) delete _sta[i]; 00211 for (Models_t::iterator it=Mdls.begin(); it!=Mdls.end(); ++it) delete it->second; 00212 } 00213 00214 inline bool MPoints2D::TimeUpdate (bool FwEuler, double Dt, ptB pB, ptLdM pM, double & t, double & DsE) 00215 { 00216 // Check if access to grid was set 00217 if (_g==NULL) return false; // failed 00218 00219 // Variables 00220 double dsek; 00221 Vector3D bk; 00222 double Mk; 00223 00224 // Update 00225 if (FwEuler) 00226 { 00227 double nincs = 1; // Number of sub-increments 00228 double dtk = Dt/nincs; // Sub-divide time-step 00229 for (int k=0; k<nincs; ++k) 00230 { 00231 // Increments 00232 (*pB) (t+dtk, bk); // Body forces 00233 (*pM) (t+dtk, Mk); // Multiplier for external forces 00234 00235 // Update points 00236 bool ok = _explicit_update (dtk, bk, Mk, &_g->dqdt(), dsek); 00237 00238 // Update time and strain energy 00239 t += dtk; 00240 DsE += dsek; 00241 00242 // Check 00243 if (!ok) return false; 00244 } 00245 return true; 00246 } 00247 else return false; // not implemented yet 00248 } 00249 00250 inline void MPoints2D::MinMaxS (int iComp, double & MinS, double & MaxS) const 00251 { 00252 if (_sta.Size()<1) { MinS=0; MaxS=0; return; } 00253 MinS = _sta[0]->Sig(iComp); 00254 MaxS = _sta[0]->Sig(iComp); 00255 for (size_t i=1; i<_p.Size(); ++i) 00256 { 00257 if (_sta[i]->Sig(iComp)<MinS) MinS = _sta[i]->Sig(iComp); 00258 if (_sta[i]->Sig(iComp)>MaxS) MaxS = _sta[i]->Sig(iComp); 00259 } 00260 } 00261 00262 inline void MPoints2D::MinMaxE (int iComp, double & MinE, double & MaxE) const 00263 { 00264 if (_sta.Size()<1) { MinE=0; MaxE=0; return; } 00265 MinE = _sta[0]->Eps(iComp); 00266 MaxE = _sta[0]->Eps(iComp); 00267 for (size_t i=1; i<_p.Size(); ++i) 00268 { 00269 if (_sta[i]->Eps(iComp)<MinE) MinE = _sta[i]->Eps(iComp); 00270 if (_sta[i]->Eps(iComp)>MaxE) MaxE = _sta[i]->Eps(iComp); 00271 } 00272 } 00273 00274 inline void MPoints2D::MinMaxCamp (double & Minp, double & Maxp) const 00275 { 00276 if (_sta.Size()<1) { Minp=0; Maxp=0; return; } 00277 Minp = Calc_pcam(_sta[0]->Sig); 00278 Maxp = Minp; 00279 for (size_t i=1; i<_p.Size(); ++i) 00280 { 00281 double p = Calc_pcam(_sta[i]->Sig); 00282 if (p<Minp) Minp = p; 00283 if (p>Maxp) Maxp = p; 00284 } 00285 } 00286 00287 inline void MPoints2D::MinMaxCamq (double & Minq, double & Maxq) const 00288 { 00289 if (_sta.Size()<1) { Minq=0; Maxq=0; return; } 00290 Minq = Calc_qcam(_sta[0]->Sig); 00291 Maxq = Minq; 00292 for (size_t i=1; i<_p.Size(); ++i) 00293 { 00294 double q = Calc_qcam(_sta[i]->Sig); 00295 if (q<Minq) Minq = q; 00296 if (q>Maxq) Maxq = q; 00297 } 00298 } 00299 00300 inline void MPoints2D::MinMaxVelN (double & MinNv, double & MaxNv) const 00301 { 00302 if (_v.Size()<1) { MinNv=0; MaxNv=0; return; } 00303 MinNv = MPM::NormV(_v[0]); 00304 MaxNv = MinNv; 00305 for (size_t i=1; i<_v.Size(); ++i) 00306 { 00307 double nv = MPM::NormV(_v[i]); 00308 if (nv<MinNv) MinNv = nv; 00309 if (nv>MaxNv) MaxNv = nv; 00310 } 00311 } 00312 00313 00314 /* update functions */ 00315 00316 inline void MPoints2D::_initialize_points () 00317 { 00318 // Check input 00319 if (!(_npcell==1 || _npcell==4 || _npcell==9 || _npcell==16)) throw new Fatal("MPoints2D::_initialize_points: Number of points per cell (NPcell=%d) must be 1, 4, 9 or 16.",_npcell); 00320 00321 /* x sqrt(x) 2*sqrt(x) log2(2*sqrt(x)) 1/sqrt(x) 1-1/sqrt(x) 00322 * 1 1 2 1 1 0.0 00323 * 4 2 4 2 0.5 0.5 00324 * 16 4 8 3 0.25 0.75 00325 * 00326 * 1 4 9 16 00327 * 1_ _______ 1_ _______ 1_ ________ 1_ _______ 00328 * | | 0.5_| | _ |_3L/4 | | | | 0.75>|_|_|_|_|<7L/8 00329 * 0_| _ |_L/2 0_|___|___| 0_|--|--|--|_L/2 0_|_|_|_|_| 00330 * | | | | _ |_L/4 |--|--|--| |_|_|_|_| 00331 * -1_|_______| -1_|___|___| 1_|__|__|__| -1_|_|_|_|_|<L/8 */ 00332 00333 // Gauss points 00334 double sqnpc = sqrt(static_cast<double>(_npcell)); 00335 double gv = 1.0-1.0/sqnpc; // Gauss point value 00336 double ksi[ 4] = {-1,1,1,-1}; // Natural coordinates 00337 double eta[ 4] = {-1,-1,1,1}; // Natural coordinates 00338 double kgp[16] = {-gv, gv,gv,-gv, -gv,-gv, -gv/3.,-gv/3.,-gv/3.,-gv/3., gv/3.,gv/3.,gv/3.,gv/3., gv,gv }; // ksi Gauss point 00339 double egp[16] = {-gv,-gv,gv, gv, -gv/3.,gv/3., -gv,-gv/3.,gv/3.,gv, -gv,-gv/3.,gv/3.,gv, -gv/3.,gv/3. }; // eta Gauss point 00340 if (_npcell==9) 00341 { 00342 gv = (1.0-(-1.0))/3.0; // one third of cell length in nat cooords 00343 kgp[0]=-gv; kgp[1]=0.0; kgp[2]=gv; kgp[3]=-gv; kgp[4]=0.0; kgp[5]=gv; kgp[6]=-gv; kgp[7]=0.0; kgp[8]=gv; 00344 egp[0]=-gv; egp[1]=-gv; egp[2]=-gv; egp[3]=0.0; egp[4]=0.0; egp[5]=0.0; egp[6]=gv; egp[7]=gv; egp[8]=gv; 00345 } 00346 00347 // Loop over cells 00348 _p .Resize(0); 00349 _clr .Resize(0); 00350 _t .Resize(0); 00351 _has_t .Resize(0); 00352 _fu .Resize(0); 00353 _has_fu.Resize(0); 00354 for (size_t c=0; c<_g->nCells(); ++c) 00355 { 00356 // For each cell c, generate _npcell mat points 00357 for (size_t j=0; j<_npcell; ++j) 00358 { 00359 // For each node j, sum the contribution of node c 00360 Vector3D p; p = 0.0; 00361 Array<Vector3D> nodes(4); 00362 for (size_t l=0; l<4; ++l) 00363 { 00364 nodes[l] = _g->X(_g->C(c)(l)); 00365 double shape = (1.0+ksi[l]*kgp[j])*(1.0+eta[l]*egp[j])/4.0; 00366 p(0) += shape*nodes[l](0); 00367 p(1) += shape*nodes[l](1); 00368 } 00369 00370 // Check if the mat point is inside the geometry 00371 int tag = -1; 00372 if ((*_is_point_in_geom)(p, tag)) 00373 { 00374 // Coords 00375 _p .Push (p); // coordinates 00376 _clr.Push (tag); // clr index 00377 00378 // Boundary conds - tractions 00379 _t .Push(0.0); 00380 _has_t.Push((*_has_traction) (_p[_p.Size()-1], nodes, _g->L(), _npcell, _t[_p.Size()-1])); 00381 00382 // Boundary conds - displacements 00383 _fu .Push(0.0); 00384 _has_fu.Push((*_has_app_disp) (_p[_p.Size()-1], nodes, _g->L(), _npcell, _fu[_p.Size()-1])); 00385 } 00386 } 00387 } 00388 00389 // Delete previous EquilibState 00390 for (size_t i=0; i<_sta.Size(); ++i) if (_sta[i]!=NULL) delete _sta[i]; 00391 00392 // Delete previous Models 00393 for (Models_t::iterator it=Mdls.begin(); it!=Mdls.end(); ++it) delete it->second; 00394 Mdls.clear(); 00395 00396 // Data for models 00397 String name, scheme; 00398 SDPair prms, inis; 00399 00400 // Initialize arrays 00401 _p0 .Resize(_p.Size()); 00402 _V0 .Resize(_p.Size()); 00403 _V .Resize(_p.Size()); 00404 _m .Resize(_p.Size()); 00405 _f .Resize(_p.Size()); 00406 _u .Resize(_p.Size()); 00407 _v .Resize(_p.Size()); 00408 _F .Resize(_p.Size()); 00409 _sta.Resize(_p.Size()); 00410 _sg .Resize(_p.Size()); 00411 _mdl.Resize(_p.Size()); 00412 double mt = 0.0; // total mass 00413 for (size_t p=0; p<_p.Size(); ++p) 00414 { 00415 double lx = 0.5*_g->L(0)/sqnpc; // half-length 00416 double ly = 0.5*_g->L(1)/sqnpc; // half-length 00417 _p0 [p] = _p[p]; 00418 _V0 [p] = 4.0*lx*ly; 00419 _V [p] = _V0[p]; 00420 _m [p] = _V[p] * (*_density) (_p[p]); 00421 _f [p] = 0.0, 0.0, 0.0; 00422 _u [p] = 0.0, 0.0, 0.0; 00423 _v [p] = 0.0, 0.0, 0.0; 00424 (*_ini_velocity) (_p[p], _v[p]); 00425 _F [p] = 1.0,1.0,1.0, 0.0,0.0,0.0, 0.0,0.0,0.0; 00426 if (NRVEC==2) 00427 { 00428 _sg[p].R0[0] = lx, 0., 0.; 00429 _sg[p].R0[1] = 0., ly, 0.; 00430 } 00431 else 00432 { 00433 _sg[p].R0[0] = -lx, -ly, 0.0; 00434 _sg[p].R0[1] = lx, -ly, 0.0; 00435 _sg[p].R0[2] = lx, ly, 0.0; 00436 _sg[p].R0[3] = -lx, ly, 0.0; 00437 } 00438 for (size_t k=0; k<NRVEC; ++k) _sg[p].R[k] = _sg[p].R0[k]; 00439 mt += _m[p]; 00440 00441 // allocate models and set initial state 00442 int tag = -1; 00443 (*_model_data) (_p[p], name, tag, NDIM, prms, inis, scheme); 00444 Models_t::iterator it = Mdls.find(tag); 00445 if (it==Mdls.end()) 00446 { 00447 Mdls[tag] = AllocModel (name, NDIM, prms, NULL); 00448 it = Mdls.find(tag); 00449 if (scheme!="") it->second->SUp.SetScheme (scheme); 00450 } 00451 _mdl[p] = it->second; 00452 _sta[p] = new EquilibState (NDIM); 00453 _mdl[p]->InitIvs (inis, _sta[p]); 00454 } 00455 std::cout << "MPoints2D::_initialize_points: total mass = " << mt << std::endl; 00456 } 00457 00458 inline void MPoints2D::_calc_veloc_grad (size_t p) 00459 { 00460 _Lp = 0.,0.,0., 0.,0.,0., 0.,0.,0.; 00461 for (n2i_it it=_sg[p].n2i.begin(); it!=_sg[p].n2i.end(); ++it) 00462 { 00463 int n = it->first; // grid node number 00464 int i = it->second; // index in N,S,G 00465 _vn = 0., 0., 0.; // node velocity 00466 if (_g->m(n)>MINMASS) _vn = _g->q(n)/_g->m(n); // node velocity 00467 if (_g->IsFixed(n,0)) _vn(0) = 0.0; // Fix nodes: x-direction 00468 if (_g->IsFixed(n,1)) _vn(1) = 0.0; // Fix nodes: y-direction 00469 DyadUp (_vn, _sg[p].G[i], _Lp); // Lp += vp dyad G 00470 } 00471 } 00472 00473 inline void MPoints2D::_stress_update (double Dt, double & DsE) 00474 { 00475 DsE = 0.0; 00476 for (size_t p=0; p<_p.Size(); ++p) 00477 { 00478 // Compute velocity gradient: _Lp 00479 _calc_veloc_grad (p); 00480 00481 // Update F and stress state 00482 DsE += _mdl[p]->SUp.Update (Dt, _Lp, _F[p], _sta[p]) * _V[p]; 00483 00484 // Update volume 00485 _V[p] = Det(_F[p]) * _V0[p]; 00486 00487 // Update centre-to-corner vectors 00488 for (size_t i=0; i<NRVEC; ++i) Dot (_F[p], _sg[p].R0[i], _sg[p].R[i]); 00489 } 00490 } 00491 00492 inline bool MPoints2D::_explicit_update (double Dt, Vector3D const & B, double LdM, Array<Vector3D> * DqDt, double & DsE) 00493 { 00494 // 1) Discard previous grid 00495 _g->ClearState(); 00496 00497 // 2) Compute interpolation values 00498 if (_cpdi) 00499 { 00500 for (size_t p=0; p<_p.Size(); ++p) 00501 { 00502 CalcC(p); // calculate corners 00503 _sg[p].n2i.clear(); 00504 int k = 0.0; 00505 for (size_t i=0; i<4; ++i) // for each corner i 00506 { 00507 int l = static_cast<int>((C[i](0)-_g->xMin())/_g->L(0)); // left-grid-index 00508 int b = static_cast<int>((C[i](1)-_g->yMin())/_g->L(1)); // bottom-grid-index 00509 int r = l+1; // right-grid-index 00510 int t = b+1; // top-grid-index 00511 int nlb = l+b*_g->nCol(); 00512 int nrb = r+b*_g->nCol(); 00513 int nlt = l+t*_g->nCol(); 00514 int nrt = r+t*_g->nCol(); 00515 _sg[p].n2i[nlb]=k; _Nnp(nlb,p,_sg[p].N[k]); _Snp(nlb,p,_sg[p].S[k]); _Gnp(nlb,p,_sg[p].G[k]); k++; 00516 _sg[p].n2i[nrb]=k; _Nnp(nrb,p,_sg[p].N[k]); _Snp(nrb,p,_sg[p].S[k]); _Gnp(nrb,p,_sg[p].G[k]); k++; 00517 _sg[p].n2i[nlt]=k; _Nnp(nlt,p,_sg[p].N[k]); _Snp(nlt,p,_sg[p].S[k]); _Gnp(nlt,p,_sg[p].G[k]); k++; 00518 _sg[p].n2i[nrt]=k; _Nnp(nrt,p,_sg[p].N[k]); _Snp(nrt,p,_sg[p].S[k]); _Gnp(nrt,p,_sg[p].G[k]); k++; 00519 } 00520 } 00521 } 00522 else 00523 { 00524 int nctb = (_mpm ? 2 : 4); // number of contributions 00525 for (size_t p=0; p<_p.Size(); ++p) 00526 { 00527 _sg[p].n2i.clear(); 00528 int k = 0; 00529 int lbn = _g->LBN(_p[p], _mpm); // Compute reference node 00530 for (int i=0; i<nctb; ++i) 00531 for (int j=0; j<nctb; ++j) 00532 { 00533 int n = lbn+i+j*_g->nCol(); // grid node number 00534 _sg[p].n2i[n] = k; // set map: node => index in S,N,G 00535 _Nnp (n,p, _sg[p].N[k]); // calc interpolation function (C0) 00536 _Snp (n,p, _sg[p].S[k]); // calc interpolation function (C1) 00537 _Gnp (n,p, _sg[p].G[k]); // calc deriv. interp. function 00538 k++; 00539 } 00540 } 00541 } 00542 00543 // 3) Initialize grid state (mass and momentum) 00544 for (size_t p=0; p<_p.Size(); ++p) 00545 { 00546 for (n2i_it it=_sg[p].n2i.begin(); it!=_sg[p].n2i.end(); ++it) 00547 { 00548 int n = it->first; // grid node number 00549 int i = it->second; // index in N,S,G 00550 _g->m(n) += _sg[p].S[i]*_m[p]; // node mass 00551 _g->q(n) += _sg[p].S[i]*_m[p]*_v[p]; // node momentum 00552 } 00553 } 00554 00555 // 4) (USF) Update strain and stress 00556 if (_usf) _stress_update (Dt, DsE); 00557 00558 // 5) Compute internal and external forces 00559 for (size_t p=0; p<_p.Size(); ++p) 00560 { 00561 for (n2i_it it=_sg[p].n2i.begin(); it!=_sg[p].n2i.end(); ++it) 00562 { 00563 int n = it->first; // grid node number 00564 int i = it->second; // index in N,S,G 00565 ScDotUp (_V[p],_sta[p]->Sig,_sg[p].G[i], _g->fi(n)); // fi += V_p*Sig.G 00566 _g->fe(n) += (_sg[p].S[i]*_m[p])*B; // fe += mp*b*S 00567 if (_has_t[p]) _g->fe(n) += LdM*_sg[p].N[i]*_t[p]; // fe += int(S*t)dA 00568 } 00569 } 00570 00571 // 6) Compute rate of momentum and momentum 00572 for (size_t n=0; n<_g->nNodes(); ++n) 00573 { 00574 (*DqDt)[n] = _g->fe(n) - _g->fi(n); // Nodes rate of momentum 00575 _g->q(n) += (*DqDt)[n]*Dt; // Update nodes momentum 00576 if (_g->IsFixed(n,0)) { (*DqDt)[n](0)=0.0; _g->q(n)(0)=0.0; } // Fix nodes: x-direction 00577 if (_g->IsFixed(n,1)) { (*DqDt)[n](1)=0.0; _g->q(n)(1)=0.0; } // Fix nodes: y-direction 00578 } 00579 00580 // 7) Update material points 00581 for (size_t p=0; p<_p.Size(); ++p) 00582 { 00583 // Update position and velocity 00584 for (n2i_it it=_sg[p].n2i.begin(); it!=_sg[p].n2i.end(); ++it) 00585 { 00586 int n = it->first; // grid node number 00587 int i = it->second; // index in N,S,G 00588 if (_g->m(n)>MINMASS) 00589 { 00590 _p[p] += (Dt*_sg[p].S[i]/_g->m(n))*_g->q(n); // point position 00591 _v[p] += (Dt*_sg[p].S[i]/_g->m(n))*(*DqDt)[n]; // point velocity 00592 _f[p] += _sg[p].S[i]*_g->fe(n); // point force 00593 } 00594 } 00595 00596 // Update displacements 00597 _u[p] = _p[p] - _p0[p]; 00598 00599 // Check 00600 if (!_g->IsInside(_p[p], /*WithBorder*/true)) 00601 { 00602 std::cout << " [1;31mError:[0m Material point moved outside the valid region inside the grid (with borders)" << std::endl; 00603 return false; 00604 } 00605 } 00606 00607 // 8) (USL) Update strain and stress 00608 if (!_usf) _stress_update (Dt, DsE); 00609 00610 // end 00611 return true; 00612 } 00613 00614 00615 /* interpolation functions */ 00616 00617 inline double MPoints2D::_mpm_snp (int n, int p, int icomp) const 00618 { 00619 double d = _p[p](icomp)-_g->x(n)(icomp); 00620 double L = _g->L(icomp); 00621 return (d<=-L ? 0.0 : 00622 (d> L ? 0.0 : 00623 (d<=0.0 ? 1.0+d/L : 00624 1.0-d/L ))); 00625 } 00626 00627 inline double MPoints2D::_mpm_gnp (int n, int p, int icomp) const 00628 { 00629 double d = _p[p](icomp)-_g->x(n)(icomp); 00630 double L = _g->L(icomp); 00631 return (d<=-L ? 0.0 : 00632 (d> L ? 0.0 : 00633 (d<= 0.0 ? 1.0/L : 00634 -1.0/L ))); 00635 } 00636 00637 inline double MPoints2D::_gmpm_snp (int n, int p, int icomp) const 00638 { 00639 double d = _p[p](icomp)-_g->x(n)(icomp); 00640 double L = _g->L(icomp); 00641 double lp = fabs(_sg[p].R0[0](icomp)); 00642 return (d<=-L-lp ? 0.0 : 00643 (d> L+lp ? 0.0 : 00644 (d<=-L+lp ? pow(L+lp+d,2.0)/(4.0*L*lp) : 00645 (d<= -lp ? 1.0+d/L : 00646 (d<= lp ? 1.0-(d*d+lp*lp)/(2.0*L*lp) : 00647 (d<= L-lp ? 1.0-d/L : 00648 pow(L+lp-d,2.0)/(4.0*L*lp) )))))); 00649 } 00650 00651 inline double MPoints2D::_gmpm_gnp (int n, int p, int icomp) const 00652 { 00653 double d = _p[p](icomp)-_g->x(n)(icomp); 00654 double L = _g->L(icomp); 00655 double lp = fabs(_sg[p].R0[0](icomp)); 00656 return (d<=-L-lp ? 0.0 : 00657 (d> L+lp ? 0.0 : 00658 (d<=-L+lp ? (L+d+lp)/(2.0*L*lp) : 00659 (d<= -lp ? 1.0/L : 00660 (d<= lp ? -d/(L*lp) : 00661 (d<= L-lp ? -1.0/L : 00662 (-L+d-lp)/(2.0*L*lp) )))))); 00663 } 00664 00665 inline void MPoints2D::_Nnp (int n, int p, double & N) const 00666 { 00667 N = _mpm_snp(n,p,0)*_mpm_snp(n,p,1); 00668 } 00669 00670 inline double MPoints2D::_S (int n, Vector3D const & X) const 00671 { 00672 double dx = X(0)-_g->x(n)(0); 00673 double dy = X(1)-_g->x(n)(1); 00674 double sx = ( dx<-_g->L(0) || dx>_g->L(0) ? 0.0 : (dx<0.0 ? 1.0+dx/_g->L(0) : 1.0-dx/_g->L(0)) ); 00675 double sy = ( dy<-_g->L(1) || dy>_g->L(1) ? 0.0 : (dy<0.0 ? 1.0+dy/_g->L(1) : 1.0-dy/_g->L(1)) ); 00676 return sx*sy; 00677 } 00678 00679 inline void MPoints2D::_Snp (int n, int p, double & S) const 00680 { 00681 if (_cpdi) 00682 { 00683 // remember to calculate corners first !!! 00684 S = (_S(n,C[0])+_S(n,C[1])+_S(n,C[2])+_S(n,C[3]))/4.0; 00685 } 00686 else 00687 { 00688 if (_mpm) S = _mpm_snp (n,p,0)*_mpm_snp (n,p,1); 00689 else S = _gmpm_snp(n,p,0)*_gmpm_snp(n,p,1); 00690 } 00691 } 00692 00693 inline void MPoints2D::_Gnp (int n, int p, Vector3D & G) const 00694 { 00695 if (_cpdi) 00696 { 00697 // remember to calculate corners first !!! 00698 double a = _S(n,C[0]) - _S(n,C[2]); 00699 double b = _S(n,C[1]) - _S(n,C[3]); 00700 G = (a*(_sg[p].R[0](1)-_sg[p].R[1](1))+b*(_sg[p].R[0](1)+_sg[p].R[1](1)))/_V[p], 00701 (a*(_sg[p].R[1](0)-_sg[p].R[0](0))-b*(_sg[p].R[1](0)+_sg[p].R[0](0)))/_V[p], 0.0; 00702 } 00703 else 00704 { 00705 if (_mpm) G = _mpm_snp (n,p,1)*_mpm_gnp (n,p,0), _mpm_snp (n,p,0)*_mpm_gnp (n,p,1), 0.0; 00706 else G = _gmpm_snp(n,p,1)*_gmpm_gnp(n,p,0), _gmpm_snp(n,p,0)*_gmpm_gnp(n,p,1), 0.0; 00707 } 00708 } 00709 00710 }; // namespace MPM 00711 00712 #endif // MPM_MPOINTS2D_H