00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FEM_FLOWELEM_H
00023 #define FEM_FLOWELEM_H
00024
00025 #ifndef REAL
00026 #define REAL double
00027 #endif
00028
00029 #include <sstream>
00030
00031 #include "models/flow/flowmodel.h"
00032 #include "fem/ele/element.h"
00033 #include "tensors/tensors.h"
00034 #include "tensors/functions.h"
00035 #include "util/numstreams.h"
00036
00037 namespace FEM
00038 {
00039
00040 class FlowElem: public virtual Element
00041 {
00042 public:
00043
00044 static int NDIM;
00045 static String DWP;
00046 static String DWD;
00047 static String DFWD;
00048
00049
00050
00051 virtual ~FlowElem() {}
00052
00053 virtual void ReAllocateModel(String const & ModelName, Array<REAL> const & ModelPrms, Array<Array<REAL> > const & AIniData);
00054 virtual bool IsEssential(String const & DOFName) const;
00055 virtual void CalcFaceNodalValues(String const & FaceDOFName ,
00056 REAL const FaceDOFValue ,
00057 Array<FEM::Node*> const & APtrFaceNodes,
00058 String & NodalDOFName ,
00059 LinAlg::Vector<REAL> & NodalValues
00060 ) const;
00061 virtual void Bp_Matrix(LinAlg::Matrix<REAL> const & derivs, LinAlg::Matrix<REAL> const & J, LinAlg::Matrix<REAL> & Bp) const;
00062 virtual void Permeability(LinAlg::Matrix<REAL> & H, Array<size_t> & EqMap) const;
00063
00064
00065 virtual void NodalDOFs(int iNode, Array<FEM::Node::DOFVarsStruct*> & DOFs) const;
00066 virtual void BackupState();
00067 virtual void UpdateState(REAL TimeInc);
00068 virtual void RestoreState();
00069 virtual void SetProperties(Array<REAL> const & EleProps) { }
00070 virtual String OutCenter(bool PrintCaptionOnly) const;
00071 virtual void OutNodes(LinAlg::Matrix<REAL> & Values, Array<String> & Labels) const;
00072
00073 size_t nOrder0Matrices() const { return 1; };
00074 void RHSVector(size_t index, LinAlg::Vector<REAL> & V, Array<size_t> & Map) const;
00075 void Order0Matrix(size_t index, LinAlg::Matrix<REAL> & V, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const;
00076 private:
00077
00078 Array<FlowModel*> _a_model;
00079
00080 virtual void _set_node_vars(int iNode);
00081 virtual void _calc_Nu_matrix(LinAlg::Vector<REAL> & Shape, LinAlg::Matrix<REAL> & Nu) const;
00082 virtual void _calc_initial_internal_pore_pressures();
00083 };
00084
00085
00086 int FlowElem::NDIM = 3;
00087 String FlowElem::DWP = _T("Dwp");
00088 String FlowElem::DWD = _T("Dwd");
00089 String FlowElem::DFWD = _T("Dfwd");
00090
00091
00092
00093
00094 inline void FlowElem::_set_node_vars(int iNode)
00095 {
00096
00097 _connects[iNode]->AddDOF(DWP,DWD);
00098 }
00099
00100 void FlowElem::ReAllocateModel(String const & ModelName, Array<REAL> const & ModelPrms, Array<Array<REAL> > const & AIniData)
00101 {
00102
00103 if (!(AIniData.size()==1 || static_cast<int>(AIniData.size())==_n_int_pts))
00104 throw new Fatal(_("FlowElem::ReAllocateModel: Array of array of initial data must have size==1 or size== %d \n"),_n_int_pts);
00105
00106
00107 if (_a_model.size()==0)
00108 {
00109
00110 _a_model.resize(_n_int_pts);
00111
00112
00113 for (int i=0; i<_n_int_pts; ++i)
00114 {
00115
00116 if (AIniData.size()==1) _a_model[i] = AllocFlowModel(ModelName, ModelPrms, AIniData[0]);
00117 else _a_model[i] = AllocFlowModel(ModelName, ModelPrms, AIniData[i]);
00118 }
00119
00120
00121 _calc_initial_internal_pore_pressures();
00122 }
00123 else
00124 {
00125
00126 for (int i=0; i<_n_int_pts; ++i)
00127 {
00128 if (_a_model[i]->Name()!=ModelName)
00129 {
00130
00131 delete _a_model[i];
00132
00133
00134 if (AIniData.size()==1) _a_model[i] = AllocFlowModel(ModelName, ModelPrms, AIniData[0]);
00135 else _a_model[i] = AllocFlowModel(ModelName, ModelPrms, AIniData[i]);
00136 }
00137
00138 }
00139 }
00140 }
00141
00142 inline bool FlowElem::IsEssential(String const & DOFName) const
00143 {
00144 if (DOFName==DWP) return true;
00145 else return false;
00146 }
00147
00148 inline void FlowElem::CalcFaceNodalValues(String const & FaceDOFName ,
00149 REAL const FaceDOFValue ,
00150 Array<FEM::Node*> const & APtrFaceNodes,
00151 String & NodalDOFName ,
00152 LinAlg::Vector<REAL> & NodalValues ) const
00153 {
00154 if (FaceDOFName==DFWD)
00155 {
00156 if (FaceDOFName==DFWD) NodalDOFName=DWD;
00157 _distrib_val_to_face_nodal_vals(APtrFaceNodes, FaceDOFValue, NodalValues);
00158 }
00159 else
00160 {
00161 std::ostringstream oss; oss << "Face nodes coordinates:\n";
00162 for (size_t i_node=0; i_node<APtrFaceNodes.size(); ++i_node)
00163 oss << "X=" << APtrFaceNodes[i_node]->X() << ", Y=" << APtrFaceNodes[i_node]->Y() << ", Z=" << APtrFaceNodes[i_node]->Z() << std::endl;
00164 throw new Fatal(_("FlowElem::CalcFaceNodalValues: This method must only be called for FaceDOFName< %d > equal to tq\n %s \n"), FaceDOFName.c_str(), oss.str().c_str());
00165 }
00166 }
00167
00168 inline void FlowElem::Permeability(LinAlg::Matrix<REAL> & He, Array<size_t> & EqMap) const
00169 {
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 He.Resize(_n_nodes, _n_nodes);
00182 He.SetValues(0.0);
00183
00184
00185 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00186 {
00187
00188 REAL r = _a_int_pts[i_ip].r;
00189 REAL s = _a_int_pts[i_ip].s;
00190 REAL t = _a_int_pts[i_ip].t;
00191 REAL w = _a_int_pts[i_ip].w;
00192
00193
00194 LinAlg::Matrix<REAL> derivs;
00195 Derivs(r,s,t, derivs);
00196
00197
00198 LinAlg::Matrix<REAL> J;
00199 Jacobian(derivs, J);
00200 REAL det_J = J.Det();
00201
00202
00203 LinAlg::Matrix<REAL> Bp;
00204 Bp_Matrix(derivs,J, Bp);
00205
00206
00207 blitz::TinyVector<REAL,6> K;
00208 _a_model[i_ip]->TgPermeability(K);
00209
00210 REAL gammaW = _a_model[i_ip]->GammaW();
00211
00212
00213 LinAlg::Matrix<REAL> KBp(Bp.Rows(),Bp.Cols());
00214 for (int i=0; i<Bp.Rows(); ++i)
00215 for (int j=0; j<Bp.Cols(); ++j)
00216 KBp(i,j) = K(i)*Bp(i,j);
00217
00218
00219 for (int i=0; i<Bp.Cols(); ++i)
00220 for (int j=0; j<Bp.Cols(); ++j)
00221 {
00222 for (int k=0; k<Bp.Rows(); ++k)
00223 He(i,j) += -Bp(k,i)*KBp(k,j)*1.0/gammaW*det_J*w;
00224 }
00225 }
00226
00227
00228
00229 int idx_He=0;
00230 EqMap.resize(He.Rows());
00231 for (int i_node=0; i_node<_n_nodes; ++i_node)
00232 {
00233
00234 EqMap[idx_He++] = _connects[i_node]->DOFVar(DWP).EqID;
00235 }
00236 }
00237
00238 inline void FlowElem::_calc_Nu_matrix(LinAlg::Vector<REAL> & Shape,
00239 LinAlg::Matrix<REAL> & Nu
00240 ) const
00241 {
00242 Nu.Resize(NDIM, NDIM*_n_nodes);
00243 for(int i=0; i<_n_nodes; i++)
00244 {
00245 Nu(0,0 + 3*i) = Shape(i); Nu(0,1 + 3*i) = 0; Nu(0,2 + 3*i) = 0;
00246 Nu(1,0 + 3*i) = 0; Nu(1,1 + 3*i) = Shape(i); Nu(1,2 + 3*i) = 0;
00247 Nu(2,0 + 3*i) = 0; Nu(2,1 + 3*i) = 0; Nu(2,2 + 3*i) = Shape(i);
00248 }
00249 }
00250
00251 inline void FlowElem::Bp_Matrix(LinAlg::Matrix<REAL> const & derivs,
00252 LinAlg::Matrix<REAL> const & J,
00253 LinAlg::Matrix<REAL> & Bp) const
00254 {
00255
00256 Bp.Resize(NDIM, _n_nodes);
00257
00258
00259 LinAlg::Matrix<REAL> inv_J(J.Rows(),J.Cols());
00260 J.Inv(inv_J);
00261
00262
00263 LinAlg::Matrix<REAL> cart_derivs;
00264 cart_derivs.Resize(J.Rows(), derivs.Cols());
00265 LinAlg::Gemm(1.0, inv_J, derivs, 0.0, cart_derivs);
00266
00267
00268 for (int i=0; i<_n_nodes; ++i)
00269 {
00270 Bp(0, i) = cart_derivs(0,i);
00271 Bp(1, i) = cart_derivs(1,i);
00272 Bp(2, i) = cart_derivs(2,i);
00273 }
00274 }
00275
00276 inline void FlowElem::NodalDOFs(int iNode, Array<FEM::Node::DOFVarsStruct*> & DOFs) const
00277 {
00278
00279 DOFs.resize(1);
00280
00281
00282 DOFs[0] = &_connects[iNode]->DOFVar(DWP);
00283
00284 }
00285
00286 inline void FlowElem::BackupState()
00287 {
00288 for (int i=0; i<_n_int_pts; ++i)
00289 _a_model[i]->BackupState();
00290 }
00291
00292 inline void FlowElem::UpdateState(REAL TimeInc)
00293 {
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 LinAlg::Vector<REAL> P(_n_nodes);
00306 LinAlg::Vector<REAL> dP(_n_nodes);
00307
00308
00309 for (int i_node=0; i_node<_n_nodes; ++i_node)
00310 {
00311
00312 dP(i_node) = _connects[i_node]->DOFVar(DWP)._IncEssenVal;
00313 P(i_node) = _connects[i_node]->DOFVar(DWP).EssentialVal;
00314 }
00315
00316
00317 LinAlg::Vector<REAL> dQ(_n_nodes);
00318 dQ.SetValues(0.0);
00319
00320
00321 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00322 {
00323
00324 REAL r = _a_int_pts[i_ip].r;
00325 REAL s = _a_int_pts[i_ip].s;
00326 REAL t = _a_int_pts[i_ip].t;
00327 REAL w = _a_int_pts[i_ip].w;
00328
00329
00330 LinAlg::Vector<REAL> shape;
00331 Shape(r,s,t, shape);
00332
00333
00334 LinAlg::Matrix<REAL> derivs;
00335 Derivs(r,s,t, derivs);
00336
00337
00338 LinAlg::Matrix<REAL> J;
00339 Jacobian(derivs, J);
00340 REAL det_J = J.Det();
00341
00342
00343 LinAlg::Matrix<REAL> Bp;
00344 Bp_Matrix(derivs, J, Bp);
00345
00346 REAL gammaW = _a_model[i_ip]->GammaW();
00347
00348
00349 Tensors::Tensor1 Grad;
00350 Grad=0,0,0;
00351 for (int i=0; i<Bp.Rows(); ++i)
00352 for (int j=0; j<Bp.Cols(); ++j)
00353 Grad(i) += Bp(i,j)*P(j)/gammaW;
00354
00355
00356 REAL dp=0;
00357 for (int i=0; i<_n_nodes; ++i)
00358 dp += shape(i)*dP(i);
00359 _a_model[i_ip]->FlowUpdate(dp);
00360
00361
00362 Tensors::Tensor1 Vel;
00363 _a_model[i_ip]->FlowVelocity(Grad,Vel);
00364
00365
00366 for (int i=0; i<dQ.Size(); ++i)
00367 for (int j=0; j<NDIM; ++j)
00368 dQ(i) += Bp(j,i)*TimeInc*Vel(j)*det_J*w;
00369 }
00370
00371
00372 for (int i_node=0; i_node<_n_nodes; ++i_node)
00373 {
00374
00375 _connects[i_node]->DOFVar(DWD)._IncNaturVal += dQ(i_node);
00376
00377 _connects[i_node]->DOFVar(DWD).NaturalVal += dQ(i_node);
00378 }
00379
00380 }
00381
00382 inline void FlowElem::RestoreState()
00383 {
00384 for (int i=0; i<_n_int_pts; ++i)
00385 _a_model[i]->RestoreState();
00386 }
00387
00388 inline String FlowElem::OutCenter(bool PrintCaptionOnly=false) const
00389 {
00390
00391 std::ostringstream oss;
00392
00393
00394 int n_int_state_vals = _a_model[0]->nInternalStateValues();
00395
00396
00397 if (PrintCaptionOnly)
00398 {
00399
00400 oss << _8s()<< DWP;
00401
00402
00403 Array<String> str_state_names; _a_model[0]->InternalStateNames(str_state_names);
00404 for (int i=0; i<n_int_state_vals; ++i)
00405 oss << _8s()<< str_state_names[i];
00406 oss << std::endl;
00407 }
00408 else
00409 {
00410
00411 REAL p_cen = 0;
00412 Array<REAL> int_state_vals_cen; int_state_vals_cen.assign(n_int_state_vals,0.0);
00413
00414
00415 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00416 {
00417
00418 p_cen += _a_model[i_ip]->Pp();
00419
00420
00421 Array<REAL> int_state_vals; _a_model[i_ip]->InternalStateValues(int_state_vals);
00422 for (int j=0; j<n_int_state_vals; ++j)
00423 int_state_vals_cen[j] += int_state_vals[j];
00424 }
00425
00426
00427 p_cen = p_cen/_n_int_pts;
00428
00429
00430 for (int j=0; j<n_int_state_vals; ++j)
00431 int_state_vals_cen[j] = int_state_vals_cen[j] / _n_int_pts;;
00432
00433
00434 oss << _8s()<< p_cen;
00435 for (int j=0; j<n_int_state_vals; ++j)
00436 oss << _8s()<< int_state_vals_cen[j];
00437 oss << std::endl;
00438 }
00439
00440 return oss.str();
00441 }
00442
00443 void FlowElem::OutNodes(LinAlg::Matrix<REAL> & Values, Array<String> & Labels) const
00444 {
00445 int const DATA_COMPS=2;
00446 Values.Resize(_n_nodes,DATA_COMPS);
00447 Labels.resize(DATA_COMPS);
00448 Labels[ 0] = DWP; Labels[ 1] = DWD;
00449 for (int i_node=0; i_node<_n_nodes; i_node++)
00450 {
00451 Values(i_node,0) = _connects[i_node]->DOFVar(DWP).EssentialVal;
00452 Values(i_node,1) = _connects[i_node]->DOFVar(DWD).EssentialVal;
00453 }
00454 }
00455
00456 inline void FlowElem::_calc_initial_internal_pore_pressures()
00457 {
00458
00459
00460
00461
00462
00463
00464
00465
00466 LinAlg::Vector<REAL> P(_n_nodes);
00467 P.SetValues(0.0);
00468
00469 REAL mean_pp_value=0;
00470
00471 for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00472 {
00473 mean_pp_value+= _a_model[i_ip]->Pp()/_n_int_pts;
00474 }
00475
00476 for (int i_node=0; i_node<_n_int_pts; ++i_node)
00477 {
00478 P(i_node) = mean_pp_value;
00479 }
00480
00481
00482 for (int i_node=0; i_node<_n_nodes; ++i_node)
00483 {
00484
00485 int node_refs = _connects[i_node]->Refs();
00486 _connects[i_node]->DOFVar(DWP).EssentialVal += P(i_node)/node_refs;
00487 }
00488 }
00489
00490 inline void FlowElem::RHSVector(size_t index, LinAlg::Vector<REAL> & V, Array<size_t> & Map) const
00491 {
00492 assert(index == 0);
00493 V.Resize(_n_nodes);
00494
00495
00496 for (int i_node=0; i_node<_n_nodes; ++i_node)
00497 {
00498
00499 V(i_node) = _connects[i_node]->DOFVar("p").EssentialVal;
00500 }
00501
00502 int idx=0;
00503 Map.resize(V.Size());
00504 for (int i_node=0; i_node<_n_nodes; ++i_node)
00505 {
00506 Map[idx++] = _connects[i_node]->DOFVar("p").EqID;
00507 }
00508 }
00509
00510 inline void FlowElem::Order0Matrix(size_t index, LinAlg::Matrix<REAL> & M, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const
00511 {
00512 assert(index == 0);
00513 Permeability(M, RowsMap);
00514 ColsMap.resize(RowsMap.size());
00515 for (size_t i=0; i<RowsMap.size(); i++) ColsMap[i] = RowsMap[i];
00516 }
00517
00518
00520
00521
00522
00523 int FlowDOFInfoRegister()
00524 {
00525
00526 DOFInfo D;
00527
00528
00529 D.NodeEssential.push_back(FlowElem::DWP + _("@Nodal pore-presure increment"));
00530 D.NodeNatural .push_back(FlowElem::DWD + _("@Nodal water discharge increment"));
00531
00532
00533 D.FaceEssential.push_back(FlowElem::DWP + _("@Pore-presure increment per area"));
00534 D.FaceNatural .push_back(FlowElem::DFWD + _("@Water discharge increment per area"));
00535
00536
00537 DOFInfoMap["WaterFlow"] = D;
00538
00539 return 0;
00540 }
00541
00542
00543 int __FlowElemDOFInfo_dummy_int = FlowDOFInfoRegister();
00544
00545 };
00546
00547 #endif // FEM_FLOWELEM_H
00548
00549