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