00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FEM_COUPLED_H
00023 #define FEM_COUPLED_H
00024
00025 #ifndef REAL
00026 #define REAL double
00027 #endif
00028
00029 #include <sstream>
00030
00031 #include "models/coupled/coupledmodel.h"
00032 #include "fem/ele/element.h"
00033 #include "fem/ele/equilibelem.h"
00034 #include "fem/ele/flowelem.h"
00035 #include "linalg/laexpr.h"
00036 #include "tensors/tensors.h"
00037 #include "tensors/functions.h"
00038 #include "util/numstreams.h"
00039
00040 using Tensors::Stress_p_q_S_sin3th;
00041 using Tensors::Strain_Ev_Ed;
00042 namespace FEM
00043 {
00044
00045
00046 class Coupled: public virtual EquilibElem, public virtual FlowElem
00047 {
00048 static const int NDIM=3;
00049 static const int NSTRESSCOMPS=6;
00050 public:
00051
00052 Coupled();
00053
00054 virtual ~Coupled() {};
00055
00056 void Deactivate();
00057 void ReAllocateModel(String const & ModelName, Array<REAL> const & ModelPrms, Array<Array<REAL> > const & AIniData);
00058 bool IsEssential(String const & DOFName) const;
00059 void CalcFaceNodalValues(String const & FaceDOFName ,
00060 REAL const FaceDOFValue ,
00061 Array<FEM::Node*> const & APtrFaceNodes,
00062 String & NodalDOFName ,
00063 LinAlg::Vector<REAL> & NodalValues
00064 ) const;
00065 void Stiffness (LinAlg::Matrix<REAL> & Ke, Array<size_t> & EqMap) const;
00066 void CouplingMatrix1 (LinAlg::Matrix<REAL> & L1, Array<size_t> & EqMapEquilib, Array<size_t> & EqMapFlow) const;
00067 void CouplingMatrix2 (LinAlg::Matrix<REAL> & L2, Array<size_t> & EqMapEquilib, Array<size_t> & EqMapFlow) const;
00068 void MassMatrix (LinAlg::Matrix<REAL> & M, Array<size_t> & EqMap) const;
00069 void Permeability (LinAlg::Matrix<REAL> & H, Array<size_t> & EqMap) const;
00070
00071
00072 void NodalDOFs(int iNode, Array<FEM::Node::DOFVarsStruct*> & DOFs) const;
00073 void BackupState();
00074 void UpdateState(REAL TimeInc);
00075 void RestoreState();
00076 void SetProperties(Array<REAL> const & EleProps) { _unit_weight=EleProps[0]; }
00077 String OutCenter(bool PrintCaptionOnly) const;
00078 void OutNodes(LinAlg::Matrix<REAL> & Values, Array<String> & Labels) const;
00079
00080 size_t nOrder0Matrices() const { return 1; };
00081 size_t nOrder1Matrices() const { return 4; };
00082 void RHSVector(size_t index, LinAlg::Vector<REAL> & V, Array<size_t> & Map) const;
00083 void Order0Matrix(size_t index, LinAlg::Matrix<REAL> & V, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const;
00084 void Order1Matrix(size_t index, LinAlg::Matrix<REAL> & M, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const;
00085
00086 REAL OutScalar1() const;
00087 REAL OutScalar2() const;
00088 void OutTensor1(String & Str) const;
00089 void OutTensor2(String & Str) const;
00090 private:
00091
00092 Array<CoupledModel*> _a_model;
00093 REAL _unit_weight;
00094
00095 mutable Array<Tensors::Tensor2> _a_d_ep;
00096
00097 void _set_node_vars(int iNode);
00098 void _calc_Nu_matrix(LinAlg::Vector<REAL> & Shape, LinAlg::Matrix<REAL> & Nu) const;
00099 void _calc_initial_internal_forces();
00100 void _calc_initial_internal_pore_pressures();
00101 };
00102
00103
00104
00105
00106 Coupled::Coupled()
00107 {
00108 _a_d_ep.resize(_n_int_pts);
00109 }
00110
00111 inline void Coupled::_set_node_vars(int iNode)
00112 {
00113
00114 _connects[iNode]->AddDOF(DUX,DFX);
00115 _connects[iNode]->AddDOF(DUY,DFY);
00116 _connects[iNode]->AddDOF(DUZ,DFZ);
00117 _connects[iNode]->AddDOF(DWP,DWD);
00118 }
00119
00120 void Coupled::Deactivate()
00121 {
00122 if (_is_active==false) return;
00123 _is_active = false;
00124
00125
00126 for (int i_node=0; i_node<_n_nodes; i_node++)
00127 {
00128 _connects[i_node]->Refs()--;
00129 }
00130
00131
00132 bool in_boundary = false;
00133 for (int i_node=0; i_node<_n_nodes; i_node++)
00134 if (_connects[i_node]->Refs()>0)
00135 {
00136 in_boundary=true;
00137 break;
00138 }
00139
00140
00141 if (in_boundary)
00142 {
00143 LinAlg::Vector<REAL> F(NDIM*_n_nodes);
00144 F.SetValues(0.0);
00145
00146
00147 LinAlg::Matrix<REAL> derivs;
00148 LinAlg::Matrix<REAL> J;
00149 LinAlg::Matrix<REAL> B;
00150 LinAlg::Vector<REAL> Sig;
00151
00152 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00153 {
00154
00155 REAL r = _a_int_pts[i_ip].r;
00156 REAL s = _a_int_pts[i_ip].s;
00157 REAL t = _a_int_pts[i_ip].t;
00158 REAL w = _a_int_pts[i_ip].w;
00159
00160 Derivs(r,s,t, derivs);
00161 Jacobian(derivs, J);
00162 B_Matrix(derivs,J, B);
00163
00164
00165 Tensors::Tensor2 const & tsrSig = _a_model[i_ip]->Sig();
00166 Copy(tsrSig, Sig);
00167
00168
00169 F += trn(B)*Sig*det(J)*w;
00170 }
00171
00172
00173 for (int i_node=0; i_node<_n_nodes; i_node++)
00174 if (_connects[i_node]->Refs()>0)
00175 {
00176 _connects[i_node]->DOFVar(DFX).NaturalBry += F(i_node*NDIM );
00177 _connects[i_node]->DOFVar(DFY).NaturalBry += F(i_node*NDIM+1);
00178 _connects[i_node]->DOFVar(DFZ).NaturalBry += F(i_node*NDIM+2);
00179
00180 _connects[i_node]->DOFVar(DWP).IsEssenPresc = true;
00181
00182 _connects[i_node]->DOFVar(DWP).EssentialBry = -_connects[i_node]->DOFVar(DWP).EssentialVal;
00183 _connects[i_node]->DOFVar(DWP).EssenPrescPersist = true;
00184 }
00185 else
00186 {
00187 _connects[i_node]->DOFVars().resize(0);
00188 }
00189
00190
00191 }
00192 }
00193
00194 void Coupled::ReAllocateModel(String const & ModelName, Array<REAL> const & ModelPrms, Array<Array<REAL> > const & AIniData)
00195 {
00196
00197 if (!(AIniData.size()==1 || static_cast<int>(AIniData.size())==_n_int_pts))
00198 throw new Fatal(_("Coupled::ReAllocateModel: Array of array of initial data must have size==1 or size== %d \n"), _n_int_pts);
00199
00200
00201 if (_a_model.size()==0)
00202 {
00203
00204 _a_model.resize(_n_int_pts);
00205
00206
00207 for (int i=0; i<_n_int_pts; ++i)
00208 {
00209
00210 if (AIniData.size()==1) _a_model[i] = AllocCoupledModel(ModelName, ModelPrms, AIniData[0]);
00211 else _a_model[i] = AllocCoupledModel(ModelName, ModelPrms, AIniData[i]);
00212 }
00213
00214
00215 _calc_initial_internal_forces();
00216
00217 _calc_initial_internal_pore_pressures();
00218 }
00219 else
00220 {
00221
00222 for (int i=0; i<_n_int_pts; ++i)
00223 {
00224 if (_a_model[i]->Name()!=ModelName)
00225 {
00226
00227 delete _a_model[i];
00228
00229
00230 if (AIniData.size()==1) _a_model[i] = AllocCoupledModel(ModelName, ModelPrms, AIniData[0]);
00231 else _a_model[i] = AllocCoupledModel(ModelName, ModelPrms, AIniData[i]);
00232 }
00233
00234 }
00235 }
00236 }
00237
00238 inline bool Coupled::IsEssential(String const & DOFName) const
00239 {
00240 if (DOFName==DUX || DOFName==DUY || DOFName==DUZ || DOFName==DWP) return true;
00241 else return false;
00242 }
00243
00244 inline void Coupled::CalcFaceNodalValues(String const & FaceDOFName ,
00245 REAL const FaceDOFValue ,
00246 Array<FEM::Node*> const & APtrFaceNodes,
00247 String & NodalDOFName ,
00248 LinAlg::Vector<REAL> & NodalValues ) const
00249 {
00250 if (FaceDOFName==DTX || FaceDOFName==DTY || FaceDOFName==DTZ || FaceDOFName==DFWD)
00251 {
00252 if (FaceDOFName==DTX) NodalDOFName=DFX;
00253 if (FaceDOFName==DTY) NodalDOFName=DFY;
00254 if (FaceDOFName==DTZ) NodalDOFName=DFZ;
00255 if (FaceDOFName==DFWD) NodalDOFName=DWD;
00256 _distrib_val_to_face_nodal_vals(APtrFaceNodes, FaceDOFValue, NodalValues);
00257 }
00258 else
00259 {
00260 std::ostringstream oss; oss << "Face nodes coordinates:\n";
00261 for (size_t i_node=0; i_node<APtrFaceNodes.size(); ++i_node)
00262 oss << "X=" << APtrFaceNodes[i_node]->X() << ", Y=" << APtrFaceNodes[i_node]->Y() << ", Z=" << APtrFaceNodes[i_node]->Z() << std::endl;
00263 throw new Fatal(_("Coupled::CalcFaceNodalValues: This method must only be called for FaceDOFName< %s > equal to tx, ty, tz or tq\n %s \n"), FaceDOFName.c_str(), oss.str().c_str());
00264 }
00265 }
00266
00267 inline void Coupled::Stiffness(LinAlg::Matrix<REAL> & Ke, Array<size_t> & EqMap) const
00268 {
00269
00270 Ke.Resize(NDIM*_n_nodes, NDIM*_n_nodes);
00271 Ke.SetValues(0.0);
00272
00273
00274 LinAlg::Matrix<REAL> derivs;
00275 LinAlg::Matrix<REAL> J;
00276 LinAlg::Matrix<REAL> B;
00277 Tensors::Tensor4 tsrD;
00278 LinAlg::Matrix<REAL> D;
00279
00280
00281 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00282 {
00283
00284 REAL r = _a_int_pts[i_ip].r;
00285 REAL s = _a_int_pts[i_ip].s;
00286 REAL t = _a_int_pts[i_ip].t;
00287 REAL w = _a_int_pts[i_ip].w;
00288
00289 Derivs(r,s,t, derivs);
00290 Jacobian(derivs, J);
00291 B_Matrix(derivs,J, B);
00292
00293
00294 _a_model[i_ip]->TgStiffness(tsrD, _a_d_ep[i_ip]); Copy(tsrD, D);
00295
00296
00297 Ke += trn(B)*D*B*det(J)*w;
00298 }
00299
00300
00301 int idx_Ke=0;
00302 EqMap.resize(Ke.Rows());
00303 for (int i_node=0; i_node<_n_nodes; ++i_node)
00304 {
00305
00306 EqMap[idx_Ke++] = _connects[i_node]->DOFVar(DUX).EqID;
00307 EqMap[idx_Ke++] = _connects[i_node]->DOFVar(DUY).EqID;
00308 EqMap[idx_Ke++] = _connects[i_node]->DOFVar(DUZ).EqID;
00309 }
00310 }
00311
00312 inline void Coupled::CouplingMatrix1(LinAlg::Matrix<REAL> & L1, Array<size_t> & EqMapEquilib, Array<size_t> & EqMapFlow) const
00313 {
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 L1.Resize(NDIM*_n_nodes, 1*_n_nodes);
00331 L1.SetValues(0.0);
00332
00333
00334 LinAlg::Matrix<REAL> derivs;
00335 LinAlg::Vector<REAL> shape;
00336 LinAlg::Matrix<REAL> J;
00337 LinAlg::Matrix<REAL> B;
00338 LinAlg::Vector<REAL> d_ep;
00339 LinAlg::Vector<REAL> m(6);
00340 m = 1, 1, 1, 0, 0, 0;
00341
00342
00343 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00344 {
00345
00346 REAL r = _a_int_pts[i_ip].r;
00347 REAL s = _a_int_pts[i_ip].s;
00348 REAL t = _a_int_pts[i_ip].t;
00349 REAL w = _a_int_pts[i_ip].w;
00350
00351 Shape(r,s,t, shape);
00352 Derivs(r,s,t, derivs);
00353 Jacobian(derivs, J);
00354 B_Matrix(derivs,J, B);
00355 REAL det_J = det(J);
00356 REAL phi = _a_model[i_ip]->phi();
00357
00358 Copy(_a_d_ep[i_ip], d_ep);
00359 L1 += trn(B)*m*trn(shape)*phi*det_J*w - trn(B)*d_ep*trn(shape)*det_J*w;
00360 }
00361
00362
00363 int idx_L1=0;
00364 EqMapEquilib.resize(L1.Rows());
00365 for (int i_node=0; i_node<_n_nodes; ++i_node)
00366 {
00367
00368 EqMapEquilib[idx_L1++] = _connects[i_node]->DOFVar(DUX).EqID;
00369 EqMapEquilib[idx_L1++] = _connects[i_node]->DOFVar(DUY).EqID;
00370 EqMapEquilib[idx_L1++] = _connects[i_node]->DOFVar(DUZ).EqID;
00371 }
00372
00373 idx_L1=0;
00374 EqMapFlow.resize(L1.Cols());
00375 for (int i_node=0; i_node<_n_nodes; ++i_node)
00376 {
00377
00378 EqMapFlow[idx_L1++] = _connects[i_node]->DOFVar(DWP).EqID;
00379 }
00380
00381 }
00382
00383 inline void Coupled::CouplingMatrix2(LinAlg::Matrix<REAL> & L2, Array<size_t> & EqMapFlow, Array<size_t> & EqMapEquilib) const
00384 {
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 L2.Resize(1*_n_nodes, NDIM*_n_nodes);
00402 L2.SetValues(0.0);
00403
00404
00405 LinAlg::Matrix<REAL> derivs;
00406 LinAlg::Vector<REAL> shape;
00407 LinAlg::Matrix<REAL> J;
00408 LinAlg::Matrix<REAL> B;
00409 LinAlg::Vector<REAL> m(6);
00410 m = 1, 1, 1, 0, 0, 0;
00411
00412
00413 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00414 {
00415
00416 REAL r = _a_int_pts[i_ip].r;
00417 REAL s = _a_int_pts[i_ip].s;
00418 REAL t = _a_int_pts[i_ip].t;
00419 REAL w = _a_int_pts[i_ip].w;
00420
00421 Shape(r,s,t, shape);
00422 Derivs(r,s,t, derivs);
00423 Jacobian(derivs, J);
00424 B_Matrix(derivs,J, B);
00425 REAL Sr = _a_model[i_ip]->Sr();
00426
00427 L2 += shape*Sr*trn(m)*B*det(J)*w;
00428 }
00429
00430
00431
00432 int idx_L2=0;
00433 EqMapFlow.resize(L2.Rows());
00434 for (int i_node=0; i_node<_n_nodes; ++i_node)
00435 {
00436
00437 EqMapFlow[idx_L2++] = _connects[i_node]->DOFVar(DWP).EqID;
00438 }
00439
00440 idx_L2=0;
00441 EqMapEquilib.resize(L2.Cols());
00442 for (int i_node=0; i_node<_n_nodes; ++i_node)
00443 {
00444
00445 EqMapEquilib[idx_L2++] = _connects[i_node]->DOFVar(DUX).EqID;
00446 EqMapEquilib[idx_L2++] = _connects[i_node]->DOFVar(DUY).EqID;
00447 EqMapEquilib[idx_L2++] = _connects[i_node]->DOFVar(DUZ).EqID;
00448 }
00449 }
00450
00451 inline void Coupled::MassMatrix(LinAlg::Matrix<REAL> & M, Array<size_t> & EqMap) const
00452 {
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 M.Resize(1*_n_nodes,1*_n_nodes);
00466 M.SetValues(0.0);
00467
00468
00469 LinAlg::Matrix<REAL> derivs;
00470 LinAlg::Vector<REAL> shape;
00471 LinAlg::Matrix<REAL> J;
00472 LinAlg::Vector<REAL> m(6);
00473 m = 1, 1, 1, 0, 0, 0;
00474
00475
00476 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00477 {
00478
00479 REAL r = _a_int_pts[i_ip].r;
00480 REAL s = _a_int_pts[i_ip].s;
00481 REAL t = _a_int_pts[i_ip].t;
00482 REAL w = _a_int_pts[i_ip].w;
00483
00484 Shape(r,s,t, shape);
00485 Derivs(r,s,t, derivs);
00486 Jacobian(derivs, J);
00487 REAL n_times_dSr_dPp = _a_model[i_ip]->n_times_dSr_dPp();
00488
00489
00490 M += -shape*trn(shape)*n_times_dSr_dPp*det(J)*w;
00491 }
00492
00493
00494 int idx_S=0;
00495 EqMap.resize(M.Rows());
00496 for (int i_node=0; i_node<_n_nodes; ++i_node)
00497 {
00498
00499 EqMap[idx_S++] = _connects[i_node]->DOFVar(DWP).EqID;
00500 }
00501
00502 }
00503
00504 inline void Coupled::Permeability(LinAlg::Matrix<REAL> & He, Array<size_t> & EqMap) const
00505 {
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 He.Resize(_n_nodes, _n_nodes);
00518 He.SetValues(0.0);
00519
00520
00521 LinAlg::Matrix<REAL> derivs;
00522 LinAlg::Vector<REAL> shape;
00523 LinAlg::Matrix<REAL> J;
00524 LinAlg::Matrix<REAL> Bp;
00525 Tensor2 tsrK;
00526 LinAlg::Matrix<REAL> K;
00527
00528
00529 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00530 {
00531
00532 REAL r = _a_int_pts[i_ip].r;
00533 REAL s = _a_int_pts[i_ip].s;
00534 REAL t = _a_int_pts[i_ip].t;
00535 REAL w = _a_int_pts[i_ip].w;
00536 Shape(r,s,t, shape);
00537 Derivs(r,s,t, derivs);
00538 Jacobian(derivs, J);
00539 Bp_Matrix(derivs,J, Bp);
00540
00541
00542 _a_model[i_ip]->TgPermeability(tsrK); Copy(tsrK, K);
00543 REAL gammaW = _a_model[i_ip]->GammaW();
00544
00545
00546 He += -trn(Bp)*K*Bp*det(J)*w/gammaW;
00547 }
00548
00549
00550 int idx_He=0;
00551 EqMap.resize(He.Rows());
00552 for (int i_node=0; i_node<_n_nodes; ++i_node)
00553 {
00554
00555 EqMap[idx_He++] = _connects[i_node]->DOFVar(DWP).EqID;
00556 }
00557 }
00558
00559 inline void Coupled::_calc_Nu_matrix(LinAlg::Vector<REAL> & Shape,
00560 LinAlg::Matrix<REAL> & Nu
00561 ) const
00562 {
00563 Nu.Resize(NDIM, NDIM*_n_nodes);
00564 for(int i=0; i<_n_nodes; i++)
00565 {
00566 Nu(0,0 + 3*i) = Shape(i); Nu(0,1 + 3*i) = 0; Nu(0,2 + 3*i) = 0;
00567 Nu(1,0 + 3*i) = 0; Nu(1,1 + 3*i) = Shape(i); Nu(1,2 + 3*i) = 0;
00568 Nu(2,0 + 3*i) = 0; Nu(2,1 + 3*i) = 0; Nu(2,2 + 3*i) = Shape(i);
00569 }
00570 }
00571
00572 inline void Coupled::NodalDOFs(int iNode, Array<FEM::Node::DOFVarsStruct*> & DOFs) const
00573 {
00574
00575 DOFs.resize(4);
00576
00577
00578 DOFs[0] = &_connects[iNode]->DOFVar(DUX);
00579 DOFs[1] = &_connects[iNode]->DOFVar(DUY);
00580 DOFs[2] = &_connects[iNode]->DOFVar(DUZ);
00581 DOFs[3] = &_connects[iNode]->DOFVar(DWP);
00582
00583 }
00584
00585 inline void Coupled::BackupState()
00586
00587 {
00588 for (int i=0; i<_n_int_pts; ++i)
00589 _a_model[i]->BackupState();
00590 }
00591
00592 inline void Coupled::UpdateState(REAL TimeInc)
00593 {
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 LinAlg::Vector<REAL> dU(NDIM*_n_nodes);
00629 LinAlg::Vector<REAL> dP(_n_nodes);
00630 LinAlg::Vector<REAL> P(_n_nodes);
00631
00632
00633 for (int i_node=0; i_node<_n_nodes; ++i_node)
00634 {
00635
00636 dU(i_node*NDIM ) = _connects[i_node]->DOFVar(DUX)._IncEssenVal;
00637 dU(i_node*NDIM+1) = _connects[i_node]->DOFVar(DUY)._IncEssenVal;
00638 dU(i_node*NDIM+2) = _connects[i_node]->DOFVar(DUZ)._IncEssenVal;
00639 dP(i_node) = _connects[i_node]->DOFVar(DWP)._IncEssenVal;
00640 P(i_node) = _connects[i_node]->DOFVar(DWP).EssentialVal;
00641 }
00642
00643
00644 LinAlg::Vector<REAL> dF(NDIM*_n_nodes);
00645 dF.SetValues(0.0);
00646
00647
00648 LinAlg::Vector<REAL> dQ(1*_n_nodes);
00649 dQ.SetValues(0.0);
00650
00651
00652 LinAlg::Matrix<REAL> derivs;
00653 LinAlg::Vector<REAL> shape;
00654 LinAlg::Matrix<REAL> J;
00655 LinAlg::Matrix<REAL> B;
00656 LinAlg::Matrix<REAL> Bp;
00657 Tensors::Tensor2 tsrDEps;
00658 Tensors::Tensor2 tsrDSig;
00659 Tensors::Tensor1 tsrVel;
00660 Tensors::Tensor1 tsrGrad;
00661 LinAlg::Vector<REAL> DEps;
00662 LinAlg::Vector<REAL> DSig;
00663 LinAlg::Vector<REAL> Vel;
00664 LinAlg::Vector<REAL> Grad;
00665 LinAlg::Vector<REAL> m(6);
00666 m = 1, 1, 1, 0, 0, 0;
00667
00668
00669 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00670 {
00671
00672 REAL r = _a_int_pts[i_ip].r;
00673 REAL s = _a_int_pts[i_ip].s;
00674 REAL t = _a_int_pts[i_ip].t;
00675 REAL w = _a_int_pts[i_ip].w;
00676
00677 Shape(r,s,t, shape);
00678 Derivs(r,s,t, derivs);
00679 Jacobian(derivs, J);
00680 B_Matrix(derivs, J, B);
00681 Bp_Matrix(derivs, J, Bp);
00682 REAL det_J = J.Det();
00683
00684
00685
00686
00687 DEps = B*dU; Copy(DEps, tsrDEps);
00688
00689
00690 REAL p = _a_model[i_ip]->Pp();
00691 REAL dp = trn(shape)*dP;
00692 REAL phi_before = _a_model[i_ip]->phi();
00693 REAL DnSr;
00694 _a_model[i_ip]->StressUpdate(tsrDEps, dp, tsrDSig, DnSr); Copy(tsrDSig, DSig);
00695 _a_model[i_ip]->FlowUpdate(dp);
00696
00697
00698
00699
00700 REAL phi_after = _a_model[i_ip]->phi();
00701 REAL dphi = phi_after - phi_before;
00702 DSig += (phi_before*dp + p*dphi)*m;
00703
00704
00705 dF += trn(B)*DSig*det_J*w;
00706
00707
00708
00709 REAL gammaW = _a_model[i_ip]->GammaW();
00710 Grad = Bp*P/gammaW; Copy(Grad, tsrGrad);
00711 _a_model[i_ip]->FlowVelocity(tsrGrad, tsrVel); Copy(tsrVel, Vel);
00712
00713
00714 dQ += -shape*DnSr*det_J*w + trn(Bp)*TimeInc*Vel*det_J*w;
00715 }
00716
00717
00718 for (int i_node=0; i_node<_n_nodes; ++i_node)
00719 {
00720
00721 _connects[i_node]->DOFVar(DFX)._IncNaturVal += dF(i_node*NDIM );
00722 _connects[i_node]->DOFVar(DFY)._IncNaturVal += dF(i_node*NDIM+1);
00723 _connects[i_node]->DOFVar(DFZ)._IncNaturVal += dF(i_node*NDIM+2);
00724 _connects[i_node]->DOFVar(DWD) ._IncNaturVal += dQ(i_node);
00725
00726
00727 _connects[i_node]->DOFVar(DFX).NaturalVal += dF(i_node*NDIM );
00728 _connects[i_node]->DOFVar(DFY).NaturalVal += dF(i_node*NDIM+1);
00729 _connects[i_node]->DOFVar(DFZ).NaturalVal += dF(i_node*NDIM+2);
00730 _connects[i_node]->DOFVar(DWD) .NaturalVal += dQ(i_node);
00731 }
00732
00733 }
00734
00735 inline void Coupled::RestoreState()
00736 {
00737 for (int i=0; i<_n_int_pts; ++i)
00738 _a_model[i]->RestoreState();
00739 }
00740
00741 inline String Coupled::OutCenter(bool PrintCaptionOnly=false) const
00742 {
00743
00744 std::ostringstream oss;
00745
00746
00747 int n_int_state_vals = _a_model[0]->nInternalStateValues();
00748
00749
00750 if (PrintCaptionOnly)
00751 {
00752
00753 oss << _8s() << "p" << _8s() << "q" << _8s() << "th" << _8s() << "Ev" << _8s() << "Ed";
00754 oss << _8s() << "Sx" << _8s() << "Sy" << _8s() << "Sz" << _8s() << "Sxy" << _8s() << "Syz" << _8s() << "Sxz";
00755 oss << _8s() << "Ex" << _8s() << "Ey" << _8s() << "Ez" << _8s() << "Exy" << _8s() << "Eyz" << _8s() << "Exz";
00756 oss << _8s() << "Pp";
00757
00758
00759 Array<String> str_state_names; _a_model[0]->InternalStateNames(str_state_names);
00760 for (int i=0; i<n_int_state_vals; ++i)
00761 oss << _8s() << str_state_names[i];
00762 oss << std::endl;
00763 }
00764 else
00765 {
00766
00767 Tensors::Tensor2 sig_cen(0.0);
00768 Tensors::Tensor2 eps_cen(0.0);
00769 REAL ppr_cen=0.0;
00770 Array<REAL> int_state_vals_cen; int_state_vals_cen.assign(n_int_state_vals,0.0);
00771
00772
00773 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00774 {
00775
00776 sig_cen += _a_model[i_ip]->Sig();
00777 eps_cen += _a_model[i_ip]->Eps();
00778 ppr_cen += _a_model[i_ip]->Pp();
00779
00780
00781 Array<REAL> int_state_vals; _a_model[i_ip]->InternalStateValues(int_state_vals);
00782 for (int j=0; j<n_int_state_vals; ++j)
00783 int_state_vals_cen[j] += int_state_vals[j];
00784 }
00785
00786
00787 sig_cen = sig_cen / _n_int_pts;
00788 eps_cen = eps_cen / _n_int_pts;
00789 ppr_cen = ppr_cen / _n_int_pts;
00790
00791
00792 for (int j=0; j<n_int_state_vals; ++j)
00793 int_state_vals_cen[j] = int_state_vals_cen[j] / _n_int_pts;;
00794
00795
00796 REAL p,q,sin3th;
00797 Tensors::Tensor2 S;
00798 Stress_p_q_S_sin3th(sig_cen,p,q,S,sin3th);
00799
00800
00801 REAL Ev,Ed;
00802 Strain_Ev_Ed(eps_cen,Ev,Ed);
00803
00804
00805 REAL sq2 = sqrt(2.0);
00806 oss << _8s()<< p << _8s()<< q << _8s()<< sin3th << _8s()<< Ev*100.0 << _8s()<< Ed*100.0;
00807 oss << _8s()<< sig_cen(0) << _8s()<< sig_cen(1) << _8s()<< sig_cen(2) << _8s()<< sig_cen(3)/sq2 << _8s()<< sig_cen(4)/sq2 << _8s()<< sig_cen(5)/sq2;
00808 oss << _8s()<< eps_cen(0) << _8s()<< eps_cen(1) << _8s()<< eps_cen(2) << _8s()<< eps_cen(3)/sq2 << _8s()<< eps_cen(4)/sq2 << _8s()<< eps_cen(5)/sq2;
00809 oss << _8s()<< ppr_cen;
00810
00811
00812 for (int j=0; j<n_int_state_vals; ++j)
00813 oss << _8s()<< int_state_vals_cen[j];
00814 oss << std::endl;
00815
00816 }
00817
00818 return oss.str();
00819 }
00820
00821 inline void Coupled::OutNodes(LinAlg::Matrix<REAL> & Values, Array<String> & Labels) const
00822 {
00823 int const DATA_COMPS=20;
00824 Values.Resize(_n_nodes,DATA_COMPS);
00825 Labels.resize(DATA_COMPS);
00826 Labels[ 0] = DUX; Labels[ 1] = DUY; Labels[ 2] = DUZ; Labels[ 3] = DWP;
00827 Labels[ 4] = DFX; Labels[ 5] = DFY; Labels[ 6] = DFZ; Labels[ 7] = DWD;
00828 Labels[ 8] = "Ex"; Labels[ 9] = "Ey"; Labels[10] = "Ez"; Labels[11] = "Exy"; Labels[12] = "Eyz"; Labels[13] = "Exz";
00829 Labels[14] = "Sx"; Labels[15] = "Sy"; Labels[16] = "Sz"; Labels[17] = "Sxy"; Labels[18] = "Syz"; Labels[19] = "Sxz";
00830 for (int i_node=0; i_node<_n_nodes; i_node++)
00831 {
00832 Values(i_node,0) = _connects[i_node]->DOFVar(DUX).EssentialVal;
00833 Values(i_node,1) = _connects[i_node]->DOFVar(DUY).EssentialVal;
00834 Values(i_node,2) = _connects[i_node]->DOFVar(DUZ).EssentialVal;
00835 Values(i_node,3) = _connects[i_node]->DOFVar(DWP).EssentialVal;
00836 Values(i_node,4) = _connects[i_node]->DOFVar(DFX).NaturalVal;
00837 Values(i_node,5) = _connects[i_node]->DOFVar(DFY).NaturalVal;
00838 Values(i_node,6) = _connects[i_node]->DOFVar(DFZ).NaturalVal;
00839 Values(i_node,7) = _connects[i_node]->DOFVar(DWD).NaturalVal;
00840 }
00841
00842
00843 LinAlg::Vector<REAL> ip_values(_n_int_pts);
00844 LinAlg::Vector<REAL> nodal_values(_n_nodes);
00845
00846
00847 for (int i_comp=0; i_comp<NSTRESSCOMPS; i_comp++)
00848 {
00849 for (int j_ip=0; j_ip<_n_int_pts; j_ip++)
00850 {
00851 Tensors::Tensor2 const & eps = _a_model[j_ip]->Eps();
00852 ip_values(j_ip) = eps(i_comp);
00853 }
00854 _extrapolate(ip_values, nodal_values);
00855 for (int j_node=0; j_node<_n_nodes; j_node++)
00856 Values(j_node,i_comp+8) = nodal_values(j_node);
00857 }
00858
00859
00860 for (int i_comp=0; i_comp<NSTRESSCOMPS; i_comp++)
00861 {
00862 for (int j_ip=0; j_ip<_n_int_pts; j_ip++)
00863 {
00864 Tensors::Tensor2 const & sig = _a_model[j_ip]->Sig();
00865 ip_values(j_ip) = sig(i_comp);
00866 }
00867 _extrapolate(ip_values, nodal_values);
00868 for (int j_node=0; j_node<_n_nodes; j_node++)
00869 Values(j_node,i_comp+14) = nodal_values(j_node);
00870 }
00871 }
00872
00873 inline void Coupled::_calc_initial_internal_forces()
00874 {
00875
00876 LinAlg::Vector<REAL> F(NDIM*_n_nodes);
00877 F.SetValues(0.0);
00878
00879
00880 LinAlg::Matrix<REAL> derivs;
00881 LinAlg::Matrix<REAL> J;
00882 LinAlg::Matrix<REAL> B;
00883 Tensors::Tensor2 tsrSig;
00884 LinAlg::Vector<REAL> Sig;
00885
00886
00887 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00888 {
00889
00890 REAL r = _a_int_pts[i_ip].r;
00891 REAL s = _a_int_pts[i_ip].s;
00892 REAL t = _a_int_pts[i_ip].t;
00893 REAL w = _a_int_pts[i_ip].w;
00894
00895 Derivs(r,s,t, derivs);
00896 Jacobian(derivs, J);
00897 B_Matrix(derivs, J, B);
00898
00899 REAL phi = _a_model[i_ip]->phi();
00900 tsrSig = _a_model[i_ip]->Sig() + phi*_a_model[i_ip]->Pp()*Tensors::I;
00901 Copy(tsrSig, Sig);
00902
00903
00904 F += trn(B)*Sig*det(J)*w;
00905 }
00906
00907
00908 for (int i_node=0; i_node<_n_nodes; ++i_node)
00909 {
00910
00911 _connects[i_node]->DOFVar(DFX).NaturalVal += F(i_node*NDIM );
00912 _connects[i_node]->DOFVar(DFY).NaturalVal += F(i_node*NDIM+1);
00913 _connects[i_node]->DOFVar(DFZ).NaturalVal += F(i_node*NDIM+2);
00914 }
00915 }
00916
00917 inline void Coupled::_calc_initial_internal_pore_pressures()
00918 {
00919
00920
00921
00922
00923
00924
00925
00926
00927 LinAlg::Vector<REAL> P(_n_nodes);
00928 P.SetValues(0.0);
00929
00930 REAL mean_pp_value=0;
00931
00932 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00933 {
00934 mean_pp_value+= _a_model[i_ip]->Pp()/_n_int_pts;
00935 }
00936
00937 for (int i_node=0; i_node<_n_int_pts; ++i_node)
00938 {
00939 P(i_node) = mean_pp_value;
00940 }
00941
00942
00943 for (int i_node=0; i_node<_n_nodes; ++i_node)
00944 {
00945
00946 int node_refs = _connects[i_node]->Refs();
00947 _connects[i_node]->DOFVar(DWP).EssentialVal += P(i_node)/node_refs;
00948
00949 }
00950 }
00951
00952 inline void Coupled::RHSVector(size_t index, LinAlg::Vector<REAL> & V, Array<size_t> & Map) const
00953 {
00954 assert(index == 0);
00955 V.Resize(_n_nodes);
00956
00957
00958 for (int i_node=0; i_node<_n_nodes; ++i_node)
00959 {
00960
00961 V(i_node) = _connects[i_node]->DOFVar(DWP).EssentialVal;
00962 }
00963
00964 int idx=0;
00965 Map.resize(V.Size());
00966 for (int i_node=0; i_node<_n_nodes; ++i_node)
00967 {
00968 Map[idx++] = _connects[i_node]->DOFVar(DWP).EqID;
00969 }
00970 }
00971
00972 inline void Coupled::Order0Matrix(size_t index, LinAlg::Matrix<REAL> & M, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const
00973 {
00974 assert(index == 0);
00975 Permeability(M, RowsMap);
00976 ColsMap.resize(RowsMap.size());
00977 for (size_t i=0; i<RowsMap.size(); i++) ColsMap[i] = RowsMap[i];
00978 }
00979
00980 inline void Coupled::Order1Matrix(size_t index, LinAlg::Matrix<REAL> & M, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const
00981 {
00982 assert(index < 4);
00983 switch(index)
00984 {
00985 case 0:
00986 Stiffness(M, RowsMap);
00987 ColsMap.resize(RowsMap.size());
00988 for (size_t i=0; i<RowsMap.size(); i++) ColsMap[i] = RowsMap[i];
00989 break;
00990 case 1:
00991 CouplingMatrix1(M, RowsMap, ColsMap);
00992 break;
00993 case 2:
00994 CouplingMatrix2(M, RowsMap, ColsMap);
00995 break;
00996 case 3:
00997 MassMatrix(M, RowsMap);
00998 ColsMap.resize(RowsMap.size());
00999 for (size_t i=0; i<RowsMap.size(); i++) ColsMap[i] = RowsMap[i];
01000 break;
01001 }
01002 }
01003
01004 inline REAL Coupled::OutScalar1() const
01005 {
01006
01007 REAL ppr=0.0;
01008
01009
01010 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
01011 ppr += _a_model[i_ip]->Pp();
01012
01013
01014 ppr = ppr / _n_int_pts;
01015
01016
01017 return ppr;
01018
01019 }
01020
01021 inline REAL Coupled::OutScalar2() const
01022 {
01023
01024 Tensors::Tensor2 e(0.0);
01025
01026
01027 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
01028 e += 100.0*_a_model[i_ip]->Eps();
01029
01030
01031 e = e / _n_int_pts;
01032
01033
01034 REAL Ev,Ed;
01035 Strain_Ev_Ed(e,Ev,Ed);
01036
01037
01038 return Ed;
01039
01040 }
01041
01042 inline void Coupled::OutTensor1(String & Str) const
01043 {
01044
01045 Tensors::Tensor2 s(0.0);
01046
01047
01048 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
01049 s += _a_model[i_ip]->Sig();
01050
01051
01052 s = s / _n_int_pts;
01053
01054
01055 REAL sq2 = sqrt(2.0);
01056 Str.Printf(_(" %e %e %e %e %e %e %e %e %e "), s(0),s(3)/sq2,s(5)/sq2, s(3)/sq2,s(1),s(4)/sq2, s(5)/sq2,s(4)/sq2,s(2));
01057
01058 }
01059
01060 inline void Coupled::OutTensor2(String & Str) const
01061 {
01062
01063 Tensors::Tensor2 e(0.0);
01064
01065
01066 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
01067 e += 100.0*_a_model[i_ip]->Eps();
01068
01069
01070 e = e / _n_int_pts;
01071
01072
01073 REAL sq2 = sqrt(2.0);
01074 Str.Printf(_(" %e %e %e %e %e %e %e %e %e "), e(0),e(3)/sq2,e(5)/sq2, e(3)/sq2,e(1),e(4)/sq2, e(5)/sq2,e(4)/sq2,e(2));
01075
01076 }
01077
01078
01079 int CoupledDOFInfoRegister()
01080 {
01081
01082 DOFInfo D;
01083 DOFInfo D_flow;
01084 D_flow = DOFInfoMap["FlowElem"];
01085
01086
01087 D = DOFInfoMap["EquilibElem"];
01088
01089
01090 for (size_t i=0; i<D_flow.NodeEssential.size(); i++)
01091 {
01092 D.NodeEssential.push_back(D_flow.NodeEssential[i]);
01093 D.NodeNatural .push_back(D_flow.NodeNatural [i]);
01094 }
01095 for (size_t i=0; i<D_flow.FaceEssential.size(); i++)
01096 {
01097 D.FaceEssential.push_back(D_flow.FaceEssential[i]);
01098 D.FaceNatural .push_back(D_flow.FaceNatural [i]);
01099 }
01100
01101
01102 DOFInfoMap["Coupled"] = D;
01103
01104 return 0;
01105 }
01106
01107
01108 int __CoupledElemDOFInfo_dummy_int = CoupledDOFInfoRegister();
01109
01110 };
01111
01112 #endif // FEM_COUPLED_H
01113
01114