MFEM v2.0
|
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at 00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights 00003 // reserved. See file COPYRIGHT for details. 00004 // 00005 // This file is part of the MFEM library. For more information and source code 00006 // availability see http://mfem.googlecode.com. 00007 // 00008 // MFEM is free software; you can redistribute it and/or modify it under the 00009 // terms of the GNU Lesser General Public License (as published by the Free 00010 // Software Foundation) version 2.1 dated February 1999. 00011 00012 // Finite Element classes 00013 00014 #include <math.h> 00015 #include "fem.hpp" 00016 00017 FiniteElement::FiniteElement(int D, int G, int Do, int O, int F) 00018 : Nodes(Do) 00019 { 00020 Dim = D ; GeomType = G ; Dof = Do ; Order = O ; FuncSpace = F; 00021 RangeType = SCALAR; 00022 } 00023 00024 void FiniteElement::CalcVShape ( 00025 const IntegrationPoint &ip, DenseMatrix &shape) const 00026 { 00027 mfem_error ("FiniteElement::CalcVShape (...)\n" 00028 " is not implemented for this class!"); 00029 } 00030 00031 void FiniteElement::CalcVShape ( 00032 ElementTransformation &Trans, DenseMatrix &shape) const 00033 { 00034 mfem_error ("FiniteElement::CalcVShape 2 (...)\n" 00035 " is not implemented for this class!"); 00036 } 00037 00038 void FiniteElement::CalcDivShape ( 00039 const IntegrationPoint &ip, Vector &divshape) const 00040 { 00041 mfem_error ("FiniteElement::CalcDivShape (...)\n" 00042 " is not implemented for this class!"); 00043 } 00044 00045 void FiniteElement::CalcCurlShape(const IntegrationPoint &ip, 00046 DenseMatrix &curl_shape) const 00047 { 00048 mfem_error ("FiniteElement::CalcCurlShape (...)\n" 00049 " is not implemented for this class!"); 00050 } 00051 00052 void FiniteElement::GetFaceDofs(int face, int **dofs, int *ndofs) const 00053 { 00054 mfem_error ("FiniteElement::GetFaceDofs (...)"); 00055 } 00056 00057 void FiniteElement::CalcHessian (const IntegrationPoint &ip, 00058 DenseMatrix &h) const 00059 { 00060 mfem_error ("FiniteElement::CalcHessian (...) is not overloaded !"); 00061 } 00062 00063 void FiniteElement::GetLocalInterpolation (ElementTransformation &Trans, 00064 DenseMatrix &I) const 00065 { 00066 mfem_error ("GetLocalInterpolation (...) is not overloaded !"); 00067 } 00068 00069 void FiniteElement::Project ( 00070 Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const 00071 { 00072 mfem_error ("FiniteElement::Project (...) is not overloaded !"); 00073 } 00074 00075 void FiniteElement::Project ( 00076 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const 00077 { 00078 mfem_error ("FiniteElement::Project (...) (vector) is not overloaded !"); 00079 } 00080 00081 void FiniteElement::ProjectDelta(int vertex, Vector &dofs) const 00082 { 00083 mfem_error("FiniteElement::ProjectDelta(...) is not implemented for " 00084 "this element!"); 00085 } 00086 00087 void FiniteElement::Project( 00088 const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const 00089 { 00090 mfem_error("FiniteElement::Project(...) (fe version) is not implemented " 00091 "for this element!"); 00092 } 00093 00094 void FiniteElement::ProjectGrad( 00095 const FiniteElement &fe, ElementTransformation &Trans, 00096 DenseMatrix &grad) const 00097 { 00098 mfem_error("FiniteElement::ProjectGrad(...) is not implemented for " 00099 "this element!"); 00100 } 00101 00102 void FiniteElement::ProjectCurl( 00103 const FiniteElement &fe, ElementTransformation &Trans, 00104 DenseMatrix &curl) const 00105 { 00106 mfem_error("FiniteElement::ProjectCurl(...) is not implemented for " 00107 "this element!"); 00108 } 00109 00110 void FiniteElement::ProjectDiv( 00111 const FiniteElement &fe, ElementTransformation &Trans, 00112 DenseMatrix &div) const 00113 { 00114 mfem_error("FiniteElement::ProjectDiv(...) is not implemented for " 00115 "this element!"); 00116 } 00117 00118 00119 void NodalFiniteElement::NodalLocalInterpolation ( 00120 ElementTransformation &Trans, DenseMatrix &I, 00121 const NodalFiniteElement &fine_fe) const 00122 { 00123 double v[3]; 00124 Vector vv (v, Dim); 00125 IntegrationPoint f_ip; 00126 00127 #ifdef MFEM_USE_OPENMP 00128 Vector c_shape(Dof); 00129 #endif 00130 00131 for (int i = 0; i < fine_fe.Dof; i++) 00132 { 00133 Trans.Transform (fine_fe.Nodes.IntPoint (i), vv); 00134 f_ip.x = v[0]; 00135 if (Dim > 1) { f_ip.y = v[1]; if (Dim > 2) f_ip.z = v[2]; } 00136 CalcShape (f_ip, c_shape); 00137 for (int j = 0; j < Dof; j++) 00138 if (fabs (I (i,j) = c_shape (j)) < 1.0e-12) 00139 I (i,j) = 0.0; 00140 } 00141 } 00142 00143 void NodalFiniteElement::Project ( 00144 Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const 00145 { 00146 for (int i = 0; i < Dof; i++) 00147 { 00148 const IntegrationPoint &ip = Nodes.IntPoint(i); 00149 // some coefficients expect that Trans.IntPoint is the same 00150 // as the second argument of Eval 00151 Trans.SetIntPoint(&ip); 00152 dofs(i) = coeff.Eval (Trans, ip); 00153 } 00154 } 00155 00156 void NodalFiniteElement::Project ( 00157 VectorCoefficient &vc, ElementTransformation &Trans, 00158 Vector &dofs) const 00159 { 00160 double v[3]; 00161 Vector x (v, vc.GetVDim()); 00162 00163 for (int i = 0; i < Dof; i++) 00164 { 00165 const IntegrationPoint &ip = Nodes.IntPoint(i); 00166 Trans.SetIntPoint(&ip); 00167 vc.Eval (x, Trans, ip); 00168 for (int j = 0; j < x.Size(); j++) 00169 dofs(Dof*j+i) = v[j]; 00170 } 00171 } 00172 00173 void NodalFiniteElement::Project( 00174 const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const 00175 { 00176 if (fe.GetRangeType() == SCALAR) 00177 { 00178 Vector shape(fe.GetDof()); 00179 00180 I.SetSize(Dof, fe.GetDof()); 00181 for (int k = 0; k < Dof; k++) 00182 { 00183 fe.CalcShape(Nodes.IntPoint(k), shape); 00184 for (int j = 0; j < shape.Size(); j++) 00185 I(k,j) = (fabs(shape(j)) < 1e-12) ? 0.0 : shape(j); 00186 } 00187 } 00188 else 00189 { 00190 DenseMatrix vshape(fe.GetDof(), Dim); 00191 00192 I.SetSize(Dim*Dof, fe.GetDof()); 00193 for (int k = 0; k < Dof; k++) 00194 { 00195 Trans.SetIntPoint(&Nodes.IntPoint(k)); 00196 fe.CalcVShape(Trans, vshape); 00197 for (int j = 0; j < vshape.Height(); j++) 00198 for (int d = 0; d < vshape.Width(); d++) 00199 I(k+d*Dof,j) = vshape(j,d); 00200 } 00201 } 00202 } 00203 00204 void NodalFiniteElement::ProjectGrad( 00205 const FiniteElement &fe, ElementTransformation &Trans, 00206 DenseMatrix &grad) const 00207 { 00208 DenseMatrix dshape(fe.GetDof(), Dim), grad_k(fe.GetDof(), Dim), Jinv(Dim); 00209 00210 grad.SetSize(Dim*Dof, fe.GetDof()); 00211 for (int k = 0; k < Dof; k++) 00212 { 00213 const IntegrationPoint &ip = Nodes.IntPoint(k); 00214 fe.CalcDShape(ip, dshape); 00215 Trans.SetIntPoint(&ip); 00216 CalcInverse(Trans.Jacobian(), Jinv); 00217 Mult(dshape, Jinv, grad_k); 00218 for (int j = 0; j < grad_k.Height(); j++) 00219 for (int d = 0; d < Dim; d++) 00220 grad(k+d*Dof,j) = grad_k(j,d); 00221 } 00222 } 00223 00224 void NodalFiniteElement::ProjectDiv( 00225 const FiniteElement &fe,ElementTransformation &Trans, 00226 DenseMatrix &div) const 00227 { 00228 double detJ; 00229 Vector div_shape(fe.GetDof()); 00230 00231 div.SetSize(Dof, fe.GetDof()); 00232 for (int k = 0; k < Dof; k++) 00233 { 00234 const IntegrationPoint &ip = Nodes.IntPoint(k); 00235 fe.CalcDivShape(ip, div_shape); 00236 Trans.SetIntPoint(&ip); 00237 detJ = Trans.Weight(); 00238 for (int j = 0; j < div_shape.Size(); j++) 00239 div(k,j) = (fabs(div_shape(j)) < 1e-12) ? 0.0 : div_shape(j)/detJ; 00240 } 00241 } 00242 00243 void VectorFiniteElement::CalcShape ( 00244 const IntegrationPoint &ip, Vector &shape ) const 00245 { 00246 mfem_error ("Error: Cannot use scalar CalcShape(...) function with\n" 00247 " VectorFiniteElements!"); 00248 } 00249 00250 void VectorFiniteElement::CalcDShape ( 00251 const IntegrationPoint &ip, DenseMatrix &dshape ) const 00252 { 00253 mfem_error ("Error: Cannot use scalar CalcDShape(...) function with\n" 00254 " VectorFiniteElements!"); 00255 } 00256 00257 void VectorFiniteElement::CalcVShape_RT ( 00258 ElementTransformation &Trans, DenseMatrix &shape) const 00259 { 00260 #ifdef MFEM_USE_OPENMP 00261 DenseMatrix vshape(Dof, Dim); 00262 #endif 00263 CalcVShape(Trans.GetIntPoint(), vshape); 00264 00265 MultABt(vshape, Trans.Jacobian(), shape); 00266 00267 shape *= (1.0 / Trans.Weight()); 00268 } 00269 00270 void VectorFiniteElement::CalcVShape_ND ( 00271 ElementTransformation &Trans, DenseMatrix &shape) const 00272 { 00273 const DenseMatrix &J = Trans.Jacobian(); 00274 00275 #ifdef MFEM_USE_OPENMP 00276 DenseMatrix vshape(Dof, Dim); 00277 DenseMatrix Jinv(J.Width(), J.Height()); 00278 #else 00279 Jinv.SetSize(J.Width(), J.Height()); 00280 #endif 00281 00282 CalcInverse(J, Jinv); 00283 00284 CalcVShape(Trans.GetIntPoint(), vshape); 00285 00286 Mult(vshape, Jinv, shape); 00287 } 00288 00289 void VectorFiniteElement::Project_RT( 00290 const double *nk, const Array<int> &d2n, 00291 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const 00292 { 00293 double vk[3]; 00294 Vector xk(vk, Dim); 00295 #ifdef MFEM_USE_OPENMP 00296 DenseMatrix Jinv(Dim); 00297 #endif 00298 00299 for (int k = 0; k < Dof; k++) 00300 { 00301 Trans.SetIntPoint(&Nodes.IntPoint(k)); 00302 // set Jinv = |J| J^{-1} = adj(J) 00303 CalcAdjugate(Trans.Jacobian(), Jinv); 00304 00305 vc.Eval(xk, Trans, Nodes.IntPoint(k)); 00306 // dof_k = nk^t adj(J) xk 00307 dofs(k) = Jinv.InnerProduct(vk, nk + d2n[k]*Dim); 00308 } 00309 } 00310 00311 void VectorFiniteElement::Project_RT( 00312 const double *nk, const Array<int> &d2n, const FiniteElement &fe, 00313 ElementTransformation &Trans, DenseMatrix &I) const 00314 { 00315 if (fe.GetRangeType() == SCALAR) 00316 { 00317 double vk[3]; 00318 Vector shape(fe.GetDof()); 00319 #ifdef MFEM_USE_OPENMP 00320 DenseMatrix Jinv(Dim); 00321 #endif 00322 00323 I.SetSize(Dof, Dim*fe.GetDof()); 00324 for (int k = 0; k < Dof; k++) 00325 { 00326 const IntegrationPoint &ip = Nodes.IntPoint(k); 00327 00328 fe.CalcShape(ip, shape); 00329 Trans.SetIntPoint(&ip); 00330 CalcAdjugateTranspose(Trans.Jacobian(), Jinv); 00331 Jinv.Mult(nk + d2n[k]*Dim, vk); 00332 00333 for (int j = 0; j < shape.Size(); j++) 00334 { 00335 double s = shape(j); 00336 if (fabs(s) < 1e-12) 00337 s = 0.0; 00338 for (int d = 0; d < Dim; d++) 00339 I(k,j+d*shape.Size()) = s*vk[d]; 00340 } 00341 } 00342 } 00343 else 00344 { 00345 mfem_error("VectorFiniteElement::Project_RT (fe version)"); 00346 } 00347 } 00348 00349 void VectorFiniteElement::ProjectGrad_RT( 00350 const double *nk, const Array<int> &d2n, const FiniteElement &fe, 00351 ElementTransformation &Trans, DenseMatrix &grad) const 00352 { 00353 if (Dim != 2) 00354 mfem_error("VectorFiniteElement::ProjectGrad_RT works only in 2D!"); 00355 00356 DenseMatrix dshape(fe.GetDof(), fe.GetDim()); 00357 Vector grad_k(fe.GetDof()); 00358 double tk[2]; 00359 00360 grad.SetSize(Dof, fe.GetDof()); 00361 for (int k = 0; k < Dof; k++) 00362 { 00363 fe.CalcDShape(Nodes.IntPoint(k), dshape); 00364 tk[0] = nk[d2n[k]*Dim+1]; 00365 tk[1] = -nk[d2n[k]*Dim]; 00366 dshape.Mult(tk, grad_k); 00367 for (int j = 0; j < grad_k.Size(); j++) 00368 grad(k,j) = (fabs(grad_k(j)) < 1e-12) ? 0.0 : grad_k(j); 00369 } 00370 } 00371 00372 void VectorFiniteElement::ProjectCurl_RT( 00373 const double *nk, const Array<int> &d2n, const FiniteElement &fe, 00374 ElementTransformation &Trans, DenseMatrix &curl) const 00375 { 00376 DenseMatrix curl_shape(fe.GetDof(), Dim); 00377 Vector curl_k(fe.GetDof()); 00378 00379 curl.SetSize(Dof, fe.GetDof()); 00380 for (int k = 0; k < Dof; k++) 00381 { 00382 fe.CalcCurlShape(Nodes.IntPoint(k), curl_shape); 00383 curl_shape.Mult(nk + d2n[k]*Dim, curl_k); 00384 for (int j = 0; j < curl_k.Size(); j++) 00385 curl(k,j) = (fabs(curl_k(j)) < 1e-12) ? 0.0 : curl_k(j); 00386 } 00387 } 00388 00389 void VectorFiniteElement::Project_ND( 00390 const double *tk, const Array<int> &d2t, 00391 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const 00392 { 00393 double vk[3]; 00394 Vector xk(vk, vc.GetVDim()); 00395 00396 for (int k = 0; k < Dof; k++) 00397 { 00398 Trans.SetIntPoint(&Nodes.IntPoint(k)); 00399 00400 vc.Eval(xk, Trans, Nodes.IntPoint(k)); 00401 // dof_k = xk^t J tk 00402 dofs(k) = Trans.Jacobian().InnerProduct(tk + d2t[k]*Dim, vk); 00403 } 00404 } 00405 00406 void VectorFiniteElement::Project_ND( 00407 const double *tk, const Array<int> &d2t, const FiniteElement &fe, 00408 ElementTransformation &Trans, DenseMatrix &I) const 00409 { 00410 if (fe.GetRangeType() == SCALAR) 00411 { 00412 double vk[3]; 00413 Vector shape(fe.GetDof()); 00414 00415 I.SetSize(Dof, Dim*fe.GetDof()); 00416 for (int k = 0; k < Dof; k++) 00417 { 00418 const IntegrationPoint &ip = Nodes.IntPoint(k); 00419 00420 fe.CalcShape(ip, shape); 00421 Trans.SetIntPoint(&ip); 00422 Trans.Jacobian().Mult(tk + d2t[k]*Dim, vk); 00423 00424 for (int j = 0; j < shape.Size(); j++) 00425 { 00426 double s = shape(j); 00427 if (fabs(s) < 1e-12) 00428 s = 0.0; 00429 for (int d = 0; d < Dim; d++) 00430 I(k, j + d*shape.Size()) = s*vk[d]; 00431 } 00432 } 00433 } 00434 else 00435 { 00436 mfem_error("VectorFiniteElement::Project_ND (fe version)"); 00437 } 00438 } 00439 00440 void VectorFiniteElement::ProjectGrad_ND( 00441 const double *tk, const Array<int> &d2t, const FiniteElement &fe, 00442 ElementTransformation &Trans, DenseMatrix &grad) const 00443 { 00444 DenseMatrix dshape(fe.GetDof(), fe.GetDim()); 00445 Vector grad_k(fe.GetDof()); 00446 00447 grad.SetSize(Dof, fe.GetDof()); 00448 for (int k = 0; k < Dof; k++) 00449 { 00450 fe.CalcDShape(Nodes.IntPoint(k), dshape); 00451 dshape.Mult(tk + d2t[k]*Dim, grad_k); 00452 for (int j = 0; j < grad_k.Size(); j++) 00453 grad(k,j) = (fabs(grad_k(j)) < 1e-12) ? 0.0 : grad_k(j); 00454 } 00455 } 00456 00457 void VectorFiniteElement::LocalInterpolation_RT( 00458 const double *nk, const Array<int> &d2n, ElementTransformation &Trans, 00459 DenseMatrix &I) const 00460 { 00461 double vk[3]; 00462 Vector xk(vk, Dim); 00463 IntegrationPoint ip; 00464 #ifdef MFEM_USE_OPENMP 00465 DenseMatrix vshape(Dof, Dim); 00466 DenseMatrix Jinv(Dim); 00467 #endif 00468 00469 // assuming Trans is linear; this should be ok for all refinement types 00470 Trans.SetIntPoint(&Geometries.GetCenter(GeomType)); 00471 // set Jinv = |J| J^{-t} = adj(J)^t 00472 CalcAdjugateTranspose(Trans.Jacobian(), Jinv); 00473 for (int k = 0; k < Dof; k++) 00474 { 00475 Trans.Transform(Nodes.IntPoint(k), xk); 00476 ip.Set3(vk); 00477 CalcVShape(ip, vshape); 00478 // xk = |J| J^{-t} n_k 00479 Jinv.Mult(nk + d2n[k]*Dim, vk); 00480 // I_k = vshape_k.adj(J)^t.n_k, k=1,...,Dof 00481 for (int j = 0; j < Dof; j++) 00482 { 00483 double Ikj = 0.; 00484 for (int i = 0; i < Dim; i++) 00485 Ikj += vshape(j, i) * vk[i]; 00486 I(k, j) = (fabs(Ikj) < 1e-12) ? 0.0 : Ikj; 00487 } 00488 } 00489 } 00490 00491 void VectorFiniteElement::LocalInterpolation_ND( 00492 const double *tk, const Array<int> &d2t, ElementTransformation &Trans, 00493 DenseMatrix &I) const 00494 { 00495 double vk[3]; 00496 Vector xk(vk, Dim); 00497 IntegrationPoint ip; 00498 #ifdef MFEM_USE_OPENMP 00499 DenseMatrix vshape(Dof, Dim); 00500 #endif 00501 00502 // assuming Trans is linear; this should be ok for all refinement types 00503 Trans.SetIntPoint(&Geometries.GetCenter(GeomType)); 00504 const DenseMatrix &J = Trans.Jacobian(); 00505 for (int k = 0; k < Dof; k++) 00506 { 00507 Trans.Transform(Nodes.IntPoint(k), xk); 00508 ip.Set3(vk); 00509 CalcVShape(ip, vshape); 00510 // xk = J t_k 00511 J.Mult(tk + d2t[k]*Dim, vk); 00512 // I_k = vshape_k.J.t_k, k=1,...,Dof 00513 for (int j = 0; j < Dof; j++) 00514 { 00515 double Ikj = 0.; 00516 for (int i = 0; i < Dim; i++) 00517 Ikj += vshape(j, i) * vk[i]; 00518 I(k, j) = (fabs(Ikj) < 1e-12) ? 0.0 : Ikj; 00519 } 00520 } 00521 } 00522 00523 00524 PointFiniteElement::PointFiniteElement() 00525 : NodalFiniteElement(0, Geometry::POINT, 1, 0) 00526 { 00527 Nodes.IntPoint(0).x = 0.0; 00528 } 00529 00530 void PointFiniteElement::CalcShape(const IntegrationPoint &ip, 00531 Vector &shape) const 00532 { 00533 shape(0) = 1.; 00534 } 00535 00536 void PointFiniteElement::CalcDShape(const IntegrationPoint &ip, 00537 DenseMatrix &dshape) const 00538 { 00539 // doesn't make sense 00540 } 00541 00542 Linear1DFiniteElement::Linear1DFiniteElement() 00543 : NodalFiniteElement(1, Geometry::SEGMENT, 2, 1) 00544 { 00545 Nodes.IntPoint(0).x = 0.0; 00546 Nodes.IntPoint(1).x = 1.0; 00547 } 00548 00549 void Linear1DFiniteElement::CalcShape(const IntegrationPoint &ip, 00550 Vector &shape) const 00551 { 00552 shape(0) = 1. - ip.x; 00553 shape(1) = ip.x; 00554 } 00555 00556 void Linear1DFiniteElement::CalcDShape(const IntegrationPoint &ip, 00557 DenseMatrix &dshape) const 00558 { 00559 dshape(0,0) = -1.; 00560 dshape(1,0) = 1.; 00561 } 00562 00563 Linear2DFiniteElement::Linear2DFiniteElement() 00564 : NodalFiniteElement(2, Geometry::TRIANGLE, 3, 1) 00565 { 00566 Nodes.IntPoint(0).x = 0.0; 00567 Nodes.IntPoint(0).y = 0.0; 00568 Nodes.IntPoint(1).x = 1.0; 00569 Nodes.IntPoint(1).y = 0.0; 00570 Nodes.IntPoint(2).x = 0.0; 00571 Nodes.IntPoint(2).y = 1.0; 00572 } 00573 00574 void Linear2DFiniteElement::CalcShape(const IntegrationPoint &ip, 00575 Vector &shape) const 00576 { 00577 shape(0) = 1. - ip.x - ip.y; 00578 shape(1) = ip.x; 00579 shape(2) = ip.y; 00580 } 00581 00582 void Linear2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 00583 DenseMatrix &dshape) const 00584 { 00585 dshape(0,0) = -1.; dshape(0,1) = -1.; 00586 dshape(1,0) = 1.; dshape(1,1) = 0.; 00587 dshape(2,0) = 0.; dshape(2,1) = 1.; 00588 } 00589 00590 BiLinear2DFiniteElement::BiLinear2DFiniteElement() 00591 : NodalFiniteElement(2, Geometry::SQUARE , 4, 1, FunctionSpace::Qk) 00592 { 00593 Nodes.IntPoint(0).x = 0.0; 00594 Nodes.IntPoint(0).y = 0.0; 00595 Nodes.IntPoint(1).x = 1.0; 00596 Nodes.IntPoint(1).y = 0.0; 00597 Nodes.IntPoint(2).x = 1.0; 00598 Nodes.IntPoint(2).y = 1.0; 00599 Nodes.IntPoint(3).x = 0.0; 00600 Nodes.IntPoint(3).y = 1.0; 00601 } 00602 00603 void BiLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip, 00604 Vector &shape) const 00605 { 00606 shape(0) = (1. - ip.x) * (1. - ip.y) ; 00607 shape(1) = ip.x * (1. - ip.y) ; 00608 shape(2) = ip.x * ip.y ; 00609 shape(3) = (1. - ip.x) * ip.y ; 00610 } 00611 00612 void BiLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 00613 DenseMatrix &dshape) const 00614 { 00615 dshape(0,0) = -1. + ip.y; dshape(0,1) = -1. + ip.x ; 00616 dshape(1,0) = 1. - ip.y; dshape(1,1) = -ip.x ; 00617 dshape(2,0) = ip.y ; dshape(2,1) = ip.x ; 00618 dshape(3,0) = -ip.y ; dshape(3,1) = 1. - ip.x ; 00619 } 00620 00621 void BiLinear2DFiniteElement::CalcHessian( 00622 const IntegrationPoint &ip, DenseMatrix &h) const 00623 { 00624 h( 0,0) = 0.; h( 0,1) = 1.; h( 0,2) = 0.; 00625 h( 1,0) = 0.; h( 1,1) = -1.; h( 1,2) = 0.; 00626 h( 2,0) = 0.; h( 2,1) = 1.; h( 2,2) = 0.; 00627 h( 3,0) = 0.; h( 3,1) = -1.; h( 3,2) = 0.; 00628 } 00629 00630 00631 GaussLinear2DFiniteElement::GaussLinear2DFiniteElement() 00632 : NodalFiniteElement(2, Geometry::TRIANGLE, 3, 1, FunctionSpace::Pk) 00633 { 00634 Nodes.IntPoint(0).x = 1./6.; 00635 Nodes.IntPoint(0).y = 1./6.; 00636 Nodes.IntPoint(1).x = 2./3.; 00637 Nodes.IntPoint(1).y = 1./6.; 00638 Nodes.IntPoint(2).x = 1./6.; 00639 Nodes.IntPoint(2).y = 2./3.; 00640 } 00641 00642 void GaussLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip, 00643 Vector &shape) const 00644 { 00645 const double x = ip.x, y = ip.y; 00646 00647 shape(0) = 5./3. - 2. * (x + y); 00648 shape(1) = 2. * (x - 1./6.); 00649 shape(2) = 2. * (y - 1./6.); 00650 } 00651 00652 void GaussLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 00653 DenseMatrix &dshape) const 00654 { 00655 dshape(0,0) = -2.; dshape(0,1) = -2.; 00656 dshape(1,0) = 2.; dshape(1,1) = 0.; 00657 dshape(2,0) = 0.; dshape(2,1) = 2.; 00658 } 00659 00660 void GaussLinear2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const 00661 { 00662 dofs(vertex) = 2./3.; 00663 dofs((vertex+1)%3) = 1./6.; 00664 dofs((vertex+2)%3) = 1./6.; 00665 } 00666 00667 00668 // 0.5-0.5/sqrt(3) and 0.5+0.5/sqrt(3) 00669 const double GaussBiLinear2DFiniteElement::p[] = 00670 { 0.2113248654051871177454256, 0.7886751345948128822545744 }; 00671 00672 GaussBiLinear2DFiniteElement::GaussBiLinear2DFiniteElement() 00673 : NodalFiniteElement(2, Geometry::SQUARE, 4, 1, FunctionSpace::Qk) 00674 { 00675 Nodes.IntPoint(0).x = p[0]; 00676 Nodes.IntPoint(0).y = p[0]; 00677 Nodes.IntPoint(1).x = p[1]; 00678 Nodes.IntPoint(1).y = p[0]; 00679 Nodes.IntPoint(2).x = p[1]; 00680 Nodes.IntPoint(2).y = p[1]; 00681 Nodes.IntPoint(3).x = p[0]; 00682 Nodes.IntPoint(3).y = p[1]; 00683 } 00684 00685 void GaussBiLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip, 00686 Vector &shape) const 00687 { 00688 const double x = ip.x, y = ip.y; 00689 00690 shape(0) = 3. * (p[1] - x) * (p[1] - y); 00691 shape(1) = 3. * (x - p[0]) * (p[1] - y); 00692 shape(2) = 3. * (x - p[0]) * (y - p[0]); 00693 shape(3) = 3. * (p[1] - x) * (y - p[0]); 00694 } 00695 00696 void GaussBiLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 00697 DenseMatrix &dshape) const 00698 { 00699 const double x = ip.x, y = ip.y; 00700 00701 dshape(0,0) = 3. * (y - p[1]); dshape(0,1) = 3. * (x - p[1]); 00702 dshape(1,0) = 3. * (p[1] - y); dshape(1,1) = 3. * (p[0] - x); 00703 dshape(2,0) = 3. * (y - p[0]); dshape(2,1) = 3. * (x - p[0]); 00704 dshape(3,0) = 3. * (p[0] - y); dshape(3,1) = 3. * (p[1] - x); 00705 } 00706 00707 void GaussBiLinear2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const 00708 { 00709 #if 1 00710 dofs(vertex) = p[1]*p[1]; 00711 dofs((vertex+1)%4) = p[0]*p[1]; 00712 dofs((vertex+2)%4) = p[0]*p[0]; 00713 dofs((vertex+3)%4) = p[0]*p[1]; 00714 #else 00715 dofs = 1.0; 00716 #endif 00717 } 00718 00719 00720 P1OnQuadFiniteElement::P1OnQuadFiniteElement() 00721 : NodalFiniteElement(2, Geometry::SQUARE , 3, 1, FunctionSpace::Qk) 00722 { 00723 Nodes.IntPoint(0).x = 0.0; 00724 Nodes.IntPoint(0).y = 0.0; 00725 Nodes.IntPoint(1).x = 1.0; 00726 Nodes.IntPoint(1).y = 0.0; 00727 Nodes.IntPoint(2).x = 0.0; 00728 Nodes.IntPoint(2).y = 1.0; 00729 } 00730 00731 void P1OnQuadFiniteElement::CalcShape(const IntegrationPoint &ip, 00732 Vector &shape) const 00733 { 00734 shape(0) = 1. - ip.x - ip.y; 00735 shape(1) = ip.x; 00736 shape(2) = ip.y; 00737 } 00738 00739 void P1OnQuadFiniteElement::CalcDShape(const IntegrationPoint &ip, 00740 DenseMatrix &dshape) const 00741 { 00742 dshape(0,0) = -1.; dshape(0,1) = -1.; 00743 dshape(1,0) = 1.; dshape(1,1) = 0.; 00744 dshape(2,0) = 0.; dshape(2,1) = 1.; 00745 } 00746 00747 00748 Quad1DFiniteElement::Quad1DFiniteElement() 00749 : NodalFiniteElement(1, Geometry::SEGMENT, 3, 2) 00750 { 00751 Nodes.IntPoint(0).x = 0.0; 00752 Nodes.IntPoint(1).x = 1.0; 00753 Nodes.IntPoint(2).x = 0.5; 00754 } 00755 00756 void Quad1DFiniteElement::CalcShape(const IntegrationPoint &ip, 00757 Vector &shape) const 00758 { 00759 double x = ip.x; 00760 double l1 = 1.0 - x, l2 = x, l3 = 2. * x - 1.; 00761 00762 shape(0) = l1 * (-l3); 00763 shape(1) = l2 * l3; 00764 shape(2) = 4. * l1 * l2; 00765 } 00766 00767 void Quad1DFiniteElement::CalcDShape(const IntegrationPoint &ip, 00768 DenseMatrix &dshape) const 00769 { 00770 double x = ip.x; 00771 00772 dshape(0,0) = 4. * x - 3.; 00773 dshape(1,0) = 4. * x - 1.; 00774 dshape(2,0) = 4. - 8. * x; 00775 } 00776 00777 00778 QuadPos1DFiniteElement::QuadPos1DFiniteElement() 00779 : FiniteElement(1, Geometry::SEGMENT, 3, 2) 00780 { 00781 Nodes.IntPoint(0).x = 0.0; 00782 Nodes.IntPoint(1).x = 1.0; 00783 Nodes.IntPoint(2).x = 0.5; 00784 } 00785 00786 void QuadPos1DFiniteElement::CalcShape(const IntegrationPoint &ip, 00787 Vector &shape) const 00788 { 00789 const double x = ip.x, x1 = 1. - x; 00790 00791 shape(0) = x1 * x1; 00792 shape(1) = x * x; 00793 shape(2) = 2. * x * x1; 00794 } 00795 00796 void QuadPos1DFiniteElement::CalcDShape(const IntegrationPoint &ip, 00797 DenseMatrix &dshape) const 00798 { 00799 const double x = ip.x; 00800 00801 dshape(0,0) = 2. * x - 2.; 00802 dshape(1,0) = 2. * x; 00803 dshape(2,0) = 2. - 4. * x; 00804 } 00805 00806 Quad2DFiniteElement::Quad2DFiniteElement() 00807 : NodalFiniteElement(2, Geometry::TRIANGLE, 6, 2) 00808 { 00809 Nodes.IntPoint(0).x = 0.0; 00810 Nodes.IntPoint(0).y = 0.0; 00811 Nodes.IntPoint(1).x = 1.0; 00812 Nodes.IntPoint(1).y = 0.0; 00813 Nodes.IntPoint(2).x = 0.0; 00814 Nodes.IntPoint(2).y = 1.0; 00815 Nodes.IntPoint(3).x = 0.5; 00816 Nodes.IntPoint(3).y = 0.0; 00817 Nodes.IntPoint(4).x = 0.5; 00818 Nodes.IntPoint(4).y = 0.5; 00819 Nodes.IntPoint(5).x = 0.0; 00820 Nodes.IntPoint(5).y = 0.5; 00821 } 00822 00823 void Quad2DFiniteElement::CalcShape(const IntegrationPoint &ip, 00824 Vector &shape) const 00825 { 00826 double x = ip.x, y = ip.y; 00827 double l1 = 1.-x-y, l2 = x, l3 = y; 00828 00829 shape(0) = l1 * (2. * l1 - 1.); 00830 shape(1) = l2 * (2. * l2 - 1.); 00831 shape(2) = l3 * (2. * l3 - 1.); 00832 shape(3) = 4. * l1 * l2; 00833 shape(4) = 4. * l2 * l3; 00834 shape(5) = 4. * l3 * l1; 00835 } 00836 00837 void Quad2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 00838 DenseMatrix &dshape) const 00839 { 00840 double x = ip.x, y = ip.y; 00841 00842 dshape(0,0) = 00843 dshape(0,1) = 4. * (x + y) - 3.; 00844 00845 dshape(1,0) = 4. * x - 1.; 00846 dshape(1,1) = 0.; 00847 00848 dshape(2,0) = 0.; 00849 dshape(2,1) = 4. * y - 1.; 00850 00851 dshape(3,0) = -4. * (2. * x + y - 1.); 00852 dshape(3,1) = -4. * x; 00853 00854 dshape(4,0) = 4. * y; 00855 dshape(4,1) = 4. * x; 00856 00857 dshape(5,0) = -4. * y; 00858 dshape(5,1) = -4. * (x + 2. * y - 1.); 00859 } 00860 00861 void Quad2DFiniteElement::CalcHessian (const IntegrationPoint &ip, 00862 DenseMatrix &h) const 00863 { 00864 h(0,0) = 4.; 00865 h(0,1) = 4.; 00866 h(0,2) = 4.; 00867 00868 h(1,0) = 4.; 00869 h(1,1) = 0.; 00870 h(1,2) = 0.; 00871 00872 h(2,0) = 0.; 00873 h(2,1) = 0.; 00874 h(2,2) = 4.; 00875 00876 h(3,0) = -8.; 00877 h(3,1) = -4.; 00878 h(3,2) = 0.; 00879 00880 h(4,0) = 0.; 00881 h(4,1) = 4.; 00882 h(4,2) = 0.; 00883 00884 h(5,0) = 0.; 00885 h(5,1) = -4.; 00886 h(5,2) = -8.; 00887 } 00888 00889 void Quad2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const 00890 { 00891 #if 0 00892 dofs = 1.; 00893 #else 00894 dofs = 0.; 00895 dofs(vertex) = 1.; 00896 switch (vertex) 00897 { 00898 case 0: dofs(3) = 0.25; dofs(5) = 0.25; break; 00899 case 1: dofs(3) = 0.25; dofs(4) = 0.25; break; 00900 case 2: dofs(4) = 0.25; dofs(5) = 0.25; break; 00901 } 00902 #endif 00903 } 00904 00905 00906 const double GaussQuad2DFiniteElement::p[] = 00907 { 0.0915762135097707434595714634022015, 0.445948490915964886318329253883051 }; 00908 00909 GaussQuad2DFiniteElement::GaussQuad2DFiniteElement() 00910 : NodalFiniteElement(2, Geometry::TRIANGLE, 6, 2), A(6), D(6,2), pol(6) 00911 { 00912 Nodes.IntPoint(0).x = p[0]; 00913 Nodes.IntPoint(0).y = p[0]; 00914 Nodes.IntPoint(1).x = 1. - 2. * p[0]; 00915 Nodes.IntPoint(1).y = p[0]; 00916 Nodes.IntPoint(2).x = p[0]; 00917 Nodes.IntPoint(2).y = 1. - 2. * p[0]; 00918 Nodes.IntPoint(3).x = p[1]; 00919 Nodes.IntPoint(3).y = p[1]; 00920 Nodes.IntPoint(4).x = 1. - 2. * p[1]; 00921 Nodes.IntPoint(4).y = p[1]; 00922 Nodes.IntPoint(5).x = p[1]; 00923 Nodes.IntPoint(5).y = 1. - 2. * p[1]; 00924 00925 for (int i = 0; i < 6; i++) 00926 { 00927 const double x = Nodes.IntPoint(i).x, y = Nodes.IntPoint(i).y; 00928 A(0,i) = 1.; 00929 A(1,i) = x; 00930 A(2,i) = y; 00931 A(3,i) = x * x; 00932 A(4,i) = x * y; 00933 A(5,i) = y * y; 00934 } 00935 00936 A.Invert(); 00937 } 00938 00939 void GaussQuad2DFiniteElement::CalcShape(const IntegrationPoint &ip, 00940 Vector &shape) const 00941 { 00942 const double x = ip.x, y = ip.y; 00943 pol(0) = 1.; 00944 pol(1) = x; 00945 pol(2) = y; 00946 pol(3) = x * x; 00947 pol(4) = x * y; 00948 pol(5) = y * y; 00949 00950 A.Mult(pol, shape); 00951 } 00952 00953 void GaussQuad2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 00954 DenseMatrix &dshape) const 00955 { 00956 const double x = ip.x, y = ip.y; 00957 D(0,0) = 0.; D(0,1) = 0.; 00958 D(1,0) = 1.; D(1,1) = 0.; 00959 D(2,0) = 0.; D(2,1) = 1.; 00960 D(3,0) = 2. * x; D(3,1) = 0.; 00961 D(4,0) = y; D(4,1) = x; 00962 D(5,0) = 0.; D(5,1) = 2. * y; 00963 00964 Mult(A, D, dshape); 00965 } 00966 00967 00968 BiQuad2DFiniteElement::BiQuad2DFiniteElement() 00969 : NodalFiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk) 00970 { 00971 Nodes.IntPoint(0).x = 0.0; 00972 Nodes.IntPoint(0).y = 0.0; 00973 Nodes.IntPoint(1).x = 1.0; 00974 Nodes.IntPoint(1).y = 0.0; 00975 Nodes.IntPoint(2).x = 1.0; 00976 Nodes.IntPoint(2).y = 1.0; 00977 Nodes.IntPoint(3).x = 0.0; 00978 Nodes.IntPoint(3).y = 1.0; 00979 Nodes.IntPoint(4).x = 0.5; 00980 Nodes.IntPoint(4).y = 0.0; 00981 Nodes.IntPoint(5).x = 1.0; 00982 Nodes.IntPoint(5).y = 0.5; 00983 Nodes.IntPoint(6).x = 0.5; 00984 Nodes.IntPoint(6).y = 1.0; 00985 Nodes.IntPoint(7).x = 0.0; 00986 Nodes.IntPoint(7).y = 0.5; 00987 Nodes.IntPoint(8).x = 0.5; 00988 Nodes.IntPoint(8).y = 0.5; 00989 } 00990 00991 void BiQuad2DFiniteElement::CalcShape(const IntegrationPoint &ip, 00992 Vector &shape) const 00993 { 00994 double x = ip.x, y = ip.y; 00995 double l1x, l2x, l3x, l1y, l2y, l3y; 00996 00997 l1x = (x - 1.) * (2. * x - 1); 00998 l2x = 4. * x * (1. - x); 00999 l3x = x * (2. * x - 1.); 01000 l1y = (y - 1.) * (2. * y - 1); 01001 l2y = 4. * y * (1. - y); 01002 l3y = y * (2. * y - 1.); 01003 01004 shape(0) = l1x * l1y; 01005 shape(4) = l2x * l1y; 01006 shape(1) = l3x * l1y; 01007 shape(7) = l1x * l2y; 01008 shape(8) = l2x * l2y; 01009 shape(5) = l3x * l2y; 01010 shape(3) = l1x * l3y; 01011 shape(6) = l2x * l3y; 01012 shape(2) = l3x * l3y; 01013 } 01014 01015 void BiQuad2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 01016 DenseMatrix &dshape) const 01017 { 01018 double x = ip.x, y = ip.y; 01019 double l1x, l2x, l3x, l1y, l2y, l3y; 01020 double d1x, d2x, d3x, d1y, d2y, d3y; 01021 01022 l1x = (x - 1.) * (2. * x - 1); 01023 l2x = 4. * x * (1. - x); 01024 l3x = x * (2. * x - 1.); 01025 l1y = (y - 1.) * (2. * y - 1); 01026 l2y = 4. * y * (1. - y); 01027 l3y = y * (2. * y - 1.); 01028 01029 d1x = 4. * x - 3.; 01030 d2x = 4. - 8. * x; 01031 d3x = 4. * x - 1.; 01032 d1y = 4. * y - 3.; 01033 d2y = 4. - 8. * y; 01034 d3y = 4. * y - 1.; 01035 01036 dshape(0,0) = d1x * l1y; 01037 dshape(0,1) = l1x * d1y; 01038 01039 dshape(4,0) = d2x * l1y; 01040 dshape(4,1) = l2x * d1y; 01041 01042 dshape(1,0) = d3x * l1y; 01043 dshape(1,1) = l3x * d1y; 01044 01045 dshape(7,0) = d1x * l2y; 01046 dshape(7,1) = l1x * d2y; 01047 01048 dshape(8,0) = d2x * l2y; 01049 dshape(8,1) = l2x * d2y; 01050 01051 dshape(5,0) = d3x * l2y; 01052 dshape(5,1) = l3x * d2y; 01053 01054 dshape(3,0) = d1x * l3y; 01055 dshape(3,1) = l1x * d3y; 01056 01057 dshape(6,0) = d2x * l3y; 01058 dshape(6,1) = l2x * d3y; 01059 01060 dshape(2,0) = d3x * l3y; 01061 dshape(2,1) = l3x * d3y; 01062 } 01063 01064 void BiQuad2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const 01065 { 01066 #if 0 01067 dofs = 1.; 01068 #else 01069 dofs = 0.; 01070 dofs(vertex) = 1.; 01071 switch (vertex) 01072 { 01073 case 0: dofs(4) = 0.25; dofs(7) = 0.25; break; 01074 case 1: dofs(4) = 0.25; dofs(5) = 0.25; break; 01075 case 2: dofs(5) = 0.25; dofs(6) = 0.25; break; 01076 case 3: dofs(6) = 0.25; dofs(7) = 0.25; break; 01077 } 01078 dofs(8) = 1./16.; 01079 #endif 01080 } 01081 01082 BiQuadPos2DFiniteElement::BiQuadPos2DFiniteElement() 01083 : FiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk) 01084 { 01085 Nodes.IntPoint(0).x = 0.0; 01086 Nodes.IntPoint(0).y = 0.0; 01087 Nodes.IntPoint(1).x = 1.0; 01088 Nodes.IntPoint(1).y = 0.0; 01089 Nodes.IntPoint(2).x = 1.0; 01090 Nodes.IntPoint(2).y = 1.0; 01091 Nodes.IntPoint(3).x = 0.0; 01092 Nodes.IntPoint(3).y = 1.0; 01093 Nodes.IntPoint(4).x = 0.5; 01094 Nodes.IntPoint(4).y = 0.0; 01095 Nodes.IntPoint(5).x = 1.0; 01096 Nodes.IntPoint(5).y = 0.5; 01097 Nodes.IntPoint(6).x = 0.5; 01098 Nodes.IntPoint(6).y = 1.0; 01099 Nodes.IntPoint(7).x = 0.0; 01100 Nodes.IntPoint(7).y = 0.5; 01101 Nodes.IntPoint(8).x = 0.5; 01102 Nodes.IntPoint(8).y = 0.5; 01103 } 01104 01105 void BiQuadPos2DFiniteElement::CalcShape(const IntegrationPoint &ip, 01106 Vector &shape) const 01107 { 01108 double x = ip.x, y = ip.y; 01109 double l1x, l2x, l3x, l1y, l2y, l3y; 01110 01111 l1x = (1. - x) * (1. - x); 01112 l2x = 2. * x * (1. - x); 01113 l3x = x * x; 01114 l1y = (1. - y) * (1. - y); 01115 l2y = 2. * y * (1. - y); 01116 l3y = y * y; 01117 01118 shape(0) = l1x * l1y; 01119 shape(4) = l2x * l1y; 01120 shape(1) = l3x * l1y; 01121 shape(7) = l1x * l2y; 01122 shape(8) = l2x * l2y; 01123 shape(5) = l3x * l2y; 01124 shape(3) = l1x * l3y; 01125 shape(6) = l2x * l3y; 01126 shape(2) = l3x * l3y; 01127 } 01128 01129 void BiQuadPos2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 01130 DenseMatrix &dshape) const 01131 { 01132 double x = ip.x, y = ip.y; 01133 double l1x, l2x, l3x, l1y, l2y, l3y; 01134 double d1x, d2x, d3x, d1y, d2y, d3y; 01135 01136 l1x = (1. - x) * (1. - x); 01137 l2x = 2. * x * (1. - x); 01138 l3x = x * x; 01139 l1y = (1. - y) * (1. - y); 01140 l2y = 2. * y * (1. - y); 01141 l3y = y * y; 01142 01143 d1x = 2. * x - 2.; 01144 d2x = 2. - 4. * x; 01145 d3x = 2. * x; 01146 d1y = 2. * y - 2.; 01147 d2y = 2. - 4. * y; 01148 d3y = 2. * y; 01149 01150 dshape(0,0) = d1x * l1y; 01151 dshape(0,1) = l1x * d1y; 01152 01153 dshape(4,0) = d2x * l1y; 01154 dshape(4,1) = l2x * d1y; 01155 01156 dshape(1,0) = d3x * l1y; 01157 dshape(1,1) = l3x * d1y; 01158 01159 dshape(7,0) = d1x * l2y; 01160 dshape(7,1) = l1x * d2y; 01161 01162 dshape(8,0) = d2x * l2y; 01163 dshape(8,1) = l2x * d2y; 01164 01165 dshape(5,0) = d3x * l2y; 01166 dshape(5,1) = l3x * d2y; 01167 01168 dshape(3,0) = d1x * l3y; 01169 dshape(3,1) = l1x * d3y; 01170 01171 dshape(6,0) = d2x * l3y; 01172 dshape(6,1) = l2x * d3y; 01173 01174 dshape(2,0) = d3x * l3y; 01175 dshape(2,1) = l3x * d3y; 01176 } 01177 01178 void BiQuadPos2DFiniteElement::Project( 01179 Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const 01180 { 01181 double *d = dofs; 01182 01183 for (int i = 0; i < 9; i++) 01184 { 01185 const IntegrationPoint &ip = Nodes.IntPoint(i); 01186 Trans.SetIntPoint(&ip); 01187 d[i] = coeff.Eval(Trans, ip); 01188 } 01189 d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]); 01190 d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]); 01191 d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]); 01192 d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]); 01193 d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) - 01194 0.25 * (d[0] + d[1] + d[2] + d[3]); 01195 } 01196 01197 void BiQuadPos2DFiniteElement::Project ( 01198 VectorCoefficient &vc, ElementTransformation &Trans, 01199 Vector &dofs) const 01200 { 01201 double v[3]; 01202 Vector x (v, vc.GetVDim()); 01203 01204 for (int i = 0; i < 9; i++) 01205 { 01206 const IntegrationPoint &ip = Nodes.IntPoint(i); 01207 Trans.SetIntPoint(&ip); 01208 vc.Eval (x, Trans, ip); 01209 for (int j = 0; j < x.Size(); j++) 01210 dofs(9*j+i) = v[j]; 01211 } 01212 for (int j = 0; j < x.Size(); j++) 01213 { 01214 double *d = &dofs(9*j); 01215 01216 d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]); 01217 d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]); 01218 d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]); 01219 d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]); 01220 d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) - 01221 0.25 * (d[0] + d[1] + d[2] + d[3]); 01222 } 01223 } 01224 01225 01226 GaussBiQuad2DFiniteElement::GaussBiQuad2DFiniteElement() 01227 : NodalFiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk) 01228 { 01229 const double p1 = 0.5*(1.-sqrt(3./5.)); 01230 01231 Nodes.IntPoint(0).x = p1; 01232 Nodes.IntPoint(0).y = p1; 01233 Nodes.IntPoint(4).x = 0.5; 01234 Nodes.IntPoint(4).y = p1; 01235 Nodes.IntPoint(1).x = 1.-p1; 01236 Nodes.IntPoint(1).y = p1; 01237 Nodes.IntPoint(7).x = p1; 01238 Nodes.IntPoint(7).y = 0.5; 01239 Nodes.IntPoint(8).x = 0.5; 01240 Nodes.IntPoint(8).y = 0.5; 01241 Nodes.IntPoint(5).x = 1.-p1; 01242 Nodes.IntPoint(5).y = 0.5; 01243 Nodes.IntPoint(3).x = p1; 01244 Nodes.IntPoint(3).y = 1.-p1; 01245 Nodes.IntPoint(6).x = 0.5; 01246 Nodes.IntPoint(6).y = 1.-p1; 01247 Nodes.IntPoint(2).x = 1.-p1; 01248 Nodes.IntPoint(2).y = 1.-p1; 01249 } 01250 01251 void GaussBiQuad2DFiniteElement::CalcShape(const IntegrationPoint &ip, 01252 Vector &shape) const 01253 { 01254 const double a = sqrt(5./3.); 01255 const double p1 = 0.5*(1.-sqrt(3./5.)); 01256 01257 double x = a*(ip.x-p1), y = a*(ip.y-p1); 01258 double l1x, l2x, l3x, l1y, l2y, l3y; 01259 01260 l1x = (x - 1.) * (2. * x - 1); 01261 l2x = 4. * x * (1. - x); 01262 l3x = x * (2. * x - 1.); 01263 l1y = (y - 1.) * (2. * y - 1); 01264 l2y = 4. * y * (1. - y); 01265 l3y = y * (2. * y - 1.); 01266 01267 shape(0) = l1x * l1y; 01268 shape(4) = l2x * l1y; 01269 shape(1) = l3x * l1y; 01270 shape(7) = l1x * l2y; 01271 shape(8) = l2x * l2y; 01272 shape(5) = l3x * l2y; 01273 shape(3) = l1x * l3y; 01274 shape(6) = l2x * l3y; 01275 shape(2) = l3x * l3y; 01276 } 01277 01278 void GaussBiQuad2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 01279 DenseMatrix &dshape) const 01280 { 01281 const double a = sqrt(5./3.); 01282 const double p1 = 0.5*(1.-sqrt(3./5.)); 01283 01284 double x = a*(ip.x-p1), y = a*(ip.y-p1); 01285 double l1x, l2x, l3x, l1y, l2y, l3y; 01286 double d1x, d2x, d3x, d1y, d2y, d3y; 01287 01288 l1x = (x - 1.) * (2. * x - 1); 01289 l2x = 4. * x * (1. - x); 01290 l3x = x * (2. * x - 1.); 01291 l1y = (y - 1.) * (2. * y - 1); 01292 l2y = 4. * y * (1. - y); 01293 l3y = y * (2. * y - 1.); 01294 01295 d1x = a * (4. * x - 3.); 01296 d2x = a * (4. - 8. * x); 01297 d3x = a * (4. * x - 1.); 01298 d1y = a * (4. * y - 3.); 01299 d2y = a * (4. - 8. * y); 01300 d3y = a * (4. * y - 1.); 01301 01302 dshape(0,0) = d1x * l1y; 01303 dshape(0,1) = l1x * d1y; 01304 01305 dshape(4,0) = d2x * l1y; 01306 dshape(4,1) = l2x * d1y; 01307 01308 dshape(1,0) = d3x * l1y; 01309 dshape(1,1) = l3x * d1y; 01310 01311 dshape(7,0) = d1x * l2y; 01312 dshape(7,1) = l1x * d2y; 01313 01314 dshape(8,0) = d2x * l2y; 01315 dshape(8,1) = l2x * d2y; 01316 01317 dshape(5,0) = d3x * l2y; 01318 dshape(5,1) = l3x * d2y; 01319 01320 dshape(3,0) = d1x * l3y; 01321 dshape(3,1) = l1x * d3y; 01322 01323 dshape(6,0) = d2x * l3y; 01324 dshape(6,1) = l2x * d3y; 01325 01326 dshape(2,0) = d3x * l3y; 01327 dshape(2,1) = l3x * d3y; 01328 } 01329 01330 BiCubic2DFiniteElement::BiCubic2DFiniteElement() 01331 : NodalFiniteElement (2, Geometry::SQUARE, 16, 3, FunctionSpace::Qk) 01332 { 01333 Nodes.IntPoint(0).x = 0.; 01334 Nodes.IntPoint(0).y = 0.; 01335 Nodes.IntPoint(1).x = 1.; 01336 Nodes.IntPoint(1).y = 0.; 01337 Nodes.IntPoint(2).x = 1.; 01338 Nodes.IntPoint(2).y = 1.; 01339 Nodes.IntPoint(3).x = 0.; 01340 Nodes.IntPoint(3).y = 1.; 01341 Nodes.IntPoint(4).x = 1./3.; 01342 Nodes.IntPoint(4).y = 0.; 01343 Nodes.IntPoint(5).x = 2./3.; 01344 Nodes.IntPoint(5).y = 0.; 01345 Nodes.IntPoint(6).x = 1.; 01346 Nodes.IntPoint(6).y = 1./3.; 01347 Nodes.IntPoint(7).x = 1.; 01348 Nodes.IntPoint(7).y = 2./3.; 01349 Nodes.IntPoint(8).x = 2./3.; 01350 Nodes.IntPoint(8).y = 1.; 01351 Nodes.IntPoint(9).x = 1./3.; 01352 Nodes.IntPoint(9).y = 1.; 01353 Nodes.IntPoint(10).x = 0.; 01354 Nodes.IntPoint(10).y = 2./3.; 01355 Nodes.IntPoint(11).x = 0.; 01356 Nodes.IntPoint(11).y = 1./3.; 01357 Nodes.IntPoint(12).x = 1./3.; 01358 Nodes.IntPoint(12).y = 1./3.; 01359 Nodes.IntPoint(13).x = 2./3.; 01360 Nodes.IntPoint(13).y = 1./3.; 01361 Nodes.IntPoint(14).x = 1./3.; 01362 Nodes.IntPoint(14).y = 2./3.; 01363 Nodes.IntPoint(15).x = 2./3.; 01364 Nodes.IntPoint(15).y = 2./3.; 01365 } 01366 01367 void BiCubic2DFiniteElement::CalcShape( 01368 const IntegrationPoint &ip, Vector &shape) const 01369 { 01370 double x = ip.x, y = ip.y; 01371 01372 double w1x, w2x, w3x, w1y, w2y, w3y; 01373 double l0x, l1x, l2x, l3x, l0y, l1y, l2y, l3y; 01374 01375 w1x = x - 1./3.; w2x = x - 2./3.; w3x = x - 1.; 01376 w1y = y - 1./3.; w2y = y - 2./3.; w3y = y - 1.; 01377 01378 l0x = (- 4.5) * w1x * w2x * w3x; 01379 l1x = ( 13.5) * x * w2x * w3x; 01380 l2x = (-13.5) * x * w1x * w3x; 01381 l3x = ( 4.5) * x * w1x * w2x; 01382 01383 l0y = (- 4.5) * w1y * w2y * w3y; 01384 l1y = ( 13.5) * y * w2y * w3y; 01385 l2y = (-13.5) * y * w1y * w3y; 01386 l3y = ( 4.5) * y * w1y * w2y; 01387 01388 shape(0) = l0x * l0y; 01389 shape(1) = l3x * l0y; 01390 shape(2) = l3x * l3y; 01391 shape(3) = l0x * l3y; 01392 shape(4) = l1x * l0y; 01393 shape(5) = l2x * l0y; 01394 shape(6) = l3x * l1y; 01395 shape(7) = l3x * l2y; 01396 shape(8) = l2x * l3y; 01397 shape(9) = l1x * l3y; 01398 shape(10) = l0x * l2y; 01399 shape(11) = l0x * l1y; 01400 shape(12) = l1x * l1y; 01401 shape(13) = l2x * l1y; 01402 shape(14) = l1x * l2y; 01403 shape(15) = l2x * l2y; 01404 } 01405 01406 void BiCubic2DFiniteElement::CalcDShape( 01407 const IntegrationPoint &ip, DenseMatrix &dshape) const 01408 { 01409 double x = ip.x, y = ip.y; 01410 01411 double w1x, w2x, w3x, w1y, w2y, w3y; 01412 double l0x, l1x, l2x, l3x, l0y, l1y, l2y, l3y; 01413 double d0x, d1x, d2x, d3x, d0y, d1y, d2y, d3y; 01414 01415 w1x = x - 1./3.; w2x = x - 2./3.; w3x = x - 1.; 01416 w1y = y - 1./3.; w2y = y - 2./3.; w3y = y - 1.; 01417 01418 l0x = (- 4.5) * w1x * w2x * w3x; 01419 l1x = ( 13.5) * x * w2x * w3x; 01420 l2x = (-13.5) * x * w1x * w3x; 01421 l3x = ( 4.5) * x * w1x * w2x; 01422 01423 l0y = (- 4.5) * w1y * w2y * w3y; 01424 l1y = ( 13.5) * y * w2y * w3y; 01425 l2y = (-13.5) * y * w1y * w3y; 01426 l3y = ( 4.5) * y * w1y * w2y; 01427 01428 d0x = -5.5 + ( 18. - 13.5 * x) * x; 01429 d1x = 9. + (-45. + 40.5 * x) * x; 01430 d2x = -4.5 + ( 36. - 40.5 * x) * x; 01431 d3x = 1. + (- 9. + 13.5 * x) * x; 01432 01433 d0y = -5.5 + ( 18. - 13.5 * y) * y; 01434 d1y = 9. + (-45. + 40.5 * y) * y; 01435 d2y = -4.5 + ( 36. - 40.5 * y) * y; 01436 d3y = 1. + (- 9. + 13.5 * y) * y; 01437 01438 dshape( 0,0) = d0x * l0y; dshape( 0,1) = l0x * d0y; 01439 dshape( 1,0) = d3x * l0y; dshape( 1,1) = l3x * d0y; 01440 dshape( 2,0) = d3x * l3y; dshape( 2,1) = l3x * d3y; 01441 dshape( 3,0) = d0x * l3y; dshape( 3,1) = l0x * d3y; 01442 dshape( 4,0) = d1x * l0y; dshape( 4,1) = l1x * d0y; 01443 dshape( 5,0) = d2x * l0y; dshape( 5,1) = l2x * d0y; 01444 dshape( 6,0) = d3x * l1y; dshape( 6,1) = l3x * d1y; 01445 dshape( 7,0) = d3x * l2y; dshape( 7,1) = l3x * d2y; 01446 dshape( 8,0) = d2x * l3y; dshape( 8,1) = l2x * d3y; 01447 dshape( 9,0) = d1x * l3y; dshape( 9,1) = l1x * d3y; 01448 dshape(10,0) = d0x * l2y; dshape(10,1) = l0x * d2y; 01449 dshape(11,0) = d0x * l1y; dshape(11,1) = l0x * d1y; 01450 dshape(12,0) = d1x * l1y; dshape(12,1) = l1x * d1y; 01451 dshape(13,0) = d2x * l1y; dshape(13,1) = l2x * d1y; 01452 dshape(14,0) = d1x * l2y; dshape(14,1) = l1x * d2y; 01453 dshape(15,0) = d2x * l2y; dshape(15,1) = l2x * d2y; 01454 } 01455 01456 void BiCubic2DFiniteElement::CalcHessian( 01457 const IntegrationPoint &ip, DenseMatrix &h) const 01458 { 01459 double x = ip.x, y = ip.y; 01460 01461 double w1x, w2x, w3x, w1y, w2y, w3y; 01462 double l0x, l1x, l2x, l3x, l0y, l1y, l2y, l3y; 01463 double d0x, d1x, d2x, d3x, d0y, d1y, d2y, d3y; 01464 double h0x, h1x, h2x, h3x, h0y, h1y, h2y, h3y; 01465 01466 w1x = x - 1./3.; w2x = x - 2./3.; w3x = x - 1.; 01467 w1y = y - 1./3.; w2y = y - 2./3.; w3y = y - 1.; 01468 01469 l0x = (- 4.5) * w1x * w2x * w3x; 01470 l1x = ( 13.5) * x * w2x * w3x; 01471 l2x = (-13.5) * x * w1x * w3x; 01472 l3x = ( 4.5) * x * w1x * w2x; 01473 01474 l0y = (- 4.5) * w1y * w2y * w3y; 01475 l1y = ( 13.5) * y * w2y * w3y; 01476 l2y = (-13.5) * y * w1y * w3y; 01477 l3y = ( 4.5) * y * w1y * w2y; 01478 01479 d0x = -5.5 + ( 18. - 13.5 * x) * x; 01480 d1x = 9. + (-45. + 40.5 * x) * x; 01481 d2x = -4.5 + ( 36. - 40.5 * x) * x; 01482 d3x = 1. + (- 9. + 13.5 * x) * x; 01483 01484 d0y = -5.5 + ( 18. - 13.5 * y) * y; 01485 d1y = 9. + (-45. + 40.5 * y) * y; 01486 d2y = -4.5 + ( 36. - 40.5 * y) * y; 01487 d3y = 1. + (- 9. + 13.5 * y) * y; 01488 01489 h0x = -27. * x + 18.; 01490 h1x = 81. * x - 45.; 01491 h2x = -81. * x + 36.; 01492 h3x = 27. * x - 9.; 01493 01494 h0y = -27. * y + 18.; 01495 h1y = 81. * y - 45.; 01496 h2y = -81. * y + 36.; 01497 h3y = 27. * y - 9.; 01498 01499 h( 0,0) = h0x * l0y; h( 0,1) = d0x * d0y; h( 0,2) = l0x * h0y; 01500 h( 1,0) = h3x * l0y; h( 1,1) = d3x * d0y; h( 1,2) = l3x * h0y; 01501 h( 2,0) = h3x * l3y; h( 2,1) = d3x * d3y; h( 2,2) = l3x * h3y; 01502 h( 3,0) = h0x * l3y; h( 3,1) = d0x * d3y; h( 3,2) = l0x * h3y; 01503 h( 4,0) = h1x * l0y; h( 4,1) = d1x * d0y; h( 4,2) = l1x * h0y; 01504 h( 5,0) = h2x * l0y; h( 5,1) = d2x * d0y; h( 5,2) = l2x * h0y; 01505 h( 6,0) = h3x * l1y; h( 6,1) = d3x * d1y; h( 6,2) = l3x * h1y; 01506 h( 7,0) = h3x * l2y; h( 7,1) = d3x * d2y; h( 7,2) = l3x * h2y; 01507 h( 8,0) = h2x * l3y; h( 8,1) = d2x * d3y; h( 8,2) = l2x * h3y; 01508 h( 9,0) = h1x * l3y; h( 9,1) = d1x * d3y; h( 9,2) = l1x * h3y; 01509 h(10,0) = h0x * l2y; h(10,1) = d0x * d2y; h(10,2) = l0x * h2y; 01510 h(11,0) = h0x * l1y; h(11,1) = d0x * d1y; h(11,2) = l0x * h1y; 01511 h(12,0) = h1x * l1y; h(12,1) = d1x * d1y; h(12,2) = l1x * h1y; 01512 h(13,0) = h2x * l1y; h(13,1) = d2x * d1y; h(13,2) = l2x * h1y; 01513 h(14,0) = h1x * l2y; h(14,1) = d1x * d2y; h(14,2) = l1x * h2y; 01514 h(15,0) = h2x * l2y; h(15,1) = d2x * d2y; h(15,2) = l2x * h2y; 01515 } 01516 01517 01518 Cubic1DFiniteElement::Cubic1DFiniteElement() 01519 : NodalFiniteElement(1, Geometry::SEGMENT, 4, 3) 01520 { 01521 Nodes.IntPoint(0).x = 0.0; 01522 Nodes.IntPoint(1).x = 1.0; 01523 Nodes.IntPoint(2).x = 0.33333333333333333333; 01524 Nodes.IntPoint(3).x = 0.66666666666666666667; 01525 } 01526 01527 void Cubic1DFiniteElement::CalcShape(const IntegrationPoint &ip, 01528 Vector &shape) const 01529 { 01530 double x = ip.x; 01531 double l1 = x, 01532 l2 = (1.0-x), 01533 l3 = (0.33333333333333333333-x), 01534 l4 = (0.66666666666666666667-x); 01535 01536 shape(0) = 4.5 * l2 * l3 * l4; 01537 shape(1) = 4.5 * l1 * l3 * l4; 01538 shape(2) = 13.5 * l1 * l2 * l4; 01539 shape(3) = -13.5 * l1 * l2 * l3; 01540 } 01541 01542 void Cubic1DFiniteElement::CalcDShape(const IntegrationPoint &ip, 01543 DenseMatrix &dshape) const 01544 { 01545 double x = ip.x; 01546 01547 dshape(0,0) = -5.5 + x * (18. - 13.5 * x); 01548 dshape(1,0) = 1. - x * (9. - 13.5 * x); 01549 dshape(2,0) = 9. - x * (45. - 40.5 * x); 01550 dshape(3,0) = -4.5 + x * (36. - 40.5 * x); 01551 } 01552 01553 01554 Cubic2DFiniteElement::Cubic2DFiniteElement() 01555 : NodalFiniteElement(2, Geometry::TRIANGLE, 10, 3) 01556 { 01557 Nodes.IntPoint(0).x = 0.0; 01558 Nodes.IntPoint(0).y = 0.0; 01559 Nodes.IntPoint(1).x = 1.0; 01560 Nodes.IntPoint(1).y = 0.0; 01561 Nodes.IntPoint(2).x = 0.0; 01562 Nodes.IntPoint(2).y = 1.0; 01563 Nodes.IntPoint(3).x = 0.33333333333333333333; 01564 Nodes.IntPoint(3).y = 0.0; 01565 Nodes.IntPoint(4).x = 0.66666666666666666667; 01566 Nodes.IntPoint(4).y = 0.0; 01567 Nodes.IntPoint(5).x = 0.66666666666666666667; 01568 Nodes.IntPoint(5).y = 0.33333333333333333333; 01569 Nodes.IntPoint(6).x = 0.33333333333333333333; 01570 Nodes.IntPoint(6).y = 0.66666666666666666667; 01571 Nodes.IntPoint(7).x = 0.0; 01572 Nodes.IntPoint(7).y = 0.66666666666666666667; 01573 Nodes.IntPoint(8).x = 0.0; 01574 Nodes.IntPoint(8).y = 0.33333333333333333333; 01575 Nodes.IntPoint(9).x = 0.33333333333333333333; 01576 Nodes.IntPoint(9).y = 0.33333333333333333333; 01577 } 01578 01579 void Cubic2DFiniteElement::CalcShape(const IntegrationPoint &ip, 01580 Vector &shape) const 01581 { 01582 double x = ip.x, y = ip.y; 01583 double l1 = (-1. + x + y), 01584 lx = (-1. + 3.*x), 01585 ly = (-1. + 3.*y); 01586 01587 shape(0) = -0.5*l1*(3.*l1 + 1.)*(3.*l1 + 2.); 01588 shape(1) = 0.5*x*(lx - 1.)*lx; 01589 shape(2) = 0.5*y*(-1. + ly)*ly; 01590 shape(3) = 4.5*x*l1*(3.*l1 + 1.); 01591 shape(4) = -4.5*x*lx*l1; 01592 shape(5) = 4.5*x*lx*y; 01593 shape(6) = 4.5*x*y*ly; 01594 shape(7) = -4.5*y*l1*ly; 01595 shape(8) = 4.5*y*l1*(1. + 3.*l1); 01596 shape(9) = -27.*x*y*l1; 01597 } 01598 01599 void Cubic2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 01600 DenseMatrix &dshape) const 01601 { 01602 double x = ip.x, y = ip.y; 01603 01604 dshape(0,0) = 0.5*(-11. + 36.*y - 9.*(x*(-4. + 3.*x) + 6.*x*y + 3.*y*y)); 01605 dshape(1,0) = 1. + 4.5*x*(-2. + 3.*x); 01606 dshape(2,0) = 0.; 01607 dshape(3,0) = 4.5*(2. + 9.*x*x - 5.*y + 3.*y*y + 2.*x*(-5. + 6.*y)); 01608 dshape(4,0) = -4.5*(1. - 1.*y + x*(-8. + 9.*x + 6.*y)); 01609 dshape(5,0) = 4.5*(-1. + 6.*x)*y; 01610 dshape(6,0) = 4.5*y*(-1. + 3.*y); 01611 dshape(7,0) = 4.5*(1. - 3.*y)*y; 01612 dshape(8,0) = 4.5*y*(-5. + 6.*x + 6.*y); 01613 dshape(9,0) = -27.*y*(-1. + 2.*x + y); 01614 01615 dshape(0,1) = 0.5*(-11. + 36.*y - 9.*(x*(-4. + 3.*x) + 6.*x*y + 3.*y*y)); 01616 dshape(1,1) = 0.; 01617 dshape(2,1) = 1. + 4.5*y*(-2. + 3.*y); 01618 dshape(3,1) = 4.5*x*(-5. + 6.*x + 6.*y); 01619 dshape(4,1) = 4.5*(1. - 3.*x)*x; 01620 dshape(5,1) = 4.5*x*(-1. + 3.*x); 01621 dshape(6,1) = 4.5*x*(-1. + 6.*y); 01622 dshape(7,1) = -4.5*(1. + x*(-1. + 6.*y) + y*(-8. + 9.*y)); 01623 dshape(8,1) = 4.5*(2. + 3.*x*x + y*(-10. + 9.*y) + x*(-5. + 12.*y)); 01624 dshape(9,1) = -27.*x*(-1. + x + 2.*y); 01625 } 01626 01627 void Cubic2DFiniteElement::CalcHessian (const IntegrationPoint &ip, 01628 DenseMatrix &h) const 01629 { 01630 double x = ip.x, y = ip.y; 01631 01632 h(0,0) = 18.-27.*(x+y); 01633 h(0,1) = 18.-27.*(x+y); 01634 h(0,2) = 18.-27.*(x+y); 01635 01636 h(1,0) = -9.+27.*x; 01637 h(1,1) = 0.; 01638 h(1,2) = 0.; 01639 01640 h(2,0) = 0.; 01641 h(2,1) = 0.; 01642 h(2,2) = -9.+27.*y; 01643 01644 h(3,0) = -45.+81.*x+54.*y; 01645 h(3,1) = -22.5+54.*x+27.*y; 01646 h(3,2) = 27.*x; 01647 01648 h(4,0) = 36.-81.*x-27.*y; 01649 h(4,1) = 4.5-27.*x; 01650 h(4,2) = 0.; 01651 01652 h(5,0) = 27.*y; 01653 h(5,1) = -4.5+27.*x; 01654 h(5,2) = 0.; 01655 01656 h(6,0) = 0.; 01657 h(6,1) = -4.5+27.*y; 01658 h(6,2) = 27.*x; 01659 01660 h(7,0) = 0.; 01661 h(7,1) = 4.5-27.*y; 01662 h(7,2) = 36.-27.*x-81.*y; 01663 01664 h(8,0) = 27.*y; 01665 h(8,1) = -22.5+27.*x+54.*y; 01666 h(8,2) = -45.+54.*x+81.*y; 01667 01668 h(9,0) = -54.*y; 01669 h(9,1) = 27.-54.*(x+y); 01670 h(9,2) = -54.*x; 01671 } 01672 01673 01674 Cubic3DFiniteElement::Cubic3DFiniteElement() 01675 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 20, 3) 01676 { 01677 Nodes.IntPoint(0).x = 0; 01678 Nodes.IntPoint(0).y = 0; 01679 Nodes.IntPoint(0).z = 0; 01680 Nodes.IntPoint(1).x = 1.; 01681 Nodes.IntPoint(1).y = 0; 01682 Nodes.IntPoint(1).z = 0; 01683 Nodes.IntPoint(2).x = 0; 01684 Nodes.IntPoint(2).y = 1.; 01685 Nodes.IntPoint(2).z = 0; 01686 Nodes.IntPoint(3).x = 0; 01687 Nodes.IntPoint(3).y = 0; 01688 Nodes.IntPoint(3).z = 1.; 01689 Nodes.IntPoint(4).x = 0.3333333333333333333333333333; 01690 Nodes.IntPoint(4).y = 0; 01691 Nodes.IntPoint(4).z = 0; 01692 Nodes.IntPoint(5).x = 0.6666666666666666666666666667; 01693 Nodes.IntPoint(5).y = 0; 01694 Nodes.IntPoint(5).z = 0; 01695 Nodes.IntPoint(6).x = 0; 01696 Nodes.IntPoint(6).y = 0.3333333333333333333333333333; 01697 Nodes.IntPoint(6).z = 0; 01698 Nodes.IntPoint(7).x = 0; 01699 Nodes.IntPoint(7).y = 0.6666666666666666666666666667; 01700 Nodes.IntPoint(7).z = 0; 01701 Nodes.IntPoint(8).x = 0; 01702 Nodes.IntPoint(8).y = 0; 01703 Nodes.IntPoint(8).z = 0.3333333333333333333333333333; 01704 Nodes.IntPoint(9).x = 0; 01705 Nodes.IntPoint(9).y = 0; 01706 Nodes.IntPoint(9).z = 0.6666666666666666666666666667; 01707 Nodes.IntPoint(10).x = 0.6666666666666666666666666667; 01708 Nodes.IntPoint(10).y = 0.3333333333333333333333333333; 01709 Nodes.IntPoint(10).z = 0; 01710 Nodes.IntPoint(11).x = 0.3333333333333333333333333333; 01711 Nodes.IntPoint(11).y = 0.6666666666666666666666666667; 01712 Nodes.IntPoint(11).z = 0; 01713 Nodes.IntPoint(12).x = 0.6666666666666666666666666667; 01714 Nodes.IntPoint(12).y = 0; 01715 Nodes.IntPoint(12).z = 0.3333333333333333333333333333; 01716 Nodes.IntPoint(13).x = 0.3333333333333333333333333333; 01717 Nodes.IntPoint(13).y = 0; 01718 Nodes.IntPoint(13).z = 0.6666666666666666666666666667; 01719 Nodes.IntPoint(14).x = 0; 01720 Nodes.IntPoint(14).y = 0.6666666666666666666666666667; 01721 Nodes.IntPoint(14).z = 0.3333333333333333333333333333; 01722 Nodes.IntPoint(15).x = 0; 01723 Nodes.IntPoint(15).y = 0.3333333333333333333333333333; 01724 Nodes.IntPoint(15).z = 0.6666666666666666666666666667; 01725 Nodes.IntPoint(16).x = 0.3333333333333333333333333333; 01726 Nodes.IntPoint(16).y = 0.3333333333333333333333333333; 01727 Nodes.IntPoint(16).z = 0.3333333333333333333333333333; 01728 Nodes.IntPoint(17).x = 0; 01729 Nodes.IntPoint(17).y = 0.3333333333333333333333333333; 01730 Nodes.IntPoint(17).z = 0.3333333333333333333333333333; 01731 Nodes.IntPoint(18).x = 0.3333333333333333333333333333; 01732 Nodes.IntPoint(18).y = 0; 01733 Nodes.IntPoint(18).z = 0.3333333333333333333333333333; 01734 Nodes.IntPoint(19).x = 0.3333333333333333333333333333; 01735 Nodes.IntPoint(19).y = 0.3333333333333333333333333333; 01736 Nodes.IntPoint(19).z = 0; 01737 } 01738 01739 void Cubic3DFiniteElement::CalcShape(const IntegrationPoint &ip, 01740 Vector &shape) const 01741 { 01742 double x = ip.x, y = ip.y, z = ip.z; 01743 01744 shape(0) = -((-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z)* 01745 (-1 + 3*x + 3*y + 3*z))/2.; 01746 shape(4) = (9*x*(-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z))/2.; 01747 shape(5) = (-9*x*(-1 + 3*x)*(-1 + x + y + z))/2.; 01748 shape(1) = (x*(2 + 9*(-1 + x)*x))/2.; 01749 shape(6) = (9*y*(-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z))/2.; 01750 shape(19) = -27*x*y*(-1 + x + y + z); 01751 shape(10) = (9*x*(-1 + 3*x)*y)/2.; 01752 shape(7) = (-9*y*(-1 + 3*y)*(-1 + x + y + z))/2.; 01753 shape(11) = (9*x*y*(-1 + 3*y))/2.; 01754 shape(2) = (y*(2 + 9*(-1 + y)*y))/2.; 01755 shape(8) = (9*z*(-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z))/2.; 01756 shape(18) = -27*x*z*(-1 + x + y + z); 01757 shape(12) = (9*x*(-1 + 3*x)*z)/2.; 01758 shape(17) = -27*y*z*(-1 + x + y + z); 01759 shape(16) = 27*x*y*z; 01760 shape(14) = (9*y*(-1 + 3*y)*z)/2.; 01761 shape(9) = (-9*z*(-1 + x + y + z)*(-1 + 3*z))/2.; 01762 shape(13) = (9*x*z*(-1 + 3*z))/2.; 01763 shape(15) = (9*y*z*(-1 + 3*z))/2.; 01764 shape(3) = (z*(2 + 9*(-1 + z)*z))/2.; 01765 } 01766 01767 void Cubic3DFiniteElement::CalcDShape(const IntegrationPoint &ip, 01768 DenseMatrix &dshape) const 01769 { 01770 double x = ip.x, y = ip.y, z = ip.z; 01771 01772 dshape(0,0) = (-11 + 36*y + 36*z - 9*(3*pow(x,2) + 3*pow(y + z,2) + 01773 x*(-4 + 6*y + 6*z)))/2.; 01774 dshape(0,1) = (-11 + 36*y + 36*z - 9*(3*pow(x,2) + 3*pow(y + z,2) + 01775 x*(-4 + 6*y + 6*z)))/2.; 01776 dshape(0,2) = (-11 + 36*y + 36*z - 9*(3*pow(x,2) + 3*pow(y + z,2) + 01777 x*(-4 + 6*y + 6*z)))/2.; 01778 dshape(4,0) = (9*(9*pow(x,2) + (-1 + y + z)*(-2 + 3*y + 3*z) + 01779 2*x*(-5 + 6*y + 6*z)))/2.; 01780 dshape(4,1) = (9*x*(-5 + 6*x + 6*y + 6*z))/2.; 01781 dshape(4,2) = (9*x*(-5 + 6*x + 6*y + 6*z))/2.; 01782 dshape(5,0) = (-9*(1 - y - z + x*(-8 + 9*x + 6*y + 6*z)))/2.; 01783 dshape(5,1) = (9*(1 - 3*x)*x)/2.; 01784 dshape(5,2) = (9*(1 - 3*x)*x)/2.; 01785 dshape(1,0) = 1 + (9*x*(-2 + 3*x))/2.; 01786 dshape(1,1) = 0; 01787 dshape(1,2) = 0; 01788 dshape(6,0) = (9*y*(-5 + 6*x + 6*y + 6*z))/2.; 01789 dshape(6,1) = (9*(2 + 3*pow(x,2) - 10*y - 5*z + 3*(y + z)*(3*y + z) + 01790 x*(-5 + 12*y + 6*z)))/2.; 01791 dshape(6,2) = (9*y*(-5 + 6*x + 6*y + 6*z))/2.; 01792 dshape(19,0) = -27*y*(-1 + 2*x + y + z); 01793 dshape(19,1) = -27*x*(-1 + x + 2*y + z); 01794 dshape(19,2) = -27*x*y; 01795 dshape(10,0) = (9*(-1 + 6*x)*y)/2.; 01796 dshape(10,1) = (9*x*(-1 + 3*x))/2.; 01797 dshape(10,2) = 0; 01798 dshape(7,0) = (9*(1 - 3*y)*y)/2.; 01799 dshape(7,1) = (-9*(1 + x*(-1 + 6*y) - z + y*(-8 + 9*y + 6*z)))/2.; 01800 dshape(7,2) = (9*(1 - 3*y)*y)/2.; 01801 dshape(11,0) = (9*y*(-1 + 3*y))/2.; 01802 dshape(11,1) = (9*x*(-1 + 6*y))/2.; 01803 dshape(11,2) = 0; 01804 dshape(2,0) = 0; 01805 dshape(2,1) = 1 + (9*y*(-2 + 3*y))/2.; 01806 dshape(2,2) = 0; 01807 dshape(8,0) = (9*z*(-5 + 6*x + 6*y + 6*z))/2.; 01808 dshape(8,1) = (9*z*(-5 + 6*x + 6*y + 6*z))/2.; 01809 dshape(8,2) = (9*(2 + 3*pow(x,2) - 5*y - 10*z + 3*(y + z)*(y + 3*z) + 01810 x*(-5 + 6*y + 12*z)))/2.; 01811 dshape(18,0) = -27*z*(-1 + 2*x + y + z); 01812 dshape(18,1) = -27*x*z; 01813 dshape(18,2) = -27*x*(-1 + x + y + 2*z); 01814 dshape(12,0) = (9*(-1 + 6*x)*z)/2.; 01815 dshape(12,1) = 0; 01816 dshape(12,2) = (9*x*(-1 + 3*x))/2.; 01817 dshape(17,0) = -27*y*z; 01818 dshape(17,1) = -27*z*(-1 + x + 2*y + z); 01819 dshape(17,2) = -27*y*(-1 + x + y + 2*z); 01820 dshape(16,0) = 27*y*z; 01821 dshape(16,1) = 27*x*z; 01822 dshape(16,2) = 27*x*y; 01823 dshape(14,0) = 0; 01824 dshape(14,1) = (9*(-1 + 6*y)*z)/2.; 01825 dshape(14,2) = (9*y*(-1 + 3*y))/2.; 01826 dshape(9,0) = (9*(1 - 3*z)*z)/2.; 01827 dshape(9,1) = (9*(1 - 3*z)*z)/2.; 01828 dshape(9,2) = (9*(-1 + x + y + 8*z - 6*(x + y)*z - 9*pow(z,2)))/2.; 01829 dshape(13,0) = (9*z*(-1 + 3*z))/2.; 01830 dshape(13,1) = 0; 01831 dshape(13,2) = (9*x*(-1 + 6*z))/2.; 01832 dshape(15,0) = 0; 01833 dshape(15,1) = (9*z*(-1 + 3*z))/2.; 01834 dshape(15,2) = (9*y*(-1 + 6*z))/2.; 01835 dshape(3,0) = 0; 01836 dshape(3,1) = 0; 01837 dshape(3,2) = 1 + (9*z*(-2 + 3*z))/2.; 01838 } 01839 01840 01841 P0TriangleFiniteElement::P0TriangleFiniteElement() 01842 : NodalFiniteElement(2, Geometry::TRIANGLE , 1, 0) 01843 { 01844 Nodes.IntPoint(0).x = 0.333333333333333333; 01845 Nodes.IntPoint(0).y = 0.333333333333333333; 01846 } 01847 01848 void P0TriangleFiniteElement::CalcShape(const IntegrationPoint &ip, 01849 Vector &shape) const 01850 { 01851 shape(0) = 1.0; 01852 } 01853 01854 void P0TriangleFiniteElement::CalcDShape(const IntegrationPoint &ip, 01855 DenseMatrix &dshape) const 01856 { 01857 dshape(0,0) = 0.0; 01858 dshape(0,1) = 0.0; 01859 } 01860 01861 01862 P0QuadFiniteElement::P0QuadFiniteElement() 01863 : NodalFiniteElement(2, Geometry::SQUARE , 1, 0, FunctionSpace::Qk) 01864 { 01865 Nodes.IntPoint(0).x = 0.5; 01866 Nodes.IntPoint(0).y = 0.5; 01867 } 01868 01869 void P0QuadFiniteElement::CalcShape(const IntegrationPoint &ip, 01870 Vector &shape) const 01871 { 01872 shape(0) = 1.0; 01873 } 01874 01875 void P0QuadFiniteElement::CalcDShape(const IntegrationPoint &ip, 01876 DenseMatrix &dshape) const 01877 { 01878 dshape(0,0) = 0.0; 01879 dshape(0,1) = 0.0; 01880 } 01881 01882 01883 Linear3DFiniteElement::Linear3DFiniteElement() 01884 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 4, 1) 01885 { 01886 Nodes.IntPoint(0).x = 0.0; 01887 Nodes.IntPoint(0).y = 0.0; 01888 Nodes.IntPoint(0).z = 0.0; 01889 Nodes.IntPoint(1).x = 1.0; 01890 Nodes.IntPoint(1).y = 0.0; 01891 Nodes.IntPoint(1).z = 0.0; 01892 Nodes.IntPoint(2).x = 0.0; 01893 Nodes.IntPoint(2).y = 1.0; 01894 Nodes.IntPoint(2).z = 0.0; 01895 Nodes.IntPoint(3).x = 0.0; 01896 Nodes.IntPoint(3).y = 0.0; 01897 Nodes.IntPoint(3).z = 1.0; 01898 } 01899 01900 void Linear3DFiniteElement::CalcShape(const IntegrationPoint &ip, 01901 Vector &shape) const 01902 { 01903 shape(0) = 1. - ip.x - ip.y - ip.z; 01904 shape(1) = ip.x; 01905 shape(2) = ip.y; 01906 shape(3) = ip.z; 01907 } 01908 01909 void Linear3DFiniteElement::CalcDShape(const IntegrationPoint &ip, 01910 DenseMatrix &dshape) const 01911 { 01912 if (dshape.Height() == 4) 01913 { 01914 double *A = &dshape(0,0); 01915 A[0] = -1.; A[4] = -1.; A[8] = -1.; 01916 A[1] = 1.; A[5] = 0.; A[9] = 0.; 01917 A[2] = 0.; A[6] = 1.; A[10] = 0.; 01918 A[3] = 0.; A[7] = 0.; A[11] = 1.; 01919 } 01920 else 01921 { 01922 dshape(0,0) = -1.; dshape(0,1) = -1.; dshape(0,2) = -1.; 01923 dshape(1,0) = 1.; dshape(1,1) = 0.; dshape(1,2) = 0.; 01924 dshape(2,0) = 0.; dshape(2,1) = 1.; dshape(2,2) = 0.; 01925 dshape(3,0) = 0.; dshape(3,1) = 0.; dshape(3,2) = 1.; 01926 } 01927 } 01928 01929 void Linear3DFiniteElement::GetFaceDofs (int face, int **dofs, int *ndofs) 01930 const 01931 { 01932 static int face_dofs[4][3] = {{1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2}}; 01933 01934 *ndofs = 3; 01935 *dofs = face_dofs[face]; 01936 } 01937 01938 01939 Quadratic3DFiniteElement::Quadratic3DFiniteElement() 01940 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 10, 2) 01941 { 01942 Nodes.IntPoint(0).x = 0.0; 01943 Nodes.IntPoint(0).y = 0.0; 01944 Nodes.IntPoint(0).z = 0.0; 01945 Nodes.IntPoint(1).x = 1.0; 01946 Nodes.IntPoint(1).y = 0.0; 01947 Nodes.IntPoint(1).z = 0.0; 01948 Nodes.IntPoint(2).x = 0.0; 01949 Nodes.IntPoint(2).y = 1.0; 01950 Nodes.IntPoint(2).z = 0.0; 01951 Nodes.IntPoint(3).x = 0.0; 01952 Nodes.IntPoint(3).y = 0.0; 01953 Nodes.IntPoint(3).z = 1.0; 01954 Nodes.IntPoint(4).x = 0.5; 01955 Nodes.IntPoint(4).y = 0.0; 01956 Nodes.IntPoint(4).z = 0.0; 01957 Nodes.IntPoint(5).x = 0.0; 01958 Nodes.IntPoint(5).y = 0.5; 01959 Nodes.IntPoint(5).z = 0.0; 01960 Nodes.IntPoint(6).x = 0.0; 01961 Nodes.IntPoint(6).y = 0.0; 01962 Nodes.IntPoint(6).z = 0.5; 01963 Nodes.IntPoint(7).x = 0.5; 01964 Nodes.IntPoint(7).y = 0.5; 01965 Nodes.IntPoint(7).z = 0.0; 01966 Nodes.IntPoint(8).x = 0.5; 01967 Nodes.IntPoint(8).y = 0.0; 01968 Nodes.IntPoint(8).z = 0.5; 01969 Nodes.IntPoint(9).x = 0.0; 01970 Nodes.IntPoint(9).y = 0.5; 01971 Nodes.IntPoint(9).z = 0.5; 01972 } 01973 01974 void Quadratic3DFiniteElement::CalcShape(const IntegrationPoint &ip, 01975 Vector &shape) const 01976 { 01977 double L0, L1, L2, L3; 01978 01979 L0 = 1. - ip.x - ip.y - ip.z; 01980 L1 = ip.x; 01981 L2 = ip.y; 01982 L3 = ip.z; 01983 01984 shape(0) = L0 * ( 2.0 * L0 - 1.0 ); 01985 shape(1) = L1 * ( 2.0 * L1 - 1.0 ); 01986 shape(2) = L2 * ( 2.0 * L2 - 1.0 ); 01987 shape(3) = L3 * ( 2.0 * L3 - 1.0 ); 01988 shape(4) = 4.0 * L0 * L1; 01989 shape(5) = 4.0 * L0 * L2; 01990 shape(6) = 4.0 * L0 * L3; 01991 shape(7) = 4.0 * L1 * L2; 01992 shape(8) = 4.0 * L1 * L3; 01993 shape(9) = 4.0 * L2 * L3; 01994 } 01995 01996 void Quadratic3DFiniteElement::CalcDShape(const IntegrationPoint &ip, 01997 DenseMatrix &dshape) const 01998 { 01999 double x, y, z, L0; 02000 02001 x = ip.x; 02002 y = ip.y; 02003 z = ip.z; 02004 L0 = 1.0 - x - y - z; 02005 02006 dshape(0,0) = dshape(0,1) = dshape(0,2) = 1.0 - 4.0 * L0; 02007 dshape(1,0) = -1.0 + 4.0 * x; dshape(1,1) = 0.0; dshape(1,2) = 0.0; 02008 dshape(2,0) = 0.0; dshape(2,1) = -1.0 + 4.0 * y; dshape(2,2) = 0.0; 02009 dshape(3,0) = dshape(3,1) = 0.0; dshape(3,2) = -1.0 + 4.0 * z; 02010 dshape(4,0) = 4.0 * (L0 - x); dshape(4,1) = dshape(4,2) = -4.0 * x; 02011 dshape(5,0) = dshape(5,2) = -4.0 * y; dshape(5,1) = 4.0 * (L0 - y); 02012 dshape(6,0) = dshape(6,1) = -4.0 * z; dshape(6,2) = 4.0 * (L0 - z); 02013 dshape(7,0) = 4.0 * y; dshape(7,1) = 4.0 * x; dshape(7,2) = 0.0; 02014 dshape(8,0) = 4.0 * z; dshape(8,1) = 0.0; dshape(8,2) = 4.0 * x; 02015 dshape(9,0) = 0.0; dshape(9,1) = 4.0 * z; dshape(9,2) = 4.0 * y; 02016 } 02017 02018 TriLinear3DFiniteElement::TriLinear3DFiniteElement() 02019 : NodalFiniteElement(3, Geometry::CUBE, 8, 1, FunctionSpace::Qk) 02020 { 02021 Nodes.IntPoint(0).x = 0.0; 02022 Nodes.IntPoint(0).y = 0.0; 02023 Nodes.IntPoint(0).z = 0.0; 02024 02025 Nodes.IntPoint(1).x = 1.0; 02026 Nodes.IntPoint(1).y = 0.0; 02027 Nodes.IntPoint(1).z = 0.0; 02028 02029 Nodes.IntPoint(2).x = 1.0; 02030 Nodes.IntPoint(2).y = 1.0; 02031 Nodes.IntPoint(2).z = 0.0; 02032 02033 Nodes.IntPoint(3).x = 0.0; 02034 Nodes.IntPoint(3).y = 1.0; 02035 Nodes.IntPoint(3).z = 0.0; 02036 02037 Nodes.IntPoint(4).x = 0.0; 02038 Nodes.IntPoint(4).y = 0.0; 02039 Nodes.IntPoint(4).z = 1.0; 02040 02041 Nodes.IntPoint(5).x = 1.0; 02042 Nodes.IntPoint(5).y = 0.0; 02043 Nodes.IntPoint(5).z = 1.0; 02044 02045 Nodes.IntPoint(6).x = 1.0; 02046 Nodes.IntPoint(6).y = 1.0; 02047 Nodes.IntPoint(6).z = 1.0; 02048 02049 Nodes.IntPoint(7).x = 0.0; 02050 Nodes.IntPoint(7).y = 1.0; 02051 Nodes.IntPoint(7).z = 1.0; 02052 } 02053 02054 void TriLinear3DFiniteElement::CalcShape(const IntegrationPoint &ip, 02055 Vector &shape) const 02056 { 02057 double x = ip.x, y = ip.y, z = ip.z; 02058 double ox = 1.-x, oy = 1.-y, oz = 1.-z; 02059 02060 shape(0) = ox * oy * oz; 02061 shape(1) = x * oy * oz; 02062 shape(2) = x * y * oz; 02063 shape(3) = ox * y * oz; 02064 shape(4) = ox * oy * z; 02065 shape(5) = x * oy * z; 02066 shape(6) = x * y * z; 02067 shape(7) = ox * y * z; 02068 } 02069 02070 void TriLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip, 02071 DenseMatrix &dshape) const 02072 { 02073 double x = ip.x, y = ip.y, z = ip.z; 02074 double ox = 1.-x, oy = 1.-y, oz = 1.-z; 02075 02076 dshape(0,0) = - oy * oz; 02077 dshape(0,1) = - ox * oz; 02078 dshape(0,2) = - ox * oy; 02079 02080 dshape(1,0) = oy * oz; 02081 dshape(1,1) = - x * oz; 02082 dshape(1,2) = - x * oy; 02083 02084 dshape(2,0) = y * oz; 02085 dshape(2,1) = x * oz; 02086 dshape(2,2) = - x * y; 02087 02088 dshape(3,0) = - y * oz; 02089 dshape(3,1) = ox * oz; 02090 dshape(3,2) = - ox * y; 02091 02092 dshape(4,0) = - oy * z; 02093 dshape(4,1) = - ox * z; 02094 dshape(4,2) = ox * oy; 02095 02096 dshape(5,0) = oy * z; 02097 dshape(5,1) = - x * z; 02098 dshape(5,2) = x * oy; 02099 02100 dshape(6,0) = y * z; 02101 dshape(6,1) = x * z; 02102 dshape(6,2) = x * y; 02103 02104 dshape(7,0) = - y * z; 02105 dshape(7,1) = ox * z; 02106 dshape(7,2) = ox * y; 02107 } 02108 02109 P0SegmentFiniteElement::P0SegmentFiniteElement(int Ord) 02110 : NodalFiniteElement(1, Geometry::SEGMENT , 1, Ord) // defaul Ord = 0 02111 { 02112 Nodes.IntPoint(0).x = 0.5; 02113 } 02114 02115 void P0SegmentFiniteElement::CalcShape(const IntegrationPoint &ip, 02116 Vector &shape) const 02117 { 02118 shape(0) = 1.0; 02119 } 02120 02121 void P0SegmentFiniteElement::CalcDShape(const IntegrationPoint &ip, 02122 DenseMatrix &dshape) const 02123 { 02124 dshape(0,0) = 0.0; 02125 } 02126 02127 CrouzeixRaviartFiniteElement::CrouzeixRaviartFiniteElement() 02128 : NodalFiniteElement(2, Geometry::TRIANGLE , 3, 1) 02129 { 02130 Nodes.IntPoint(0).x = 0.5; 02131 Nodes.IntPoint(0).y = 0.0; 02132 Nodes.IntPoint(1).x = 0.5; 02133 Nodes.IntPoint(1).y = 0.5; 02134 Nodes.IntPoint(2).x = 0.0; 02135 Nodes.IntPoint(2).y = 0.5; 02136 } 02137 02138 void CrouzeixRaviartFiniteElement::CalcShape(const IntegrationPoint &ip, 02139 Vector &shape) const 02140 { 02141 shape(0) = 1.0 - 2.0 * ip.y; 02142 shape(1) = -1.0 + 2.0 * ( ip.x + ip.y ); 02143 shape(2) = 1.0 - 2.0 * ip.x; 02144 } 02145 02146 void CrouzeixRaviartFiniteElement::CalcDShape(const IntegrationPoint &ip, 02147 DenseMatrix &dshape) const 02148 { 02149 dshape(0,0) = 0.0; dshape(0,1) = -2.0; 02150 dshape(1,0) = 2.0; dshape(1,1) = 2.0; 02151 dshape(2,0) = -2.0; dshape(2,1) = 0.0; 02152 } 02153 02154 CrouzeixRaviartQuadFiniteElement::CrouzeixRaviartQuadFiniteElement() 02155 // the FunctionSpace should be rotated (45 degrees) Q_1 02156 // i.e. the span of { 1, x, y, x^2 - y^2 } 02157 : NodalFiniteElement(2, Geometry::SQUARE , 4, 2, FunctionSpace::Qk) 02158 02159 { 02160 Nodes.IntPoint(0).x = 0.5; 02161 Nodes.IntPoint(0).y = 0.0; 02162 Nodes.IntPoint(1).x = 1.0; 02163 Nodes.IntPoint(1).y = 0.5; 02164 Nodes.IntPoint(2).x = 0.5; 02165 Nodes.IntPoint(2).y = 1.0; 02166 Nodes.IntPoint(3).x = 0.0; 02167 Nodes.IntPoint(3).y = 0.5; 02168 } 02169 02170 void CrouzeixRaviartQuadFiniteElement::CalcShape(const IntegrationPoint &ip, 02171 Vector &shape) const 02172 { 02173 const double l1 = ip.x+ip.y-0.5, l2 = 1.-l1, l3 = ip.x-ip.y+0.5, l4 = 1.-l3; 02174 02175 shape(0) = l2 * l3; 02176 shape(1) = l1 * l3; 02177 shape(2) = l1 * l4; 02178 shape(3) = l2 * l4; 02179 } 02180 02181 void CrouzeixRaviartQuadFiniteElement::CalcDShape(const IntegrationPoint &ip, 02182 DenseMatrix &dshape) const 02183 { 02184 const double x2 = 2.*ip.x, y2 = 2.*ip.y; 02185 02186 dshape(0,0) = 1. - x2; dshape(0,1) = -2. + y2; 02187 dshape(1,0) = x2; dshape(1,1) = 1. - y2; 02188 dshape(2,0) = 1. - x2; dshape(2,1) = y2; 02189 dshape(3,0) = -2. + x2; dshape(3,1) = 1. - y2; 02190 } 02191 02192 02193 RT0TriangleFiniteElement::RT0TriangleFiniteElement() 02194 : VectorFiniteElement (2, Geometry::TRIANGLE, 3, 1) 02195 { 02196 Nodes.IntPoint(0).x = 0.5; 02197 Nodes.IntPoint(0).y = 0.0; 02198 Nodes.IntPoint(1).x = 0.5; 02199 Nodes.IntPoint(1).y = 0.5; 02200 Nodes.IntPoint(2).x = 0.0; 02201 Nodes.IntPoint(2).y = 0.5; 02202 } 02203 02204 void RT0TriangleFiniteElement::CalcVShape(const IntegrationPoint &ip, 02205 DenseMatrix &shape) const 02206 { 02207 double x = ip.x, y = ip.y; 02208 02209 shape(0,0) = x; 02210 shape(0,1) = y - 1.; 02211 shape(1,0) = x; 02212 shape(1,1) = y; 02213 shape(2,0) = x - 1.; 02214 shape(2,1) = y; 02215 } 02216 02217 void RT0TriangleFiniteElement::CalcDivShape(const IntegrationPoint &ip, 02218 Vector &divshape) const 02219 { 02220 divshape(0) = 2.; 02221 divshape(1) = 2.; 02222 divshape(2) = 2.; 02223 } 02224 02225 const double RT0TriangleFiniteElement::nk[3][2] = 02226 { {0, -1}, {1, 1}, {-1, 0} }; 02227 02228 void RT0TriangleFiniteElement::GetLocalInterpolation ( 02229 ElementTransformation &Trans, DenseMatrix &I) const 02230 { 02231 int k, j; 02232 #ifdef MFEM_USE_OPENMP 02233 DenseMatrix vshape(Dof, Dim); 02234 DenseMatrix Jinv(Dim); 02235 #endif 02236 02237 #ifdef MFEM_DEBUG 02238 for (k = 0; k < 3; k++) 02239 { 02240 CalcVShape (Nodes.IntPoint(k), vshape); 02241 for (j = 0; j < 3; j++) 02242 { 02243 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1]; 02244 if (j == k) d -= 1.0; 02245 if (fabs(d) > 1.0e-12) 02246 { 02247 cerr << "RT0TriangleFiniteElement::GetLocalInterpolation (...)\n" 02248 " k = " << k << ", j = " << j << ", d = " << d << endl; 02249 mfem_error(); 02250 } 02251 } 02252 } 02253 #endif 02254 02255 IntegrationPoint ip; 02256 ip.x = ip.y = 0.0; 02257 Trans.SetIntPoint (&ip); 02258 // Trans must be linear 02259 // set Jinv = |J| J^{-t} = adj(J)^t 02260 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 02261 double vk[2]; 02262 Vector xk (vk, 2); 02263 02264 for (k = 0; k < 3; k++) 02265 { 02266 Trans.Transform (Nodes.IntPoint (k), xk); 02267 ip.x = vk[0]; ip.y = vk[1]; 02268 CalcVShape (ip, vshape); 02269 // vk = |J| J^{-t} nk 02270 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]; 02271 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]; 02272 for (j = 0; j < 3; j++) 02273 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12) 02274 I(k,j) = 0.0; 02275 } 02276 } 02277 02278 void RT0TriangleFiniteElement::Project ( 02279 VectorCoefficient &vc, ElementTransformation &Trans, 02280 Vector &dofs) const 02281 { 02282 double vk[2]; 02283 Vector xk (vk, 2); 02284 #ifdef MFEM_USE_OPENMP 02285 DenseMatrix Jinv(Dim); 02286 #endif 02287 02288 for (int k = 0; k < 3; k++) 02289 { 02290 Trans.SetIntPoint (&Nodes.IntPoint (k)); 02291 // set Jinv = |J| J^{-t} = adj(J)^t 02292 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 02293 02294 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 02295 // xk^t |J| J^{-t} nk 02296 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) + 02297 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] )); 02298 } 02299 } 02300 02301 RT0QuadFiniteElement::RT0QuadFiniteElement() 02302 : VectorFiniteElement (2, Geometry::SQUARE, 4, 1, FunctionSpace::Qk) 02303 { 02304 Nodes.IntPoint(0).x = 0.5; 02305 Nodes.IntPoint(0).y = 0.0; 02306 Nodes.IntPoint(1).x = 1.0; 02307 Nodes.IntPoint(1).y = 0.5; 02308 Nodes.IntPoint(2).x = 0.5; 02309 Nodes.IntPoint(2).y = 1.0; 02310 Nodes.IntPoint(3).x = 0.0; 02311 Nodes.IntPoint(3).y = 0.5; 02312 } 02313 02314 void RT0QuadFiniteElement::CalcVShape(const IntegrationPoint &ip, 02315 DenseMatrix &shape) const 02316 { 02317 double x = ip.x, y = ip.y; 02318 02319 shape(0,0) = 0; 02320 shape(0,1) = y - 1.; 02321 shape(1,0) = x; 02322 shape(1,1) = 0; 02323 shape(2,0) = 0; 02324 shape(2,1) = y; 02325 shape(3,0) = x - 1.; 02326 shape(3,1) = 0; 02327 } 02328 02329 void RT0QuadFiniteElement::CalcDivShape(const IntegrationPoint &ip, 02330 Vector &divshape) const 02331 { 02332 divshape(0) = 1.; 02333 divshape(1) = 1.; 02334 divshape(2) = 1.; 02335 divshape(3) = 1.; 02336 } 02337 02338 const double RT0QuadFiniteElement::nk[4][2] = 02339 { {0, -1}, {1, 0}, {0, 1}, {-1, 0} }; 02340 02341 void RT0QuadFiniteElement::GetLocalInterpolation ( 02342 ElementTransformation &Trans, DenseMatrix &I) const 02343 { 02344 int k, j; 02345 #ifdef MFEM_USE_OPENMP 02346 DenseMatrix vshape(Dof, Dim); 02347 DenseMatrix Jinv(Dim); 02348 #endif 02349 02350 #ifdef MFEM_DEBUG 02351 for (k = 0; k < 4; k++) 02352 { 02353 CalcVShape (Nodes.IntPoint(k), vshape); 02354 for (j = 0; j < 4; j++) 02355 { 02356 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1]; 02357 if (j == k) d -= 1.0; 02358 if (fabs(d) > 1.0e-12) 02359 { 02360 cerr << "RT0QuadFiniteElement::GetLocalInterpolation (...)\n" 02361 " k = " << k << ", j = " << j << ", d = " << d << endl; 02362 mfem_error(); 02363 } 02364 } 02365 } 02366 #endif 02367 02368 IntegrationPoint ip; 02369 ip.x = ip.y = 0.0; 02370 Trans.SetIntPoint (&ip); 02371 // Trans must be linear (more to have embedding?) 02372 // set Jinv = |J| J^{-t} = adj(J)^t 02373 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 02374 double vk[2]; 02375 Vector xk (vk, 2); 02376 02377 for (k = 0; k < 4; k++) 02378 { 02379 Trans.Transform (Nodes.IntPoint (k), xk); 02380 ip.x = vk[0]; ip.y = vk[1]; 02381 CalcVShape (ip, vshape); 02382 // vk = |J| J^{-t} nk 02383 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]; 02384 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]; 02385 for (j = 0; j < 4; j++) 02386 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12) 02387 I(k,j) = 0.0; 02388 } 02389 } 02390 02391 void RT0QuadFiniteElement::Project ( 02392 VectorCoefficient &vc, ElementTransformation &Trans, 02393 Vector &dofs) const 02394 { 02395 double vk[2]; 02396 Vector xk (vk, 2); 02397 #ifdef MFEM_USE_OPENMP 02398 DenseMatrix Jinv(Dim); 02399 #endif 02400 02401 for (int k = 0; k < 4; k++) 02402 { 02403 Trans.SetIntPoint (&Nodes.IntPoint (k)); 02404 // set Jinv = |J| J^{-t} = adj(J)^t 02405 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 02406 02407 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 02408 // xk^t |J| J^{-t} nk 02409 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) + 02410 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] )); 02411 } 02412 } 02413 02414 RT1TriangleFiniteElement::RT1TriangleFiniteElement() 02415 : VectorFiniteElement (2, Geometry::TRIANGLE, 8, 2) 02416 { 02417 Nodes.IntPoint(0).x = 0.33333333333333333333; 02418 Nodes.IntPoint(0).y = 0.0; 02419 Nodes.IntPoint(1).x = 0.66666666666666666667; 02420 Nodes.IntPoint(1).y = 0.0; 02421 Nodes.IntPoint(2).x = 0.66666666666666666667; 02422 Nodes.IntPoint(2).y = 0.33333333333333333333; 02423 Nodes.IntPoint(3).x = 0.33333333333333333333; 02424 Nodes.IntPoint(3).y = 0.66666666666666666667; 02425 Nodes.IntPoint(4).x = 0.0; 02426 Nodes.IntPoint(4).y = 0.66666666666666666667; 02427 Nodes.IntPoint(5).x = 0.0; 02428 Nodes.IntPoint(5).y = 0.33333333333333333333; 02429 Nodes.IntPoint(6).x = 0.33333333333333333333; 02430 Nodes.IntPoint(6).y = 0.33333333333333333333; 02431 Nodes.IntPoint(7).x = 0.33333333333333333333; 02432 Nodes.IntPoint(7).y = 0.33333333333333333333; 02433 } 02434 02435 void RT1TriangleFiniteElement::CalcVShape(const IntegrationPoint &ip, 02436 DenseMatrix &shape) const 02437 { 02438 double x = ip.x, y = ip.y; 02439 02440 shape(0,0) = -2 * x * (-1 + x + 2 * y); 02441 shape(0,1) = -2 * (-1 + y) * (-1 + x + 2 * y); 02442 shape(1,0) = 2 * x * (x - y); 02443 shape(1,1) = 2 * (x - y) * (-1 + y); 02444 shape(2,0) = 2 * x * (-1 + 2 * x + y); 02445 shape(2,1) = 2 * y * (-1 + 2 * x + y); 02446 shape(3,0) = 2 * x * (-1 + x + 2 * y); 02447 shape(3,1) = 2 * y * (-1 + x + 2 * y); 02448 shape(4,0) = -2 * (-1 + x) * (x - y); 02449 shape(4,1) = 2 * y * (-x + y); 02450 shape(5,0) = -2 * (-1 + x) * (-1 + 2 * x + y); 02451 shape(5,1) = -2 * y * (-1 + 2 * x + y); 02452 shape(6,0) = -3 * x * (-2 + 2 * x + y); 02453 shape(6,1) = -3 * y * (-1 + 2 * x + y); 02454 shape(7,0) = -3 * x * (-1 + x + 2 * y); 02455 shape(7,1) = -3 * y * (-2 + x + 2 * y); 02456 } 02457 02458 void RT1TriangleFiniteElement::CalcDivShape(const IntegrationPoint &ip, 02459 Vector &divshape) const 02460 { 02461 double x = ip.x, y = ip.y; 02462 02463 divshape(0) = -2 * (-4 + 3 * x + 6 * y); 02464 divshape(1) = 2 + 6 * x - 6 * y; 02465 divshape(2) = -4 + 12 * x + 6 * y; 02466 divshape(3) = -4 + 6 * x + 12 * y; 02467 divshape(4) = 2 - 6 * x + 6 * y; 02468 divshape(5) = -2 * (-4 + 6 * x + 3 * y); 02469 divshape(6) = -9 * (-1 + 2 * x + y); 02470 divshape(7) = -9 * (-1 + x + 2 * y); 02471 } 02472 02473 const double RT1TriangleFiniteElement::nk[8][2] = 02474 { 02475 { 0,-1}, { 0,-1}, 02476 { 1, 1}, { 1, 1}, 02477 {-1, 0}, {-1, 0}, 02478 { 1, 0}, { 0, 1} 02479 }; 02480 02481 void RT1TriangleFiniteElement::GetLocalInterpolation ( 02482 ElementTransformation &Trans, DenseMatrix &I) const 02483 { 02484 int k, j; 02485 #ifdef MFEM_USE_OPENMP 02486 DenseMatrix vshape(Dof, Dim); 02487 DenseMatrix Jinv(Dim); 02488 #endif 02489 02490 #ifdef MFEM_DEBUG 02491 for (k = 0; k < 8; k++) 02492 { 02493 CalcVShape (Nodes.IntPoint(k), vshape); 02494 for (j = 0; j < 8; j++) 02495 { 02496 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1]; 02497 if (j == k) d -= 1.0; 02498 if (fabs(d) > 1.0e-12) 02499 { 02500 cerr << "RT1QuadFiniteElement::GetLocalInterpolation (...)\n" 02501 " k = " << k << ", j = " << j << ", d = " << d << endl; 02502 mfem_error(); 02503 } 02504 } 02505 } 02506 #endif 02507 02508 IntegrationPoint ip; 02509 ip.x = ip.y = 0.0; 02510 Trans.SetIntPoint (&ip); 02511 // Trans must be linear (more to have embedding?) 02512 // set Jinv = |J| J^{-t} = adj(J)^t 02513 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 02514 double vk[2]; 02515 Vector xk (vk, 2); 02516 02517 for (k = 0; k < 8; k++) 02518 { 02519 Trans.Transform (Nodes.IntPoint (k), xk); 02520 ip.x = vk[0]; ip.y = vk[1]; 02521 CalcVShape (ip, vshape); 02522 // vk = |J| J^{-t} nk 02523 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]; 02524 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]; 02525 for (j = 0; j < 8; j++) 02526 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12) 02527 I(k,j) = 0.0; 02528 } 02529 } 02530 02531 void RT1TriangleFiniteElement::Project ( 02532 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const 02533 { 02534 double vk[2]; 02535 Vector xk (vk, 2); 02536 #ifdef MFEM_USE_OPENMP 02537 DenseMatrix Jinv(Dim); 02538 #endif 02539 02540 for (int k = 0; k < 8; k++) 02541 { 02542 Trans.SetIntPoint (&Nodes.IntPoint (k)); 02543 // set Jinv = |J| J^{-t} = adj(J)^t 02544 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 02545 02546 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 02547 // xk^t |J| J^{-t} nk 02548 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) + 02549 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] )); 02550 dofs(k) *= 0.5; 02551 } 02552 } 02553 02554 RT1QuadFiniteElement::RT1QuadFiniteElement() 02555 : VectorFiniteElement (2, Geometry::SQUARE, 12, 2, FunctionSpace::Qk) 02556 { 02557 // y = 0 02558 Nodes.IntPoint(0).x = 1./3.; 02559 Nodes.IntPoint(0).y = 0.0; 02560 Nodes.IntPoint(1).x = 2./3.; 02561 Nodes.IntPoint(1).y = 0.0; 02562 // x = 1 02563 Nodes.IntPoint(2).x = 1.0; 02564 Nodes.IntPoint(2).y = 1./3.; 02565 Nodes.IntPoint(3).x = 1.0; 02566 Nodes.IntPoint(3).y = 2./3.; 02567 // y = 1 02568 Nodes.IntPoint(4).x = 2./3.; 02569 Nodes.IntPoint(4).y = 1.0; 02570 Nodes.IntPoint(5).x = 1./3.; 02571 Nodes.IntPoint(5).y = 1.0; 02572 // x = 0 02573 Nodes.IntPoint(6).x = 0.0; 02574 Nodes.IntPoint(6).y = 2./3.; 02575 Nodes.IntPoint(7).x = 0.0; 02576 Nodes.IntPoint(7).y = 1./3.; 02577 // x = 0.5 (interior) 02578 Nodes.IntPoint(8).x = 0.5; 02579 Nodes.IntPoint(8).y = 1./3.; 02580 Nodes.IntPoint(9).x = 0.5; 02581 Nodes.IntPoint(9).y = 2./3.; 02582 // y = 0.5 (interior) 02583 Nodes.IntPoint(10).x = 1./3.; 02584 Nodes.IntPoint(10).y = 0.5; 02585 Nodes.IntPoint(11).x = 2./3.; 02586 Nodes.IntPoint(11).y = 0.5; 02587 } 02588 02589 void RT1QuadFiniteElement::CalcVShape(const IntegrationPoint &ip, 02590 DenseMatrix &shape) const 02591 { 02592 double x = ip.x, y = ip.y; 02593 02594 // y = 0 02595 shape(0,0) = 0; 02596 shape(0,1) = -( 1. - 3.*y + 2.*y*y)*( 2. - 3.*x); 02597 shape(1,0) = 0; 02598 shape(1,1) = -( 1. - 3.*y + 2.*y*y)*(-1. + 3.*x); 02599 // x = 1 02600 shape(2,0) = (-x + 2.*x*x)*( 2. - 3.*y); 02601 shape(2,1) = 0; 02602 shape(3,0) = (-x + 2.*x*x)*(-1. + 3.*y); 02603 shape(3,1) = 0; 02604 // y = 1 02605 shape(4,0) = 0; 02606 shape(4,1) = (-y + 2.*y*y)*(-1. + 3.*x); 02607 shape(5,0) = 0; 02608 shape(5,1) = (-y + 2.*y*y)*( 2. - 3.*x); 02609 // x = 0 02610 shape(6,0) = -(1. - 3.*x + 2.*x*x)*(-1. + 3.*y); 02611 shape(6,1) = 0; 02612 shape(7,0) = -(1. - 3.*x + 2.*x*x)*( 2. - 3.*y); 02613 shape(7,1) = 0; 02614 // x = 0.5 (interior) 02615 shape(8,0) = (4.*x - 4.*x*x)*( 2. - 3.*y); 02616 shape(8,1) = 0; 02617 shape(9,0) = (4.*x - 4.*x*x)*(-1. + 3.*y); 02618 shape(9,1) = 0; 02619 // y = 0.5 (interior) 02620 shape(10,0) = 0; 02621 shape(10,1) = (4.*y - 4.*y*y)*( 2. - 3.*x); 02622 shape(11,0) = 0; 02623 shape(11,1) = (4.*y - 4.*y*y)*(-1. + 3.*x); 02624 } 02625 02626 void RT1QuadFiniteElement::CalcDivShape(const IntegrationPoint &ip, 02627 Vector &divshape) const 02628 { 02629 double x = ip.x, y = ip.y; 02630 02631 divshape(0) = -(-3. + 4.*y)*( 2. - 3.*x); 02632 divshape(1) = -(-3. + 4.*y)*(-1. + 3.*x); 02633 divshape(2) = (-1. + 4.*x)*( 2. - 3.*y); 02634 divshape(3) = (-1. + 4.*x)*(-1. + 3.*y); 02635 divshape(4) = (-1. + 4.*y)*(-1. + 3.*x); 02636 divshape(5) = (-1. + 4.*y)*( 2. - 3.*x); 02637 divshape(6) = -(-3. + 4.*x)*(-1. + 3.*y); 02638 divshape(7) = -(-3. + 4.*x)*( 2. - 3.*y); 02639 divshape(8) = ( 4. - 8.*x)*( 2. - 3.*y); 02640 divshape(9) = ( 4. - 8.*x)*(-1. + 3.*y); 02641 divshape(10) = ( 4. - 8.*y)*( 2. - 3.*x); 02642 divshape(11) = ( 4. - 8.*y)*(-1. + 3.*x); 02643 } 02644 02645 const double RT1QuadFiniteElement::nk[12][2] = 02646 { 02647 // y = 0 02648 {0,-1}, {0,-1}, 02649 // X = 1 02650 {1, 0}, {1, 0}, 02651 // y = 1 02652 {0, 1}, {0, 1}, 02653 // x = 0 02654 {-1,0}, {-1,0}, 02655 // x = 0.5 (interior) 02656 {1, 0}, {1, 0}, 02657 // y = 0.5 (interior) 02658 {0, 1}, {0, 1} 02659 }; 02660 02661 void RT1QuadFiniteElement::GetLocalInterpolation ( 02662 ElementTransformation &Trans, DenseMatrix &I) const 02663 { 02664 int k, j; 02665 #ifdef MFEM_USE_OPENMP 02666 DenseMatrix vshape(Dof, Dim); 02667 DenseMatrix Jinv(Dim); 02668 #endif 02669 02670 #ifdef MFEM_DEBUG 02671 for (k = 0; k < 12; k++) 02672 { 02673 CalcVShape (Nodes.IntPoint(k), vshape); 02674 for (j = 0; j < 12; j++) 02675 { 02676 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1]; 02677 if (j == k) d -= 1.0; 02678 if (fabs(d) > 1.0e-12) 02679 { 02680 cerr << "RT1QuadFiniteElement::GetLocalInterpolation (...)\n" 02681 " k = " << k << ", j = " << j << ", d = " << d << endl; 02682 mfem_error(); 02683 } 02684 } 02685 } 02686 #endif 02687 02688 IntegrationPoint ip; 02689 ip.x = ip.y = 0.0; 02690 Trans.SetIntPoint (&ip); 02691 // Trans must be linear (more to have embedding?) 02692 // set Jinv = |J| J^{-t} = adj(J)^t 02693 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 02694 double vk[2]; 02695 Vector xk (vk, 2); 02696 02697 for (k = 0; k < 12; k++) 02698 { 02699 Trans.Transform (Nodes.IntPoint (k), xk); 02700 ip.x = vk[0]; ip.y = vk[1]; 02701 CalcVShape (ip, vshape); 02702 // vk = |J| J^{-t} nk 02703 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]; 02704 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]; 02705 for (j = 0; j < 12; j++) 02706 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12) 02707 I(k,j) = 0.0; 02708 } 02709 } 02710 02711 void RT1QuadFiniteElement::Project ( 02712 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const 02713 { 02714 double vk[2]; 02715 Vector xk (vk, 2); 02716 #ifdef MFEM_USE_OPENMP 02717 DenseMatrix Jinv(Dim); 02718 #endif 02719 02720 for (int k = 0; k < 12; k++) 02721 { 02722 Trans.SetIntPoint (&Nodes.IntPoint (k)); 02723 // set Jinv = |J| J^{-t} = adj(J)^t 02724 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 02725 02726 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 02727 // xk^t |J| J^{-t} nk 02728 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) + 02729 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] )); 02730 } 02731 } 02732 02733 const double RT2TriangleFiniteElement::M[15][15] = 02734 {{ 0, -5.3237900077244501311, 5.3237900077244501311, 16.647580015448900262, 02735 0, 24.442740046346700787, -16.647580015448900262, -12., 02736 -19.118950038622250656, -47.237900077244501311, 0, -34.414110069520051180, 02737 12., 30.590320061795601049, 15.295160030897800524}, 02738 { 0, 1.5, -1.5, -15., 0, 2.625, 15., 15., -4.125, 30., 0, -14.625, -15., 02739 -15., 10.5}, 02740 { 0, -0.67620999227554986889, 0.67620999227554986889, 7.3524199845510997378, 02741 0, -3.4427400463467007866, -7.3524199845510997378, -12., 02742 4.1189500386222506555, -0.76209992275549868892, 0, 7.4141100695200511800, 02743 12., -6.5903200617956010489, -3.2951600308978005244}, 02744 { 0, 0, 1.5, 0, 0, 1.5, -11.471370023173350393, 0, 2.4713700231733503933, 02745 -11.471370023173350393, 0, 2.4713700231733503933, 15.295160030897800524, 02746 0, -3.2951600308978005244}, 02747 { 0, 0, 4.875, 0, 0, 4.875, -16.875, 0, -16.875, -16.875, 0, -16.875, 10.5, 02748 36., 10.5}, 02749 { 0, 0, 1.5, 0, 0, 1.5, 2.4713700231733503933, 0, -11.471370023173350393, 02750 2.4713700231733503933, 0, -11.471370023173350393, -3.2951600308978005244, 02751 0, 15.295160030897800524}, 02752 { -0.67620999227554986889, 0, -3.4427400463467007866, 0, 02753 7.3524199845510997378, 0.67620999227554986889, 7.4141100695200511800, 0, 02754 -0.76209992275549868892, 4.1189500386222506555, -12., 02755 -7.3524199845510997378, -3.2951600308978005244, -6.5903200617956010489, 02756 12.}, 02757 { 1.5, 0, 2.625, 0, -15., -1.5, -14.625, 0, 30., -4.125, 15., 15., 10.5, 02758 -15., -15.}, 02759 { -5.3237900077244501311, 0, 24.442740046346700787, 0, 16.647580015448900262, 02760 5.3237900077244501311, -34.414110069520051180, 0, -47.237900077244501311, 02761 -19.118950038622250656, -12., -16.647580015448900262, 15.295160030897800524, 02762 30.590320061795601049, 12.}, 02763 { 0, 0, 18., 0, 0, 6., -42., 0, -30., -26., 0, -14., 24., 32., 8.}, 02764 { 0, 0, 6., 0, 0, 18., -14., 0, -26., -30., 0, -42., 8., 32., 24.}, 02765 { 0, 0, -6., 0, 0, -4., 30., 0, 4., 22., 0, 4., -24., -16., 0}, 02766 { 0, 0, -4., 0, 0, -8., 20., 0, 8., 36., 0, 8., -16., -32., 0}, 02767 { 0, 0, -8., 0, 0, -4., 8., 0, 36., 8., 0, 20., 0, -32., -16.}, 02768 { 0, 0, -4., 0, 0, -6., 4., 0, 22., 4., 0, 30., 0, -16., -24.} 02769 }; 02770 02771 RT2TriangleFiniteElement::RT2TriangleFiniteElement() 02772 : VectorFiniteElement (2, Geometry::TRIANGLE, 15, 3) 02773 { 02774 const double p = 0.11270166537925831148; 02775 02776 Nodes.IntPoint(0).x = p; 02777 Nodes.IntPoint(0).y = 0.0; 02778 Nodes.IntPoint(1).x = 0.5; 02779 Nodes.IntPoint(1).y = 0.0; 02780 Nodes.IntPoint(2).x = 1.-p; 02781 Nodes.IntPoint(2).y = 0.0; 02782 Nodes.IntPoint(3).x = 1.-p; 02783 Nodes.IntPoint(3).y = p; 02784 Nodes.IntPoint(4).x = 0.5; 02785 Nodes.IntPoint(4).y = 0.5; 02786 Nodes.IntPoint(5).x = p; 02787 Nodes.IntPoint(5).y = 1.-p; 02788 Nodes.IntPoint(6).x = 0.0; 02789 Nodes.IntPoint(6).y = 1.-p; 02790 Nodes.IntPoint(7).x = 0.0; 02791 Nodes.IntPoint(7).y = 0.5; 02792 Nodes.IntPoint(8).x = 0.0; 02793 Nodes.IntPoint(8).y = p; 02794 Nodes.IntPoint(9).x = 0.25; 02795 Nodes.IntPoint(9).y = 0.25; 02796 Nodes.IntPoint(10).x = 0.25; 02797 Nodes.IntPoint(10).y = 0.25; 02798 Nodes.IntPoint(11).x = 0.5; 02799 Nodes.IntPoint(11).y = 0.25; 02800 Nodes.IntPoint(12).x = 0.5; 02801 Nodes.IntPoint(12).y = 0.25; 02802 Nodes.IntPoint(13).x = 0.25; 02803 Nodes.IntPoint(13).y = 0.5; 02804 Nodes.IntPoint(14).x = 0.25; 02805 Nodes.IntPoint(14).y = 0.5; 02806 } 02807 02808 void RT2TriangleFiniteElement::CalcVShape(const IntegrationPoint &ip, 02809 DenseMatrix &shape) const 02810 { 02811 double x = ip.x, y = ip.y; 02812 02813 double Bx[15] = {1., 0., x, 0., y, 0., x*x, 0., x*y, 0., y*y, 0., x*x*x, 02814 x*x*y, x*y*y}; 02815 double By[15] = {0., 1., 0., x, 0., y, 0., x*x, 0., x*y, 0., y*y, 02816 x*x*y, x*y*y, y*y*y}; 02817 02818 for (int i = 0; i < 15; i++) 02819 { 02820 double cx = 0.0, cy = 0.0; 02821 for (int j = 0; j < 15; j++) 02822 { 02823 cx += M[i][j] * Bx[j]; 02824 cy += M[i][j] * By[j]; 02825 } 02826 shape(i,0) = cx; 02827 shape(i,1) = cy; 02828 } 02829 } 02830 02831 void RT2TriangleFiniteElement::CalcDivShape(const IntegrationPoint &ip, 02832 Vector &divshape) const 02833 { 02834 double x = ip.x, y = ip.y; 02835 02836 double DivB[15] = {0., 0., 1., 0., 0., 1., 2.*x, 0., y, x, 0., 2.*y, 02837 4.*x*x, 4.*x*y, 4.*y*y}; 02838 02839 for (int i = 0; i < 15; i++) 02840 { 02841 double div = 0.0; 02842 for (int j = 0; j < 15; j++) 02843 div += M[i][j] * DivB[j]; 02844 divshape(i) = div; 02845 } 02846 } 02847 02848 const double RT2QuadFiniteElement::pt[4] = {0.,1./3.,2./3.,1.}; 02849 02850 const double RT2QuadFiniteElement::dpt[3] = {0.25,0.5,0.75}; 02851 02852 RT2QuadFiniteElement::RT2QuadFiniteElement() 02853 : VectorFiniteElement (2, Geometry::SQUARE, 24, 3, FunctionSpace::Qk) 02854 { 02855 // y = 0 (pt[0]) 02856 Nodes.IntPoint(0).x = dpt[0]; Nodes.IntPoint(0).y = pt[0]; 02857 Nodes.IntPoint(1).x = dpt[1]; Nodes.IntPoint(1).y = pt[0]; 02858 Nodes.IntPoint(2).x = dpt[2]; Nodes.IntPoint(2).y = pt[0]; 02859 // x = 1 (pt[3]) 02860 Nodes.IntPoint(3).x = pt[3]; Nodes.IntPoint(3).y = dpt[0]; 02861 Nodes.IntPoint(4).x = pt[3]; Nodes.IntPoint(4).y = dpt[1]; 02862 Nodes.IntPoint(5).x = pt[3]; Nodes.IntPoint(5).y = dpt[2]; 02863 // y = 1 (pt[3]) 02864 Nodes.IntPoint(6).x = dpt[2]; Nodes.IntPoint(6).y = pt[3]; 02865 Nodes.IntPoint(7).x = dpt[1]; Nodes.IntPoint(7).y = pt[3]; 02866 Nodes.IntPoint(8).x = dpt[0]; Nodes.IntPoint(8).y = pt[3]; 02867 // x = 0 (pt[0]) 02868 Nodes.IntPoint(9).x = pt[0]; Nodes.IntPoint(9).y = dpt[2]; 02869 Nodes.IntPoint(10).x = pt[0]; Nodes.IntPoint(10).y = dpt[1]; 02870 Nodes.IntPoint(11).x = pt[0]; Nodes.IntPoint(11).y = dpt[0]; 02871 // x = pt[1] (interior) 02872 Nodes.IntPoint(12).x = pt[1]; Nodes.IntPoint(12).y = dpt[0]; 02873 Nodes.IntPoint(13).x = pt[1]; Nodes.IntPoint(13).y = dpt[1]; 02874 Nodes.IntPoint(14).x = pt[1]; Nodes.IntPoint(14).y = dpt[2]; 02875 // x = pt[2] (interior) 02876 Nodes.IntPoint(15).x = pt[2]; Nodes.IntPoint(15).y = dpt[0]; 02877 Nodes.IntPoint(16).x = pt[2]; Nodes.IntPoint(16).y = dpt[1]; 02878 Nodes.IntPoint(17).x = pt[2]; Nodes.IntPoint(17).y = dpt[2]; 02879 // y = pt[1] (interior) 02880 Nodes.IntPoint(18).x = dpt[0]; Nodes.IntPoint(18).y = pt[1]; 02881 Nodes.IntPoint(19).x = dpt[1]; Nodes.IntPoint(19).y = pt[1]; 02882 Nodes.IntPoint(20).x = dpt[2]; Nodes.IntPoint(20).y = pt[1]; 02883 // y = pt[2] (interior) 02884 Nodes.IntPoint(21).x = dpt[0]; Nodes.IntPoint(21).y = pt[2]; 02885 Nodes.IntPoint(22).x = dpt[1]; Nodes.IntPoint(22).y = pt[2]; 02886 Nodes.IntPoint(23).x = dpt[2]; Nodes.IntPoint(23).y = pt[2]; 02887 } 02888 02889 void RT2QuadFiniteElement::CalcVShape(const IntegrationPoint &ip, 02890 DenseMatrix &shape) const 02891 { 02892 double x = ip.x, y = ip.y; 02893 02894 double ax0 = pt[0] - x; 02895 double ax1 = pt[1] - x; 02896 double ax2 = pt[2] - x; 02897 double ax3 = pt[3] - x; 02898 02899 double by0 = dpt[0] - y; 02900 double by1 = dpt[1] - y; 02901 double by2 = dpt[2] - y; 02902 02903 double ay0 = pt[0] - y; 02904 double ay1 = pt[1] - y; 02905 double ay2 = pt[2] - y; 02906 double ay3 = pt[3] - y; 02907 02908 double bx0 = dpt[0] - x; 02909 double bx1 = dpt[1] - x; 02910 double bx2 = dpt[2] - x; 02911 02912 double A01 = pt[0] - pt[1]; 02913 double A02 = pt[0] - pt[2]; 02914 double A12 = pt[1] - pt[2]; 02915 double A03 = pt[0] - pt[3]; 02916 double A13 = pt[1] - pt[3]; 02917 double A23 = pt[2] - pt[3]; 02918 02919 double B01 = dpt[0] - dpt[1]; 02920 double B02 = dpt[0] - dpt[2]; 02921 double B12 = dpt[1] - dpt[2]; 02922 02923 double tx0 = (bx1*bx2)/(B01*B02); 02924 double tx1 = -(bx0*bx2)/(B01*B12); 02925 double tx2 = (bx0*bx1)/(B02*B12); 02926 02927 double ty0 = (by1*by2)/(B01*B02); 02928 double ty1 = -(by0*by2)/(B01*B12); 02929 double ty2 = (by0*by1)/(B02*B12); 02930 02931 // y = 0 (p[0]) 02932 shape(0, 0) = 0; 02933 shape(0, 1) = (ay1*ay2*ay3)/(A01*A02*A03)*tx0; 02934 shape(1, 0) = 0; 02935 shape(1, 1) = (ay1*ay2*ay3)/(A01*A02*A03)*tx1; 02936 shape(2, 0) = 0; 02937 shape(2, 1) = (ay1*ay2*ay3)/(A01*A02*A03)*tx2; 02938 // x = 1 (p[3]) 02939 shape(3, 0) = (ax0*ax1*ax2)/(A03*A13*A23)*ty0; 02940 shape(3, 1) = 0; 02941 shape(4, 0) = (ax0*ax1*ax2)/(A03*A13*A23)*ty1; 02942 shape(4, 1) = 0; 02943 shape(5, 0) = (ax0*ax1*ax2)/(A03*A13*A23)*ty2; 02944 shape(5, 1) = 0; 02945 // y = 1 (p[3]) 02946 shape(6, 0) = 0; 02947 shape(6, 1) = (ay0*ay1*ay2)/(A03*A13*A23)*tx2; 02948 shape(7, 0) = 0; 02949 shape(7, 1) = (ay0*ay1*ay2)/(A03*A13*A23)*tx1; 02950 shape(8, 0) = 0; 02951 shape(8, 1) = (ay0*ay1*ay2)/(A03*A13*A23)*tx0; 02952 // x = 0 (p[0]) 02953 shape(9, 0) = (ax1*ax2*ax3)/(A01*A02*A03)*ty2; 02954 shape(9, 1) = 0; 02955 shape(10, 0) = (ax1*ax2*ax3)/(A01*A02*A03)*ty1; 02956 shape(10, 1) = 0; 02957 shape(11, 0) = (ax1*ax2*ax3)/(A01*A02*A03)*ty0; 02958 shape(11, 1) = 0; 02959 // x = p[1] (interior) 02960 shape(12, 0) = (ax0*ax2*ax3)/(A01*A12*A13)*ty0; 02961 shape(12, 1) = 0; 02962 shape(13, 0) = (ax0*ax2*ax3)/(A01*A12*A13)*ty1; 02963 shape(13, 1) = 0; 02964 shape(14, 0) = (ax0*ax2*ax3)/(A01*A12*A13)*ty2; 02965 shape(14, 1) = 0; 02966 // x = p[2] (interior) 02967 shape(15, 0) = -(ax0*ax1*ax3)/(A02*A12*A23)*ty0; 02968 shape(15, 1) = 0; 02969 shape(16, 0) = -(ax0*ax1*ax3)/(A02*A12*A23)*ty1; 02970 shape(16, 1) = 0; 02971 shape(17, 0) = -(ax0*ax1*ax3)/(A02*A12*A23)*ty2; 02972 shape(17, 1) = 0; 02973 // y = p[1] (interior) 02974 shape(18, 0) = 0; 02975 shape(18, 1) = (ay0*ay2*ay3)/(A01*A12*A13)*tx0; 02976 shape(19, 0) = 0; 02977 shape(19, 1) = (ay0*ay2*ay3)/(A01*A12*A13)*tx1; 02978 shape(20, 0) = 0; 02979 shape(20, 1) = (ay0*ay2*ay3)/(A01*A12*A13)*tx2; 02980 // y = p[2] (interior) 02981 shape(21, 0) = 0; 02982 shape(21, 1) = -(ay0*ay1*ay3)/(A02*A12*A23)*tx0; 02983 shape(22, 0) = 0; 02984 shape(22, 1) = -(ay0*ay1*ay3)/(A02*A12*A23)*tx1; 02985 shape(23, 0) = 0; 02986 shape(23, 1) = -(ay0*ay1*ay3)/(A02*A12*A23)*tx2; 02987 } 02988 02989 void RT2QuadFiniteElement::CalcDivShape(const IntegrationPoint &ip, 02990 Vector &divshape) const 02991 { 02992 double x = ip.x, y = ip.y; 02993 02994 double a01 = pt[0]*pt[1]; 02995 double a02 = pt[0]*pt[2]; 02996 double a12 = pt[1]*pt[2]; 02997 double a03 = pt[0]*pt[3]; 02998 double a13 = pt[1]*pt[3]; 02999 double a23 = pt[2]*pt[3]; 03000 03001 double bx0 = dpt[0] - x; 03002 double bx1 = dpt[1] - x; 03003 double bx2 = dpt[2] - x; 03004 03005 double by0 = dpt[0] - y; 03006 double by1 = dpt[1] - y; 03007 double by2 = dpt[2] - y; 03008 03009 double A01 = pt[0] - pt[1]; 03010 double A02 = pt[0] - pt[2]; 03011 double A12 = pt[1] - pt[2]; 03012 double A03 = pt[0] - pt[3]; 03013 double A13 = pt[1] - pt[3]; 03014 double A23 = pt[2] - pt[3]; 03015 03016 double A012 = pt[0] + pt[1] + pt[2]; 03017 double A013 = pt[0] + pt[1] + pt[3]; 03018 double A023 = pt[0] + pt[2] + pt[3]; 03019 double A123 = pt[1] + pt[2] + pt[3]; 03020 03021 double B01 = dpt[0] - dpt[1]; 03022 double B02 = dpt[0] - dpt[2]; 03023 double B12 = dpt[1] - dpt[2]; 03024 03025 double tx0 = (bx1*bx2)/(B01*B02); 03026 double tx1 = -(bx0*bx2)/(B01*B12); 03027 double tx2 = (bx0*bx1)/(B02*B12); 03028 03029 double ty0 = (by1*by2)/(B01*B02); 03030 double ty1 = -(by0*by2)/(B01*B12); 03031 double ty2 = (by0*by1)/(B02*B12); 03032 03033 // y = 0 (p[0]) 03034 divshape(0) = -(a12 + a13 + a23 - 2.*A123*y + 3.*y*y)/(A01*A02*A03)*tx0; 03035 divshape(1) = -(a12 + a13 + a23 - 2.*A123*y + 3.*y*y)/(A01*A02*A03)*tx1; 03036 divshape(2) = -(a12 + a13 + a23 - 2.*A123*y + 3.*y*y)/(A01*A02*A03)*tx2; 03037 // x = 1 (p[3]) 03038 divshape(3) = -(a01 + a02 + a12 - 2.*A012*x + 3.*x*x)/(A03*A13*A23)*ty0; 03039 divshape(4) = -(a01 + a02 + a12 - 2.*A012*x + 3.*x*x)/(A03*A13*A23)*ty1; 03040 divshape(5) = -(a01 + a02 + a12 - 2.*A012*x + 3.*x*x)/(A03*A13*A23)*ty2; 03041 // y = 1 (p[3]) 03042 divshape(6) = -(a01 + a02 + a12 - 2.*A012*y + 3.*y*y)/(A03*A13*A23)*tx2; 03043 divshape(7) = -(a01 + a02 + a12 - 2.*A012*y + 3.*y*y)/(A03*A13*A23)*tx1; 03044 divshape(8) = -(a01 + a02 + a12 - 2.*A012*y + 3.*y*y)/(A03*A13*A23)*tx0; 03045 // x = 0 (p[0]) 03046 divshape(9) = -(a12 + a13 + a23 - 2.*A123*x + 3.*x*x)/(A01*A02*A03)*ty2; 03047 divshape(10) = -(a12 + a13 + a23 - 2.*A123*x + 3.*x*x)/(A01*A02*A03)*ty1; 03048 divshape(11) = -(a12 + a13 + a23 - 2.*A123*x + 3.*x*x)/(A01*A02*A03)*ty0; 03049 // x = p[1] (interior) 03050 divshape(12) = -(a02 + a03 + a23 - 2.*A023*x + 3.*x*x)/(A01*A12*A13)*ty0; 03051 divshape(13) = -(a02 + a03 + a23 - 2.*A023*x + 3.*x*x)/(A01*A12*A13)*ty1; 03052 divshape(14) = -(a02 + a03 + a23 - 2.*A023*x + 3.*x*x)/(A01*A12*A13)*ty2; 03053 // x = p[2] (interior) 03054 divshape(15) = (a01 + a03 + a13 - 2.*A013*x + 3.*x*x)/(A02*A12*A23)*ty0; 03055 divshape(16) = (a01 + a03 + a13 - 2.*A013*x + 3.*x*x)/(A02*A12*A23)*ty1; 03056 divshape(17) = (a01 + a03 + a13 - 2.*A013*x + 3.*x*x)/(A02*A12*A23)*ty2; 03057 // y = p[1] (interior) 03058 divshape(18) = -(a02 + a03 + a23 - 2.*A023*y + 3.*y*y)/(A01*A12*A13)*tx0; 03059 divshape(19) = -(a02 + a03 + a23 - 2.*A023*y + 3.*y*y)/(A01*A12*A13)*tx1; 03060 divshape(20) = -(a02 + a03 + a23 - 2.*A023*y + 3.*y*y)/(A01*A12*A13)*tx2; 03061 // y = p[2] (interior) 03062 divshape(21) = (a01 + a03 + a13 - 2.*A013*y + 3.*y*y)/(A02*A12*A23)*tx0; 03063 divshape(22) = (a01 + a03 + a13 - 2.*A013*y + 3.*y*y)/(A02*A12*A23)*tx1; 03064 divshape(23) = (a01 + a03 + a13 - 2.*A013*y + 3.*y*y)/(A02*A12*A23)*tx2; 03065 } 03066 03067 const double RT2QuadFiniteElement::nk[24][2] = 03068 { 03069 // y = 0 03070 {0,-1}, {0,-1}, {0,-1}, 03071 // x = 1 03072 {1, 0}, {1, 0}, {1, 0}, 03073 // y = 1 03074 {0, 1}, {0, 1}, {0, 1}, 03075 // x = 0 03076 {-1,0}, {-1,0}, {-1,0}, 03077 // x = p[1] (interior) 03078 {1, 0}, {1, 0}, {1, 0}, 03079 // x = p[2] (interior) 03080 {1, 0}, {1, 0}, {1, 0}, 03081 // y = p[1] (interior) 03082 {0, 1}, {0, 1}, {0, 1}, 03083 // y = p[1] (interior) 03084 {0, 1}, {0, 1}, {0, 1} 03085 }; 03086 03087 void RT2QuadFiniteElement::GetLocalInterpolation ( 03088 ElementTransformation &Trans, DenseMatrix &I) const 03089 { 03090 int k, j; 03091 #ifdef MFEM_USE_OPENMP 03092 DenseMatrix vshape(Dof, Dim); 03093 DenseMatrix Jinv(Dim); 03094 #endif 03095 03096 #ifdef MFEM_DEBUG 03097 for (k = 0; k < 24; k++) 03098 { 03099 CalcVShape (Nodes.IntPoint(k), vshape); 03100 for (j = 0; j < 24; j++) 03101 { 03102 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1]; 03103 if (j == k) d -= 1.0; 03104 if (fabs(d) > 1.0e-12) 03105 { 03106 cerr << "RT2QuadFiniteElement::GetLocalInterpolation (...)\n" 03107 " k = " << k << ", j = " << j << ", d = " << d << endl; 03108 mfem_error(); 03109 } 03110 } 03111 } 03112 #endif 03113 03114 IntegrationPoint ip; 03115 ip.x = ip.y = 0.0; 03116 Trans.SetIntPoint (&ip); 03117 // Trans must be linear (more to have embedding?) 03118 // set Jinv = |J| J^{-t} = adj(J)^t 03119 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 03120 double vk[2]; 03121 Vector xk (vk, 2); 03122 03123 for (k = 0; k < 24; k++) 03124 { 03125 Trans.Transform (Nodes.IntPoint (k), xk); 03126 ip.x = vk[0]; ip.y = vk[1]; 03127 CalcVShape (ip, vshape); 03128 // vk = |J| J^{-t} nk 03129 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]; 03130 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]; 03131 for (j = 0; j < 24; j++) 03132 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12) 03133 I(k,j) = 0.0; 03134 } 03135 } 03136 03137 void RT2QuadFiniteElement::Project ( 03138 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const 03139 { 03140 double vk[2]; 03141 Vector xk (vk, 2); 03142 #ifdef MFEM_USE_OPENMP 03143 DenseMatrix Jinv(Dim); 03144 #endif 03145 03146 for (int k = 0; k < 24; k++) 03147 { 03148 Trans.SetIntPoint (&Nodes.IntPoint (k)); 03149 // set Jinv = |J| J^{-t} = adj(J)^t 03150 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 03151 03152 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 03153 // xk^t |J| J^{-t} nk 03154 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) + 03155 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] )); 03156 } 03157 } 03158 03159 P1SegmentFiniteElement::P1SegmentFiniteElement() 03160 : NodalFiniteElement(1, Geometry::SEGMENT, 2, 1) 03161 { 03162 Nodes.IntPoint(0).x = 0.33333333333333333333; 03163 Nodes.IntPoint(1).x = 0.66666666666666666667; 03164 } 03165 03166 void P1SegmentFiniteElement::CalcShape(const IntegrationPoint &ip, 03167 Vector &shape) const 03168 { 03169 double x = ip.x; 03170 03171 shape(0) = 2. - 3. * x; 03172 shape(1) = 3. * x - 1.; 03173 } 03174 03175 void P1SegmentFiniteElement::CalcDShape(const IntegrationPoint &ip, 03176 DenseMatrix &dshape) const 03177 { 03178 dshape(0,0) = -3.; 03179 dshape(1,0) = 3.; 03180 } 03181 03182 03183 P2SegmentFiniteElement::P2SegmentFiniteElement() 03184 : NodalFiniteElement(1, Geometry::SEGMENT, 3, 2) 03185 { 03186 const double p = 0.11270166537925831148; 03187 03188 Nodes.IntPoint(0).x = p; 03189 Nodes.IntPoint(1).x = 0.5; 03190 Nodes.IntPoint(2).x = 1.-p; 03191 } 03192 03193 void P2SegmentFiniteElement::CalcShape(const IntegrationPoint &ip, 03194 Vector &shape) const 03195 { 03196 const double p = 0.11270166537925831148; 03197 const double w = 1./((1-2*p)*(1-2*p)); 03198 double x = ip.x; 03199 03200 shape(0) = (2*x-1)*(x-1+p)*w; 03201 shape(1) = 4*(x-1+p)*(p-x)*w; 03202 shape(2) = (2*x-1)*(x-p)*w; 03203 } 03204 03205 void P2SegmentFiniteElement::CalcDShape(const IntegrationPoint &ip, 03206 DenseMatrix &dshape) const 03207 { 03208 const double p = 0.11270166537925831148; 03209 const double w = 1./((1-2*p)*(1-2*p)); 03210 double x = ip.x; 03211 03212 dshape(0,0) = (-3+4*x+2*p)*w; 03213 dshape(1,0) = (4-8*x)*w; 03214 dshape(2,0) = (-1+4*x-2*p)*w; 03215 } 03216 03217 03218 Lagrange1DFiniteElement::Lagrange1DFiniteElement(int degree) 03219 : NodalFiniteElement(1, Geometry::SEGMENT, degree+1, degree) 03220 { 03221 int i, m = degree; 03222 03223 Nodes.IntPoint(0).x = 0.0; 03224 Nodes.IntPoint(1).x = 1.0; 03225 for (i = 1; i < m; i++) 03226 Nodes.IntPoint(i+1).x = double(i) / m; 03227 03228 rwk.SetSize(degree+1); 03229 #ifndef MFEM_USE_OPENMP 03230 rxxk.SetSize(degree+1); 03231 #endif 03232 03233 rwk(0) = 1.0; 03234 for (i = 1; i <= m; i++) 03235 rwk(i) = rwk(i-1) * ( (double)(m) / (double)(i) ); 03236 for (i = 0; i < m/2+1; i++) 03237 rwk(m-i) = ( rwk(i) *= rwk(m-i) ); 03238 for (i = m-1; i >= 0; i -= 2) 03239 rwk(i) = -rwk(i); 03240 } 03241 03242 void Lagrange1DFiniteElement::CalcShape(const IntegrationPoint &ip, 03243 Vector &shape) const 03244 { 03245 double w, wk, x = ip.x; 03246 int i, k, m = GetOrder(); 03247 03248 #ifdef MFEM_USE_OPENMP 03249 Vector rxxk(m+1); 03250 #endif 03251 03252 k = (int) floor ( m * x + 0.5 ); 03253 wk = 1.0; 03254 for (i = 0; i <= m; i++) 03255 if (i != k) 03256 wk *= ( rxxk(i) = x - (double)(i) / m ); 03257 w = wk * ( rxxk(k) = x - (double)(k) / m ); 03258 03259 if (k != 0) 03260 shape(0) = w * rwk(0) / rxxk(0); 03261 else 03262 shape(0) = wk * rwk(0); 03263 if (k != m) 03264 shape(1) = w * rwk(m) / rxxk(m); 03265 else 03266 shape(1) = wk * rwk(k); 03267 for (i = 1; i < m; i++) 03268 if (i != k) 03269 shape(i+1) = w * rwk(i) / rxxk(i); 03270 else 03271 shape(k+1) = wk * rwk(k); 03272 } 03273 03274 void Lagrange1DFiniteElement::CalcDShape(const IntegrationPoint &ip, 03275 DenseMatrix &dshape) const 03276 { 03277 double s, srx, w, wk, x = ip.x; 03278 int i, k, m = GetOrder(); 03279 03280 #ifdef MFEM_USE_OPENMP 03281 Vector rxxk(m+1); 03282 #endif 03283 03284 k = (int) floor ( m * x + 0.5 ); 03285 wk = 1.0; 03286 for (i = 0; i <= m; i++) 03287 if (i != k) 03288 wk *= ( rxxk(i) = x - (double)(i) / m ); 03289 w = wk * ( rxxk(k) = x - (double)(k) / m ); 03290 03291 for (i = 0; i <= m; i++) 03292 rxxk(i) = 1.0 / rxxk(i); 03293 srx = 0.0; 03294 for (i = 0; i <= m; i++) 03295 if (i != k) 03296 srx += rxxk(i); 03297 s = w * srx + wk; 03298 03299 if (k != 0) 03300 dshape(0,0) = (s - w * rxxk(0)) * rwk(0) * rxxk(0); 03301 else 03302 dshape(0,0) = wk * srx * rwk(0); 03303 if (k != m) 03304 dshape(1,0) = (s - w * rxxk(m)) * rwk(m) * rxxk(m); 03305 else 03306 dshape(1,0) = wk * srx * rwk(k); 03307 for (i = 1; i < m; i++) 03308 if (i != k) 03309 dshape(i+1,0) = (s - w * rxxk(i)) * rwk(i) * rxxk(i); 03310 else 03311 dshape(k+1,0) = wk * srx * rwk(k); 03312 } 03313 03314 03315 P1TetNonConfFiniteElement::P1TetNonConfFiniteElement() 03316 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 4, 1) 03317 { 03318 Nodes.IntPoint(0).x = 0.33333333333333333333; 03319 Nodes.IntPoint(0).y = 0.33333333333333333333; 03320 Nodes.IntPoint(0).z = 0.33333333333333333333; 03321 03322 Nodes.IntPoint(1).x = 0.0; 03323 Nodes.IntPoint(1).y = 0.33333333333333333333; 03324 Nodes.IntPoint(1).z = 0.33333333333333333333; 03325 03326 Nodes.IntPoint(2).x = 0.33333333333333333333; 03327 Nodes.IntPoint(2).y = 0.0; 03328 Nodes.IntPoint(2).z = 0.33333333333333333333; 03329 03330 Nodes.IntPoint(3).x = 0.33333333333333333333; 03331 Nodes.IntPoint(3).y = 0.33333333333333333333; 03332 Nodes.IntPoint(3).z = 0.0; 03333 03334 } 03335 03336 void P1TetNonConfFiniteElement::CalcShape(const IntegrationPoint &ip, 03337 Vector &shape) const 03338 { 03339 double L0, L1, L2, L3; 03340 03341 L1 = ip.x; L2 = ip.y; L3 = ip.z; L0 = 1.0 - L1 - L2 - L3; 03342 shape(0) = 1.0 - 3.0 * L0; 03343 shape(1) = 1.0 - 3.0 * L1; 03344 shape(2) = 1.0 - 3.0 * L2; 03345 shape(3) = 1.0 - 3.0 * L3; 03346 } 03347 03348 void P1TetNonConfFiniteElement::CalcDShape(const IntegrationPoint &ip, 03349 DenseMatrix &dshape) const 03350 { 03351 dshape(0,0) = 3.0; dshape(0,1) = 3.0; dshape(0,2) = 3.0; 03352 dshape(1,0) = -3.0; dshape(1,1) = 0.0; dshape(1,2) = 0.0; 03353 dshape(2,0) = 0.0; dshape(2,1) = -3.0; dshape(2,2) = 0.0; 03354 dshape(3,0) = 0.0; dshape(3,1) = 0.0; dshape(3,2) = -3.0; 03355 } 03356 03357 03358 P0TetFiniteElement::P0TetFiniteElement() 03359 : NodalFiniteElement(3, Geometry::TETRAHEDRON , 1, 0) 03360 { 03361 Nodes.IntPoint(0).x = 0.25; 03362 Nodes.IntPoint(0).y = 0.25; 03363 Nodes.IntPoint(0).z = 0.25; 03364 } 03365 03366 void P0TetFiniteElement::CalcShape(const IntegrationPoint &ip, 03367 Vector &shape) const 03368 { 03369 shape(0) = 1.0; 03370 } 03371 03372 void P0TetFiniteElement::CalcDShape(const IntegrationPoint &ip, 03373 DenseMatrix &dshape) const 03374 { 03375 dshape(0,0) = 0.0; dshape(0,1) = 0.0; dshape(0,2) = 0.0; 03376 } 03377 03378 03379 P0HexFiniteElement::P0HexFiniteElement() 03380 : NodalFiniteElement(3, Geometry::CUBE, 1, 0, FunctionSpace::Qk) 03381 { 03382 Nodes.IntPoint(0).x = 0.5; 03383 Nodes.IntPoint(0).y = 0.5; 03384 Nodes.IntPoint(0).z = 0.5; 03385 } 03386 03387 void P0HexFiniteElement::CalcShape(const IntegrationPoint &ip, 03388 Vector &shape) const 03389 { 03390 shape(0) = 1.0; 03391 } 03392 03393 void P0HexFiniteElement::CalcDShape(const IntegrationPoint &ip, 03394 DenseMatrix &dshape) const 03395 { 03396 dshape(0,0) = 0.0; dshape(0,1) = 0.0; dshape(0,2) = 0.0; 03397 } 03398 03399 03400 LagrangeHexFiniteElement::LagrangeHexFiniteElement (int degree) 03401 : NodalFiniteElement(3, Geometry::CUBE, (degree+1)*(degree+1)*(degree+1), 03402 degree, FunctionSpace::Qk) 03403 { 03404 if (degree == 2) 03405 { 03406 I = new int[Dof]; 03407 J = new int[Dof]; 03408 K = new int[Dof]; 03409 // nodes 03410 I[ 0] = 0; J[ 0] = 0; K[ 0] = 0; 03411 I[ 1] = 1; J[ 1] = 0; K[ 1] = 0; 03412 I[ 2] = 1; J[ 2] = 1; K[ 2] = 0; 03413 I[ 3] = 0; J[ 3] = 1; K[ 3] = 0; 03414 I[ 4] = 0; J[ 4] = 0; K[ 4] = 1; 03415 I[ 5] = 1; J[ 5] = 0; K[ 5] = 1; 03416 I[ 6] = 1; J[ 6] = 1; K[ 6] = 1; 03417 I[ 7] = 0; J[ 7] = 1; K[ 7] = 1; 03418 // edges 03419 I[ 8] = 2; J[ 8] = 0; K[ 8] = 0; 03420 I[ 9] = 1; J[ 9] = 2; K[ 9] = 0; 03421 I[10] = 2; J[10] = 1; K[10] = 0; 03422 I[11] = 0; J[11] = 2; K[11] = 0; 03423 I[12] = 2; J[12] = 0; K[12] = 1; 03424 I[13] = 1; J[13] = 2; K[13] = 1; 03425 I[14] = 2; J[14] = 1; K[14] = 1; 03426 I[15] = 0; J[15] = 2; K[15] = 1; 03427 I[16] = 0; J[16] = 0; K[16] = 2; 03428 I[17] = 1; J[17] = 0; K[17] = 2; 03429 I[18] = 1; J[18] = 1; K[18] = 2; 03430 I[19] = 0; J[19] = 1; K[19] = 2; 03431 // faces 03432 I[20] = 2; J[20] = 2; K[20] = 0; 03433 I[21] = 2; J[21] = 0; K[21] = 2; 03434 I[22] = 1; J[22] = 2; K[22] = 2; 03435 I[23] = 2; J[23] = 1; K[23] = 2; 03436 I[24] = 0; J[24] = 2; K[24] = 2; 03437 I[25] = 2; J[25] = 2; K[25] = 1; 03438 // element 03439 I[26] = 2; J[26] = 2; K[26] = 2; 03440 } 03441 else if (degree == 3) 03442 { 03443 I = new int[Dof]; 03444 J = new int[Dof]; 03445 K = new int[Dof]; 03446 // nodes 03447 I[ 0] = 0; J[ 0] = 0; K[ 0] = 0; 03448 I[ 1] = 1; J[ 1] = 0; K[ 1] = 0; 03449 I[ 2] = 1; J[ 2] = 1; K[ 2] = 0; 03450 I[ 3] = 0; J[ 3] = 1; K[ 3] = 0; 03451 I[ 4] = 0; J[ 4] = 0; K[ 4] = 1; 03452 I[ 5] = 1; J[ 5] = 0; K[ 5] = 1; 03453 I[ 6] = 1; J[ 6] = 1; K[ 6] = 1; 03454 I[ 7] = 0; J[ 7] = 1; K[ 7] = 1; 03455 // edges 03456 I[ 8] = 2; J[ 8] = 0; K[ 8] = 0; 03457 I[ 9] = 3; J[ 9] = 0; K[ 9] = 0; 03458 I[10] = 1; J[10] = 2; K[10] = 0; 03459 I[11] = 1; J[11] = 3; K[11] = 0; 03460 I[12] = 2; J[12] = 1; K[12] = 0; 03461 I[13] = 3; J[13] = 1; K[13] = 0; 03462 I[14] = 0; J[14] = 2; K[14] = 0; 03463 I[15] = 0; J[15] = 3; K[15] = 0; 03464 I[16] = 2; J[16] = 0; K[16] = 1; 03465 I[17] = 3; J[17] = 0; K[17] = 1; 03466 I[18] = 1; J[18] = 2; K[18] = 1; 03467 I[19] = 1; J[19] = 3; K[19] = 1; 03468 I[20] = 2; J[20] = 1; K[20] = 1; 03469 I[21] = 3; J[21] = 1; K[21] = 1; 03470 I[22] = 0; J[22] = 2; K[22] = 1; 03471 I[23] = 0; J[23] = 3; K[23] = 1; 03472 I[24] = 0; J[24] = 0; K[24] = 2; 03473 I[25] = 0; J[25] = 0; K[25] = 3; 03474 I[26] = 1; J[26] = 0; K[26] = 2; 03475 I[27] = 1; J[27] = 0; K[27] = 3; 03476 I[28] = 1; J[28] = 1; K[28] = 2; 03477 I[29] = 1; J[29] = 1; K[29] = 3; 03478 I[30] = 0; J[30] = 1; K[30] = 2; 03479 I[31] = 0; J[31] = 1; K[31] = 3; 03480 // faces 03481 I[32] = 2; J[32] = 3; K[32] = 0; 03482 I[33] = 3; J[33] = 3; K[33] = 0; 03483 I[34] = 2; J[34] = 2; K[34] = 0; 03484 I[35] = 3; J[35] = 2; K[35] = 0; 03485 I[36] = 2; J[36] = 0; K[36] = 2; 03486 I[37] = 3; J[37] = 0; K[37] = 2; 03487 I[38] = 2; J[38] = 0; K[38] = 3; 03488 I[39] = 3; J[39] = 0; K[39] = 3; 03489 I[40] = 1; J[40] = 2; K[40] = 2; 03490 I[41] = 1; J[41] = 3; K[41] = 2; 03491 I[42] = 1; J[42] = 2; K[42] = 3; 03492 I[43] = 1; J[43] = 3; K[43] = 3; 03493 I[44] = 3; J[44] = 1; K[44] = 2; 03494 I[45] = 2; J[45] = 1; K[45] = 2; 03495 I[46] = 3; J[46] = 1; K[46] = 3; 03496 I[47] = 2; J[47] = 1; K[47] = 3; 03497 I[48] = 0; J[48] = 3; K[48] = 2; 03498 I[49] = 0; J[49] = 2; K[49] = 2; 03499 I[50] = 0; J[50] = 3; K[50] = 3; 03500 I[51] = 0; J[51] = 2; K[51] = 3; 03501 I[52] = 2; J[52] = 2; K[52] = 1; 03502 I[53] = 3; J[53] = 2; K[53] = 1; 03503 I[54] = 2; J[54] = 3; K[54] = 1; 03504 I[55] = 3; J[55] = 3; K[55] = 1; 03505 // element 03506 I[56] = 2; J[56] = 2; K[56] = 2; 03507 I[57] = 3; J[57] = 2; K[57] = 2; 03508 I[58] = 3; J[58] = 3; K[58] = 2; 03509 I[59] = 2; J[59] = 3; K[59] = 2; 03510 I[60] = 2; J[60] = 2; K[60] = 3; 03511 I[61] = 3; J[61] = 2; K[61] = 3; 03512 I[62] = 3; J[62] = 3; K[62] = 3; 03513 I[63] = 2; J[63] = 3; K[63] = 3; 03514 } 03515 else 03516 { 03517 mfem_error ("LagrangeHexFiniteElement::LagrangeHexFiniteElement"); 03518 } 03519 03520 fe1d = new Lagrange1DFiniteElement(degree); 03521 dof1d = fe1d -> GetDof(); 03522 03523 #ifndef MFEM_USE_OPENMP 03524 shape1dx.SetSize(dof1d); 03525 shape1dy.SetSize(dof1d); 03526 shape1dz.SetSize(dof1d); 03527 03528 dshape1dx.SetSize(dof1d,1); 03529 dshape1dy.SetSize(dof1d,1); 03530 dshape1dz.SetSize(dof1d,1); 03531 #endif 03532 03533 for (int n = 0; n < Dof; n++) 03534 { 03535 Nodes.IntPoint(n).x = fe1d -> GetNodes().IntPoint(I[n]).x; 03536 Nodes.IntPoint(n).y = fe1d -> GetNodes().IntPoint(J[n]).x; 03537 Nodes.IntPoint(n).z = fe1d -> GetNodes().IntPoint(K[n]).x; 03538 } 03539 } 03540 03541 void LagrangeHexFiniteElement::CalcShape(const IntegrationPoint &ip, 03542 Vector &shape) const 03543 { 03544 IntegrationPoint ipy, ipz; 03545 ipy.x = ip.y; 03546 ipz.x = ip.z; 03547 03548 #ifdef MFEM_USE_OPENMP 03549 Vector shape1dx(dof1d), shape1dy(dof1d), shape1dz(dof1d); 03550 #endif 03551 03552 fe1d -> CalcShape(ip, shape1dx); 03553 fe1d -> CalcShape(ipy, shape1dy); 03554 fe1d -> CalcShape(ipz, shape1dz); 03555 03556 for (int n = 0; n < Dof; n++) 03557 shape(n) = shape1dx(I[n]) * shape1dy(J[n]) * shape1dz(K[n]); 03558 } 03559 03560 void LagrangeHexFiniteElement::CalcDShape(const IntegrationPoint &ip, 03561 DenseMatrix &dshape) const 03562 { 03563 IntegrationPoint ipy, ipz; 03564 ipy.x = ip.y; 03565 ipz.x = ip.z; 03566 03567 #ifdef MFEM_USE_OPENMP 03568 Vector shape1dx(dof1d), shape1dy(dof1d), shape1dz(dof1d); 03569 DenseMatrix dshape1dx(dof1d,1), dshape1dy(dof1d,1), dshape1dz(dof1d,1); 03570 #endif 03571 03572 fe1d -> CalcShape(ip, shape1dx); 03573 fe1d -> CalcShape(ipy, shape1dy); 03574 fe1d -> CalcShape(ipz, shape1dz); 03575 03576 fe1d -> CalcDShape(ip, dshape1dx); 03577 fe1d -> CalcDShape(ipy, dshape1dy); 03578 fe1d -> CalcDShape(ipz, dshape1dz); 03579 03580 for (int n = 0; n < Dof; n++) { 03581 dshape(n,0) = dshape1dx(I[n],0) * shape1dy(J[n]) * shape1dz(K[n]); 03582 dshape(n,1) = shape1dx(I[n]) * dshape1dy(J[n],0) * shape1dz(K[n]); 03583 dshape(n,2) = shape1dx(I[n]) * shape1dy(J[n]) * dshape1dz(K[n],0); 03584 } 03585 } 03586 03587 LagrangeHexFiniteElement::~LagrangeHexFiniteElement () 03588 { 03589 delete fe1d; 03590 03591 delete [] I; 03592 delete [] J; 03593 delete [] K; 03594 } 03595 03596 03597 RefinedLinear1DFiniteElement::RefinedLinear1DFiniteElement() 03598 : NodalFiniteElement(1, Geometry::SEGMENT, 3, 4) 03599 { 03600 Nodes.IntPoint(0).x = 0.0; 03601 Nodes.IntPoint(1).x = 1.0; 03602 Nodes.IntPoint(2).x = 0.5; 03603 } 03604 03605 void RefinedLinear1DFiniteElement::CalcShape(const IntegrationPoint &ip, 03606 Vector &shape) const 03607 { 03608 double x = ip.x; 03609 03610 if (x <= 0.5) { 03611 shape(0) = 1.0 - 2.0 * x; 03612 shape(1) = 0.0; 03613 shape(2) = 2.0 * x; 03614 } else { 03615 shape(0) = 0.0; 03616 shape(1) = 2.0 * x - 1.0; 03617 shape(2) = 2.0 - 2.0 * x; 03618 } 03619 } 03620 03621 void RefinedLinear1DFiniteElement::CalcDShape(const IntegrationPoint &ip, 03622 DenseMatrix &dshape) const 03623 { 03624 double x = ip.x; 03625 03626 if (x <= 0.5) { 03627 dshape(0,0) = - 2.0; 03628 dshape(1,0) = 0.0; 03629 dshape(2,0) = 2.0; 03630 } else { 03631 dshape(0,0) = 0.0; 03632 dshape(1,0) = 2.0; 03633 dshape(2,0) = - 2.0; 03634 } 03635 } 03636 03637 RefinedLinear2DFiniteElement::RefinedLinear2DFiniteElement() 03638 : NodalFiniteElement(2, Geometry::TRIANGLE, 6, 5) 03639 { 03640 Nodes.IntPoint(0).x = 0.0; 03641 Nodes.IntPoint(0).y = 0.0; 03642 Nodes.IntPoint(1).x = 1.0; 03643 Nodes.IntPoint(1).y = 0.0; 03644 Nodes.IntPoint(2).x = 0.0; 03645 Nodes.IntPoint(2).y = 1.0; 03646 Nodes.IntPoint(3).x = 0.5; 03647 Nodes.IntPoint(3).y = 0.0; 03648 Nodes.IntPoint(4).x = 0.5; 03649 Nodes.IntPoint(4).y = 0.5; 03650 Nodes.IntPoint(5).x = 0.0; 03651 Nodes.IntPoint(5).y = 0.5; 03652 } 03653 03654 void RefinedLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip, 03655 Vector &shape) const 03656 { 03657 int i; 03658 03659 double L0, L1, L2; 03660 L0 = 2.0 * ( 1. - ip.x - ip.y ); 03661 L1 = 2.0 * ( ip.x ); 03662 L2 = 2.0 * ( ip.y ); 03663 03664 // The reference triangle is split in 4 triangles as follows: 03665 // 03666 // T0 - 0,3,5 03667 // T1 - 1,3,4 03668 // T2 - 2,4,5 03669 // T3 - 3,4,5 03670 03671 for (i = 0; i < 6; i++) 03672 shape(i) = 0.0; 03673 03674 if (L0 >= 1.0) { // T0 03675 shape(0) = L0 - 1.0; 03676 shape(3) = L1; 03677 shape(5) = L2; 03678 } 03679 else if (L1 >= 1.0) { // T1 03680 shape(3) = L0; 03681 shape(1) = L1 - 1.0; 03682 shape(4) = L2; 03683 } 03684 else if (L2 >= 1.0) { // T2 03685 shape(5) = L0; 03686 shape(4) = L1; 03687 shape(2) = L2 - 1.0; 03688 } 03689 else { // T3 03690 shape(3) = 1.0 - L2; 03691 shape(4) = 1.0 - L0; 03692 shape(5) = 1.0 - L1; 03693 } 03694 } 03695 03696 void RefinedLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 03697 DenseMatrix &dshape) const 03698 { 03699 int i,j; 03700 03701 double L0, L1, L2; 03702 L0 = 2.0 * ( 1. - ip.x - ip.y ); 03703 L1 = 2.0 * ( ip.x ); 03704 L2 = 2.0 * ( ip.y ); 03705 03706 double DL0[2], DL1[2], DL2[2]; 03707 DL0[0] = -2.0; DL0[1] = -2.0; 03708 DL1[0] = 2.0; DL1[1] = 0.0; 03709 DL2[0] = 0.0; DL2[1] = 2.0; 03710 03711 for (i = 0; i < 6; i++) 03712 for (j = 0; j < 2; j++) 03713 dshape(i,j) = 0.0; 03714 03715 if (L0 >= 1.0) { // T0 03716 for (j = 0; j < 2; j++) { 03717 dshape(0,j) = DL0[j]; 03718 dshape(3,j) = DL1[j]; 03719 dshape(5,j) = DL2[j]; 03720 } 03721 } 03722 else if (L1 >= 1.0) { // T1 03723 for (j = 0; j < 2; j++) { 03724 dshape(3,j) = DL0[j]; 03725 dshape(1,j) = DL1[j]; 03726 dshape(4,j) = DL2[j]; 03727 } 03728 } 03729 else if (L2 >= 1.0) { // T2 03730 for (j = 0; j < 2; j++) { 03731 dshape(5,j) = DL0[j]; 03732 dshape(4,j) = DL1[j]; 03733 dshape(2,j) = DL2[j]; 03734 } 03735 } 03736 else { // T3 03737 for (j = 0; j < 2; j++) { 03738 dshape(3,j) = - DL2[j]; 03739 dshape(4,j) = - DL0[j]; 03740 dshape(5,j) = - DL1[j]; 03741 } 03742 } 03743 } 03744 03745 RefinedLinear3DFiniteElement::RefinedLinear3DFiniteElement() 03746 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 10, 4) 03747 { 03748 Nodes.IntPoint(0).x = 0.0; 03749 Nodes.IntPoint(0).y = 0.0; 03750 Nodes.IntPoint(0).z = 0.0; 03751 Nodes.IntPoint(1).x = 1.0; 03752 Nodes.IntPoint(1).y = 0.0; 03753 Nodes.IntPoint(1).z = 0.0; 03754 Nodes.IntPoint(2).x = 0.0; 03755 Nodes.IntPoint(2).y = 1.0; 03756 Nodes.IntPoint(2).z = 0.0; 03757 Nodes.IntPoint(3).x = 0.0; 03758 Nodes.IntPoint(3).y = 0.0; 03759 Nodes.IntPoint(3).z = 1.0; 03760 Nodes.IntPoint(4).x = 0.5; 03761 Nodes.IntPoint(4).y = 0.0; 03762 Nodes.IntPoint(4).z = 0.0; 03763 Nodes.IntPoint(5).x = 0.0; 03764 Nodes.IntPoint(5).y = 0.5; 03765 Nodes.IntPoint(5).z = 0.0; 03766 Nodes.IntPoint(6).x = 0.0; 03767 Nodes.IntPoint(6).y = 0.0; 03768 Nodes.IntPoint(6).z = 0.5; 03769 Nodes.IntPoint(7).x = 0.5; 03770 Nodes.IntPoint(7).y = 0.5; 03771 Nodes.IntPoint(7).z = 0.0; 03772 Nodes.IntPoint(8).x = 0.5; 03773 Nodes.IntPoint(8).y = 0.0; 03774 Nodes.IntPoint(8).z = 0.5; 03775 Nodes.IntPoint(9).x = 0.0; 03776 Nodes.IntPoint(9).y = 0.5; 03777 Nodes.IntPoint(9).z = 0.5; 03778 } 03779 03780 void RefinedLinear3DFiniteElement::CalcShape(const IntegrationPoint &ip, 03781 Vector &shape) const 03782 { 03783 int i; 03784 03785 double L0, L1, L2, L3, L4, L5; 03786 L0 = 2.0 * ( 1. - ip.x - ip.y - ip.z ); 03787 L1 = 2.0 * ( ip.x ); 03788 L2 = 2.0 * ( ip.y ); 03789 L3 = 2.0 * ( ip.z ); 03790 L4 = 2.0 * ( ip.x + ip.y ); 03791 L5 = 2.0 * ( ip.y + ip.z ); 03792 03793 // The reference tetrahedron is split in 8 tetrahedra as follows: 03794 // 03795 // T0 - 0,4,5,6 03796 // T1 - 1,4,7,8 03797 // T2 - 2,5,7,9 03798 // T3 - 3,6,8,9 03799 // T4 - 4,5,6,8 03800 // T5 - 4,5,7,8 03801 // T6 - 5,6,8,9 03802 // T7 - 5,7,8,9 03803 03804 for (i = 0; i < 10; i++) 03805 shape(i) = 0.0; 03806 03807 if (L0 >= 1.0) { // T0 03808 shape(0) = L0 - 1.0; 03809 shape(4) = L1; 03810 shape(5) = L2; 03811 shape(6) = L3; 03812 } 03813 else if (L1 >= 1.0) { // T1 03814 shape(4) = L0; 03815 shape(1) = L1 - 1.0; 03816 shape(7) = L2; 03817 shape(8) = L3; 03818 } 03819 else if (L2 >= 1.0) { // T2 03820 shape(5) = L0; 03821 shape(7) = L1; 03822 shape(2) = L2 - 1.0; 03823 shape(9) = L3; 03824 } 03825 else if (L3 >= 1.0) { // T3 03826 shape(6) = L0; 03827 shape(8) = L1; 03828 shape(9) = L2; 03829 shape(3) = L3 - 1.0; 03830 } 03831 else if ((L4 <= 1.0) && (L5 <= 1.0)) { // T4 03832 shape(4) = 1.0 - L5; 03833 shape(5) = L2; 03834 shape(6) = 1.0 - L4; 03835 shape(8) = 1.0 - L0; 03836 } 03837 else if ((L4 >= 1.0) && (L5 <= 1.0)) { // T5 03838 shape(4) = 1.0 - L5; 03839 shape(5) = 1.0 - L1; 03840 shape(7) = L4 - 1.0; 03841 shape(8) = L3; 03842 } 03843 else if ((L4 <= 1.0) && (L5 >= 1.0)) { // T6 03844 shape(5) = 1.0 - L3; 03845 shape(6) = 1.0 - L4; 03846 shape(8) = L1; 03847 shape(9) = L5 - 1.0; 03848 } 03849 else if ((L4 >= 1.0) && (L5 >= 1.0)) { // T7 03850 shape(5) = L0; 03851 shape(7) = L4 - 1.0; 03852 shape(8) = 1.0 - L2; 03853 shape(9) = L5 - 1.0; 03854 } 03855 } 03856 03857 void RefinedLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip, 03858 DenseMatrix &dshape) const 03859 { 03860 int i,j; 03861 03862 double L0, L1, L2, L3, L4, L5; 03863 L0 = 2.0 * ( 1. - ip.x - ip.y - ip.z ); 03864 L1 = 2.0 * ( ip.x ); 03865 L2 = 2.0 * ( ip.y ); 03866 L3 = 2.0 * ( ip.z ); 03867 L4 = 2.0 * ( ip.x + ip.y ); 03868 L5 = 2.0 * ( ip.y + ip.z ); 03869 03870 double DL0[3], DL1[3], DL2[3], DL3[3], DL4[3], DL5[3]; 03871 DL0[0] = -2.0; DL0[1] = -2.0; DL0[2] = -2.0; 03872 DL1[0] = 2.0; DL1[1] = 0.0; DL1[2] = 0.0; 03873 DL2[0] = 0.0; DL2[1] = 2.0; DL2[2] = 0.0; 03874 DL3[0] = 0.0; DL3[1] = 0.0; DL3[2] = 2.0; 03875 DL4[0] = 2.0; DL4[1] = 2.0; DL4[2] = 0.0; 03876 DL5[0] = 0.0; DL5[1] = 2.0; DL5[2] = 2.0; 03877 03878 for (i = 0; i < 10; i++) 03879 for (j = 0; j < 3; j++) 03880 dshape(i,j) = 0.0; 03881 03882 if (L0 >= 1.0) { // T0 03883 for (j = 0; j < 3; j++) { 03884 dshape(0,j) = DL0[j]; 03885 dshape(4,j) = DL1[j]; 03886 dshape(5,j) = DL2[j]; 03887 dshape(6,j) = DL3[j]; 03888 } 03889 } 03890 else if (L1 >= 1.0) { // T1 03891 for (j = 0; j < 3; j++) { 03892 dshape(4,j) = DL0[j]; 03893 dshape(1,j) = DL1[j]; 03894 dshape(7,j) = DL2[j]; 03895 dshape(8,j) = DL3[j]; 03896 } 03897 } 03898 else if (L2 >= 1.0) { // T2 03899 for (j = 0; j < 3; j++) { 03900 dshape(5,j) = DL0[j]; 03901 dshape(7,j) = DL1[j]; 03902 dshape(2,j) = DL2[j]; 03903 dshape(9,j) = DL3[j]; 03904 } 03905 } 03906 else if (L3 >= 1.0) { // T3 03907 for (j = 0; j < 3; j++) { 03908 dshape(6,j) = DL0[j]; 03909 dshape(8,j) = DL1[j]; 03910 dshape(9,j) = DL2[j]; 03911 dshape(3,j) = DL3[j]; 03912 } 03913 } 03914 else if ((L4 <= 1.0) && (L5 <= 1.0)) { // T4 03915 for (j = 0; j < 3; j++) { 03916 dshape(4,j) = - DL5[j]; 03917 dshape(5,j) = DL2[j]; 03918 dshape(6,j) = - DL4[j]; 03919 dshape(8,j) = - DL0[j]; 03920 } 03921 } 03922 else if ((L4 >= 1.0) && (L5 <= 1.0)) { // T5 03923 for (j = 0; j < 3; j++) { 03924 dshape(4,j) = - DL5[j]; 03925 dshape(5,j) = - DL1[j]; 03926 dshape(7,j) = DL4[j]; 03927 dshape(8,j) = DL3[j]; 03928 } 03929 } 03930 else if ((L4 <= 1.0) && (L5 >= 1.0)) { // T6 03931 for (j = 0; j < 3; j++) { 03932 dshape(5,j) = - DL3[j]; 03933 dshape(6,j) = - DL4[j]; 03934 dshape(8,j) = DL1[j]; 03935 dshape(9,j) = DL5[j]; 03936 } 03937 } 03938 else if ((L4 >= 1.0) && (L5 >= 1.0)) { // T7 03939 for (j = 0; j < 3; j++) { 03940 dshape(5,j) = DL0[j]; 03941 dshape(7,j) = DL4[j]; 03942 dshape(8,j) = - DL2[j]; 03943 dshape(9,j) = DL5[j]; 03944 } 03945 } 03946 } 03947 03948 03949 RefinedBiLinear2DFiniteElement::RefinedBiLinear2DFiniteElement() 03950 : NodalFiniteElement(2, Geometry::SQUARE , 9, 1, FunctionSpace::rQk) 03951 { 03952 Nodes.IntPoint(0).x = 0.0; 03953 Nodes.IntPoint(0).y = 0.0; 03954 Nodes.IntPoint(1).x = 1.0; 03955 Nodes.IntPoint(1).y = 0.0; 03956 Nodes.IntPoint(2).x = 1.0; 03957 Nodes.IntPoint(2).y = 1.0; 03958 Nodes.IntPoint(3).x = 0.0; 03959 Nodes.IntPoint(3).y = 1.0; 03960 Nodes.IntPoint(4).x = 0.5; 03961 Nodes.IntPoint(4).y = 0.0; 03962 Nodes.IntPoint(5).x = 1.0; 03963 Nodes.IntPoint(5).y = 0.5; 03964 Nodes.IntPoint(6).x = 0.5; 03965 Nodes.IntPoint(6).y = 1.0; 03966 Nodes.IntPoint(7).x = 0.0; 03967 Nodes.IntPoint(7).y = 0.5; 03968 Nodes.IntPoint(8).x = 0.5; 03969 Nodes.IntPoint(8).y = 0.5; 03970 } 03971 03972 void RefinedBiLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip, 03973 Vector &shape) const 03974 { 03975 int i; 03976 double x = ip.x, y = ip.y; 03977 double Lx, Ly; 03978 Lx = 2.0 * ( 1. - x ); 03979 Ly = 2.0 * ( 1. - y ); 03980 03981 // The reference square is split in 4 squares as follows: 03982 // 03983 // T0 - 0,4,7,8 03984 // T1 - 1,4,5,8 03985 // T2 - 2,5,6,8 03986 // T3 - 3,6,7,8 03987 03988 for (i = 0; i < 9; i++) 03989 shape(i) = 0.0; 03990 03991 if ((x <= 0.5) && (y <= 0.5)) { // T0 03992 shape(0) = (Lx - 1.0) * (Ly - 1.0); 03993 shape(4) = (2.0 - Lx) * (Ly - 1.0); 03994 shape(8) = (2.0 - Lx) * (2.0 - Ly); 03995 shape(7) = (Lx - 1.0) * (2.0 - Ly); 03996 } 03997 else if ((x >= 0.5) && (y <= 0.5)) { // T1 03998 shape(4) = Lx * (Ly - 1.0); 03999 shape(1) = (1.0 - Lx) * (Ly - 1.0); 04000 shape(5) = (1.0 - Lx) * (2.0 - Ly); 04001 shape(8) = Lx * (2.0 - Ly); 04002 } 04003 else if ((x >= 0.5) && (y >= 0.5)) { // T2 04004 shape(8) = Lx * Ly ; 04005 shape(5) = (1.0 - Lx) * Ly ; 04006 shape(2) = (1.0 - Lx) * (1.0 - Ly); 04007 shape(6) = Lx * (1.0 - Ly); 04008 } 04009 else if ((x <= 0.5) && (y >= 0.5)) { // T3 04010 shape(7) = (Lx - 1.0) * Ly ; 04011 shape(8) = (2.0 - Lx) * Ly ; 04012 shape(6) = (2.0 - Lx) * (1.0 - Ly); 04013 shape(3) = (Lx - 1.0) * (1.0 - Ly); 04014 } 04015 } 04016 04017 void RefinedBiLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 04018 DenseMatrix &dshape) const 04019 { 04020 int i,j; 04021 double x = ip.x, y = ip.y; 04022 double Lx, Ly; 04023 Lx = 2.0 * ( 1. - x ); 04024 Ly = 2.0 * ( 1. - y ); 04025 04026 for (i = 0; i < 9; i++) 04027 for (j = 0; j < 2; j++) 04028 dshape(i,j) = 0.0; 04029 04030 if ((x <= 0.5) && (y <= 0.5)) { // T0 04031 dshape(0,0) = 2.0 * (1.0 - Ly); 04032 dshape(0,1) = 2.0 * (1.0 - Lx); 04033 04034 dshape(4,0) = 2.0 * (Ly - 1.0); 04035 dshape(4,1) = -2.0 * (2.0 - Lx); 04036 04037 dshape(8,0) = 2.0 * (2.0 - Ly); 04038 dshape(8,1) = 2.0 * (2.0 - Lx); 04039 04040 dshape(7,0) = -2.0 * (2.0 - Ly); 04041 dshape(7,0) = 2.0 * (Lx - 1.0); 04042 } 04043 else if ((x >= 0.5) && (y <= 0.5)) { // T1 04044 dshape(4,0) = -2.0 * (Ly - 1.0); 04045 dshape(4,1) = -2.0 * Lx; 04046 04047 dshape(1,0) = 2.0 * (Ly - 1.0); 04048 dshape(1,1) = -2.0 * (1.0 - Lx); 04049 04050 dshape(5,0) = 2.0 * (2.0 - Ly); 04051 dshape(5,1) = 2.0 * (1.0 - Lx); 04052 04053 dshape(8,0) = -2.0 * (2.0 - Ly); 04054 dshape(8,1) = 2.0 * Lx; 04055 } 04056 else if ((x >= 0.5) && (y >= 0.5)) { // T2 04057 dshape(8,0) = -2.0 * Ly; 04058 dshape(8,1) = -2.0 * Lx; 04059 04060 dshape(5,0) = 2.0 * Ly; 04061 dshape(5,1) = -2.0 * (1.0 - Lx); 04062 04063 dshape(2,0) = 2.0 * (1.0 - Ly); 04064 dshape(2,1) = 2.0 * (1.0 - Lx); 04065 04066 dshape(6,0) = -2.0 * (1.0 - Ly); 04067 dshape(6,1) = 2.0 * Lx; 04068 } 04069 else if ((x <= 0.5) && (y >= 0.5)) { // T3 04070 dshape(7,0) = -2.0 * Ly; 04071 dshape(7,1) = -2.0 * (Lx - 1.0); 04072 04073 dshape(8,0) = 2.0 * Ly ; 04074 dshape(8,1) = -2.0 * (2.0 - Lx); 04075 04076 dshape(6,0) = 2.0 * (1.0 - Ly); 04077 dshape(6,1) = 2.0 * (2.0 - Lx); 04078 04079 dshape(3,0) = -2.0 * (1.0 - Ly); 04080 dshape(3,1) = 2.0 * (Lx - 1.0); 04081 } 04082 } 04083 04084 RefinedTriLinear3DFiniteElement::RefinedTriLinear3DFiniteElement() 04085 : NodalFiniteElement(3, Geometry::CUBE, 27, 2, FunctionSpace::rQk) 04086 { 04087 double I[27]; 04088 double J[27]; 04089 double K[27]; 04090 // nodes 04091 I[ 0] = 0.0; J[ 0] = 0.0; K[ 0] = 0.0; 04092 I[ 1] = 1.0; J[ 1] = 0.0; K[ 1] = 0.0; 04093 I[ 2] = 1.0; J[ 2] = 1.0; K[ 2] = 0.0; 04094 I[ 3] = 0.0; J[ 3] = 1.0; K[ 3] = 0.0; 04095 I[ 4] = 0.0; J[ 4] = 0.0; K[ 4] = 1.0; 04096 I[ 5] = 1.0; J[ 5] = 0.0; K[ 5] = 1.0; 04097 I[ 6] = 1.0; J[ 6] = 1.0; K[ 6] = 1.0; 04098 I[ 7] = 0.0; J[ 7] = 1.0; K[ 7] = 1.0; 04099 // edges 04100 I[ 8] = 0.5; J[ 8] = 0.0; K[ 8] = 0.0; 04101 I[ 9] = 1.0; J[ 9] = 0.5; K[ 9] = 0.0; 04102 I[10] = 0.5; J[10] = 1.0; K[10] = 0.0; 04103 I[11] = 0.0; J[11] = 0.5; K[11] = 0.0; 04104 I[12] = 0.5; J[12] = 0.0; K[12] = 1.0; 04105 I[13] = 1.0; J[13] = 0.5; K[13] = 1.0; 04106 I[14] = 0.5; J[14] = 1.0; K[14] = 1.0; 04107 I[15] = 0.0; J[15] = 0.5; K[15] = 1.0; 04108 I[16] = 0.0; J[16] = 0.0; K[16] = 0.5; 04109 I[17] = 1.0; J[17] = 0.0; K[17] = 0.5; 04110 I[18] = 1.0; J[18] = 1.0; K[18] = 0.5; 04111 I[19] = 0.0; J[19] = 1.0; K[19] = 0.5; 04112 // faces 04113 I[20] = 0.5; J[20] = 0.5; K[20] = 0.0; 04114 I[21] = 0.5; J[21] = 0.0; K[21] = 0.5; 04115 I[22] = 1.0; J[22] = 0.5; K[22] = 0.5; 04116 I[23] = 0.5; J[23] = 1.0; K[23] = 0.5; 04117 I[24] = 0.0; J[24] = 0.5; K[24] = 0.5; 04118 I[25] = 0.5; J[25] = 0.5; K[25] = 1.0; 04119 // element 04120 I[26] = 0.5; J[26] = 0.5; K[26] = 0.5; 04121 04122 for (int n = 0; n < 27; n++) { 04123 Nodes.IntPoint(n).x = I[n]; 04124 Nodes.IntPoint(n).y = J[n]; 04125 Nodes.IntPoint(n).z = K[n]; 04126 } 04127 } 04128 04129 void RefinedTriLinear3DFiniteElement::CalcShape(const IntegrationPoint &ip, 04130 Vector &shape) const 04131 { 04132 int i, N[8]; 04133 double Lx, Ly, Lz; 04134 double x = ip.x, y = ip.y, z = ip.z; 04135 04136 for (i = 0; i < 27; i++) 04137 shape(i) = 0.0; 04138 04139 if ((x <= 0.5) && (y <= 0.5) && (z <= 0.5)) { // T0 04140 Lx = 1.0 - 2.0 * x; 04141 Ly = 1.0 - 2.0 * y; 04142 Lz = 1.0 - 2.0 * z; 04143 04144 N[0] = 0; 04145 N[1] = 8; 04146 N[2] = 20; 04147 N[3] = 11; 04148 N[4] = 16; 04149 N[5] = 21; 04150 N[6] = 26; 04151 N[7] = 24; 04152 } 04153 else if ((x >= 0.5) && (y <= 0.5) && (z <= 0.5)) { // T1 04154 Lx = 2.0 - 2.0 * x; 04155 Ly = 1.0 - 2.0 * y; 04156 Lz = 1.0 - 2.0 * z; 04157 04158 N[0] = 8; 04159 N[1] = 1; 04160 N[2] = 9; 04161 N[3] = 20; 04162 N[4] = 21; 04163 N[5] = 17; 04164 N[6] = 22; 04165 N[7] = 26; 04166 } 04167 else if ((x <= 0.5) && (y >= 0.5) && (z <= 0.5)) { // T2 04168 Lx = 2.0 - 2.0 * x; 04169 Ly = 2.0 - 2.0 * y; 04170 Lz = 1.0 - 2.0 * z; 04171 04172 N[0] = 20; 04173 N[1] = 9; 04174 N[2] = 2; 04175 N[3] = 10; 04176 N[4] = 26; 04177 N[5] = 22; 04178 N[6] = 18; 04179 N[7] = 23; 04180 } 04181 else if ((x >= 0.5) && (y >= 0.5) && (z <= 0.5)) { // T3 04182 Lx = 1.0 - 2.0 * x; 04183 Ly = 2.0 - 2.0 * y; 04184 Lz = 1.0 - 2.0 * z; 04185 04186 N[0] = 11; 04187 N[1] = 20; 04188 N[2] = 10; 04189 N[3] = 3; 04190 N[4] = 24; 04191 N[5] = 26; 04192 N[6] = 23; 04193 N[7] = 19; 04194 } 04195 else if ((x <= 0.5) && (y <= 0.5) && (z >= 0.5)) { // T4 04196 Lx = 1.0 - 2.0 * x; 04197 Ly = 1.0 - 2.0 * y; 04198 Lz = 2.0 - 2.0 * z; 04199 04200 N[0] = 16; 04201 N[1] = 21; 04202 N[2] = 26; 04203 N[3] = 24; 04204 N[4] = 4; 04205 N[5] = 12; 04206 N[6] = 25; 04207 N[7] = 15; 04208 } 04209 else if ((x >= 0.5) && (y <= 0.5) && (z >= 0.5)) { // T5 04210 Lx = 2.0 - 2.0 * x; 04211 Ly = 1.0 - 2.0 * y; 04212 Lz = 2.0 - 2.0 * z; 04213 04214 N[0] = 21; 04215 N[1] = 17; 04216 N[2] = 22; 04217 N[3] = 26; 04218 N[4] = 12; 04219 N[5] = 5; 04220 N[6] = 13; 04221 N[7] = 25; 04222 } 04223 else if ((x <= 0.5) && (y >= 0.5) && (z >= 0.5)) { // T6 04224 Lx = 2.0 - 2.0 * x; 04225 Ly = 2.0 - 2.0 * y; 04226 Lz = 2.0 - 2.0 * z; 04227 04228 N[0] = 26; 04229 N[1] = 22; 04230 N[2] = 18; 04231 N[3] = 23; 04232 N[4] = 25; 04233 N[5] = 13; 04234 N[6] = 6; 04235 N[7] = 14; 04236 } 04237 else if ((x >= 0.5) && (y >= 0.5) && (z >= 0.5)) { // T7 04238 Lx = 1.0 - 2.0 * x; 04239 Ly = 2.0 - 2.0 * y; 04240 Lz = 2.0 - 2.0 * z; 04241 04242 N[0] = 24; 04243 N[1] = 26; 04244 N[2] = 23; 04245 N[3] = 19; 04246 N[4] = 15; 04247 N[5] = 25; 04248 N[6] = 14; 04249 N[7] = 7; 04250 } 04251 04252 shape(N[0]) = Lx * Ly * Lz; 04253 shape(N[1]) = (1 - Lx) * Ly * Lz; 04254 shape(N[2]) = (1 - Lx) * (1 - Ly) * Lz; 04255 shape(N[3]) = Lx * (1 - Ly) * Lz; 04256 shape(N[4]) = Lx * Ly * (1 - Lz); 04257 shape(N[5]) = (1 - Lx) * Ly * (1 - Lz); 04258 shape(N[6]) = (1 - Lx) * (1 - Ly) * (1 - Lz); 04259 shape(N[7]) = Lx * (1 - Ly) * (1 - Lz); 04260 } 04261 04262 void RefinedTriLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip, 04263 DenseMatrix &dshape) const 04264 { 04265 int i, j, N[8]; 04266 double Lx, Ly, Lz; 04267 double x = ip.x, y = ip.y, z = ip.z; 04268 04269 for (i = 0; i < 27; i++) 04270 for (j = 0; j < 3; j++) 04271 dshape(i,j) = 0.0; 04272 04273 if ((x <= 0.5) && (y <= 0.5) && (z <= 0.5)) { // T0 04274 Lx = 1.0 - 2.0 * x; 04275 Ly = 1.0 - 2.0 * y; 04276 Lz = 1.0 - 2.0 * z; 04277 04278 N[0] = 0; 04279 N[1] = 8; 04280 N[2] = 20; 04281 N[3] = 11; 04282 N[4] = 16; 04283 N[5] = 21; 04284 N[6] = 26; 04285 N[7] = 24; 04286 } 04287 else if ((x >= 0.5) && (y <= 0.5) && (z <= 0.5)) { // T1 04288 Lx = 2.0 - 2.0 * x; 04289 Ly = 1.0 - 2.0 * y; 04290 Lz = 1.0 - 2.0 * z; 04291 04292 N[0] = 8; 04293 N[1] = 1; 04294 N[2] = 9; 04295 N[3] = 20; 04296 N[4] = 21; 04297 N[5] = 17; 04298 N[6] = 22; 04299 N[7] = 26; 04300 } 04301 else if ((x <= 0.5) && (y >= 0.5) && (z <= 0.5)) { // T2 04302 Lx = 2.0 - 2.0 * x; 04303 Ly = 2.0 - 2.0 * y; 04304 Lz = 1.0 - 2.0 * z; 04305 04306 N[0] = 20; 04307 N[1] = 9; 04308 N[2] = 2; 04309 N[3] = 10; 04310 N[4] = 26; 04311 N[5] = 22; 04312 N[6] = 18; 04313 N[7] = 23; 04314 } 04315 else if ((x >= 0.5) && (y >= 0.5) && (z <= 0.5)) { // T3 04316 Lx = 1.0 - 2.0 * x; 04317 Ly = 2.0 - 2.0 * y; 04318 Lz = 1.0 - 2.0 * z; 04319 04320 N[0] = 11; 04321 N[1] = 20; 04322 N[2] = 10; 04323 N[3] = 3; 04324 N[4] = 24; 04325 N[5] = 26; 04326 N[6] = 23; 04327 N[7] = 19; 04328 } 04329 else if ((x <= 0.5) && (y <= 0.5) && (z >= 0.5)) { // T4 04330 Lx = 1.0 - 2.0 * x; 04331 Ly = 1.0 - 2.0 * y; 04332 Lz = 2.0 - 2.0 * z; 04333 04334 N[0] = 16; 04335 N[1] = 21; 04336 N[2] = 26; 04337 N[3] = 24; 04338 N[4] = 4; 04339 N[5] = 12; 04340 N[6] = 25; 04341 N[7] = 15; 04342 } 04343 else if ((x >= 0.5) && (y <= 0.5) && (z >= 0.5)) { // T5 04344 Lx = 2.0 - 2.0 * x; 04345 Ly = 1.0 - 2.0 * y; 04346 Lz = 2.0 - 2.0 * z; 04347 04348 N[0] = 21; 04349 N[1] = 17; 04350 N[2] = 22; 04351 N[3] = 26; 04352 N[4] = 12; 04353 N[5] = 5; 04354 N[6] = 13; 04355 N[7] = 25; 04356 } 04357 else if ((x <= 0.5) && (y >= 0.5) && (z >= 0.5)) { // T6 04358 Lx = 2.0 - 2.0 * x; 04359 Ly = 2.0 - 2.0 * y; 04360 Lz = 2.0 - 2.0 * z; 04361 04362 N[0] = 26; 04363 N[1] = 22; 04364 N[2] = 18; 04365 N[3] = 23; 04366 N[4] = 25; 04367 N[5] = 13; 04368 N[6] = 6; 04369 N[7] = 14; 04370 } 04371 else if ((x >= 0.5) && (y >= 0.5) && (z >= 0.5)) { // T7 04372 Lx = 1.0 - 2.0 * x; 04373 Ly = 2.0 - 2.0 * y; 04374 Lz = 2.0 - 2.0 * z; 04375 04376 N[0] = 24; 04377 N[1] = 26; 04378 N[2] = 23; 04379 N[3] = 19; 04380 N[4] = 15; 04381 N[5] = 25; 04382 N[6] = 14; 04383 N[7] = 7; 04384 } 04385 04386 dshape(N[0],0) = -2.0 * Ly * Lz ; 04387 dshape(N[0],1) = -2.0 * Lx * Lz ; 04388 dshape(N[0],2) = -2.0 * Lx * Ly ; 04389 04390 dshape(N[1],0) = 2.0 * Ly * Lz ; 04391 dshape(N[1],1) = -2.0 * (1 - Lx) * Lz ; 04392 dshape(N[1],2) = -2.0 * (1 - Lx) * Ly ; 04393 04394 dshape(N[2],0) = 2.0 * (1 - Ly) * Lz ; 04395 dshape(N[2],1) = 2.0 * (1 - Lx) * Lz ; 04396 dshape(N[2],2) = -2.0 * (1 - Lx) * (1 - Ly); 04397 04398 dshape(N[3],0) = -2.0 * (1 - Ly) * Lz ; 04399 dshape(N[3],1) = 2.0 * Lx * Lz ; 04400 dshape(N[3],2) = -2.0 * Lx * (1 - Ly); 04401 04402 dshape(N[4],0) = -2.0 * Ly * (1 - Lz); 04403 dshape(N[4],1) = -2.0 * Lx * (1 - Lz); 04404 dshape(N[4],2) = 2.0 * Lx * Ly ; 04405 04406 dshape(N[5],0) = 2.0 * Ly * (1 - Lz); 04407 dshape(N[5],1) = -2.0 * (1 - Lx) * (1 - Lz); 04408 dshape(N[5],2) = 2.0 * (1 - Lx) * Ly ; 04409 04410 dshape(N[6],0) = 2.0 * (1 - Ly) * (1 - Lz); 04411 dshape(N[6],1) = 2.0 * (1 - Lx) * (1 - Lz); 04412 dshape(N[6],2) = 2.0 * (1 - Lx) * (1 - Ly); 04413 04414 dshape(N[7],0) = -2.0 * (1 - Ly) * (1 - Lz); 04415 dshape(N[7],1) = 2.0 * Lx * (1 - Lz); 04416 dshape(N[7],2) = 2.0 * Lx * (1 - Ly); 04417 } 04418 04419 04420 Nedelec1HexFiniteElement::Nedelec1HexFiniteElement() 04421 : VectorFiniteElement (3, Geometry::CUBE, 12, 1, FunctionSpace::Qk) 04422 { 04423 // not real nodes ... 04424 Nodes.IntPoint(0).x = 0.5; 04425 Nodes.IntPoint(0).y = 0.0; 04426 Nodes.IntPoint(0).z = 0.0; 04427 04428 Nodes.IntPoint(1).x = 1.0; 04429 Nodes.IntPoint(1).y = 0.5; 04430 Nodes.IntPoint(1).z = 0.0; 04431 04432 Nodes.IntPoint(2).x = 0.5; 04433 Nodes.IntPoint(2).y = 1.0; 04434 Nodes.IntPoint(2).z = 0.0; 04435 04436 Nodes.IntPoint(3).x = 0.0; 04437 Nodes.IntPoint(3).y = 0.5; 04438 Nodes.IntPoint(3).z = 0.0; 04439 04440 Nodes.IntPoint(4).x = 0.5; 04441 Nodes.IntPoint(4).y = 0.0; 04442 Nodes.IntPoint(4).z = 1.0; 04443 04444 Nodes.IntPoint(5).x = 1.0; 04445 Nodes.IntPoint(5).y = 0.5; 04446 Nodes.IntPoint(5).z = 1.0; 04447 04448 Nodes.IntPoint(6).x = 0.5; 04449 Nodes.IntPoint(6).y = 1.0; 04450 Nodes.IntPoint(6).z = 1.0; 04451 04452 Nodes.IntPoint(7).x = 0.0; 04453 Nodes.IntPoint(7).y = 0.5; 04454 Nodes.IntPoint(7).z = 1.0; 04455 04456 Nodes.IntPoint(8).x = 0.0; 04457 Nodes.IntPoint(8).y = 0.0; 04458 Nodes.IntPoint(8).z = 0.5; 04459 04460 Nodes.IntPoint(9).x = 1.0; 04461 Nodes.IntPoint(9).y = 0.0; 04462 Nodes.IntPoint(9).z = 0.5; 04463 04464 Nodes.IntPoint(10).x= 1.0; 04465 Nodes.IntPoint(10).y= 1.0; 04466 Nodes.IntPoint(10).z= 0.5; 04467 04468 Nodes.IntPoint(11).x= 0.0; 04469 Nodes.IntPoint(11).y= 1.0; 04470 Nodes.IntPoint(11).z= 0.5; 04471 } 04472 04473 void Nedelec1HexFiniteElement::CalcVShape(const IntegrationPoint &ip, 04474 DenseMatrix &shape) const 04475 { 04476 double x = ip.x, y = ip.y, z = ip.z; 04477 04478 shape(0,0) = (1. - y) * (1. - z); 04479 shape(0,1) = 0.; 04480 shape(0,2) = 0.; 04481 04482 shape(2,0) = y * (1. - z); 04483 shape(2,1) = 0.; 04484 shape(2,2) = 0.; 04485 04486 shape(4,0) = z * (1. - y); 04487 shape(4,1) = 0.; 04488 shape(4,2) = 0.; 04489 04490 shape(6,0) = y * z; 04491 shape(6,1) = 0.; 04492 shape(6,2) = 0.; 04493 04494 shape(1,0) = 0.; 04495 shape(1,1) = x * (1. - z); 04496 shape(1,2) = 0.; 04497 04498 shape(3,0) = 0.; 04499 shape(3,1) = (1. - x) * (1. - z); 04500 shape(3,2) = 0.; 04501 04502 shape(5,0) = 0.; 04503 shape(5,1) = x * z; 04504 shape(5,2) = 0.; 04505 04506 shape(7,0) = 0.; 04507 shape(7,1) = (1. - x) * z; 04508 shape(7,2) = 0.; 04509 04510 shape(8,0) = 0.; 04511 shape(8,1) = 0.; 04512 shape(8,2) = (1. - x) * (1. - y); 04513 04514 shape(9,0) = 0.; 04515 shape(9,1) = 0.; 04516 shape(9,2) = x * (1. - y); 04517 04518 shape(10,0) = 0.; 04519 shape(10,1) = 0.; 04520 shape(10,2) = x * y; 04521 04522 shape(11,0) = 0.; 04523 shape(11,1) = 0.; 04524 shape(11,2) = y * (1. - x); 04525 04526 } 04527 04528 void Nedelec1HexFiniteElement::CalcCurlShape(const IntegrationPoint &ip, 04529 DenseMatrix &curl_shape) 04530 const 04531 { 04532 double x = ip.x, y = ip.y, z = ip.z; 04533 04534 curl_shape(0,0) = 0.; 04535 curl_shape(0,1) = y - 1.; 04536 curl_shape(0,2) = 1. - z; 04537 04538 curl_shape(2,0) = 0.; 04539 curl_shape(2,1) = -y; 04540 curl_shape(2,2) = z - 1.; 04541 04542 curl_shape(4,0) = 0; 04543 curl_shape(4,1) = 1. - y; 04544 curl_shape(4,2) = z; 04545 04546 curl_shape(6,0) = 0.; 04547 curl_shape(6,1) = y; 04548 curl_shape(6,2) = -z; 04549 04550 curl_shape(1,0) = x; 04551 curl_shape(1,1) = 0.; 04552 curl_shape(1,2) = 1. - z; 04553 04554 curl_shape(3,0) = 1. - x; 04555 curl_shape(3,1) = 0.; 04556 curl_shape(3,2) = z - 1.; 04557 04558 curl_shape(5,0) = -x; 04559 curl_shape(5,1) = 0.; 04560 curl_shape(5,2) = z; 04561 04562 curl_shape(7,0) = x - 1.; 04563 curl_shape(7,1) = 0.; 04564 curl_shape(7,2) = -z; 04565 04566 curl_shape(8,0) = x - 1.; 04567 curl_shape(8,1) = 1. - y; 04568 curl_shape(8,2) = 0.; 04569 04570 curl_shape(9,0) = -x; 04571 curl_shape(9,1) = y - 1.; 04572 curl_shape(9,2) = 0; 04573 04574 curl_shape(10,0) = x; 04575 curl_shape(10,1) = -y; 04576 curl_shape(10,2) = 0.; 04577 04578 curl_shape(11,0) = 1. - x; 04579 curl_shape(11,1) = y; 04580 curl_shape(11,2) = 0.; 04581 } 04582 04583 const double Nedelec1HexFiniteElement::tk[12][3] = 04584 {{1,0,0}, {0,1,0}, {1,0,0}, {0,1,0}, 04585 {1,0,0}, {0,1,0}, {1,0,0}, {0,1,0}, 04586 {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}}; 04587 04588 void Nedelec1HexFiniteElement::GetLocalInterpolation ( 04589 ElementTransformation &Trans, DenseMatrix &I) const 04590 { 04591 int k, j; 04592 #ifdef MFEM_USE_OPENMP 04593 DenseMatrix vshape(Dof, Dim); 04594 #endif 04595 04596 #ifdef MFEM_DEBUG 04597 for (k = 0; k < 12; k++) 04598 { 04599 CalcVShape (Nodes.IntPoint(k), vshape); 04600 for (j = 0; j < 12; j++) 04601 { 04602 double d = ( vshape(j,0)*tk[k][0] + vshape(j,1)*tk[k][1] + 04603 vshape(j,2)*tk[k][2] ); 04604 if (j == k) d -= 1.0; 04605 if (fabs(d) > 1.0e-12) 04606 { 04607 cerr << "Nedelec1HexFiniteElement::GetLocalInterpolation (...)\n" 04608 " k = " << k << ", j = " << j << ", d = " << d << endl; 04609 mfem_error(); 04610 } 04611 } 04612 } 04613 #endif 04614 04615 IntegrationPoint ip; 04616 ip.x = ip.y = ip.z = 0.0; 04617 Trans.SetIntPoint (&ip); 04618 // Trans must be linear (more to have embedding?) 04619 const DenseMatrix &J = Trans.Jacobian(); 04620 double vk[3]; 04621 Vector xk (vk, 3); 04622 04623 for (k = 0; k < 12; k++) 04624 { 04625 Trans.Transform (Nodes.IntPoint (k), xk); 04626 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2]; 04627 CalcVShape (ip, vshape); 04628 // vk = J tk 04629 vk[0] = J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2]; 04630 vk[1] = J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2]; 04631 vk[2] = J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2]; 04632 for (j = 0; j < 12; j++) 04633 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+ 04634 vshape(j,2)*vk[2])) < 1.0e-12) 04635 I(k,j) = 0.0; 04636 } 04637 } 04638 04639 void Nedelec1HexFiniteElement::Project ( 04640 VectorCoefficient &vc, ElementTransformation &Trans, 04641 Vector &dofs) const 04642 { 04643 double vk[3]; 04644 Vector xk (vk, 3); 04645 04646 for (int k = 0; k < 12; k++) 04647 { 04648 Trans.SetIntPoint (&Nodes.IntPoint (k)); 04649 const DenseMatrix &J = Trans.Jacobian(); 04650 04651 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 04652 // xk^t J tk 04653 dofs(k) = 04654 vk[0] * ( J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2] ) + 04655 vk[1] * ( J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2] ) + 04656 vk[2] * ( J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2] ); 04657 } 04658 } 04659 04660 04661 Nedelec1TetFiniteElement::Nedelec1TetFiniteElement() 04662 : VectorFiniteElement (3, Geometry::TETRAHEDRON, 6, 1) 04663 { 04664 // not real nodes ... 04665 Nodes.IntPoint(0).x = 0.5; 04666 Nodes.IntPoint(0).y = 0.0; 04667 Nodes.IntPoint(0).z = 0.0; 04668 04669 Nodes.IntPoint(1).x = 0.0; 04670 Nodes.IntPoint(1).y = 0.5; 04671 Nodes.IntPoint(1).z = 0.0; 04672 04673 Nodes.IntPoint(2).x = 0.0; 04674 Nodes.IntPoint(2).y = 0.0; 04675 Nodes.IntPoint(2).z = 0.5; 04676 04677 Nodes.IntPoint(3).x = 0.5; 04678 Nodes.IntPoint(3).y = 0.5; 04679 Nodes.IntPoint(3).z = 0.0; 04680 04681 Nodes.IntPoint(4).x = 0.5; 04682 Nodes.IntPoint(4).y = 0.0; 04683 Nodes.IntPoint(4).z = 0.5; 04684 04685 Nodes.IntPoint(5).x = 0.0; 04686 Nodes.IntPoint(5).y = 0.5; 04687 Nodes.IntPoint(5).z = 0.5; 04688 } 04689 04690 void Nedelec1TetFiniteElement::CalcVShape(const IntegrationPoint &ip, 04691 DenseMatrix &shape) const 04692 { 04693 double x = ip.x, y = ip.y, z = ip.z; 04694 04695 shape(0,0) = 1. - y - z; 04696 shape(0,1) = x; 04697 shape(0,2) = x; 04698 04699 shape(1,0) = y; 04700 shape(1,1) = 1. - x - z; 04701 shape(1,2) = y; 04702 04703 shape(2,0) = z; 04704 shape(2,1) = z; 04705 shape(2,2) = 1. - x - y; 04706 04707 shape(3,0) = -y; 04708 shape(3,1) = x; 04709 shape(3,2) = 0.; 04710 04711 shape(4,0) = -z; 04712 shape(4,1) = 0.; 04713 shape(4,2) = x; 04714 04715 shape(5,0) = 0.; 04716 shape(5,1) = -z; 04717 shape(5,2) = y; 04718 } 04719 04720 void Nedelec1TetFiniteElement::CalcCurlShape(const IntegrationPoint &ip, 04721 DenseMatrix &curl_shape) 04722 const 04723 { 04724 curl_shape(0,0) = 0.; 04725 curl_shape(0,1) = -2.; 04726 curl_shape(0,2) = 2.; 04727 04728 curl_shape(1,0) = 2.; 04729 curl_shape(1,1) = 0.; 04730 curl_shape(1,2) = -2.; 04731 04732 curl_shape(2,0) = -2.; 04733 curl_shape(2,1) = 2.; 04734 curl_shape(2,2) = 0.; 04735 04736 curl_shape(3,0) = 0.; 04737 curl_shape(3,1) = 0.; 04738 curl_shape(3,2) = 2.; 04739 04740 curl_shape(4,0) = 0.; 04741 curl_shape(4,1) = -2.; 04742 curl_shape(4,2) = 0.; 04743 04744 curl_shape(5,0) = 2.; 04745 curl_shape(5,1) = 0.; 04746 curl_shape(5,2) = 0.; 04747 } 04748 04749 const double Nedelec1TetFiniteElement::tk[6][3] = 04750 {{1,0,0}, {0,1,0}, {0,0,1}, {-1,1,0}, {-1,0,1}, {0,-1,1}}; 04751 04752 void Nedelec1TetFiniteElement::GetLocalInterpolation ( 04753 ElementTransformation &Trans, DenseMatrix &I) const 04754 { 04755 int k, j; 04756 #ifdef MFEM_USE_OPENMP 04757 DenseMatrix vshape(Dof, Dim); 04758 #endif 04759 04760 #ifdef MFEM_DEBUG 04761 for (k = 0; k < 6; k++) 04762 { 04763 CalcVShape (Nodes.IntPoint(k), vshape); 04764 for (j = 0; j < 6; j++) 04765 { 04766 double d = ( vshape(j,0)*tk[k][0] + vshape(j,1)*tk[k][1] + 04767 vshape(j,2)*tk[k][2] ); 04768 if (j == k) d -= 1.0; 04769 if (fabs(d) > 1.0e-12) 04770 { 04771 cerr << "Nedelec1TetFiniteElement::GetLocalInterpolation (...)\n" 04772 " k = " << k << ", j = " << j << ", d = " << d << endl; 04773 mfem_error(); 04774 } 04775 } 04776 } 04777 #endif 04778 04779 IntegrationPoint ip; 04780 ip.x = ip.y = ip.z = 0.0; 04781 Trans.SetIntPoint (&ip); 04782 // Trans must be linear 04783 const DenseMatrix &J = Trans.Jacobian(); 04784 double vk[3]; 04785 Vector xk (vk, 3); 04786 04787 for (k = 0; k < 6; k++) 04788 { 04789 Trans.Transform (Nodes.IntPoint (k), xk); 04790 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2]; 04791 CalcVShape (ip, vshape); 04792 // vk = J tk 04793 vk[0] = J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2]; 04794 vk[1] = J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2]; 04795 vk[2] = J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2]; 04796 for (j = 0; j < 6; j++) 04797 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+ 04798 vshape(j,2)*vk[2])) < 1.0e-12) 04799 I(k,j) = 0.0; 04800 } 04801 } 04802 04803 void Nedelec1TetFiniteElement::Project ( 04804 VectorCoefficient &vc, ElementTransformation &Trans, 04805 Vector &dofs) const 04806 { 04807 double vk[3]; 04808 Vector xk (vk, 3); 04809 04810 for (int k = 0; k < 6; k++) 04811 { 04812 Trans.SetIntPoint (&Nodes.IntPoint (k)); 04813 const DenseMatrix &J = Trans.Jacobian(); 04814 04815 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 04816 // xk^t J tk 04817 dofs(k) = 04818 vk[0] * ( J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2] ) + 04819 vk[1] * ( J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2] ) + 04820 vk[2] * ( J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2] ); 04821 } 04822 } 04823 04824 RT0HexFiniteElement::RT0HexFiniteElement() 04825 : VectorFiniteElement (3, Geometry::CUBE, 6, 1, FunctionSpace::Qk) 04826 { 04827 // not real nodes ... 04828 // z = 0, y = 0, x = 1, y = 1, x = 0, z = 1 04829 Nodes.IntPoint(0).x = 0.5; 04830 Nodes.IntPoint(0).y = 0.5; 04831 Nodes.IntPoint(0).z = 0.0; 04832 04833 Nodes.IntPoint(1).x = 0.5; 04834 Nodes.IntPoint(1).y = 0.0; 04835 Nodes.IntPoint(1).z = 0.5; 04836 04837 Nodes.IntPoint(2).x = 1.0; 04838 Nodes.IntPoint(2).y = 0.5; 04839 Nodes.IntPoint(2).z = 0.5; 04840 04841 Nodes.IntPoint(3).x = 0.5; 04842 Nodes.IntPoint(3).y = 1.0; 04843 Nodes.IntPoint(3).z = 0.5; 04844 04845 Nodes.IntPoint(4).x = 0.0; 04846 Nodes.IntPoint(4).y = 0.5; 04847 Nodes.IntPoint(4).z = 0.5; 04848 04849 Nodes.IntPoint(5).x = 0.5; 04850 Nodes.IntPoint(5).y = 0.5; 04851 Nodes.IntPoint(5).z = 1.0; 04852 } 04853 04854 void RT0HexFiniteElement::CalcVShape(const IntegrationPoint &ip, 04855 DenseMatrix &shape) const 04856 { 04857 double x = ip.x, y = ip.y, z = ip.z; 04858 // z = 0 04859 shape(0,0) = 0.; 04860 shape(0,1) = 0.; 04861 shape(0,2) = z - 1.; 04862 // y = 0 04863 shape(1,0) = 0.; 04864 shape(1,1) = y - 1.; 04865 shape(1,2) = 0.; 04866 // x = 1 04867 shape(2,0) = x; 04868 shape(2,1) = 0.; 04869 shape(2,2) = 0.; 04870 // y = 1 04871 shape(3,0) = 0.; 04872 shape(3,1) = y; 04873 shape(3,2) = 0.; 04874 // x = 0 04875 shape(4,0) = x - 1.; 04876 shape(4,1) = 0.; 04877 shape(4,2) = 0.; 04878 // z = 1 04879 shape(5,0) = 0.; 04880 shape(5,1) = 0.; 04881 shape(5,2) = z; 04882 } 04883 04884 void RT0HexFiniteElement::CalcDivShape(const IntegrationPoint &ip, 04885 Vector &divshape) const 04886 { 04887 divshape(0) = 1.; 04888 divshape(1) = 1.; 04889 divshape(2) = 1.; 04890 divshape(3) = 1.; 04891 divshape(4) = 1.; 04892 divshape(5) = 1.; 04893 } 04894 04895 const double RT0HexFiniteElement::nk[6][3] = 04896 {{0,0,-1}, {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0}, {0,0,1}}; 04897 04898 void RT0HexFiniteElement::GetLocalInterpolation ( 04899 ElementTransformation &Trans, DenseMatrix &I) const 04900 { 04901 int k, j; 04902 #ifdef MFEM_USE_OPENMP 04903 DenseMatrix vshape(Dof, Dim); 04904 DenseMatrix Jinv(Dim); 04905 #endif 04906 04907 #ifdef MFEM_DEBUG 04908 for (k = 0; k < 6; k++) 04909 { 04910 CalcVShape (Nodes.IntPoint(k), vshape); 04911 for (j = 0; j < 6; j++) 04912 { 04913 double d = ( vshape(j,0)*nk[k][0] + vshape(j,1)*nk[k][1] + 04914 vshape(j,2)*nk[k][2] ); 04915 if (j == k) d -= 1.0; 04916 if (fabs(d) > 1.0e-12) 04917 { 04918 cerr << "RT0HexFiniteElement::GetLocalInterpolation (...)\n" 04919 " k = " << k << ", j = " << j << ", d = " << d << endl; 04920 mfem_error(); 04921 } 04922 } 04923 } 04924 #endif 04925 04926 IntegrationPoint ip; 04927 ip.x = ip.y = ip.z = 0.0; 04928 Trans.SetIntPoint (&ip); 04929 // Trans must be linear 04930 // set Jinv = |J| J^{-t} = adj(J)^t 04931 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 04932 double vk[3]; 04933 Vector xk (vk, 3); 04934 04935 for (k = 0; k < 6; k++) 04936 { 04937 Trans.Transform (Nodes.IntPoint (k), xk); 04938 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2]; 04939 CalcVShape (ip, vshape); 04940 // vk = |J| J^{-t} nk 04941 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2]; 04942 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2]; 04943 vk[2] = Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2]; 04944 for (j = 0; j < 6; j++) 04945 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+ 04946 vshape(j,2)*vk[2])) < 1.0e-12) 04947 I(k,j) = 0.0; 04948 } 04949 } 04950 04951 void RT0HexFiniteElement::Project ( 04952 VectorCoefficient &vc, ElementTransformation &Trans, 04953 Vector &dofs) const 04954 { 04955 double vk[3]; 04956 Vector xk (vk, 3); 04957 #ifdef MFEM_USE_OPENMP 04958 DenseMatrix Jinv(Dim); 04959 #endif 04960 04961 for (int k = 0; k < 6; k++) 04962 { 04963 Trans.SetIntPoint (&Nodes.IntPoint (k)); 04964 // set Jinv = |J| J^{-t} = adj(J)^t 04965 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 04966 04967 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 04968 // xk^t |J| J^{-t} nk 04969 dofs(k) = 04970 vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2] ) + 04971 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2] ) + 04972 vk[2] * ( Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2] ); 04973 } 04974 } 04975 04976 RT1HexFiniteElement::RT1HexFiniteElement() 04977 : VectorFiniteElement (3, Geometry::CUBE, 36, 2, FunctionSpace::Qk) 04978 { 04979 // z = 0 04980 Nodes.IntPoint(2).x = 1./3.; 04981 Nodes.IntPoint(2).y = 1./3.; 04982 Nodes.IntPoint(2).z = 0.0; 04983 Nodes.IntPoint(3).x = 2./3.; 04984 Nodes.IntPoint(3).y = 1./3.; 04985 Nodes.IntPoint(3).z = 0.0; 04986 Nodes.IntPoint(0).x = 1./3.; 04987 Nodes.IntPoint(0).y = 2./3.; 04988 Nodes.IntPoint(0).z = 0.0; 04989 Nodes.IntPoint(1).x = 2./3.; 04990 Nodes.IntPoint(1).y = 2./3.; 04991 Nodes.IntPoint(1).z = 0.0; 04992 // y = 0 04993 Nodes.IntPoint(4).x = 1./3.; 04994 Nodes.IntPoint(4).y = 0.0; 04995 Nodes.IntPoint(4).z = 1./3.; 04996 Nodes.IntPoint(5).x = 2./3.; 04997 Nodes.IntPoint(5).y = 0.0; 04998 Nodes.IntPoint(5).z = 1./3.; 04999 Nodes.IntPoint(6).x = 1./3.; 05000 Nodes.IntPoint(6).y = 0.0; 05001 Nodes.IntPoint(6).z = 2./3.; 05002 Nodes.IntPoint(7).x = 2./3.; 05003 Nodes.IntPoint(7).y = 0.0; 05004 Nodes.IntPoint(7).z = 2./3.; 05005 // x = 1 05006 Nodes.IntPoint(8).x = 1.0; 05007 Nodes.IntPoint(8).y = 1./3.; 05008 Nodes.IntPoint(8).z = 1./3.; 05009 Nodes.IntPoint(9).x = 1.0; 05010 Nodes.IntPoint(9).y = 2./3.; 05011 Nodes.IntPoint(9).z = 1./3.; 05012 Nodes.IntPoint(10).x = 1.0; 05013 Nodes.IntPoint(10).y = 1./3.; 05014 Nodes.IntPoint(10).z = 2./3.; 05015 Nodes.IntPoint(11).x = 1.0; 05016 Nodes.IntPoint(11).y = 2./3.; 05017 Nodes.IntPoint(11).z = 2./3.; 05018 // y = 1 05019 Nodes.IntPoint(13).x = 1./3.; 05020 Nodes.IntPoint(13).y = 1.0; 05021 Nodes.IntPoint(13).z = 1./3.; 05022 Nodes.IntPoint(12).x = 2./3.; 05023 Nodes.IntPoint(12).y = 1.0; 05024 Nodes.IntPoint(12).z = 1./3.; 05025 Nodes.IntPoint(15).x = 1./3.; 05026 Nodes.IntPoint(15).y = 1.0; 05027 Nodes.IntPoint(15).z = 2./3.; 05028 Nodes.IntPoint(14).x = 2./3.; 05029 Nodes.IntPoint(14).y = 1.0; 05030 Nodes.IntPoint(14).z = 2./3.; 05031 // x = 0 05032 Nodes.IntPoint(17).x = 0.0; 05033 Nodes.IntPoint(17).y = 1./3.; 05034 Nodes.IntPoint(17).z = 1./3.; 05035 Nodes.IntPoint(16).x = 0.0; 05036 Nodes.IntPoint(16).y = 2./3.; 05037 Nodes.IntPoint(16).z = 1./3.; 05038 Nodes.IntPoint(19).x = 0.0; 05039 Nodes.IntPoint(19).y = 1./3.; 05040 Nodes.IntPoint(19).z = 2./3.; 05041 Nodes.IntPoint(18).x = 0.0; 05042 Nodes.IntPoint(18).y = 2./3.; 05043 Nodes.IntPoint(18).z = 2./3.; 05044 // z = 1 05045 Nodes.IntPoint(20).x = 1./3.; 05046 Nodes.IntPoint(20).y = 1./3.; 05047 Nodes.IntPoint(20).z = 1.0; 05048 Nodes.IntPoint(21).x = 2./3.; 05049 Nodes.IntPoint(21).y = 1./3.; 05050 Nodes.IntPoint(21).z = 1.0; 05051 Nodes.IntPoint(22).x = 1./3.; 05052 Nodes.IntPoint(22).y = 2./3.; 05053 Nodes.IntPoint(22).z = 1.0; 05054 Nodes.IntPoint(23).x = 2./3.; 05055 Nodes.IntPoint(23).y = 2./3.; 05056 Nodes.IntPoint(23).z = 1.0; 05057 // x = 0.5 (interior) 05058 Nodes.IntPoint(24).x = 0.5; 05059 Nodes.IntPoint(24).y = 1./3.; 05060 Nodes.IntPoint(24).z = 1./3.; 05061 Nodes.IntPoint(25).x = 0.5; 05062 Nodes.IntPoint(25).y = 1./3.; 05063 Nodes.IntPoint(25).z = 2./3.; 05064 Nodes.IntPoint(26).x = 0.5; 05065 Nodes.IntPoint(26).y = 2./3.; 05066 Nodes.IntPoint(26).z = 1./3.; 05067 Nodes.IntPoint(27).x = 0.5; 05068 Nodes.IntPoint(27).y = 2./3.; 05069 Nodes.IntPoint(27).z = 2./3.; 05070 // y = 0.5 (interior) 05071 Nodes.IntPoint(28).x = 1./3.; 05072 Nodes.IntPoint(28).y = 0.5; 05073 Nodes.IntPoint(28).z = 1./3.; 05074 Nodes.IntPoint(29).x = 1./3.; 05075 Nodes.IntPoint(29).y = 0.5; 05076 Nodes.IntPoint(29).z = 2./3.; 05077 Nodes.IntPoint(30).x = 2./3.; 05078 Nodes.IntPoint(30).y = 0.5; 05079 Nodes.IntPoint(30).z = 1./3.; 05080 Nodes.IntPoint(31).x = 2./3.; 05081 Nodes.IntPoint(31).y = 0.5; 05082 Nodes.IntPoint(31).z = 2./3.; 05083 // z = 0.5 (interior) 05084 Nodes.IntPoint(32).x = 1./3.; 05085 Nodes.IntPoint(32).y = 1./3.; 05086 Nodes.IntPoint(32).z = 0.5; 05087 Nodes.IntPoint(33).x = 1./3.; 05088 Nodes.IntPoint(33).y = 2./3.; 05089 Nodes.IntPoint(33).z = 0.5; 05090 Nodes.IntPoint(34).x = 2./3.; 05091 Nodes.IntPoint(34).y = 1./3.; 05092 Nodes.IntPoint(34).z = 0.5; 05093 Nodes.IntPoint(35).x = 2./3.; 05094 Nodes.IntPoint(35).y = 2./3.; 05095 Nodes.IntPoint(35).z = 0.5; 05096 } 05097 05098 void RT1HexFiniteElement::CalcVShape(const IntegrationPoint &ip, 05099 DenseMatrix &shape) const 05100 { 05101 double x = ip.x, y = ip.y, z = ip.z; 05102 // z = 0 05103 shape(2,0) = 0.; 05104 shape(2,1) = 0.; 05105 shape(2,2) = -(1. - 3.*z + 2.*z*z)*( 2. - 3.*x)*( 2. - 3.*y); 05106 shape(3,0) = 0.; 05107 shape(3,1) = 0.; 05108 shape(3,2) = -(1. - 3.*z + 2.*z*z)*(-1. + 3.*x)*( 2. - 3.*y); 05109 shape(0,0) = 0.; 05110 shape(0,1) = 0.; 05111 shape(0,2) = -(1. - 3.*z + 2.*z*z)*( 2. - 3.*x)*(-1. + 3.*y); 05112 shape(1,0) = 0.; 05113 shape(1,1) = 0.; 05114 shape(1,2) = -(1. - 3.*z + 2.*z*z)*(-1. + 3.*x)*(-1. + 3.*y); 05115 // y = 0 05116 shape(4,0) = 0.; 05117 shape(4,1) = -(1. - 3.*y + 2.*y*y)*( 2. - 3.*x)*( 2. - 3.*z); 05118 shape(4,2) = 0.; 05119 shape(5,0) = 0.; 05120 shape(5,1) = -(1. - 3.*y + 2.*y*y)*(-1. + 3.*x)*( 2. - 3.*z); 05121 shape(5,2) = 0.; 05122 shape(6,0) = 0.; 05123 shape(6,1) = -(1. - 3.*y + 2.*y*y)*( 2. - 3.*x)*(-1. + 3.*z); 05124 shape(6,2) = 0.; 05125 shape(7,0) = 0.; 05126 shape(7,1) = -(1. - 3.*y + 2.*y*y)*(-1. + 3.*x)*(-1. + 3.*z); 05127 shape(7,2) = 0.; 05128 // x = 1 05129 shape(8,0) = (-x + 2.*x*x)*( 2. - 3.*y)*( 2. - 3.*z); 05130 shape(8,1) = 0.; 05131 shape(8,2) = 0.; 05132 shape(9,0) = (-x + 2.*x*x)*(-1. + 3.*y)*( 2. - 3.*z); 05133 shape(9,1) = 0.; 05134 shape(9,2) = 0.; 05135 shape(10,0) = (-x + 2.*x*x)*( 2. - 3.*y)*(-1. + 3.*z); 05136 shape(10,1) = 0.; 05137 shape(10,2) = 0.; 05138 shape(11,0) = (-x + 2.*x*x)*(-1. + 3.*y)*(-1. + 3.*z); 05139 shape(11,1) = 0.; 05140 shape(11,2) = 0.; 05141 // y = 1 05142 shape(13,0) = 0.; 05143 shape(13,1) = (-y + 2.*y*y)*( 2. - 3.*x)*( 2. - 3.*z); 05144 shape(13,2) = 0.; 05145 shape(12,0) = 0.; 05146 shape(12,1) = (-y + 2.*y*y)*(-1. + 3.*x)*( 2. - 3.*z); 05147 shape(12,2) = 0.; 05148 shape(15,0) = 0.; 05149 shape(15,1) = (-y + 2.*y*y)*( 2. - 3.*x)*(-1. + 3.*z); 05150 shape(15,2) = 0.; 05151 shape(14,0) = 0.; 05152 shape(14,1) = (-y + 2.*y*y)*(-1. + 3.*x)*(-1. + 3.*z); 05153 shape(14,2) = 0.; 05154 // x = 0 05155 shape(17,0) = -(1. - 3.*x + 2.*x*x)*( 2. - 3.*y)*( 2. - 3.*z); 05156 shape(17,1) = 0.; 05157 shape(17,2) = 0.; 05158 shape(16,0) = -(1. - 3.*x + 2.*x*x)*(-1. + 3.*y)*( 2. - 3.*z); 05159 shape(16,1) = 0.; 05160 shape(16,2) = 0.; 05161 shape(19,0) = -(1. - 3.*x + 2.*x*x)*( 2. - 3.*y)*(-1. + 3.*z); 05162 shape(19,1) = 0.; 05163 shape(19,2) = 0.; 05164 shape(18,0) = -(1. - 3.*x + 2.*x*x)*(-1. + 3.*y)*(-1. + 3.*z); 05165 shape(18,1) = 0.; 05166 shape(18,2) = 0.; 05167 // z = 1 05168 shape(20,0) = 0.; 05169 shape(20,1) = 0.; 05170 shape(20,2) = (-z + 2.*z*z)*( 2. - 3.*x)*( 2. - 3.*y); 05171 shape(21,0) = 0.; 05172 shape(21,1) = 0.; 05173 shape(21,2) = (-z + 2.*z*z)*(-1. + 3.*x)*( 2. - 3.*y); 05174 shape(22,0) = 0.; 05175 shape(22,1) = 0.; 05176 shape(22,2) = (-z + 2.*z*z)*( 2. - 3.*x)*(-1. + 3.*y); 05177 shape(23,0) = 0.; 05178 shape(23,1) = 0.; 05179 shape(23,2) = (-z + 2.*z*z)*(-1. + 3.*x)*(-1. + 3.*y); 05180 // x = 0.5 (interior) 05181 shape(24,0) = (4.*x - 4.*x*x)*( 2. - 3.*y)*( 2. - 3.*z); 05182 shape(24,1) = 0.; 05183 shape(24,2) = 0.; 05184 shape(25,0) = (4.*x - 4.*x*x)*( 2. - 3.*y)*(-1. + 3.*z); 05185 shape(25,1) = 0.; 05186 shape(25,2) = 0.; 05187 shape(26,0) = (4.*x - 4.*x*x)*(-1. + 3.*y)*( 2. - 3.*z); 05188 shape(26,1) = 0.; 05189 shape(26,2) = 0.; 05190 shape(27,0) = (4.*x - 4.*x*x)*(-1. + 3.*y)*(-1. + 3.*z); 05191 shape(27,1) = 0.; 05192 shape(27,2) = 0.; 05193 // y = 0.5 (interior) 05194 shape(28,0) = 0.; 05195 shape(28,1) = (4.*y - 4.*y*y)*( 2. - 3.*x)*( 2. - 3.*z); 05196 shape(28,2) = 0.; 05197 shape(29,0) = 0.; 05198 shape(29,1) = (4.*y - 4.*y*y)*( 2. - 3.*x)*(-1. + 3.*z); 05199 shape(29,2) = 0.; 05200 shape(30,0) = 0.; 05201 shape(30,1) = (4.*y - 4.*y*y)*(-1. + 3.*x)*( 2. - 3.*z); 05202 shape(30,2) = 0.; 05203 shape(31,0) = 0.; 05204 shape(31,1) = (4.*y - 4.*y*y)*(-1. + 3.*x)*(-1. + 3.*z); 05205 shape(31,2) = 0.; 05206 // z = 0.5 (interior) 05207 shape(32,0) = 0.; 05208 shape(32,1) = 0.; 05209 shape(32,2) = (4.*z - 4.*z*z)*( 2. - 3.*x)*( 2. - 3.*y); 05210 shape(33,0) = 0.; 05211 shape(33,1) = 0.; 05212 shape(33,2) = (4.*z - 4.*z*z)*( 2. - 3.*x)*(-1. + 3.*y); 05213 shape(34,0) = 0.; 05214 shape(34,1) = 0.; 05215 shape(34,2) = (4.*z - 4.*z*z)*(-1. + 3.*x)*( 2. - 3.*y); 05216 shape(35,0) = 0.; 05217 shape(35,1) = 0.; 05218 shape(35,2) = (4.*z - 4.*z*z)*(-1. + 3.*x)*(-1. + 3.*y); 05219 } 05220 05221 void RT1HexFiniteElement::CalcDivShape(const IntegrationPoint &ip, 05222 Vector &divshape) const 05223 { 05224 double x = ip.x, y = ip.y, z = ip.z; 05225 // z = 0 05226 divshape(2) = -(-3. + 4.*z)*( 2. - 3.*x)*( 2. - 3.*y); 05227 divshape(3) = -(-3. + 4.*z)*(-1. + 3.*x)*( 2. - 3.*y); 05228 divshape(0) = -(-3. + 4.*z)*( 2. - 3.*x)*(-1. + 3.*y); 05229 divshape(1) = -(-3. + 4.*z)*(-1. + 3.*x)*(-1. + 3.*y); 05230 // y = 0 05231 divshape(4) = -(-3. + 4.*y)*( 2. - 3.*x)*( 2. - 3.*z); 05232 divshape(5) = -(-3. + 4.*y)*(-1. + 3.*x)*( 2. - 3.*z); 05233 divshape(6) = -(-3. + 4.*y)*( 2. - 3.*x)*(-1. + 3.*z); 05234 divshape(7) = -(-3. + 4.*y)*(-1. + 3.*x)*(-1. + 3.*z); 05235 // x = 1 05236 divshape(8) = (-1. + 4.*x)*( 2. - 3.*y)*( 2. - 3.*z); 05237 divshape(9) = (-1. + 4.*x)*(-1. + 3.*y)*( 2. - 3.*z); 05238 divshape(10) = (-1. + 4.*x)*( 2. - 3.*y)*(-1. + 3.*z); 05239 divshape(11) = (-1. + 4.*x)*(-1. + 3.*y)*(-1. + 3.*z); 05240 // y = 1 05241 divshape(13) = (-1. + 4.*y)*( 2. - 3.*x)*( 2. - 3.*z); 05242 divshape(12) = (-1. + 4.*y)*(-1. + 3.*x)*( 2. - 3.*z); 05243 divshape(15) = (-1. + 4.*y)*( 2. - 3.*x)*(-1. + 3.*z); 05244 divshape(14) = (-1. + 4.*y)*(-1. + 3.*x)*(-1. + 3.*z); 05245 // x = 0 05246 divshape(17) = -(-3. + 4.*x)*( 2. - 3.*y)*( 2. - 3.*z); 05247 divshape(16) = -(-3. + 4.*x)*(-1. + 3.*y)*( 2. - 3.*z); 05248 divshape(19) = -(-3. + 4.*x)*( 2. - 3.*y)*(-1. + 3.*z); 05249 divshape(18) = -(-3. + 4.*x)*(-1. + 3.*y)*(-1. + 3.*z); 05250 // z = 1 05251 divshape(20) = (-1. + 4.*z)*( 2. - 3.*x)*( 2. - 3.*y); 05252 divshape(21) = (-1. + 4.*z)*(-1. + 3.*x)*( 2. - 3.*y); 05253 divshape(22) = (-1. + 4.*z)*( 2. - 3.*x)*(-1. + 3.*y); 05254 divshape(23) = (-1. + 4.*z)*(-1. + 3.*x)*(-1. + 3.*y); 05255 // x = 0.5 (interior) 05256 divshape(24) = ( 4. - 8.*x)*( 2. - 3.*y)*( 2. - 3.*z); 05257 divshape(25) = ( 4. - 8.*x)*( 2. - 3.*y)*(-1. + 3.*z); 05258 divshape(26) = ( 4. - 8.*x)*(-1. + 3.*y)*( 2. - 3.*z); 05259 divshape(27) = ( 4. - 8.*x)*(-1. + 3.*y)*(-1. + 3.*z); 05260 // y = 0.5 (interior) 05261 divshape(28) = ( 4. - 8.*y)*( 2. - 3.*x)*( 2. - 3.*z); 05262 divshape(29) = ( 4. - 8.*y)*( 2. - 3.*x)*(-1. + 3.*z); 05263 divshape(30) = ( 4. - 8.*y)*(-1. + 3.*x)*( 2. - 3.*z); 05264 divshape(31) = ( 4. - 8.*y)*(-1. + 3.*x)*(-1. + 3.*z); 05265 // z = 0.5 (interior) 05266 divshape(32) = ( 4. - 8.*z)*( 2. - 3.*x)*( 2. - 3.*y); 05267 divshape(33) = ( 4. - 8.*z)*( 2. - 3.*x)*(-1. + 3.*y); 05268 divshape(34) = ( 4. - 8.*z)*(-1. + 3.*x)*( 2. - 3.*y); 05269 divshape(35) = ( 4. - 8.*z)*(-1. + 3.*x)*(-1. + 3.*y); 05270 } 05271 05272 const double RT1HexFiniteElement::nk[36][3] = 05273 { 05274 {0, 0,-1}, {0, 0,-1}, {0, 0,-1}, {0, 0,-1}, 05275 {0,-1, 0}, {0,-1, 0}, {0,-1, 0}, {0,-1, 0}, 05276 {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, 05277 {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, 05278 {-1,0, 0}, {-1,0, 0}, {-1,0, 0}, {-1,0, 0}, 05279 {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, 05280 {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, 05281 {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, 05282 {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1} 05283 }; 05284 05285 void RT1HexFiniteElement::GetLocalInterpolation ( 05286 ElementTransformation &Trans, DenseMatrix &I) const 05287 { 05288 int k, j; 05289 #ifdef MFEM_USE_OPENMP 05290 DenseMatrix vshape(Dof, Dim); 05291 DenseMatrix Jinv(Dim); 05292 #endif 05293 05294 #ifdef MFEM_DEBUG 05295 for (k = 0; k < 36; k++) 05296 { 05297 CalcVShape (Nodes.IntPoint(k), vshape); 05298 for (j = 0; j < 36; j++) 05299 { 05300 double d = ( vshape(j,0)*nk[k][0] + vshape(j,1)*nk[k][1] + 05301 vshape(j,2)*nk[k][2] ); 05302 if (j == k) d -= 1.0; 05303 if (fabs(d) > 1.0e-12) 05304 { 05305 cerr << "RT0HexFiniteElement::GetLocalInterpolation (...)\n" 05306 " k = " << k << ", j = " << j << ", d = " << d << endl; 05307 mfem_error(); 05308 } 05309 } 05310 } 05311 #endif 05312 05313 IntegrationPoint ip; 05314 ip.x = ip.y = ip.z = 0.0; 05315 Trans.SetIntPoint (&ip); 05316 // Trans must be linear 05317 // set Jinv = |J| J^{-t} = adj(J)^t 05318 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 05319 double vk[3]; 05320 Vector xk (vk, 3); 05321 05322 for (k = 0; k < 36; k++) 05323 { 05324 Trans.Transform (Nodes.IntPoint (k), xk); 05325 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2]; 05326 CalcVShape (ip, vshape); 05327 // vk = |J| J^{-t} nk 05328 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2]; 05329 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2]; 05330 vk[2] = Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2]; 05331 for (j = 0; j < 36; j++) 05332 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+ 05333 vshape(j,2)*vk[2])) < 1.0e-12) 05334 I(k,j) = 0.0; 05335 } 05336 } 05337 05338 void RT1HexFiniteElement::Project ( 05339 VectorCoefficient &vc, ElementTransformation &Trans, 05340 Vector &dofs) const 05341 { 05342 double vk[3]; 05343 Vector xk (vk, 3); 05344 #ifdef MFEM_USE_OPENMP 05345 DenseMatrix Jinv(Dim); 05346 #endif 05347 05348 for (int k = 0; k < 36; k++) 05349 { 05350 Trans.SetIntPoint (&Nodes.IntPoint (k)); 05351 // set Jinv = |J| J^{-t} = adj(J)^t 05352 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 05353 05354 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 05355 // xk^t |J| J^{-t} nk 05356 dofs(k) = 05357 vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2] ) + 05358 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2] ) + 05359 vk[2] * ( Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2] ); 05360 } 05361 } 05362 05363 RT0TetFiniteElement::RT0TetFiniteElement() 05364 : VectorFiniteElement (3, Geometry::TETRAHEDRON, 4, 1) 05365 { 05366 // not real nodes ... 05367 Nodes.IntPoint(0).x = 0.33333333333333333333; 05368 Nodes.IntPoint(0).y = 0.33333333333333333333; 05369 Nodes.IntPoint(0).z = 0.33333333333333333333; 05370 05371 Nodes.IntPoint(1).x = 0.0; 05372 Nodes.IntPoint(1).y = 0.33333333333333333333; 05373 Nodes.IntPoint(1).z = 0.33333333333333333333; 05374 05375 Nodes.IntPoint(2).x = 0.33333333333333333333; 05376 Nodes.IntPoint(2).y = 0.0; 05377 Nodes.IntPoint(2).z = 0.33333333333333333333; 05378 05379 Nodes.IntPoint(3).x = 0.33333333333333333333; 05380 Nodes.IntPoint(3).y = 0.33333333333333333333; 05381 Nodes.IntPoint(3).z = 0.0; 05382 } 05383 05384 void RT0TetFiniteElement::CalcVShape(const IntegrationPoint &ip, 05385 DenseMatrix &shape) const 05386 { 05387 double x2 = 2.0*ip.x, y2 = 2.0*ip.y, z2 = 2.0*ip.z; 05388 05389 shape(0,0) = x2; 05390 shape(0,1) = y2; 05391 shape(0,2) = z2; 05392 05393 shape(1,0) = x2 - 2.0; 05394 shape(1,1) = y2; 05395 shape(1,2) = z2; 05396 05397 shape(2,0) = x2; 05398 shape(2,1) = y2 - 2.0; 05399 shape(2,2) = z2; 05400 05401 shape(3,0) = x2; 05402 shape(3,1) = y2; 05403 shape(3,2) = z2 - 2.0; 05404 } 05405 05406 void RT0TetFiniteElement::CalcDivShape(const IntegrationPoint &ip, 05407 Vector &divshape) const 05408 { 05409 divshape(0) = 6.0; 05410 divshape(1) = 6.0; 05411 divshape(2) = 6.0; 05412 divshape(3) = 6.0; 05413 } 05414 05415 const double RT0TetFiniteElement::nk[4][3] = 05416 {{.5,.5,.5}, {-.5,0,0}, {0,-.5,0}, {0,0,-.5}}; 05417 05418 void RT0TetFiniteElement::GetLocalInterpolation ( 05419 ElementTransformation &Trans, DenseMatrix &I) const 05420 { 05421 int k, j; 05422 #ifdef MFEM_USE_OPENMP 05423 DenseMatrix vshape(Dof, Dim); 05424 DenseMatrix Jinv(Dim); 05425 #endif 05426 05427 #ifdef MFEM_DEBUG 05428 for (k = 0; k < 4; k++) 05429 { 05430 CalcVShape (Nodes.IntPoint(k), vshape); 05431 for (j = 0; j < 4; j++) 05432 { 05433 double d = ( vshape(j,0)*nk[k][0] + vshape(j,1)*nk[k][1] + 05434 vshape(j,2)*nk[k][2] ); 05435 if (j == k) d -= 1.0; 05436 if (fabs(d) > 1.0e-12) 05437 { 05438 cerr << "RT0TetFiniteElement::GetLocalInterpolation (...)\n" 05439 " k = " << k << ", j = " << j << ", d = " << d << endl; 05440 mfem_error(); 05441 } 05442 } 05443 } 05444 #endif 05445 05446 IntegrationPoint ip; 05447 ip.x = ip.y = ip.z = 0.0; 05448 Trans.SetIntPoint (&ip); 05449 // Trans must be linear 05450 // set Jinv = |J| J^{-t} = adj(J)^t 05451 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 05452 double vk[3]; 05453 Vector xk (vk, 3); 05454 05455 for (k = 0; k < 4; k++) 05456 { 05457 Trans.Transform (Nodes.IntPoint (k), xk); 05458 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2]; 05459 CalcVShape (ip, vshape); 05460 // vk = |J| J^{-t} nk 05461 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2]; 05462 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2]; 05463 vk[2] = Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2]; 05464 for (j = 0; j < 4; j++) 05465 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+ 05466 vshape(j,2)*vk[2])) < 1.0e-12) 05467 I(k,j) = 0.0; 05468 } 05469 } 05470 05471 void RT0TetFiniteElement::Project ( 05472 VectorCoefficient &vc, ElementTransformation &Trans, 05473 Vector &dofs) const 05474 { 05475 double vk[3]; 05476 Vector xk (vk, 3); 05477 #ifdef MFEM_USE_OPENMP 05478 DenseMatrix Jinv(Dim); 05479 #endif 05480 05481 for (int k = 0; k < 4; k++) 05482 { 05483 Trans.SetIntPoint (&Nodes.IntPoint (k)); 05484 // set Jinv = |J| J^{-t} = adj(J)^t 05485 CalcAdjugateTranspose (Trans.Jacobian(), Jinv); 05486 05487 vc.Eval (xk, Trans, Nodes.IntPoint (k)); 05488 // xk^t |J| J^{-t} nk 05489 dofs(k) = 05490 vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2] ) + 05491 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2] ) + 05492 vk[2] * ( Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2] ); 05493 } 05494 } 05495 05496 RotTriLinearHexFiniteElement::RotTriLinearHexFiniteElement() 05497 : NodalFiniteElement(3, Geometry::CUBE, 6, 2, FunctionSpace::Qk) 05498 { 05499 Nodes.IntPoint(0).x = 0.5; 05500 Nodes.IntPoint(0).y = 0.5; 05501 Nodes.IntPoint(0).z = 0.0; 05502 05503 Nodes.IntPoint(1).x = 0.5; 05504 Nodes.IntPoint(1).y = 0.0; 05505 Nodes.IntPoint(1).z = 0.5; 05506 05507 Nodes.IntPoint(2).x = 1.0; 05508 Nodes.IntPoint(2).y = 0.5; 05509 Nodes.IntPoint(2).z = 0.5; 05510 05511 Nodes.IntPoint(3).x = 0.5; 05512 Nodes.IntPoint(3).y = 1.0; 05513 Nodes.IntPoint(3).z = 0.5; 05514 05515 Nodes.IntPoint(4).x = 0.0; 05516 Nodes.IntPoint(4).y = 0.5; 05517 Nodes.IntPoint(4).z = 0.5; 05518 05519 Nodes.IntPoint(5).x = 0.5; 05520 Nodes.IntPoint(5).y = 0.5; 05521 Nodes.IntPoint(5).z = 1.0; 05522 } 05523 05524 void RotTriLinearHexFiniteElement::CalcShape(const IntegrationPoint &ip, 05525 Vector &shape) const 05526 { 05527 double x = 2. * ip.x - 1.; 05528 double y = 2. * ip.y - 1.; 05529 double z = 2. * ip.z - 1.; 05530 double f5 = x * x - y * y; 05531 double f6 = y * y - z * z; 05532 05533 shape(0) = (1./6.) * (1. - 3. * z - f5 - 2. * f6); 05534 shape(1) = (1./6.) * (1. - 3. * y - f5 + f6); 05535 shape(2) = (1./6.) * (1. + 3. * x + 2. * f5 + f6); 05536 shape(3) = (1./6.) * (1. + 3. * y - f5 + f6); 05537 shape(4) = (1./6.) * (1. - 3. * x + 2. * f5 + f6); 05538 shape(5) = (1./6.) * (1. + 3. * z - f5 - 2. * f6); 05539 } 05540 05541 void RotTriLinearHexFiniteElement::CalcDShape(const IntegrationPoint &ip, 05542 DenseMatrix &dshape) const 05543 { 05544 const double a = 2./3.; 05545 05546 double xt = a * (1. - 2. * ip.x); 05547 double yt = a * (1. - 2. * ip.y); 05548 double zt = a * (1. - 2. * ip.z); 05549 05550 dshape(0,0) = xt; 05551 dshape(0,1) = yt; 05552 dshape(0,2) = -1. - 2. * zt; 05553 05554 dshape(1,0) = xt; 05555 dshape(1,1) = -1. - 2. * yt; 05556 dshape(1,2) = zt; 05557 05558 dshape(2,0) = 1. - 2. * xt; 05559 dshape(2,1) = yt; 05560 dshape(2,2) = zt; 05561 05562 dshape(3,0) = xt; 05563 dshape(3,1) = 1. - 2. * yt; 05564 dshape(3,2) = zt; 05565 05566 dshape(4,0) = -1. - 2. * xt; 05567 dshape(4,1) = yt; 05568 dshape(4,2) = zt; 05569 05570 dshape(5,0) = xt; 05571 dshape(5,1) = yt; 05572 dshape(5,2) = 1. - 2. * zt; 05573 } 05574 05575 05576 Poly_1D::Basis::Basis(const int p, const double *nodes) 05577 : A(p + 1) 05578 { 05579 #ifdef MFEM_USE_OPENMP 05580 Vector a(p+1); 05581 #else 05582 a.SetSize(p+1); 05583 b.SetSize(p+1); 05584 #endif 05585 for (int i = 0; i <= p; i++) 05586 { 05587 CalcBasis(p, nodes[i], a); 05588 for (int j = 0; j <= p; j++) 05589 A(j, i) = a(j); 05590 } 05591 05592 A.Invert(); 05593 // cout << "Poly_1D::Basis(" << p << ",...) : "; A.TestInversion(); 05594 } 05595 05596 void Poly_1D::Basis::Eval(const double x, Vector &u) const 05597 { 05598 #ifdef MFEM_USE_OPENMP 05599 Vector a(A.Size()); 05600 #endif 05601 const int p = A.Size() - 1; 05602 CalcBasis(p, x, a); 05603 A.Mult(a, u); 05604 } 05605 05606 void Poly_1D::Basis::Eval(const double x, Vector &u, Vector &d) const 05607 { 05608 #ifdef MFEM_USE_OPENMP 05609 Vector a(A.Size()), b(A.Size()); 05610 #endif 05611 const int p = A.Size() - 1; 05612 CalcBasis(p, x, a, b); 05613 A.Mult(a, u); 05614 A.Mult(b, d); 05615 } 05616 05617 void Poly_1D::UniformPoints(const int p, double *x) 05618 { 05619 if (p == 0) 05620 { 05621 x[0] = 0.5; 05622 } 05623 else 05624 { 05625 for (int i = 0; i <= p; i++) 05626 x[i] = double(i)/p; 05627 } 05628 } 05629 05630 void Poly_1D::GaussPoints(const int p, double *x) 05631 { 05632 int m = (p+1)/2, odd_p = p%2; 05633 05634 if (!odd_p) 05635 x[m] = 0.5; 05636 05637 for (int i = 0; i < m; i++) 05638 { 05639 double z, y, p0, d0; 05640 z = cos(M_PI*(i + 0.75)/(p + 1.5)); 05641 05642 for (int k = 0; true; ) 05643 { 05644 // compute p0, d0 -- P_{p+1}(z), P'_{p+1}(z) using 05645 // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z) 05646 // P'_{n+1}(z) = (2*n+1)*P_n(z)+P'_{n-1}(z) 05647 { 05648 double p1, p2; 05649 p2 = 1.; 05650 p1 = z; 05651 d0 = 1 - odd_p; 05652 for (int n = 1; true; n++) 05653 { 05654 p0 = ((2*n+1)*z*p1 - n*p2)/(n + 1); 05655 if (n%2 == odd_p) 05656 d0 += (2*n+1)*p1; 05657 if (n == p) break; 05658 p2 = p1; 05659 p1 = p0; 05660 } 05661 // d0 = (p + 1)*(z*p0 - p1)/(z*z - 1); // alternative formula 05662 } 05663 05664 if (fabs(p0/d0) < 2e-16) break; 05665 05666 if (++k == 5) 05667 { 05668 std::cout << "Poly_1D::GaussPoints : No convergence!" 05669 " p = " << p << ", i = " << i << ", p0/d0 = " << p0/d0 05670 << std::endl; 05671 break; 05672 } 05673 05674 z = z - p0/d0; 05675 } 05676 05677 // z = z - p0/d0; y = (1 - z)/2; // bad roundoff !!! 05678 y = ((1 - z) + p0/d0)/2; 05679 05680 x[i] = y; 05681 x[p-i] = 1 - y; 05682 // the weight is: 1./(4*y*(1 - y)*d0*d0) 05683 } 05684 } 05685 05686 void Poly_1D::GaussLobattoPoints(const int p, double *x) 05687 { 05688 if (p == 0) 05689 { 05690 x[0] = 0.5; 05691 } 05692 else 05693 { 05694 x[0] = 0.; 05695 x[p] = 1.; 05696 if (p == 1) return; 05697 05698 // x[1],...,x[p-1] are the (shifted) roots of P'_p 05699 int m = (p - 1)/2, odd_p = p%2; 05700 05701 if (!odd_p) 05702 x[m+1] = 0.5; 05703 for (int i = 0; i < m; ) 05704 { 05705 double y, z, d0, s0; 05706 z = cos(M_PI*(i + 1)/p); 05707 05708 for (int k = 0; true; ) 05709 { 05710 // compute d0, s0 -- P'_p(z), P"_p(z) 05711 // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z) 05712 // P'_{n+1}(z) = (2*n+1)* P_n(z)+P'_{n-1}(z) 05713 // P"_{n+1}(z) = (2*n+1)*P'_n(z)+P"_{n-1}(z) 05714 { 05715 double p0, p1, p2, d1; 05716 p2 = 1.; 05717 p1 = z; 05718 d0 = odd_p; 05719 d1 = 1 - odd_p; 05720 s0 = 0; 05721 for (int n = 1; true; n++) 05722 { 05723 p0 = ((2*n+1)*z*p1 - n*p2)/(n + 1); 05724 if (n%2 != odd_p) 05725 { 05726 d0 += (2*n+1)*p1; 05727 s0 += (2*n+1)*d1; 05728 } 05729 else 05730 { 05731 d1 += (2*n+1)*p1; 05732 } 05733 if (n == p - 1) break; 05734 p2 = p1; 05735 p1 = p0; 05736 } 05737 } 05738 05739 if (fabs(d0/s0) < 2e-16) break; 05740 05741 if (++k == 6) 05742 { 05743 std::cout << "Poly_1D::GaussLobattoPoints : No convergence!" 05744 " p = " << p << ", i = " << i << ", d0/s0 = " << d0/s0 05745 << std::endl; 05746 break; 05747 } 05748 05749 z = z - d0/s0; 05750 } 05751 05752 y = ((1 - z) + d0/s0)/2; 05753 05754 x[++i] = y; 05755 x[p-i] = 1 - y; 05756 } 05757 } 05758 } 05759 05760 void Poly_1D::ChebyshevPoints(const int p, double *x) 05761 { 05762 for (int i = 0; i <= p; i++) 05763 { 05764 // x[i] = 0.5*(1. + cos(M_PI*(p - i + 0.5)/(p + 1))); 05765 double s = sin(M_PI_2*(i + 0.5)/(p + 1)); 05766 x[i] = s*s; 05767 } 05768 } 05769 05770 void Poly_1D::CalcMono(const int p, const double x, double *u) 05771 { 05772 double xn; 05773 u[0] = xn = 1.; 05774 for (int n = 1; n <= p; n++) 05775 u[n] = (xn *= x); 05776 } 05777 05778 void Poly_1D::CalcMono(const int p, const double x, double *u, double *d) 05779 { 05780 double xn; 05781 u[0] = xn = 1.; 05782 d[0] = 0.; 05783 for (int n = 1; n <= p; n++) 05784 { 05785 d[n] = n * xn; 05786 u[n] = (xn *= x); 05787 } 05788 } 05789 05790 void Poly_1D::CalcBernstein(const int p, const double x, double *u) 05791 { 05792 // not the best way to evaluate; just for testing 05793 u[0] = 1.; 05794 for (int n = 1; n <= p; n++) 05795 { 05796 u[n] = x*u[n-1]; 05797 for (int k = n - 1; k > 0; k--) 05798 u[k] = x*u[k-1] + (1. - x)*u[k]; 05799 u[0] = (1. - x)*u[0]; 05800 } 05801 } 05802 05803 void Poly_1D::CalcBernstein(const int p, const double x, double *u, double *d) 05804 { 05805 // not the best way to evaluate; just for testing 05806 u[0] = 1.; 05807 d[0] = 0.; 05808 for (int n = 1; n <= p; n++) 05809 { 05810 d[n] = u[n-1] + x*d[n-1]; 05811 u[n] = x*u[n-1]; 05812 for (int k = n - 1; k > 0; k--) 05813 { 05814 d[k] = u[k-1] + x*d[k-1] - u[k] + (1. - x)*d[k]; 05815 u[k] = x*u[k-1] + (1. - x)*u[k]; 05816 } 05817 d[0] = -u[0] + (1. - x)*d[0]; 05818 u[0] = (1. - x)*u[0]; 05819 } 05820 } 05821 05822 void Poly_1D::CalcLegendre(const int p, const double x, double *u) 05823 { 05824 // use the recursive definition for [-1,1]: 05825 // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z) 05826 double z; 05827 u[0] = 1.; 05828 if (p == 0) return; 05829 u[1] = z = 2.*x - 1.; 05830 for (int n = 1; n < p; n++) 05831 { 05832 u[n+1] = ((2*n + 1)*z*u[n] - n*u[n-1])/(n + 1); 05833 } 05834 } 05835 05836 void Poly_1D::CalcLegendre(const int p, const double x, double *u, double *d) 05837 { 05838 // use the recursive definition for [-1,1]: 05839 // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z) 05840 // for the derivative use, z in [-1,1]: 05841 // P'_{n+1}(z) = (2*n+1)*P_n(z)+P'_{n-1}(z) 05842 double z; 05843 u[0] = 1.; 05844 d[0] = 0.; 05845 if (p == 0) return; 05846 u[1] = z = 2.*x - 1.; 05847 d[1] = 2.; 05848 for (int n = 1; n < p; n++) 05849 { 05850 u[n+1] = ((2*n + 1)*z*u[n] - n*u[n-1])/(n + 1); 05851 d[n+1] = (4*n + 2)*u[n] + d[n-1]; 05852 } 05853 } 05854 05855 void Poly_1D::CalcChebyshev(const int p, const double x, double *u) 05856 { 05857 // recursive definition, z in [-1,1] 05858 // T_0(z) = 1, T_1(z) = z 05859 // T_{n+1}(z) = 2*z*T_n(z) - T_{n-1}(z) 05860 double z; 05861 u[0] = 1.; 05862 if (p == 0) return; 05863 u[1] = z = 2.*x - 1.; 05864 for (int n = 1; n < p; n++) 05865 { 05866 u[n+1] = 2*z*u[n] - u[n-1]; 05867 } 05868 } 05869 05870 void Poly_1D::CalcChebyshev(const int p, const double x, double *u, double *d) 05871 { 05872 // recursive definition, z in [-1,1] 05873 // T_0(z) = 1, T_1(z) = z 05874 // T_{n+1}(z) = 2*z*T_n(z) - T_{n-1}(z) 05875 // T'_n(z) = n*U_{n-1}(z) 05876 // U_0(z) = 1 U_1(z) = 2*z 05877 // U_{n+1}(z) = 2*z*U_n(z) - U_{n-1}(z) 05878 // U_n(z) = z*U_{n-1}(z) + T_n(z) = z*T'_n(z)/n + T_n(z) 05879 // T'_{n+1}(z) = (n + 1)*(z*T'_n(z)/n + T_n(z)) 05880 double z; 05881 u[0] = 1.; 05882 d[0] = 0.; 05883 if (p == 0) return; 05884 u[1] = z = 2.*x - 1.; 05885 d[1] = 2.; 05886 for (int n = 1; n < p; n++) 05887 { 05888 u[n+1] = 2*z*u[n] - u[n-1]; 05889 d[n+1] = (n + 1)*(z*d[n]/n + 2*u[n]); 05890 } 05891 } 05892 05893 const double *Poly_1D::OpenPoints(const int p) 05894 { 05895 double *op; 05896 05897 if (open_pts.Size() <= p) 05898 { 05899 int i = open_pts.Size(); 05900 open_pts.SetSize(p + 1); 05901 for ( ; i < p; i++) 05902 open_pts[i] = NULL; 05903 goto alloc_open; 05904 } 05905 if ((op = open_pts[p]) != NULL) 05906 return op; 05907 alloc_open: 05908 open_pts[p] = op = new double[p + 1]; 05909 GaussPoints(p, op); 05910 // ChebyshevPoints(p, op); 05911 return op; 05912 } 05913 05914 const double *Poly_1D::ClosedPoints(const int p) 05915 { 05916 double *cp; 05917 05918 if (closed_pts.Size() <= p) 05919 { 05920 int i = closed_pts.Size(); 05921 closed_pts.SetSize(p + 1); 05922 for ( ; i < p; i++) 05923 closed_pts[i] = NULL; 05924 goto alloc_closed; 05925 } 05926 if ((cp = closed_pts[p]) != NULL) 05927 return cp; 05928 alloc_closed: 05929 closed_pts[p] = cp = new double[p + 1]; 05930 GaussLobattoPoints(p, cp); 05931 // UniformPoints(p, cp); 05932 return cp; 05933 } 05934 05935 Poly_1D::Basis &Poly_1D::OpenBasis(const int p) 05936 { 05937 Basis *ob; 05938 05939 if (open_basis.Size() <= p) 05940 { 05941 int i = open_basis.Size(); 05942 open_basis.SetSize(p + 1); 05943 for ( ; i < p; i++) 05944 open_basis[i] = NULL; 05945 goto alloc_obasis; 05946 } 05947 if ((ob = open_basis[p]) != NULL) 05948 return *ob; 05949 alloc_obasis: 05950 open_basis[p] = ob = new Basis(p, OpenPoints(p)); 05951 return *ob; 05952 } 05953 05954 Poly_1D::Basis &Poly_1D::ClosedBasis(const int p) 05955 { 05956 Basis *cb; 05957 05958 if (closed_basis.Size() <= p) 05959 { 05960 int i = closed_basis.Size(); 05961 closed_basis.SetSize(p + 1); 05962 for ( ; i < p; i++) 05963 closed_basis[i] = NULL; 05964 goto alloc_cbasis; 05965 } 05966 if ((cb = closed_basis[p]) != NULL) 05967 return *cb; 05968 alloc_cbasis: 05969 closed_basis[p] = cb = new Basis(p, ClosedPoints(p)); 05970 return *cb; 05971 } 05972 05973 Poly_1D::~Poly_1D() 05974 { 05975 for (int i = 0; i < open_pts.Size(); i++) 05976 delete [] open_pts[i]; 05977 for (int i = 0; i < closed_pts.Size(); i++) 05978 delete [] closed_pts[i]; 05979 for (int i = 0; i < open_basis.Size(); i++) 05980 delete open_basis[i]; 05981 for (int i = 0; i < closed_basis.Size(); i++) 05982 delete closed_basis[i]; 05983 } 05984 05985 Poly_1D poly1d; 05986 05987 05988 H1_SegmentElement::H1_SegmentElement(const int p) 05989 : NodalFiniteElement(1, Geometry::SEGMENT, p + 1, p, FunctionSpace::Pk), 05990 basis1d(poly1d.ClosedBasis(p)) 05991 { 05992 const double *cp = poly1d.ClosedPoints(p); 05993 05994 #ifndef MFEM_USE_OPENMP 05995 shape_x.SetSize(p+1); 05996 dshape_x.SetSize(p+1); 05997 #endif 05998 05999 Nodes.IntPoint(0).x = cp[0]; 06000 Nodes.IntPoint(1).x = cp[p]; 06001 for (int i = 1; i < p; i++) 06002 Nodes.IntPoint(i+1).x = cp[i]; 06003 } 06004 06005 void H1_SegmentElement::CalcShape(const IntegrationPoint &ip, 06006 Vector &shape) const 06007 { 06008 const int p = Order; 06009 06010 #ifdef MFEM_USE_OPENMP 06011 Vector shape_x(p+1); 06012 #endif 06013 06014 basis1d.Eval(ip.x, shape_x); 06015 06016 shape(0) = shape_x(0); 06017 shape(1) = shape_x(p); 06018 for (int i = 1; i < p; i++) 06019 shape(i+1) = shape_x(i); 06020 } 06021 06022 void H1_SegmentElement::CalcDShape(const IntegrationPoint &ip, 06023 DenseMatrix &dshape) const 06024 { 06025 const int p = Order; 06026 06027 #ifdef MFEM_USE_OPENMP 06028 Vector shape_x(p+1), dshape_x(p+1); 06029 #endif 06030 06031 basis1d.Eval(ip.x, shape_x, dshape_x); 06032 06033 dshape(0,0) = dshape_x(0); 06034 dshape(1,0) = dshape_x(p); 06035 for (int i = 1; i < p; i++) 06036 dshape(i+1,0) = dshape_x(i); 06037 } 06038 06039 06040 H1_QuadrilateralElement::H1_QuadrilateralElement(const int p) 06041 : NodalFiniteElement(2, Geometry::SQUARE, (p + 1)*(p + 1), p, 06042 FunctionSpace::Qk), 06043 basis1d(poly1d.ClosedBasis(p)), dof_map((p + 1)*(p + 1)) 06044 { 06045 const double *cp = poly1d.ClosedPoints(p); 06046 06047 const int p1 = p + 1; 06048 06049 #ifndef MFEM_USE_OPENMP 06050 shape_x.SetSize(p1); 06051 shape_y.SetSize(p1); 06052 dshape_x.SetSize(p1); 06053 dshape_y.SetSize(p1); 06054 #endif 06055 06056 // vertices 06057 dof_map[0 + 0*p1] = 0; 06058 dof_map[p + 0*p1] = 1; 06059 dof_map[p + p*p1] = 2; 06060 dof_map[0 + p*p1] = 3; 06061 06062 // edges 06063 int o = 4; 06064 for (int i = 1; i < p; i++) 06065 dof_map[i + 0*p1] = o++; 06066 for (int i = 1; i < p; i++) 06067 dof_map[p + i*p1] = o++; 06068 for (int i = 1; i < p; i++) 06069 dof_map[(p-i) + p*p1] = o++; 06070 for (int i = 1; i < p; i++) 06071 dof_map[0 + (p-i)*p1] = o++; 06072 06073 // interior 06074 for (int j = 1; j < p; j++) 06075 for (int i = 1; i < p; i++) 06076 dof_map[i + j*p1] = o++; 06077 06078 o = 0; 06079 for (int j = 0; j <= p; j++) 06080 for (int i = 0; i <= p; i++) 06081 Nodes.IntPoint(dof_map[o++]).Set2(cp[i], cp[j]); 06082 } 06083 06084 void H1_QuadrilateralElement::CalcShape(const IntegrationPoint &ip, 06085 Vector &shape) const 06086 { 06087 const int p = Order; 06088 06089 #ifdef MFEM_USE_OPENMP 06090 Vector shape_x(p+1), shape_y(p+1); 06091 #endif 06092 06093 basis1d.Eval(ip.x, shape_x); 06094 basis1d.Eval(ip.y, shape_y); 06095 06096 for (int o = 0, j = 0; j <= p; j++) 06097 for (int i = 0; i <= p; i++) 06098 shape(dof_map[o++]) = shape_x(i)*shape_y(j); 06099 } 06100 06101 void H1_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip, 06102 DenseMatrix &dshape) const 06103 { 06104 const int p = Order; 06105 06106 #ifdef MFEM_USE_OPENMP 06107 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1); 06108 #endif 06109 06110 basis1d.Eval(ip.x, shape_x, dshape_x); 06111 basis1d.Eval(ip.y, shape_y, dshape_y); 06112 06113 for (int o = 0, j = 0; j <= p; j++) 06114 for (int i = 0; i <= p; i++) 06115 { 06116 dshape(dof_map[o],0) = dshape_x(i)* shape_y(j); 06117 dshape(dof_map[o],1) = shape_x(i)*dshape_y(j); o++; 06118 } 06119 } 06120 06121 H1_HexahedronElement::H1_HexahedronElement(const int p) 06122 : NodalFiniteElement(3, Geometry::CUBE, (p + 1)*(p + 1)*(p + 1), p, 06123 FunctionSpace::Qk), 06124 basis1d(poly1d.ClosedBasis(p)), dof_map((p + 1)*(p + 1)*(p + 1)) 06125 { 06126 const double *cp = poly1d.ClosedPoints(p); 06127 06128 const int p1 = p + 1; 06129 06130 #ifndef MFEM_USE_OPENMP 06131 shape_x.SetSize(p1); 06132 shape_y.SetSize(p1); 06133 shape_z.SetSize(p1); 06134 dshape_x.SetSize(p1); 06135 dshape_y.SetSize(p1); 06136 dshape_z.SetSize(p1); 06137 #endif 06138 06139 // vertices 06140 dof_map[0 + (0 + 0*p1)*p1] = 0; 06141 dof_map[p + (0 + 0*p1)*p1] = 1; 06142 dof_map[p + (p + 0*p1)*p1] = 2; 06143 dof_map[0 + (p + 0*p1)*p1] = 3; 06144 dof_map[0 + (0 + p*p1)*p1] = 4; 06145 dof_map[p + (0 + p*p1)*p1] = 5; 06146 dof_map[p + (p + p*p1)*p1] = 6; 06147 dof_map[0 + (p + p*p1)*p1] = 7; 06148 06149 // edges (see Hexahedron::edges in mesh/hexahedron.cpp) 06150 int o = 8; 06151 for (int i = 1; i < p; i++) 06152 dof_map[i + (0 + 0*p1)*p1] = o++; // (0,1) 06153 for (int i = 1; i < p; i++) 06154 dof_map[p + (i + 0*p1)*p1] = o++; // (1,2) 06155 for (int i = 1; i < p; i++) 06156 dof_map[i + (p + 0*p1)*p1] = o++; // (3,2) 06157 for (int i = 1; i < p; i++) 06158 dof_map[0 + (i + 0*p1)*p1] = o++; // (0,3) 06159 for (int i = 1; i < p; i++) 06160 dof_map[i + (0 + p*p1)*p1] = o++; // (4,5) 06161 for (int i = 1; i < p; i++) 06162 dof_map[p + (i + p*p1)*p1] = o++; // (5,6) 06163 for (int i = 1; i < p; i++) 06164 dof_map[i + (p + p*p1)*p1] = o++; // (7,6) 06165 for (int i = 1; i < p; i++) 06166 dof_map[0 + (i + p*p1)*p1] = o++; // (4,7) 06167 for (int i = 1; i < p; i++) 06168 dof_map[0 + (0 + i*p1)*p1] = o++; // (0,4) 06169 for (int i = 1; i < p; i++) 06170 dof_map[p + (0 + i*p1)*p1] = o++; // (1,5) 06171 for (int i = 1; i < p; i++) 06172 dof_map[p + (p + i*p1)*p1] = o++; // (2,6) 06173 for (int i = 1; i < p; i++) 06174 dof_map[0 + (p + i*p1)*p1] = o++; // (3,7) 06175 06176 // faces (see Mesh::GenerateFaces in mesh/mesh.cpp) 06177 for (int j = 1; j < p; j++) 06178 for (int i = 1; i < p; i++) 06179 dof_map[i + ((p-j) + 0*p1)*p1] = o++; // (3,2,1,0) 06180 for (int j = 1; j < p; j++) 06181 for (int i = 1; i < p; i++) 06182 dof_map[i + (0 + j*p1)*p1] = o++; // (0,1,5,4) 06183 for (int j = 1; j < p; j++) 06184 for (int i = 1; i < p; i++) 06185 dof_map[p + (i + j*p1)*p1] = o++; // (1,2,6,5) 06186 for (int j = 1; j < p; j++) 06187 for (int i = 1; i < p; i++) 06188 dof_map[(p-i) + (p + j*p1)*p1] = o++; // (2,3,7,6) 06189 for (int j = 1; j < p; j++) 06190 for (int i = 1; i < p; i++) 06191 dof_map[0 + ((p-i) + j*p1)*p1] = o++; // (3,0,4,7) 06192 for (int j = 1; j < p; j++) 06193 for (int i = 1; i < p; i++) 06194 dof_map[i + (j + p*p1)*p1] = o++; // (4,5,6,7) 06195 06196 // interior 06197 for (int k = 1; k < p; k++) 06198 for (int j = 1; j < p; j++) 06199 for (int i = 1; i < p; i++) 06200 dof_map[i + (j + k*p1)*p1] = o++; 06201 06202 o = 0; 06203 for (int k = 0; k <= p; k++) 06204 for (int j = 0; j <= p; j++) 06205 for (int i = 0; i <= p; i++) 06206 Nodes.IntPoint(dof_map[o++]).Set3(cp[i], cp[j], cp[k]); 06207 } 06208 06209 void H1_HexahedronElement::CalcShape(const IntegrationPoint &ip, 06210 Vector &shape) const 06211 { 06212 const int p = Order; 06213 06214 #ifdef MFEM_USE_OPENMP 06215 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1); 06216 #endif 06217 06218 basis1d.Eval(ip.x, shape_x); 06219 basis1d.Eval(ip.y, shape_y); 06220 basis1d.Eval(ip.z, shape_z); 06221 06222 for (int o = 0, k = 0; k <= p; k++) 06223 for (int j = 0; j <= p; j++) 06224 for (int i = 0; i <= p; i++) 06225 shape(dof_map[o++]) = shape_x(i)*shape_y(j)*shape_z(k); 06226 } 06227 06228 void H1_HexahedronElement::CalcDShape(const IntegrationPoint &ip, 06229 DenseMatrix &dshape) const 06230 { 06231 const int p = Order; 06232 06233 #ifdef MFEM_USE_OPENMP 06234 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1); 06235 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1); 06236 #endif 06237 06238 basis1d.Eval(ip.x, shape_x, dshape_x); 06239 basis1d.Eval(ip.y, shape_y, dshape_y); 06240 basis1d.Eval(ip.z, shape_z, dshape_z); 06241 06242 for (int o = 0, k = 0; k <= p; k++) 06243 for (int j = 0; j <= p; j++) 06244 for (int i = 0; i <= p; i++) 06245 { 06246 dshape(dof_map[o],0) = dshape_x(i)* shape_y(j)* shape_z(k); 06247 dshape(dof_map[o],1) = shape_x(i)*dshape_y(j)* shape_z(k); 06248 dshape(dof_map[o],2) = shape_x(i)* shape_y(j)*dshape_z(k); o++; 06249 } 06250 } 06251 06252 06253 H1_TriangleElement::H1_TriangleElement(const int p) 06254 : NodalFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p, 06255 FunctionSpace::Pk), T(Dof) 06256 { 06257 const double *cp = poly1d.ClosedPoints(p); 06258 06259 #ifndef MFEM_USE_OPENMP 06260 shape_x.SetSize(p + 1); 06261 shape_y.SetSize(p + 1); 06262 shape_l.SetSize(p + 1); 06263 dshape_x.SetSize(p + 1); 06264 dshape_y.SetSize(p + 1); 06265 dshape_l.SetSize(p + 1); 06266 u.SetSize(Dof); 06267 du.SetSize(Dof, Dim); 06268 #else 06269 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1); 06270 #endif 06271 06272 // vertices 06273 Nodes.IntPoint(0).Set2(cp[0], cp[0]); 06274 Nodes.IntPoint(1).Set2(cp[p], cp[0]); 06275 Nodes.IntPoint(2).Set2(cp[0], cp[p]); 06276 06277 // edges 06278 int o = 3; 06279 for (int i = 1; i < p; i++) 06280 Nodes.IntPoint(o++).Set2(cp[i], cp[0]); 06281 for (int i = 1; i < p; i++) 06282 Nodes.IntPoint(o++).Set2(cp[p-i], cp[i]); 06283 for (int i = 1; i < p; i++) 06284 Nodes.IntPoint(o++).Set2(cp[0], cp[p-i]); 06285 06286 // interior 06287 for (int j = 1; j < p; j++) 06288 for (int i = 1; i + j < p; i++) 06289 { 06290 const double w = cp[i] + cp[j] + cp[p-i-j]; 06291 Nodes.IntPoint(o++).Set2(cp[i]/w, cp[j]/w); 06292 } 06293 06294 for (int k = 0; k < Dof; k++) 06295 { 06296 IntegrationPoint &ip = Nodes.IntPoint(k); 06297 poly1d.CalcBasis(p, ip.x, shape_x); 06298 poly1d.CalcBasis(p, ip.y, shape_y); 06299 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l); 06300 06301 o = 0; 06302 for (int j = 0; j <= p; j++) 06303 for (int i = 0; i + j <= p; i++) 06304 T(o++, k) = shape_x(i)*shape_y(j)*shape_l(p-i-j); 06305 } 06306 06307 T.Invert(); 06308 // cout << "H1_TriangleElement(" << p << ") : "; T.TestInversion(); 06309 } 06310 06311 void H1_TriangleElement::CalcShape(const IntegrationPoint &ip, 06312 Vector &shape) const 06313 { 06314 const int p = Order; 06315 06316 #ifdef MFEM_USE_OPENMP 06317 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1), u(Dof); 06318 #endif 06319 06320 poly1d.CalcBasis(p, ip.x, shape_x); 06321 poly1d.CalcBasis(p, ip.y, shape_y); 06322 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l); 06323 06324 for (int o = 0, j = 0; j <= p; j++) 06325 for (int i = 0; i + j <= p; i++) 06326 u(o++) = shape_x(i)*shape_y(j)*shape_l(p-i-j); 06327 06328 T.Mult(u, shape); 06329 } 06330 06331 void H1_TriangleElement::CalcDShape(const IntegrationPoint &ip, 06332 DenseMatrix &dshape) const 06333 { 06334 const int p = Order; 06335 06336 #ifdef MFEM_USE_OPENMP 06337 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1); 06338 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1); 06339 DenseMatrix du(Dof, Dim); 06340 #endif 06341 06342 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x); 06343 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y); 06344 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l); 06345 06346 for (int o = 0, j = 0; j <= p; j++) 06347 for (int i = 0; i + j <= p; i++) 06348 { 06349 int k = p - i - j; 06350 du(o,0) = ((dshape_x(i)* shape_l(k)) - 06351 ( shape_x(i)*dshape_l(k)))*shape_y(j); 06352 du(o,1) = ((dshape_y(j)* shape_l(k)) - 06353 ( shape_y(j)*dshape_l(k)))*shape_x(i); 06354 o++; 06355 } 06356 06357 Mult(T, du, dshape); 06358 } 06359 06360 06361 H1_TetrahedronElement::H1_TetrahedronElement(const int p) 06362 : NodalFiniteElement(3, Geometry::TETRAHEDRON, ((p + 1)*(p + 2)*(p + 3))/6, 06363 p, FunctionSpace::Pk), T(Dof) 06364 { 06365 const double *cp = poly1d.ClosedPoints(p); 06366 06367 #ifndef MFEM_USE_OPENMP 06368 shape_x.SetSize(p + 1); 06369 shape_y.SetSize(p + 1); 06370 shape_z.SetSize(p + 1); 06371 shape_l.SetSize(p + 1); 06372 dshape_x.SetSize(p + 1); 06373 dshape_y.SetSize(p + 1); 06374 dshape_z.SetSize(p + 1); 06375 dshape_l.SetSize(p + 1); 06376 u.SetSize(Dof); 06377 du.SetSize(Dof, Dim); 06378 #else 06379 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1); 06380 #endif 06381 06382 // vertices 06383 Nodes.IntPoint(0).Set3(cp[0], cp[0], cp[0]); 06384 Nodes.IntPoint(1).Set3(cp[p], cp[0], cp[0]); 06385 Nodes.IntPoint(2).Set3(cp[0], cp[p], cp[0]); 06386 Nodes.IntPoint(3).Set3(cp[0], cp[0], cp[p]); 06387 06388 // edges (see Tetrahedron::edges in mesh/tetrahedron.cpp) 06389 int o = 4; 06390 for (int i = 1; i < p; i++) // (0,1) 06391 Nodes.IntPoint(o++).Set3(cp[i], cp[0], cp[0]); 06392 for (int i = 1; i < p; i++) // (0,2) 06393 Nodes.IntPoint(o++).Set3(cp[0], cp[i], cp[0]); 06394 for (int i = 1; i < p; i++) // (0,3) 06395 Nodes.IntPoint(o++).Set3(cp[0], cp[0], cp[i]); 06396 for (int i = 1; i < p; i++) // (1,2) 06397 Nodes.IntPoint(o++).Set3(cp[p-i], cp[i], cp[0]); 06398 for (int i = 1; i < p; i++) // (1,3) 06399 Nodes.IntPoint(o++).Set3(cp[p-i], cp[0], cp[i]); 06400 for (int i = 1; i < p; i++) // (2,3) 06401 Nodes.IntPoint(o++).Set3(cp[0], cp[p-i], cp[i]); 06402 06403 // faces (see Mesh::GenerateFaces in mesh/mesh.cpp) 06404 for (int j = 1; j < p; j++) 06405 for (int i = 1; i + j < p; i++) // (1,2,3) 06406 { 06407 double w = cp[i] + cp[j] + cp[p-i-j]; 06408 Nodes.IntPoint(o++).Set3(cp[p-i-j]/w, cp[i]/w, cp[j]/w); 06409 } 06410 for (int j = 1; j < p; j++) 06411 for (int i = 1; i + j < p; i++) // (0,3,2) 06412 { 06413 double w = cp[i] + cp[j] + cp[p-i-j]; 06414 Nodes.IntPoint(o++).Set3(cp[0], cp[j]/w, cp[i]/w); 06415 } 06416 for (int j = 1; j < p; j++) 06417 for (int i = 1; i + j < p; i++) // (0,1,3) 06418 { 06419 double w = cp[i] + cp[j] + cp[p-i-j]; 06420 Nodes.IntPoint(o++).Set3(cp[i]/w, cp[0], cp[j]/w); 06421 } 06422 for (int j = 1; j < p; j++) 06423 for (int i = 1; i + j < p; i++) // (0,2,1) 06424 { 06425 double w = cp[i] + cp[j] + cp[p-i-j]; 06426 Nodes.IntPoint(o++).Set3(cp[j]/w, cp[i]/w, cp[0]); 06427 } 06428 06429 // interior 06430 for (int k = 1; k < p; k++) 06431 for (int j = 1; j + k < p; j++) 06432 for (int i = 1; i + j + k < p; i++) 06433 { 06434 double w = cp[i] + cp[j] + cp[k] + cp[p-i-j-k]; 06435 Nodes.IntPoint(o++).Set3(cp[i]/w, cp[j]/w, cp[k]/w); 06436 } 06437 06438 for (int m = 0; m < Dof; m++) 06439 { 06440 IntegrationPoint &ip = Nodes.IntPoint(m); 06441 poly1d.CalcBasis(p, ip.x, shape_x); 06442 poly1d.CalcBasis(p, ip.y, shape_y); 06443 poly1d.CalcBasis(p, ip.z, shape_z); 06444 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l); 06445 06446 o = 0; 06447 for (int k = 0; k <= p; k++) 06448 for (int j = 0; j + k <= p; j++) 06449 for (int i = 0; i + j + k <= p; i++) 06450 T(o++, m) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k); 06451 } 06452 06453 T.Invert(); 06454 // cout << "H1_TetrahedronElement(" << p << ") : "; T.TestInversion(); 06455 } 06456 06457 void H1_TetrahedronElement::CalcShape(const IntegrationPoint &ip, 06458 Vector &shape) const 06459 { 06460 const int p = Order; 06461 06462 #ifdef MFEM_USE_OPENMP 06463 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1); 06464 Vector u(Dof); 06465 #endif 06466 06467 poly1d.CalcBasis(p, ip.x, shape_x); 06468 poly1d.CalcBasis(p, ip.y, shape_y); 06469 poly1d.CalcBasis(p, ip.z, shape_z); 06470 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l); 06471 06472 for (int o = 0, k = 0; k <= p; k++) 06473 for (int j = 0; j + k <= p; j++) 06474 for (int i = 0; i + j + k <= p; i++) 06475 u(o++) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k); 06476 06477 T.Mult(u, shape); 06478 } 06479 06480 void H1_TetrahedronElement::CalcDShape(const IntegrationPoint &ip, 06481 DenseMatrix &dshape) const 06482 { 06483 const int p = Order; 06484 06485 #ifdef MFEM_USE_OPENMP 06486 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1); 06487 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1); 06488 DenseMatrix du(Dof, Dim); 06489 #endif 06490 06491 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x); 06492 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y); 06493 poly1d.CalcBasis(p, ip.z, shape_z, dshape_z); 06494 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l); 06495 06496 for (int o = 0, k = 0; k <= p; k++) 06497 for (int j = 0; j + k <= p; j++) 06498 for (int i = 0; i + j + k <= p; i++) 06499 { 06500 int l = p - i - j - k; 06501 du(o,0) = ((dshape_x(i)* shape_l(l)) - 06502 ( shape_x(i)*dshape_l(l)))*shape_y(j)*shape_z(k); 06503 du(o,1) = ((dshape_y(j)* shape_l(l)) - 06504 ( shape_y(j)*dshape_l(l)))*shape_x(i)*shape_z(k); 06505 du(o,2) = ((dshape_z(k)* shape_l(l)) - 06506 ( shape_z(k)*dshape_l(l)))*shape_x(i)*shape_y(j); 06507 o++; 06508 } 06509 06510 Mult(T, du, dshape); 06511 } 06512 06513 06514 L2_SegmentElement::L2_SegmentElement(const int p) 06515 : NodalFiniteElement(1, Geometry::SEGMENT, p + 1, p, FunctionSpace::Pk), 06516 basis1d(poly1d.OpenBasis(p)) 06517 { 06518 const double *op = poly1d.OpenPoints(p); 06519 06520 #ifndef MFEM_USE_OPENMP 06521 shape_x.SetSize(p + 1); 06522 dshape_x.SetDataAndSize(NULL, p + 1); 06523 #endif 06524 06525 for (int i = 0; i <= p; i++) 06526 Nodes.IntPoint(i).x = op[i]; 06527 } 06528 06529 void L2_SegmentElement::CalcShape(const IntegrationPoint &ip, 06530 Vector &shape) const 06531 { 06532 basis1d.Eval(ip.x, shape); 06533 } 06534 06535 void L2_SegmentElement::CalcDShape(const IntegrationPoint &ip, 06536 DenseMatrix &dshape) const 06537 { 06538 #ifdef MFEM_USE_OPENMP 06539 Vector shape_x(Dof), dshape_x(dshape.Data(), Dof); 06540 #else 06541 dshape_x.SetData(dshape.Data()); 06542 #endif 06543 basis1d.Eval(ip.x, shape_x, dshape_x); 06544 } 06545 06546 void L2_SegmentElement::ProjectDelta(int vertex, 06547 Vector &dofs) const 06548 { 06549 const int p = Order; 06550 const double *op = poly1d.OpenPoints(p); 06551 switch (vertex) 06552 { 06553 case 0: 06554 for (int i = 0; i <= p; i++) 06555 dofs(i) = poly1d.CalcDelta(p,(1.0 - op[i])); 06556 break; 06557 06558 case 1: 06559 for (int i = 0; i <= p; i++) 06560 dofs(i) = poly1d.CalcDelta(p,op[i]); 06561 break; 06562 } 06563 } 06564 06565 06566 L2_QuadrilateralElement::L2_QuadrilateralElement(const int p) 06567 : NodalFiniteElement(2, Geometry::SQUARE, (p + 1)*(p + 1), p, 06568 FunctionSpace::Qk), basis1d(poly1d.OpenBasis(p)) 06569 { 06570 const double *op = poly1d.OpenPoints(p); 06571 06572 #ifndef MFEM_USE_OPENMP 06573 shape_x.SetSize(p + 1); 06574 shape_y.SetSize(p + 1); 06575 dshape_x.SetSize(p + 1); 06576 dshape_y.SetSize(p + 1); 06577 #endif 06578 06579 for (int o = 0, j = 0; j <= p; j++) 06580 for (int i = 0; i <= p; i++) 06581 Nodes.IntPoint(o++).Set2(op[i], op[j]); 06582 } 06583 06584 void L2_QuadrilateralElement::CalcShape(const IntegrationPoint &ip, 06585 Vector &shape) const 06586 { 06587 const int p = Order; 06588 06589 #ifdef MFEM_USE_OPENMP 06590 Vector shape_x(p+1), shape_y(p+1); 06591 #endif 06592 06593 basis1d.Eval(ip.x, shape_x); 06594 basis1d.Eval(ip.y, shape_y); 06595 06596 for (int o = 0, j = 0; j <= p; j++) 06597 for (int i = 0; i <= p; i++) 06598 shape(o++) = shape_x(i)*shape_y(j); 06599 } 06600 06601 void L2_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip, 06602 DenseMatrix &dshape) const 06603 { 06604 const int p = Order; 06605 06606 #ifdef MFEM_USE_OPENMP 06607 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1); 06608 #endif 06609 06610 basis1d.Eval(ip.x, shape_x, dshape_x); 06611 basis1d.Eval(ip.y, shape_y, dshape_y); 06612 06613 for (int o = 0, j = 0; j <= p; j++) 06614 for (int i = 0; i <= p; i++) 06615 { 06616 dshape(o,0) = dshape_x(i)* shape_y(j); 06617 dshape(o,1) = shape_x(i)*dshape_y(j); o++; 06618 } 06619 } 06620 06621 void L2_QuadrilateralElement::ProjectDelta(int vertex, 06622 Vector &dofs) const 06623 { 06624 const int p = Order; 06625 const double *op = poly1d.OpenPoints(p); 06626 06627 #ifdef MFEM_USE_OPENMP 06628 Vector shape_x(p+1), shape_y(p+1); 06629 #endif 06630 06631 for (int i = 0; i <= p; i++) 06632 { 06633 shape_x(i) = poly1d.CalcDelta(p,(1.0 - op[i])); 06634 shape_y(i) = poly1d.CalcDelta(p,op[i]); 06635 } 06636 06637 switch (vertex) 06638 { 06639 case 0: 06640 for (int o = 0, j = 0; j <= p; j++) 06641 for (int i = 0; i <= p; i++) 06642 dofs[o++] = shape_x(i)*shape_x(j); 06643 break; 06644 case 1: 06645 for (int o = 0, j = 0; j <= p; j++) 06646 for (int i = 0; i <= p; i++) 06647 dofs[o++] = shape_y(i)*shape_x(j); 06648 break; 06649 case 2: 06650 for (int o = 0, j = 0; j <= p; j++) 06651 for (int i = 0; i <= p; i++) 06652 dofs[o++] = shape_y(i)*shape_y(j); 06653 break; 06654 case 3: 06655 for (int o = 0, j = 0; j <= p; j++) 06656 for (int i = 0; i <= p; i++) 06657 dofs[o++] = shape_x(i)*shape_y(j); 06658 break; 06659 } 06660 } 06661 06662 06663 L2_HexahedronElement::L2_HexahedronElement(const int p) 06664 : NodalFiniteElement(3, Geometry::CUBE, (p + 1)*(p + 1)*(p + 1), p, 06665 FunctionSpace::Qk), basis1d(poly1d.OpenBasis(p)) 06666 { 06667 const double *op = poly1d.OpenPoints(p); 06668 06669 #ifndef MFEM_USE_OPENMP 06670 shape_x.SetSize(p + 1); 06671 shape_y.SetSize(p + 1); 06672 shape_z.SetSize(p + 1); 06673 dshape_x.SetSize(p + 1); 06674 dshape_y.SetSize(p + 1); 06675 dshape_z.SetSize(p + 1); 06676 #endif 06677 06678 for (int o = 0, k = 0; k <= p; k++) 06679 for (int j = 0; j <= p; j++) 06680 for (int i = 0; i <= p; i++) 06681 Nodes.IntPoint(o++).Set3(op[i], op[j], op[k]); 06682 } 06683 06684 void L2_HexahedronElement::CalcShape(const IntegrationPoint &ip, 06685 Vector &shape) const 06686 { 06687 const int p = Order; 06688 06689 #ifdef MFEM_USE_OPENMP 06690 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1); 06691 #endif 06692 06693 basis1d.Eval(ip.x, shape_x); 06694 basis1d.Eval(ip.y, shape_y); 06695 basis1d.Eval(ip.z, shape_z); 06696 06697 for (int o = 0, k = 0; k <= p; k++) 06698 for (int j = 0; j <= p; j++) 06699 for (int i = 0; i <= p; i++) 06700 shape(o++) = shape_x(i)*shape_y(j)*shape_z(k); 06701 } 06702 06703 void L2_HexahedronElement::CalcDShape(const IntegrationPoint &ip, 06704 DenseMatrix &dshape) const 06705 { 06706 const int p = Order; 06707 06708 #ifdef MFEM_USE_OPENMP 06709 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1); 06710 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1); 06711 #endif 06712 06713 basis1d.Eval(ip.x, shape_x, dshape_x); 06714 basis1d.Eval(ip.y, shape_y, dshape_y); 06715 basis1d.Eval(ip.z, shape_z, dshape_z); 06716 06717 for (int o = 0, k = 0; k <= p; k++) 06718 for (int j = 0; j <= p; j++) 06719 for (int i = 0; i <= p; i++) 06720 { 06721 dshape(o,0) = dshape_x(i)* shape_y(j)* shape_z(k); 06722 dshape(o,1) = shape_x(i)*dshape_y(j)* shape_z(k); 06723 dshape(o,2) = shape_x(i)* shape_y(j)*dshape_z(k); o++; 06724 } 06725 } 06726 06727 void L2_HexahedronElement::ProjectDelta(int vertex, 06728 Vector &dofs) const 06729 { 06730 const int p = Order; 06731 const double *op = poly1d.OpenPoints(p); 06732 06733 #ifdef MFEM_USE_OPENMP 06734 Vector shape_x(p+1), shape_y(p+1); 06735 #endif 06736 06737 for (int i = 0; i <= p; i++) 06738 { 06739 shape_x(i) = poly1d.CalcDelta(p,(1.0 - op[i])); 06740 shape_y(i) = poly1d.CalcDelta(p,op[i]); 06741 } 06742 06743 switch (vertex) 06744 { 06745 case 0: 06746 for (int o = 0, k = 0; k <= p; k++) 06747 for (int j = 0; j <= p; j++) 06748 for (int i = 0; i <= p; i++) 06749 dofs[o++] = shape_x(i)*shape_x(j)*shape_x(k); 06750 break; 06751 case 1: 06752 for (int o = 0, k = 0; k <= p; k++) 06753 for (int j = 0; j <= p; j++) 06754 for (int i = 0; i <= p; i++) 06755 dofs[o++] = shape_y(i)*shape_x(j)*shape_x(k); 06756 break; 06757 case 2: 06758 for (int o = 0, k = 0; k <= p; k++) 06759 for (int j = 0; j <= p; j++) 06760 for (int i = 0; i <= p; i++) 06761 dofs[o++] = shape_y(i)*shape_y(j)*shape_x(k); 06762 break; 06763 case 3: 06764 for (int o = 0, k = 0; k <= p; k++) 06765 for (int j = 0; j <= p; j++) 06766 for (int i = 0; i <= p; i++) 06767 dofs[o++] = shape_x(i)*shape_y(j)*shape_x(k); 06768 break; 06769 case 4: 06770 for (int o = 0, k = 0; k <= p; k++) 06771 for (int j = 0; j <= p; j++) 06772 for (int i = 0; i <= p; i++) 06773 dofs[o++] = shape_x(i)*shape_x(j)*shape_y(k); 06774 break; 06775 case 5: 06776 for (int o = 0, k = 0; k <= p; k++) 06777 for (int j = 0; j <= p; j++) 06778 for (int i = 0; i <= p; i++) 06779 dofs[o++] = shape_y(i)*shape_x(j)*shape_y(k); 06780 break; 06781 case 6: 06782 for (int o = 0, k = 0; k <= p; k++) 06783 for (int j = 0; j <= p; j++) 06784 for (int i = 0; i <= p; i++) 06785 dofs[o++] = shape_y(i)*shape_y(j)*shape_y(k); 06786 break; 06787 case 7: 06788 for (int o = 0, k = 0; k <= p; k++) 06789 for (int j = 0; j <= p; j++) 06790 for (int i = 0; i <= p; i++) 06791 dofs[o++] = shape_x(i)*shape_y(j)*shape_y(k); 06792 break; 06793 } 06794 } 06795 06796 06797 L2_TriangleElement::L2_TriangleElement(const int p) 06798 : NodalFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p, 06799 FunctionSpace::Pk), T(Dof) 06800 { 06801 const double *op = poly1d.OpenPoints(p); 06802 06803 #ifndef MFEM_USE_OPENMP 06804 shape_x.SetSize(p + 1); 06805 shape_y.SetSize(p + 1); 06806 shape_l.SetSize(p + 1); 06807 dshape_x.SetSize(p + 1); 06808 dshape_y.SetSize(p + 1); 06809 dshape_l.SetSize(p + 1); 06810 u.SetSize(Dof); 06811 du.SetSize(Dof, Dim); 06812 #else 06813 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1); 06814 #endif 06815 06816 for (int o = 0, j = 0; j <= p; j++) 06817 for (int i = 0; i + j <= p; i++) 06818 { 06819 double w = op[i] + op[j] + op[p-i-j]; 06820 Nodes.IntPoint(o++).Set2(op[i]/w, op[j]/w); 06821 } 06822 06823 for (int k = 0; k < Dof; k++) 06824 { 06825 IntegrationPoint &ip = Nodes.IntPoint(k); 06826 poly1d.CalcBasis(p, ip.x, shape_x); 06827 poly1d.CalcBasis(p, ip.y, shape_y); 06828 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l); 06829 06830 for (int o = 0, j = 0; j <= p; j++) 06831 for (int i = 0; i + j <= p; i++) 06832 T(o++, k) = shape_x(i)*shape_y(j)*shape_l(p-i-j); 06833 } 06834 06835 T.Invert(); 06836 // cout << "L2_TriangleElement(" << p << ") : "; T.TestInversion(); 06837 } 06838 06839 void L2_TriangleElement::CalcShape(const IntegrationPoint &ip, 06840 Vector &shape) const 06841 { 06842 const int p = Order; 06843 06844 #ifdef MFEM_USE_OPENMP 06845 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1), u(Dof); 06846 #endif 06847 06848 poly1d.CalcBasis(p, ip.x, shape_x); 06849 poly1d.CalcBasis(p, ip.y, shape_y); 06850 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l); 06851 06852 for (int o = 0, j = 0; j <= p; j++) 06853 for (int i = 0; i + j <= p; i++) 06854 u(o++) = shape_x(i)*shape_y(j)*shape_l(p-i-j); 06855 06856 T.Mult(u, shape); 06857 } 06858 06859 void L2_TriangleElement::CalcDShape(const IntegrationPoint &ip, 06860 DenseMatrix &dshape) const 06861 { 06862 const int p = Order; 06863 06864 #ifdef MFEM_USE_OPENMP 06865 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1); 06866 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1); 06867 DenseMatrix du(Dof, Dim); 06868 #endif 06869 06870 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x); 06871 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y); 06872 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l); 06873 06874 for (int o = 0, j = 0; j <= p; j++) 06875 for (int i = 0; i + j <= p; i++) 06876 { 06877 int k = p - i - j; 06878 du(o,0) = ((dshape_x(i)* shape_l(k)) - 06879 ( shape_x(i)*dshape_l(k)))*shape_y(j); 06880 du(o,1) = ((dshape_y(j)* shape_l(k)) - 06881 ( shape_y(j)*dshape_l(k)))*shape_x(i); 06882 o++; 06883 } 06884 06885 Mult(T, du, dshape); 06886 } 06887 06888 06889 L2_TetrahedronElement::L2_TetrahedronElement(const int p) 06890 : NodalFiniteElement(3, Geometry::TETRAHEDRON, ((p + 1)*(p + 2)*(p + 3))/6, 06891 p, FunctionSpace::Pk), T(Dof) 06892 { 06893 const double *op = poly1d.OpenPoints(p); 06894 06895 #ifndef MFEM_USE_OPENMP 06896 shape_x.SetSize(p + 1); 06897 shape_y.SetSize(p + 1); 06898 shape_z.SetSize(p + 1); 06899 shape_l.SetSize(p + 1); 06900 dshape_x.SetSize(p + 1); 06901 dshape_y.SetSize(p + 1); 06902 dshape_z.SetSize(p + 1); 06903 dshape_l.SetSize(p + 1); 06904 u.SetSize(Dof); 06905 du.SetSize(Dof, Dim); 06906 #else 06907 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1); 06908 #endif 06909 06910 for (int o = 0, k = 0; k <= p; k++) 06911 for (int j = 0; j + k <= p; j++) 06912 for (int i = 0; i + j + k <= p; i++) 06913 { 06914 double w = op[i] + op[j] + op[k] + op[p-i-j-k]; 06915 Nodes.IntPoint(o++).Set3(op[i]/w, op[j]/w, op[k]/w); 06916 } 06917 06918 for (int m = 0; m < Dof; m++) 06919 { 06920 IntegrationPoint &ip = Nodes.IntPoint(m); 06921 poly1d.CalcBasis(p, ip.x, shape_x); 06922 poly1d.CalcBasis(p, ip.y, shape_y); 06923 poly1d.CalcBasis(p, ip.z, shape_z); 06924 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l); 06925 06926 for (int o = 0, k = 0; k <= p; k++) 06927 for (int j = 0; j + k <= p; j++) 06928 for (int i = 0; i + j + k <= p; i++) 06929 T(o++, m) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k); 06930 } 06931 06932 T.Invert(); 06933 // cout << "L2_TetrahedronElement(" << p << ") : "; T.TestInversion(); 06934 } 06935 06936 void L2_TetrahedronElement::CalcShape(const IntegrationPoint &ip, 06937 Vector &shape) const 06938 { 06939 const int p = Order; 06940 06941 #ifdef MFEM_USE_OPENMP 06942 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1); 06943 Vector u(Dof); 06944 #endif 06945 06946 poly1d.CalcBasis(p, ip.x, shape_x); 06947 poly1d.CalcBasis(p, ip.y, shape_y); 06948 poly1d.CalcBasis(p, ip.z, shape_z); 06949 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l); 06950 06951 for (int o = 0, k = 0; k <= p; k++) 06952 for (int j = 0; j + k <= p; j++) 06953 for (int i = 0; i + j + k <= p; i++) 06954 u(o++) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k); 06955 06956 T.Mult(u, shape); 06957 } 06958 06959 void L2_TetrahedronElement::CalcDShape(const IntegrationPoint &ip, 06960 DenseMatrix &dshape) const 06961 { 06962 const int p = Order; 06963 06964 #ifdef MFEM_USE_OPENMP 06965 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1); 06966 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1); 06967 DenseMatrix du(Dof, Dim); 06968 #endif 06969 06970 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x); 06971 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y); 06972 poly1d.CalcBasis(p, ip.z, shape_z, dshape_z); 06973 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l); 06974 06975 for (int o = 0, k = 0; k <= p; k++) 06976 for (int j = 0; j + k <= p; j++) 06977 for (int i = 0; i + j + k <= p; i++) 06978 { 06979 int l = p - i - j - k; 06980 du(o,0) = ((dshape_x(i)* shape_l(l)) - 06981 ( shape_x(i)*dshape_l(l)))*shape_y(j)*shape_z(k); 06982 du(o,1) = ((dshape_y(j)* shape_l(l)) - 06983 ( shape_y(j)*dshape_l(l)))*shape_x(i)*shape_z(k); 06984 du(o,2) = ((dshape_z(k)* shape_l(l)) - 06985 ( shape_z(k)*dshape_l(l)))*shape_x(i)*shape_y(j); 06986 o++; 06987 } 06988 06989 Mult(T, du, dshape); 06990 } 06991 06992 06993 const double RT_QuadrilateralElement::nk[8] = 06994 { 0., -1., 1., 0., 0., 1., -1., 0. }; 06995 06996 RT_QuadrilateralElement::RT_QuadrilateralElement(const int p) 06997 : VectorFiniteElement(2, Geometry::SQUARE, 2*(p + 1)*(p + 2), p + 1, 06998 FunctionSpace::Qk), 06999 cbasis1d(poly1d.ClosedBasis(p + 1)), obasis1d(poly1d.OpenBasis(p)), 07000 dof_map(Dof), dof2nk(Dof) 07001 { 07002 const double *cp = poly1d.ClosedPoints(p + 1); 07003 const double *op = poly1d.OpenPoints(p); 07004 const int dof2 = Dof/2; 07005 07006 #ifndef MFEM_USE_OPENMP 07007 shape_cx.SetSize(p + 2); 07008 shape_ox.SetSize(p + 1); 07009 shape_cy.SetSize(p + 2); 07010 shape_oy.SetSize(p + 1); 07011 dshape_cx.SetSize(p + 2); 07012 dshape_cy.SetSize(p + 2); 07013 #endif 07014 07015 // edges 07016 int o = 0; 07017 for (int i = 0; i <= p; i++) // (0,1) 07018 dof_map[1*dof2 + i + 0*(p + 1)] = o++; 07019 for (int i = 0; i <= p; i++) // (1,2) 07020 dof_map[0*dof2 + (p + 1) + i*(p + 2)] = o++; 07021 for (int i = 0; i <= p; i++) // (2,3) 07022 dof_map[1*dof2 + (p - i) + (p + 1)*(p + 1)] = o++; 07023 for (int i = 0; i <= p; i++) // (3,0) 07024 dof_map[0*dof2 + 0 + (p - i)*(p + 2)] = o++; 07025 07026 // interior 07027 for (int j = 0; j <= p; j++) // x-components 07028 for (int i = 1; i <= p; i++) 07029 dof_map[0*dof2 + i + j*(p + 2)] = o++; 07030 for (int j = 1; j <= p; j++) // y-components 07031 for (int i = 0; i <= p; i++) 07032 dof_map[1*dof2 + i + j*(p + 1)] = o++; 07033 07034 // dof orientations 07035 // x-components 07036 for (int j = 0; j <= p; j++) 07037 for (int i = 0; i <= p/2; i++) 07038 { 07039 int idx = 0*dof2 + i + j*(p + 2); 07040 dof_map[idx] = -1 - dof_map[idx]; 07041 } 07042 if (p%2 == 1) 07043 for (int j = p/2 + 1; j <= p; j++) 07044 { 07045 int idx = 0*dof2 + (p/2 + 1) + j*(p + 2); 07046 dof_map[idx] = -1 - dof_map[idx]; 07047 } 07048 // y-components 07049 for (int j = 0; j <= p/2; j++) 07050 for (int i = 0; i <= p; i++) 07051 { 07052 int idx = 1*dof2 + i + j*(p + 1); 07053 dof_map[idx] = -1 - dof_map[idx]; 07054 } 07055 if (p%2 == 1) 07056 for (int i = p/2 + 1; i <= p; i++) 07057 { 07058 int idx = 1*dof2 + i + (p/2 + 1)*(p + 1); 07059 dof_map[idx] = -1 - dof_map[idx]; 07060 } 07061 07062 o = 0; 07063 for (int j = 0; j <= p; j++) 07064 for (int i = 0; i <= p + 1; i++) 07065 { 07066 int idx; 07067 if ((idx = dof_map[o++]) < 0) 07068 { 07069 idx = -1 - idx; 07070 dof2nk[idx] = 3; 07071 } 07072 else 07073 { 07074 dof2nk[idx] = 1; 07075 } 07076 Nodes.IntPoint(idx).Set2(cp[i], op[j]); 07077 } 07078 for (int j = 0; j <= p + 1; j++) 07079 for (int i = 0; i <= p; i++) 07080 { 07081 int idx; 07082 if ((idx = dof_map[o++]) < 0) 07083 { 07084 idx = -1 - idx; 07085 dof2nk[idx] = 0; 07086 } 07087 else 07088 { 07089 dof2nk[idx] = 2; 07090 } 07091 Nodes.IntPoint(idx).Set2(op[i], cp[j]); 07092 } 07093 } 07094 07095 void RT_QuadrilateralElement::CalcVShape(const IntegrationPoint &ip, 07096 DenseMatrix &shape) const 07097 { 07098 const int pp1 = Order; 07099 07100 #ifdef MFEM_USE_OPENMP 07101 Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1); 07102 #endif 07103 07104 cbasis1d.Eval(ip.x, shape_cx); 07105 obasis1d.Eval(ip.x, shape_ox); 07106 cbasis1d.Eval(ip.y, shape_cy); 07107 obasis1d.Eval(ip.y, shape_oy); 07108 07109 int o = 0; 07110 for (int j = 0; j < pp1; j++) 07111 for (int i = 0; i <= pp1; i++) 07112 { 07113 int idx, s; 07114 if ((idx = dof_map[o++]) < 0) 07115 idx = -1 - idx, s = -1; 07116 else 07117 s = +1; 07118 shape(idx,0) = s*shape_cx(i)*shape_oy(j); 07119 shape(idx,1) = 0.; 07120 } 07121 for (int j = 0; j <= pp1; j++) 07122 for (int i = 0; i < pp1; i++) 07123 { 07124 int idx, s; 07125 if ((idx = dof_map[o++]) < 0) 07126 idx = -1 - idx, s = -1; 07127 else 07128 s = +1; 07129 shape(idx,0) = 0.; 07130 shape(idx,1) = s*shape_ox(i)*shape_cy(j); 07131 } 07132 } 07133 07134 void RT_QuadrilateralElement::CalcDivShape(const IntegrationPoint &ip, 07135 Vector &divshape) const 07136 { 07137 const int pp1 = Order; 07138 07139 #ifdef MFEM_USE_OPENMP 07140 Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1); 07141 Vector dshape_cx(pp1 + 1), dshape_cy(pp1 + 1); 07142 #endif 07143 07144 cbasis1d.Eval(ip.x, shape_cx, dshape_cx); 07145 obasis1d.Eval(ip.x, shape_ox); 07146 cbasis1d.Eval(ip.y, shape_cy, dshape_cy); 07147 obasis1d.Eval(ip.y, shape_oy); 07148 07149 int o = 0; 07150 for (int j = 0; j < pp1; j++) 07151 for (int i = 0; i <= pp1; i++) 07152 { 07153 int idx, s; 07154 if ((idx = dof_map[o++]) < 0) 07155 idx = -1 - idx, s = -1; 07156 else 07157 s = +1; 07158 divshape(idx) = s*dshape_cx(i)*shape_oy(j); 07159 } 07160 for (int j = 0; j <= pp1; j++) 07161 for (int i = 0; i < pp1; i++) 07162 { 07163 int idx, s; 07164 if ((idx = dof_map[o++]) < 0) 07165 idx = -1 - idx, s = -1; 07166 else 07167 s = +1; 07168 divshape(idx) = s*shape_ox(i)*dshape_cy(j); 07169 } 07170 } 07171 07172 07173 const double RT_HexahedronElement::nk[18] = 07174 { 0.,0.,-1., 0.,-1.,0., 1.,0.,0., 0.,1.,0., -1.,0.,0., 0.,0.,1. }; 07175 07176 RT_HexahedronElement::RT_HexahedronElement(const int p) 07177 : VectorFiniteElement(3, Geometry::CUBE, 3*(p + 1)*(p + 1)*(p + 2), p + 1, 07178 FunctionSpace::Qk), 07179 cbasis1d(poly1d.ClosedBasis(p + 1)), obasis1d(poly1d.OpenBasis(p)), 07180 dof_map(Dof), dof2nk(Dof) 07181 { 07182 const double *cp = poly1d.ClosedPoints(p + 1); 07183 const double *op = poly1d.OpenPoints(p); 07184 const int dof3 = Dof/3; 07185 07186 #ifndef MFEM_USE_OPENMP 07187 shape_cx.SetSize(p + 2); 07188 shape_ox.SetSize(p + 1); 07189 shape_cy.SetSize(p + 2); 07190 shape_oy.SetSize(p + 1); 07191 shape_cz.SetSize(p + 2); 07192 shape_oz.SetSize(p + 1); 07193 dshape_cx.SetSize(p + 2); 07194 dshape_cy.SetSize(p + 2); 07195 dshape_cz.SetSize(p + 2); 07196 #endif 07197 07198 // faces 07199 int o = 0; 07200 for (int j = 0; j <= p; j++) // (3,2,1,0) -- bottom 07201 for (int i = 0; i <= p; i++) 07202 dof_map[2*dof3 + i + ((p - j) + 0*(p + 1))*(p + 1)] = o++; 07203 for (int j = 0; j <= p; j++) // (0,1,5,4) -- front 07204 for (int i = 0; i <= p; i++) 07205 dof_map[1*dof3 + i + (0 + j*(p + 2))*(p + 1)] = o++; 07206 for (int j = 0; j <= p; j++) // (1,2,6,5) -- right 07207 for (int i = 0; i <= p; i++) 07208 dof_map[0*dof3 + (p + 1) + (i + j*(p + 1))*(p + 2)] = o++; 07209 for (int j = 0; j <= p; j++) // (2,3,7,6) -- back 07210 for (int i = 0; i <= p; i++) 07211 dof_map[1*dof3 + (p - i) + ((p + 1) + j*(p + 2))*(p + 1)] = o++; 07212 for (int j = 0; j <= p; j++) // (3,0,4,7) -- left 07213 for (int i = 0; i <= p; i++) 07214 dof_map[0*dof3 + 0 + ((p - i) + j*(p + 1))*(p + 2)] = o++; 07215 for (int j = 0; j <= p; j++) // (4,5,6,7) -- top 07216 for (int i = 0; i <= p; i++) 07217 dof_map[2*dof3 + i + (j + (p + 1)*(p + 1))*(p + 1)] = o++; 07218 07219 // interior 07220 // x-components 07221 for (int k = 0; k <= p; k++) 07222 for (int j = 0; j <= p; j++) 07223 for (int i = 1; i <= p; i++) 07224 dof_map[0*dof3 + i + (j + k*(p + 1))*(p + 2)] = o++; 07225 // y-components 07226 for (int k = 0; k <= p; k++) 07227 for (int j = 1; j <= p; j++) 07228 for (int i = 0; i <= p; i++) 07229 dof_map[1*dof3 + i + (j + k*(p + 2))*(p + 1)] = o++; 07230 // z-components 07231 for (int k = 1; k <= p; k++) 07232 for (int j = 0; j <= p; j++) 07233 for (int i = 0; i <= p; i++) 07234 dof_map[2*dof3 + i + (j + k*(p + 1))*(p + 1)] = o++; 07235 07236 // dof orientations 07237 // for odd p, do not change the orientations in the mid-planes 07238 // {i = p/2 + 1}, {j = p/2 + 1}, {k = p/2 + 1} in the x, y, z-components 07239 // respectively. 07240 // x-components 07241 for (int k = 0; k <= p; k++) 07242 for (int j = 0; j <= p; j++) 07243 for (int i = 0; i <= p/2; i++) 07244 { 07245 int idx = 0*dof3 + i + (j + k*(p + 1))*(p + 2); 07246 dof_map[idx] = -1 - dof_map[idx]; 07247 } 07248 // y-components 07249 for (int k = 0; k <= p; k++) 07250 for (int j = 0; j <= p/2; j++) 07251 for (int i = 0; i <= p; i++) 07252 { 07253 int idx = 1*dof3 + i + (j + k*(p + 2))*(p + 1); 07254 dof_map[idx] = -1 - dof_map[idx]; 07255 } 07256 // z-components 07257 for (int k = 0; k <= p/2; k++) 07258 for (int j = 0; j <= p; j++) 07259 for (int i = 0; i <= p; i++) 07260 { 07261 int idx = 2*dof3 + i + (j + k*(p + 1))*(p + 1); 07262 dof_map[idx] = -1 - dof_map[idx]; 07263 } 07264 07265 o = 0; 07266 // x-components 07267 for (int k = 0; k <= p; k++) 07268 for (int j = 0; j <= p; j++) 07269 for (int i = 0; i <= p + 1; i++) 07270 { 07271 int idx; 07272 if ((idx = dof_map[o++]) < 0) 07273 { 07274 idx = -1 - idx; 07275 dof2nk[idx] = 4; 07276 } 07277 else 07278 { 07279 dof2nk[idx] = 2; 07280 } 07281 Nodes.IntPoint(idx).Set3(cp[i], op[j], op[k]); 07282 } 07283 // y-components 07284 for (int k = 0; k <= p; k++) 07285 for (int j = 0; j <= p + 1; j++) 07286 for (int i = 0; i <= p; i++) 07287 { 07288 int idx; 07289 if ((idx = dof_map[o++]) < 0) 07290 { 07291 idx = -1 - idx; 07292 dof2nk[idx] = 1; 07293 } 07294 else 07295 { 07296 dof2nk[idx] = 3; 07297 } 07298 Nodes.IntPoint(idx).Set3(op[i], cp[j], op[k]); 07299 } 07300 // z-components 07301 for (int k = 0; k <= p + 1; k++) 07302 for (int j = 0; j <= p; j++) 07303 for (int i = 0; i <= p; i++) 07304 { 07305 int idx; 07306 if ((idx = dof_map[o++]) < 0) 07307 { 07308 idx = -1 - idx; 07309 dof2nk[idx] = 0; 07310 } 07311 else 07312 { 07313 dof2nk[idx] = 5; 07314 } 07315 Nodes.IntPoint(idx).Set3(op[i], op[j], cp[k]); 07316 } 07317 } 07318 07319 void RT_HexahedronElement::CalcVShape(const IntegrationPoint &ip, 07320 DenseMatrix &shape) const 07321 { 07322 const int pp1 = Order; 07323 07324 #ifdef MFEM_USE_OPENMP 07325 Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1); 07326 Vector shape_cz(pp1 + 1), shape_oz(pp1); 07327 #endif 07328 07329 cbasis1d.Eval(ip.x, shape_cx); 07330 obasis1d.Eval(ip.x, shape_ox); 07331 cbasis1d.Eval(ip.y, shape_cy); 07332 obasis1d.Eval(ip.y, shape_oy); 07333 cbasis1d.Eval(ip.z, shape_cz); 07334 obasis1d.Eval(ip.z, shape_oz); 07335 07336 int o = 0; 07337 // x-components 07338 for (int k = 0; k < pp1; k++) 07339 for (int j = 0; j < pp1; j++) 07340 for (int i = 0; i <= pp1; i++) 07341 { 07342 int idx, s; 07343 if ((idx = dof_map[o++]) < 0) 07344 idx = -1 - idx, s = -1; 07345 else 07346 s = +1; 07347 shape(idx,0) = s*shape_cx(i)*shape_oy(j)*shape_oz(k); 07348 shape(idx,1) = 0.; 07349 shape(idx,2) = 0.; 07350 } 07351 // y-components 07352 for (int k = 0; k < pp1; k++) 07353 for (int j = 0; j <= pp1; j++) 07354 for (int i = 0; i < pp1; i++) 07355 { 07356 int idx, s; 07357 if ((idx = dof_map[o++]) < 0) 07358 idx = -1 - idx, s = -1; 07359 else 07360 s = +1; 07361 shape(idx,0) = 0.; 07362 shape(idx,1) = s*shape_ox(i)*shape_cy(j)*shape_oz(k); 07363 shape(idx,2) = 0.; 07364 } 07365 // z-components 07366 for (int k = 0; k <= pp1; k++) 07367 for (int j = 0; j < pp1; j++) 07368 for (int i = 0; i < pp1; i++) 07369 { 07370 int idx, s; 07371 if ((idx = dof_map[o++]) < 0) 07372 idx = -1 - idx, s = -1; 07373 else 07374 s = +1; 07375 shape(idx,0) = 0.; 07376 shape(idx,1) = 0.; 07377 shape(idx,2) = s*shape_ox(i)*shape_oy(j)*shape_cz(k); 07378 } 07379 } 07380 07381 void RT_HexahedronElement::CalcDivShape(const IntegrationPoint &ip, 07382 Vector &divshape) const 07383 { 07384 const int pp1 = Order; 07385 07386 #ifdef MFEM_USE_OPENMP 07387 Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1); 07388 Vector shape_cz(pp1 + 1), shape_oz(pp1); 07389 Vector dshape_cx(pp1 + 1), dshape_cy(pp1 + 1), dshape_cz(pp1 + 1); 07390 #endif 07391 07392 cbasis1d.Eval(ip.x, shape_cx, dshape_cx); 07393 obasis1d.Eval(ip.x, shape_ox); 07394 cbasis1d.Eval(ip.y, shape_cy, dshape_cy); 07395 obasis1d.Eval(ip.y, shape_oy); 07396 cbasis1d.Eval(ip.z, shape_cz, dshape_cz); 07397 obasis1d.Eval(ip.z, shape_oz); 07398 07399 int o = 0; 07400 // x-components 07401 for (int k = 0; k < pp1; k++) 07402 for (int j = 0; j < pp1; j++) 07403 for (int i = 0; i <= pp1; i++) 07404 { 07405 int idx, s; 07406 if ((idx = dof_map[o++]) < 0) 07407 idx = -1 - idx, s = -1; 07408 else 07409 s = +1; 07410 divshape(idx) = s*dshape_cx(i)*shape_oy(j)*shape_oz(k); 07411 } 07412 // y-components 07413 for (int k = 0; k < pp1; k++) 07414 for (int j = 0; j <= pp1; j++) 07415 for (int i = 0; i < pp1; i++) 07416 { 07417 int idx, s; 07418 if ((idx = dof_map[o++]) < 0) 07419 idx = -1 - idx, s = -1; 07420 else 07421 s = +1; 07422 divshape(idx) = s*shape_ox(i)*dshape_cy(j)*shape_oz(k); 07423 } 07424 // z-components 07425 for (int k = 0; k <= pp1; k++) 07426 for (int j = 0; j < pp1; j++) 07427 for (int i = 0; i < pp1; i++) 07428 { 07429 int idx, s; 07430 if ((idx = dof_map[o++]) < 0) 07431 idx = -1 - idx, s = -1; 07432 else 07433 s = +1; 07434 divshape(idx) = s*shape_ox(i)*shape_oy(j)*dshape_cz(k); 07435 } 07436 } 07437 07438 07439 const double RT_TriangleElement::nk[6] = 07440 { 0., -1., 1., 1., -1., 0. }; 07441 07442 const double RT_TriangleElement::c = 1./3.; 07443 07444 RT_TriangleElement::RT_TriangleElement(const int p) 07445 : VectorFiniteElement(2, Geometry::TRIANGLE, (p + 1)*(p + 3), p + 1, 07446 FunctionSpace::Pk), dof2nk(Dof), T(Dof) 07447 { 07448 const double *iop = (p > 0) ? poly1d.OpenPoints(p - 1) : NULL; 07449 const double *bop = poly1d.OpenPoints(p); 07450 07451 #ifndef MFEM_USE_OPENMP 07452 shape_x.SetSize(p + 1); 07453 shape_y.SetSize(p + 1); 07454 shape_l.SetSize(p + 1); 07455 dshape_x.SetSize(p + 1); 07456 dshape_y.SetSize(p + 1); 07457 dshape_l.SetSize(p + 1); 07458 u.SetSize(Dof, Dim); 07459 divu.SetSize(Dof); 07460 #else 07461 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1); 07462 #endif 07463 07464 // edges 07465 int o = 0; 07466 for (int i = 0; i <= p; i++) // (0,1) 07467 { 07468 Nodes.IntPoint(o).Set2(bop[i], 0.); 07469 dof2nk[o++] = 0; 07470 } 07471 for (int i = 0; i <= p; i++) // (1,2) 07472 { 07473 Nodes.IntPoint(o).Set2(bop[p-i], bop[i]); 07474 dof2nk[o++] = 1; 07475 } 07476 for (int i = 0; i <= p; i++) // (2,0) 07477 { 07478 Nodes.IntPoint(o).Set2(0., bop[p-i]); 07479 dof2nk[o++] = 2; 07480 } 07481 07482 // interior 07483 for (int j = 0; j < p; j++) 07484 for (int i = 0; i + j < p; i++) 07485 { 07486 double w = iop[i] + iop[j] + iop[p-1-i-j]; 07487 Nodes.IntPoint(o).Set2(iop[i]/w, iop[j]/w); 07488 dof2nk[o++] = 0; 07489 Nodes.IntPoint(o).Set2(iop[i]/w, iop[j]/w); 07490 dof2nk[o++] = 2; 07491 } 07492 07493 for (int k = 0; k < Dof; k++) 07494 { 07495 const IntegrationPoint &ip = Nodes.IntPoint(k); 07496 poly1d.CalcBasis(p, ip.x, shape_x); 07497 poly1d.CalcBasis(p, ip.y, shape_y); 07498 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l); 07499 const double *n_k = nk + 2*dof2nk[k]; 07500 07501 o = 0; 07502 for (int j = 0; j <= p; j++) 07503 for (int i = 0; i + j <= p; i++) 07504 { 07505 double s = shape_x(i)*shape_y(j)*shape_l(p-i-j); 07506 T(o++, k) = s*n_k[0]; 07507 T(o++, k) = s*n_k[1]; 07508 } 07509 for (int i = 0; i <= p; i++) 07510 { 07511 double s = shape_x(i)*shape_y(p-i); 07512 T(o++, k) = s*((ip.x - c)*n_k[0] + (ip.y - c)*n_k[1]); 07513 } 07514 } 07515 07516 T.Invert(); 07517 // cout << "RT_TriangleElement(" << p << ") : "; T.TestInversion(); 07518 } 07519 07520 void RT_TriangleElement::CalcVShape(const IntegrationPoint &ip, 07521 DenseMatrix &shape) const 07522 { 07523 const int p = Order - 1; 07524 07525 #ifdef MFEM_USE_OPENMP 07526 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1); 07527 DenseMatrix u(Dof, Dim); 07528 #endif 07529 07530 poly1d.CalcBasis(p, ip.x, shape_x); 07531 poly1d.CalcBasis(p, ip.y, shape_y); 07532 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l); 07533 07534 int o = 0; 07535 for (int j = 0; j <= p; j++) 07536 for (int i = 0; i + j <= p; i++) 07537 { 07538 double s = shape_x(i)*shape_y(j)*shape_l(p-i-j); 07539 u(o,0) = s; u(o,1) = 0; o++; 07540 u(o,0) = 0; u(o,1) = s; o++; 07541 } 07542 for (int i = 0; i <= p; i++) 07543 { 07544 double s = shape_x(i)*shape_y(p-i); 07545 u(o,0) = (ip.x - c)*s; u(o,1) = (ip.y - c)*s; o++; 07546 } 07547 07548 Mult(T, u, shape); 07549 } 07550 07551 void RT_TriangleElement::CalcDivShape(const IntegrationPoint &ip, 07552 Vector &divshape) const 07553 { 07554 const int p = Order - 1; 07555 07556 #ifdef MFEM_USE_OPENMP 07557 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1); 07558 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1); 07559 Vector divu(Dof); 07560 #endif 07561 07562 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x); 07563 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y); 07564 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l); 07565 07566 int o = 0; 07567 for (int j = 0; j <= p; j++) 07568 for (int i = 0; i + j <= p; i++) 07569 { 07570 int k = p - i - j; 07571 divu(o++) = (dshape_x(i)*shape_l(k) - 07572 shape_x(i)*dshape_l(k))*shape_y(j); 07573 divu(o++) = (dshape_y(j)*shape_l(k) - 07574 shape_y(j)*dshape_l(k))*shape_x(i); 07575 } 07576 for (int i = 0; i <= p; i++) 07577 { 07578 int j = p - i; 07579 divu(o++) = ((shape_x(i) + (ip.x - c)*dshape_x(i))*shape_y(j) + 07580 (shape_y(j) + (ip.y - c)*dshape_y(j))*shape_x(i)); 07581 } 07582 07583 T.Mult(divu, divshape); 07584 } 07585 07586 07587 const double RT_TetrahedronElement::nk[12] = 07588 { 1,1,1, -1,0,0, 0,-1,0, 0,0,-1 }; 07589 // { .5,.5,.5, -.5,0,0, 0,-.5,0, 0,0,-.5}; // n_F |F| 07590 07591 const double RT_TetrahedronElement::c = 1./4.; 07592 07593 RT_TetrahedronElement::RT_TetrahedronElement(const int p) 07594 : VectorFiniteElement(3, Geometry::TETRAHEDRON, (p + 1)*(p + 2)*(p + 4)/2, 07595 p + 1, FunctionSpace::Pk), dof2nk(Dof), T(Dof) 07596 { 07597 const double *iop = (p > 0) ? poly1d.OpenPoints(p - 1) : NULL; 07598 const double *bop = poly1d.OpenPoints(p); 07599 07600 #ifndef MFEM_USE_OPENMP 07601 shape_x.SetSize(p + 1); 07602 shape_y.SetSize(p + 1); 07603 shape_z.SetSize(p + 1); 07604 shape_l.SetSize(p + 1); 07605 dshape_x.SetSize(p + 1); 07606 dshape_y.SetSize(p + 1); 07607 dshape_z.SetSize(p + 1); 07608 dshape_l.SetSize(p + 1); 07609 u.SetSize(Dof, Dim); 07610 divu.SetSize(Dof); 07611 #else 07612 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1); 07613 #endif 07614 07615 int o = 0; 07616 // faces (see Mesh::GenerateFaces in mesh/mesh.cpp, 07617 // the constructor of H1_TetrahedronElement) 07618 for (int j = 0; j <= p; j++) 07619 for (int i = 0; i + j <= p; i++) // (1,2,3) 07620 { 07621 double w = bop[i] + bop[j] + bop[p-i-j]; 07622 Nodes.IntPoint(o).Set3(bop[p-i-j]/w, bop[i]/w, bop[j]/w); 07623 dof2nk[o++] = 0; 07624 } 07625 for (int j = 0; j <= p; j++) 07626 for (int i = 0; i + j <= p; i++) // (0,3,2) 07627 { 07628 double w = bop[i] + bop[j] + bop[p-i-j]; 07629 Nodes.IntPoint(o).Set3(0., bop[j]/w, bop[i]/w); 07630 dof2nk[o++] = 1; 07631 } 07632 for (int j = 0; j <= p; j++) 07633 for (int i = 0; i + j <= p; i++) // (0,1,3) 07634 { 07635 double w = bop[i] + bop[j] + bop[p-i-j]; 07636 Nodes.IntPoint(o).Set3(bop[i]/w, 0., bop[j]/w); 07637 dof2nk[o++] = 2; 07638 } 07639 for (int j = 0; j <= p; j++) 07640 for (int i = 0; i + j <= p; i++) // (0,2,1) 07641 { 07642 double w = bop[i] + bop[j] + bop[p-i-j]; 07643 Nodes.IntPoint(o).Set3(bop[j]/w, bop[i]/w, 0.); 07644 dof2nk[o++] = 3; 07645 } 07646 07647 // interior 07648 for (int k = 0; k < p; k++) 07649 for (int j = 0; j + k < p; j++) 07650 for (int i = 0; i + j + k < p; i++) 07651 { 07652 double w = iop[i] + iop[j] + iop[k] + iop[p-1-i-j-k]; 07653 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w); 07654 dof2nk[o++] = 1; 07655 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w); 07656 dof2nk[o++] = 2; 07657 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w); 07658 dof2nk[o++] = 3; 07659 } 07660 07661 for (int m = 0; m < Dof; m++) 07662 { 07663 const IntegrationPoint &ip = Nodes.IntPoint(m); 07664 poly1d.CalcBasis(p, ip.x, shape_x); 07665 poly1d.CalcBasis(p, ip.y, shape_y); 07666 poly1d.CalcBasis(p, ip.z, shape_z); 07667 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l); 07668 const double *nm = nk + 3*dof2nk[m]; 07669 07670 o = 0; 07671 for (int k = 0; k <= p; k++) 07672 for (int j = 0; j + k <= p; j++) 07673 for (int i = 0; i + j + k <= p; i++) 07674 { 07675 double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k); 07676 T(o++, m) = s * nm[0]; 07677 T(o++, m) = s * nm[1]; 07678 T(o++, m) = s * nm[2]; 07679 } 07680 for (int j = 0; j <= p; j++) 07681 for (int i = 0; i + j <= p; i++) 07682 { 07683 double s = shape_x(i)*shape_y(j)*shape_z(p-i-j); 07684 T(o++, m) = s*((ip.x - c)*nm[0] + (ip.y - c)*nm[1] + 07685 (ip.z - c)*nm[2]); 07686 } 07687 } 07688 07689 T.Invert(); 07690 // cout << "RT_TetrahedronElement(" << p << ") : "; T.TestInversion(); 07691 } 07692 07693 void RT_TetrahedronElement::CalcVShape(const IntegrationPoint &ip, 07694 DenseMatrix &shape) const 07695 { 07696 const int p = Order - 1; 07697 07698 #ifdef MFEM_USE_OPENMP 07699 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1); 07700 DenseMatrix u(Dof, Dim); 07701 #endif 07702 07703 poly1d.CalcBasis(p, ip.x, shape_x); 07704 poly1d.CalcBasis(p, ip.y, shape_y); 07705 poly1d.CalcBasis(p, ip.z, shape_z); 07706 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l); 07707 07708 int o = 0; 07709 for (int k = 0; k <= p; k++) 07710 for (int j = 0; j + k <= p; j++) 07711 for (int i = 0; i + j + k <= p; i++) 07712 { 07713 double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k); 07714 u(o,0) = s; u(o,1) = 0; u(o,2) = 0; o++; 07715 u(o,0) = 0; u(o,1) = s; u(o,2) = 0; o++; 07716 u(o,0) = 0; u(o,1) = 0; u(o,2) = s; o++; 07717 } 07718 for (int j = 0; j <= p; j++) 07719 for (int i = 0; i + j <= p; i++) 07720 { 07721 double s = shape_x(i)*shape_y(j)*shape_z(p-i-j); 07722 u(o,0) = (ip.x - c)*s; u(o,1) = (ip.y - c)*s; u(o,2) = (ip.z - c)*s; 07723 o++; 07724 } 07725 07726 Mult(T, u, shape); 07727 } 07728 07729 void RT_TetrahedronElement::CalcDivShape(const IntegrationPoint &ip, 07730 Vector &divshape) const 07731 { 07732 const int p = Order - 1; 07733 07734 #ifdef MFEM_USE_OPENMP 07735 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1); 07736 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1); 07737 Vector divu(Dof); 07738 #endif 07739 07740 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x); 07741 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y); 07742 poly1d.CalcBasis(p, ip.z, shape_z, dshape_z); 07743 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l); 07744 07745 int o = 0; 07746 for (int k = 0; k <= p; k++) 07747 for (int j = 0; j + k <= p; j++) 07748 for (int i = 0; i + j + k <= p; i++) 07749 { 07750 int l = p - i - j - k; 07751 divu(o++) = (dshape_x(i)*shape_l(l) - 07752 shape_x(i)*dshape_l(l))*shape_y(j)*shape_z(k); 07753 divu(o++) = (dshape_y(j)*shape_l(l) - 07754 shape_y(j)*dshape_l(l))*shape_x(i)*shape_z(k); 07755 divu(o++) = (dshape_z(k)*shape_l(l) - 07756 shape_z(k)*dshape_l(l))*shape_x(i)*shape_y(j); 07757 } 07758 for (int j = 0; j <= p; j++) 07759 for (int i = 0; i + j <= p; i++) 07760 { 07761 int k = p - i - j; 07762 divu(o++) = 07763 (shape_x(i) + (ip.x - c)*dshape_x(i))*shape_y(j)*shape_z(k) + 07764 (shape_y(j) + (ip.y - c)*dshape_y(j))*shape_x(i)*shape_z(k) + 07765 (shape_z(k) + (ip.z - c)*dshape_z(k))*shape_x(i)*shape_y(j); 07766 } 07767 07768 T.Mult(divu, divshape); 07769 } 07770 07771 07772 const double ND_HexahedronElement::tk[18] = 07773 { 1.,0.,0., 0.,1.,0., 0.,0.,1., -1.,0.,0., 0.,-1.,0., 0.,0.,-1. }; 07774 07775 ND_HexahedronElement::ND_HexahedronElement(const int p) 07776 : VectorFiniteElement(3, Geometry::CUBE, 3*p*(p + 1)*(p + 1), p, 07777 FunctionSpace::Qk), 07778 cbasis1d(poly1d.ClosedBasis(p)), obasis1d(poly1d.OpenBasis(p - 1)), 07779 dof_map(Dof), dof2tk(Dof) 07780 { 07781 const double *cp = poly1d.ClosedPoints(p); 07782 const double *op = poly1d.OpenPoints(p - 1); 07783 const int dof3 = Dof/3; 07784 07785 #ifndef MFEM_USE_OPENMP 07786 shape_cx.SetSize(p + 1); 07787 shape_ox.SetSize(p); 07788 shape_cy.SetSize(p + 1); 07789 shape_oy.SetSize(p); 07790 shape_cz.SetSize(p + 1); 07791 shape_oz.SetSize(p); 07792 dshape_cx.SetSize(p + 1); 07793 dshape_cy.SetSize(p + 1); 07794 dshape_cz.SetSize(p + 1); 07795 #endif 07796 07797 // edges 07798 int o = 0; 07799 for (int i = 0; i < p; i++) // (0,1) 07800 dof_map[0*dof3 + i + (0 + 0*(p + 1))*p] = o++; 07801 for (int i = 0; i < p; i++) // (1,2) 07802 dof_map[1*dof3 + p + (i + 0*p)*(p + 1)] = o++; 07803 for (int i = 0; i < p; i++) // (3,2) 07804 dof_map[0*dof3 + i + (p + 0*(p + 1))*p] = o++; 07805 for (int i = 0; i < p; i++) // (0,3) 07806 dof_map[1*dof3 + 0 + (i + 0*p)*(p + 1)] = o++; 07807 for (int i = 0; i < p; i++) // (4,5) 07808 dof_map[0*dof3 + i + (0 + p*(p + 1))*p] = o++; 07809 for (int i = 0; i < p; i++) // (5,6) 07810 dof_map[1*dof3 + p + (i + p*p)*(p + 1)] = o++; 07811 for (int i = 0; i < p; i++) // (7,6) 07812 dof_map[0*dof3 + i + (p + p*(p + 1))*p] = o++; 07813 for (int i = 0; i < p; i++) // (4,7) 07814 dof_map[1*dof3 + 0 + (i + p*p)*(p + 1)] = o++; 07815 for (int i = 0; i < p; i++) // (0,4) 07816 dof_map[2*dof3 + 0 + (0 + i*(p + 1))*(p + 1)] = o++; 07817 for (int i = 0; i < p; i++) // (1,5) 07818 dof_map[2*dof3 + p + (0 + i*(p + 1))*(p + 1)] = o++; 07819 for (int i = 0; i < p; i++) // (2,6) 07820 dof_map[2*dof3 + p + (p + i*(p + 1))*(p + 1)] = o++; 07821 for (int i = 0; i < p; i++) // (3,7) 07822 dof_map[2*dof3 + 0 + (p + i*(p + 1))*(p + 1)] = o++; 07823 07824 // faces 07825 // (3,2,1,0) -- bottom 07826 for (int j = 1; j < p; j++) // x - components 07827 for (int i = 0; i < p; i++) 07828 dof_map[0*dof3 + i + ((p - j) + 0*(p + 1))*p] = o++; 07829 for (int j = 0; j < p; j++) // y - components 07830 for (int i = 1; i < p; i++) 07831 dof_map[1*dof3 + i + ((p - 1 - j) + 0*p)*(p + 1)] = -1 - (o++); 07832 // (0,1,5,4) -- front 07833 for (int k = 1; k < p; k++) // x - components 07834 for (int i = 0; i < p; i++) 07835 dof_map[0*dof3 + i + (0 + k*(p + 1))*p] = o++; 07836 for (int k = 0; k < p; k++) // z - components 07837 for (int i = 1; i < p; i++ ) 07838 dof_map[2*dof3 + i + (0 + k*(p + 1))*(p + 1)] = o++; 07839 // (1,2,6,5) -- right 07840 for (int k = 1; k < p; k++) // y - components 07841 for (int j = 0; j < p; j++) 07842 dof_map[1*dof3 + p + (j + k*p)*(p + 1)] = o++; 07843 for (int k = 0; k < p; k++) // z - components 07844 for (int j = 1; j < p; j++) 07845 dof_map[2*dof3 + p + (j + k*(p + 1))*(p + 1)] = o++; 07846 // (2,3,7,6) -- back 07847 for (int k = 1; k < p; k++) // x - components 07848 for (int i = 0; i < p; i++) 07849 dof_map[0*dof3 + (p - 1 - i) + (p + k*(p + 1))*p] = -1 - (o++); 07850 for (int k = 0; k < p; k++) // z - components 07851 for (int i = 1; i < p; i++) 07852 dof_map[2*dof3 + (p - i) + (p + k*(p + 1))*(p + 1)] = o++; 07853 // (3,0,4,7) -- left 07854 for (int k = 1; k < p; k++) // y - components 07855 for (int j = 0; j < p; j++) 07856 dof_map[1*dof3 + 0 + ((p - 1 - j) + k*p)*(p + 1)] = -1 - (o++); 07857 for (int k = 0; k < p; k++) // z - components 07858 for (int j = 1; j < p; j++) 07859 dof_map[2*dof3 + 0 + ((p - j) + k*(p + 1))*(p + 1)] = o++; 07860 // (4,5,6,7) -- top 07861 for (int j = 1; j < p; j++) // x - components 07862 for (int i = 0; i < p; i++) 07863 dof_map[0*dof3 + i + (j + p*(p + 1))*p] = o++; 07864 for (int j = 0; j < p; j++) // y - components 07865 for (int i = 1; i < p; i++) 07866 dof_map[1*dof3 + i + (j + p*p)*(p + 1)] = o++; 07867 07868 // interior 07869 // x-components 07870 for (int k = 1; k < p; k++) 07871 for (int j = 1; j < p; j++) 07872 for (int i = 0; i < p; i++) 07873 dof_map[0*dof3 + i + (j + k*(p + 1))*p] = o++; 07874 // y-components 07875 for (int k = 1; k < p; k++) 07876 for (int j = 0; j < p; j++) 07877 for (int i = 1; i < p; i++) 07878 dof_map[1*dof3 + i + (j + k*p)*(p + 1)] = o++; 07879 // z-components 07880 for (int k = 0; k < p; k++) 07881 for (int j = 1; j < p; j++) 07882 for (int i = 1; i < p; i++) 07883 dof_map[2*dof3 + i + (j + k*(p + 1))*(p + 1)] = o++; 07884 07885 // set dof2tk and Nodes 07886 o = 0; 07887 // x-components 07888 for (int k = 0; k <= p; k++) 07889 for (int j = 0; j <= p; j++) 07890 for (int i = 0; i < p; i++) 07891 { 07892 int idx; 07893 if ((idx = dof_map[o++]) < 0) 07894 dof2tk[idx = -1 - idx] = 3; 07895 else 07896 dof2tk[idx] = 0; 07897 Nodes.IntPoint(idx).Set3(op[i], cp[j], cp[k]); 07898 } 07899 // y-components 07900 for (int k = 0; k <= p; k++) 07901 for (int j = 0; j < p; j++) 07902 for (int i = 0; i <= p; i++) 07903 { 07904 int idx; 07905 if ((idx = dof_map[o++]) < 0) 07906 dof2tk[idx = -1 - idx] = 4; 07907 else 07908 dof2tk[idx] = 1; 07909 Nodes.IntPoint(idx).Set3(cp[i], op[j], cp[k]); 07910 } 07911 // z-components 07912 for (int k = 0; k < p; k++) 07913 for (int j = 0; j <= p; j++) 07914 for (int i = 0; i <= p; i++) 07915 { 07916 int idx; 07917 if ((idx = dof_map[o++]) < 0) 07918 dof2tk[idx = -1 - idx] = 5; 07919 else 07920 dof2tk[idx] = 2; 07921 Nodes.IntPoint(idx).Set3(cp[i], cp[j], op[k]); 07922 } 07923 } 07924 07925 void ND_HexahedronElement::CalcVShape(const IntegrationPoint &ip, 07926 DenseMatrix &shape) const 07927 { 07928 const int p = Order; 07929 07930 #ifdef MFEM_USE_OPENMP 07931 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p); 07932 Vector shape_cz(p + 1), shape_oz(p); 07933 #endif 07934 07935 cbasis1d.Eval(ip.x, shape_cx); 07936 obasis1d.Eval(ip.x, shape_ox); 07937 cbasis1d.Eval(ip.y, shape_cy); 07938 obasis1d.Eval(ip.y, shape_oy); 07939 cbasis1d.Eval(ip.z, shape_cz); 07940 obasis1d.Eval(ip.z, shape_oz); 07941 07942 int o = 0; 07943 // x-components 07944 for (int k = 0; k <= p; k++) 07945 for (int j = 0; j <= p; j++) 07946 for (int i = 0; i < p; i++) 07947 { 07948 int idx, s; 07949 if ((idx = dof_map[o++]) < 0) 07950 idx = -1 - idx, s = -1; 07951 else 07952 s = +1; 07953 shape(idx,0) = s*shape_ox(i)*shape_cy(j)*shape_cz(k); 07954 shape(idx,1) = 0.; 07955 shape(idx,2) = 0.; 07956 } 07957 // y-components 07958 for (int k = 0; k <= p; k++) 07959 for (int j = 0; j < p; j++) 07960 for (int i = 0; i <= p; i++) 07961 { 07962 int idx, s; 07963 if ((idx = dof_map[o++]) < 0) 07964 idx = -1 - idx, s = -1; 07965 else 07966 s = +1; 07967 shape(idx,0) = 0.; 07968 shape(idx,1) = s*shape_cx(i)*shape_oy(j)*shape_cz(k); 07969 shape(idx,2) = 0.; 07970 } 07971 // z-components 07972 for (int k = 0; k < p; k++) 07973 for (int j = 0; j <= p; j++) 07974 for (int i = 0; i <= p; i++) 07975 { 07976 int idx, s; 07977 if ((idx = dof_map[o++]) < 0) 07978 idx = -1 - idx, s = -1; 07979 else 07980 s = +1; 07981 shape(idx,0) = 0.; 07982 shape(idx,1) = 0.; 07983 shape(idx,2) = s*shape_cx(i)*shape_cy(j)*shape_oz(k); 07984 } 07985 } 07986 07987 void ND_HexahedronElement::CalcCurlShape(const IntegrationPoint &ip, 07988 DenseMatrix &curl_shape) const 07989 { 07990 const int p = Order; 07991 07992 #ifdef MFEM_USE_OPENMP 07993 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p); 07994 Vector shape_cz(p + 1), shape_oz(p); 07995 Vector dshape_cx(p + 1), dshape_cy(p + 1), dshape_cz(p + 1); 07996 #endif 07997 07998 cbasis1d.Eval(ip.x, shape_cx, dshape_cx); 07999 obasis1d.Eval(ip.x, shape_ox); 08000 cbasis1d.Eval(ip.y, shape_cy, dshape_cy); 08001 obasis1d.Eval(ip.y, shape_oy); 08002 cbasis1d.Eval(ip.z, shape_cz, dshape_cz); 08003 obasis1d.Eval(ip.z, shape_oz); 08004 08005 int o = 0; 08006 // x-components 08007 for (int k = 0; k <= p; k++) 08008 for (int j = 0; j <= p; j++) 08009 for (int i = 0; i < p; i++) 08010 { 08011 int idx, s; 08012 if ((idx = dof_map[o++]) < 0) 08013 idx = -1 - idx, s = -1; 08014 else 08015 s = +1; 08016 curl_shape(idx,0) = 0.; 08017 curl_shape(idx,1) = s*shape_ox(i)* shape_cy(j)*dshape_cz(k); 08018 curl_shape(idx,2) = -s*shape_ox(i)*dshape_cy(j)* shape_cz(k); 08019 } 08020 // y-components 08021 for (int k = 0; k <= p; k++) 08022 for (int j = 0; j < p; j++) 08023 for (int i = 0; i <= p; i++) 08024 { 08025 int idx, s; 08026 if ((idx = dof_map[o++]) < 0) 08027 idx = -1 - idx, s = -1; 08028 else 08029 s = +1; 08030 curl_shape(idx,0) = -s* shape_cx(i)*shape_oy(j)*dshape_cz(k); 08031 curl_shape(idx,1) = 0.; 08032 curl_shape(idx,2) = s*dshape_cx(i)*shape_oy(j)* shape_cz(k); 08033 } 08034 // z-components 08035 for (int k = 0; k < p; k++) 08036 for (int j = 0; j <= p; j++) 08037 for (int i = 0; i <= p; i++) 08038 { 08039 int idx, s; 08040 if ((idx = dof_map[o++]) < 0) 08041 idx = -1 - idx, s = -1; 08042 else 08043 s = +1; 08044 curl_shape(idx,0) = s* shape_cx(i)*dshape_cy(j)*shape_oz(k); 08045 curl_shape(idx,1) = -s*dshape_cx(i)* shape_cy(j)*shape_oz(k); 08046 curl_shape(idx,2) = 0.; 08047 } 08048 } 08049 08050 08051 const double ND_QuadrilateralElement::tk[8] = 08052 { 1.,0., 0.,1., -1.,0., 0.,-1. }; 08053 08054 ND_QuadrilateralElement::ND_QuadrilateralElement(const int p) 08055 : VectorFiniteElement(2, Geometry::SQUARE, 2*p*(p + 1), p, 08056 FunctionSpace::Qk), 08057 cbasis1d(poly1d.ClosedBasis(p)), obasis1d(poly1d.OpenBasis(p - 1)), 08058 dof_map(Dof), dof2tk(Dof) 08059 { 08060 const double *cp = poly1d.ClosedPoints(p); 08061 const double *op = poly1d.OpenPoints(p - 1); 08062 const int dof2 = Dof/2; 08063 08064 #ifndef MFEM_USE_OPENMP 08065 shape_cx.SetSize(p + 1); 08066 shape_ox.SetSize(p); 08067 shape_cy.SetSize(p + 1); 08068 shape_oy.SetSize(p); 08069 dshape_cx.SetSize(p + 1); 08070 dshape_cy.SetSize(p + 1); 08071 #endif 08072 08073 // edges 08074 int o = 0; 08075 for (int i = 0; i < p; i++) // (0,1) 08076 dof_map[0*dof2 + i + 0*p] = o++; 08077 for (int j = 0; j < p; j++) // (1,2) 08078 dof_map[1*dof2 + p + j*(p + 1)] = o++; 08079 for (int i = 0; i < p; i++) // (2,3) 08080 dof_map[0*dof2 + (p - 1 - i) + p*p] = -1 - (o++); 08081 for (int j = 0; j < p; j++) // (3,0) 08082 dof_map[1*dof2 + 0 + (p - 1 - j)*(p + 1)] = -1 - (o++); 08083 08084 // interior 08085 // x-components 08086 for (int j = 1; j < p; j++) 08087 for (int i = 0; i < p; i++) 08088 dof_map[0*dof2 + i + j*p] = o++; 08089 // y-components 08090 for (int j = 0; j < p; j++) 08091 for (int i = 1; i < p; i++) 08092 dof_map[1*dof2 + i + j*(p + 1)] = o++; 08093 08094 // set dof2tk and Nodes 08095 o = 0; 08096 // x-components 08097 for (int j = 0; j <= p; j++) 08098 for (int i = 0; i < p; i++) 08099 { 08100 int idx; 08101 if ((idx = dof_map[o++]) < 0) 08102 dof2tk[idx = -1 - idx] = 2; 08103 else 08104 dof2tk[idx] = 0; 08105 Nodes.IntPoint(idx).Set2(op[i], cp[j]); 08106 } 08107 // y-components 08108 for (int j = 0; j < p; j++) 08109 for (int i = 0; i <= p; i++) 08110 { 08111 int idx; 08112 if ((idx = dof_map[o++]) < 0) 08113 dof2tk[idx = -1 - idx] = 3; 08114 else 08115 dof2tk[idx] = 1; 08116 Nodes.IntPoint(idx).Set2(cp[i], op[j]); 08117 } 08118 } 08119 08120 void ND_QuadrilateralElement::CalcVShape(const IntegrationPoint &ip, 08121 DenseMatrix &shape) const 08122 { 08123 const int p = Order; 08124 08125 #ifdef MFEM_USE_OPENMP 08126 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p); 08127 #endif 08128 08129 cbasis1d.Eval(ip.x, shape_cx); 08130 obasis1d.Eval(ip.x, shape_ox); 08131 cbasis1d.Eval(ip.y, shape_cy); 08132 obasis1d.Eval(ip.y, shape_oy); 08133 08134 int o = 0; 08135 // x-components 08136 for (int j = 0; j <= p; j++) 08137 for (int i = 0; i < p; i++) 08138 { 08139 int idx, s; 08140 if ((idx = dof_map[o++]) < 0) 08141 idx = -1 - idx, s = -1; 08142 else 08143 s = +1; 08144 shape(idx,0) = s*shape_ox(i)*shape_cy(j); 08145 shape(idx,1) = 0.; 08146 } 08147 // y-components 08148 for (int j = 0; j < p; j++) 08149 for (int i = 0; i <= p; i++) 08150 { 08151 int idx, s; 08152 if ((idx = dof_map[o++]) < 0) 08153 idx = -1 - idx, s = -1; 08154 else 08155 s = +1; 08156 shape(idx,0) = 0.; 08157 shape(idx,1) = s*shape_cx(i)*shape_oy(j); 08158 } 08159 } 08160 08161 void ND_QuadrilateralElement::CalcCurlShape(const IntegrationPoint &ip, 08162 DenseMatrix &curl_shape) const 08163 { 08164 mfem_error("ND_QuadrilateralElement::CalcCurlShape"); 08165 } 08166 08167 08168 const double ND_TetrahedronElement::tk[18] = 08169 { 1.,0.,0., 0.,1.,0., 0.,0.,1., -1.,1.,0., -1.,0.,1., 0.,-1.,1. }; 08170 08171 const double ND_TetrahedronElement::c = 1./4.; 08172 08173 ND_TetrahedronElement::ND_TetrahedronElement(const int p) 08174 : VectorFiniteElement(3, Geometry::TETRAHEDRON, p*(p + 2)*(p + 3)/2, p, 08175 FunctionSpace::Pk), dof2tk(Dof), T(Dof) 08176 { 08177 const double *eop = poly1d.OpenPoints(p - 1); 08178 const double *fop = (p > 1) ? poly1d.OpenPoints(p - 2) : NULL; 08179 const double *iop = (p > 2) ? poly1d.OpenPoints(p - 3) : NULL; 08180 08181 const int pm1 = p - 1, pm2 = p - 2, pm3 = p - 3; 08182 08183 #ifndef MFEM_USE_OPENMP 08184 shape_x.SetSize(p); 08185 shape_y.SetSize(p); 08186 shape_z.SetSize(p); 08187 shape_l.SetSize(p); 08188 dshape_x.SetSize(p); 08189 dshape_y.SetSize(p); 08190 dshape_z.SetSize(p); 08191 dshape_l.SetSize(p); 08192 u.SetSize(Dof, Dim); 08193 #else 08194 Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p); 08195 #endif 08196 08197 int o = 0; 08198 // edges 08199 for (int i = 0; i < p; i++) // (0,1) 08200 { 08201 Nodes.IntPoint(o).Set3(eop[i], 0., 0.); 08202 dof2tk[o++] = 0; 08203 } 08204 for (int i = 0; i < p; i++) // (0,2) 08205 { 08206 Nodes.IntPoint(o).Set3(0., eop[i], 0.); 08207 dof2tk[o++] = 1; 08208 } 08209 for (int i = 0; i < p; i++) // (0,3) 08210 { 08211 Nodes.IntPoint(o).Set3(0., 0., eop[i]); 08212 dof2tk[o++] = 2; 08213 } 08214 for (int i = 0; i < p; i++) // (1,2) 08215 { 08216 Nodes.IntPoint(o).Set3(eop[pm1-i], eop[i], 0.); 08217 dof2tk[o++] = 3; 08218 } 08219 for (int i = 0; i < p; i++) // (1,3) 08220 { 08221 Nodes.IntPoint(o).Set3(eop[pm1-i], 0., eop[i]); 08222 dof2tk[o++] = 4; 08223 } 08224 for (int i = 0; i < p; i++) // (2,3) 08225 { 08226 Nodes.IntPoint(o).Set3(0., eop[pm1-i], eop[i]); 08227 dof2tk[o++] = 5; 08228 } 08229 08230 // faces 08231 for (int j = 0; j <= pm2; j++) // (1,2,3) 08232 for (int i = 0; i + j <= pm2; i++) 08233 { 08234 double w = fop[i] + fop[j] + fop[pm2-i-j]; 08235 Nodes.IntPoint(o).Set3(fop[pm2-i-j]/w, fop[i]/w, fop[j]/w); 08236 dof2tk[o++] = 3; 08237 Nodes.IntPoint(o).Set3(fop[pm2-i-j]/w, fop[i]/w, fop[j]/w); 08238 dof2tk[o++] = 4; 08239 } 08240 for (int j = 0; j <= pm2; j++) // (0,3,2) 08241 for (int i = 0; i + j <= pm2; i++) 08242 { 08243 double w = fop[i] + fop[j] + fop[pm2-i-j]; 08244 Nodes.IntPoint(o).Set3(0., fop[j]/w, fop[i]/w); 08245 dof2tk[o++] = 2; 08246 Nodes.IntPoint(o).Set3(0., fop[j]/w, fop[i]/w); 08247 dof2tk[o++] = 1; 08248 } 08249 for (int j = 0; j <= pm2; j++) // (0,1,3) 08250 for (int i = 0; i + j <= pm2; i++) 08251 { 08252 double w = fop[i] + fop[j] + fop[pm2-i-j]; 08253 Nodes.IntPoint(o).Set3(fop[i]/w, 0., fop[j]/w); 08254 dof2tk[o++] = 0; 08255 Nodes.IntPoint(o).Set3(fop[i]/w, 0., fop[j]/w); 08256 dof2tk[o++] = 2; 08257 } 08258 for (int j = 0; j <= pm2; j++) // (0,2,1) 08259 for (int i = 0; i + j <= pm2; i++) 08260 { 08261 double w = fop[i] + fop[j] + fop[pm2-i-j]; 08262 Nodes.IntPoint(o).Set3(fop[j]/w, fop[i]/w, 0.); 08263 dof2tk[o++] = 1; 08264 Nodes.IntPoint(o).Set3(fop[j]/w, fop[i]/w, 0.); 08265 dof2tk[o++] = 0; 08266 } 08267 08268 // interior 08269 for (int k = 0; k <= pm3; k++) 08270 for (int j = 0; j + k <= pm3; j++) 08271 for (int i = 0; i + j + k <= pm3; i++) 08272 { 08273 double w = iop[i] + iop[j] + iop[k] + iop[pm3-i-j-k]; 08274 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w); 08275 dof2tk[o++] = 0; 08276 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w); 08277 dof2tk[o++] = 1; 08278 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w); 08279 dof2tk[o++] = 2; 08280 } 08281 08282 for (int m = 0; m < Dof; m++) 08283 { 08284 const IntegrationPoint &ip = Nodes.IntPoint(m); 08285 const double *tm = tk + 3*dof2tk[m]; 08286 o = 0; 08287 08288 poly1d.CalcBasis(pm1, ip.x, shape_x); 08289 poly1d.CalcBasis(pm1, ip.y, shape_y); 08290 poly1d.CalcBasis(pm1, ip.z, shape_z); 08291 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l); 08292 08293 for (int k = 0; k <= pm1; k++) 08294 for (int j = 0; j + k <= pm1; j++) 08295 for (int i = 0; i + j + k <= pm1; i++) 08296 { 08297 double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(pm1-i-j-k); 08298 T(o++, m) = s * tm[0]; 08299 T(o++, m) = s * tm[1]; 08300 T(o++, m) = s * tm[2]; 08301 } 08302 for (int k = 0; k <= pm1; k++) 08303 for (int j = 0; j + k <= pm1; j++) 08304 { 08305 double s = shape_x(pm1-j-k)*shape_y(j)*shape_z(k); 08306 T(o++, m) = s*((ip.y - c)*tm[0] - (ip.x - c)*tm[1]); 08307 T(o++, m) = s*((ip.z - c)*tm[0] - (ip.x - c)*tm[2]); 08308 } 08309 for (int k = 0; k <= pm1; k++) 08310 { 08311 T(o++, m) = 08312 shape_y(pm1-k)*shape_z(k)*((ip.z - c)*tm[1] - (ip.y - c)*tm[2]); 08313 } 08314 } 08315 08316 T.Invert(); 08317 // cout << "ND_TetrahedronElement(" << p << ") : "; T.TestInversion(); 08318 } 08319 08320 void ND_TetrahedronElement::CalcVShape(const IntegrationPoint &ip, 08321 DenseMatrix &shape) const 08322 { 08323 const int pm1 = Order - 1; 08324 08325 #ifdef MFEM_USE_OPENMP 08326 const int p = Order; 08327 Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p); 08328 DenseMatrix u(Dof, Dim); 08329 #endif 08330 08331 poly1d.CalcBasis(pm1, ip.x, shape_x); 08332 poly1d.CalcBasis(pm1, ip.y, shape_y); 08333 poly1d.CalcBasis(pm1, ip.z, shape_z); 08334 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l); 08335 08336 int n = 0; 08337 for (int k = 0; k <= pm1; k++) 08338 for (int j = 0; j + k <= pm1; j++) 08339 for (int i = 0; i + j + k <= pm1; i++) 08340 { 08341 double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(pm1-i-j-k); 08342 u(n,0) = s; u(n,1) = 0.; u(n,2) = 0.; n++; 08343 u(n,0) = 0.; u(n,1) = s; u(n,2) = 0.; n++; 08344 u(n,0) = 0.; u(n,1) = 0.; u(n,2) = s; n++; 08345 } 08346 for (int k = 0; k <= pm1; k++) 08347 for (int j = 0; j + k <= pm1; j++) 08348 { 08349 double s = shape_x(pm1-j-k)*shape_y(j)*shape_z(k); 08350 u(n,0) = s*(ip.y - c); u(n,1) = -s*(ip.x - c); u(n,2) = 0.; n++; 08351 u(n,0) = s*(ip.z - c); u(n,1) = 0.; u(n,2) = -s*(ip.x - c); n++; 08352 } 08353 for (int k = 0; k <= pm1; k++) 08354 { 08355 double s = shape_y(pm1-k)*shape_z(k); 08356 u(n,0) = 0.; u(n,1) = s*(ip.z - c); u(n,2) = -s*(ip.y - c); n++; 08357 } 08358 08359 Mult(T, u, shape); 08360 } 08361 08362 void ND_TetrahedronElement::CalcCurlShape(const IntegrationPoint &ip, 08363 DenseMatrix &curl_shape) const 08364 { 08365 const int pm1 = Order - 1; 08366 08367 #ifdef MFEM_USE_OPENMP 08368 const int p = Order; 08369 Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p); 08370 Vector dshape_x(p), dshape_y(p), dshape_z(p), dshape_l(p); 08371 DenseMatrix u(Dof, Dim); 08372 #endif 08373 08374 poly1d.CalcBasis(pm1, ip.x, shape_x, dshape_x); 08375 poly1d.CalcBasis(pm1, ip.y, shape_y, dshape_y); 08376 poly1d.CalcBasis(pm1, ip.z, shape_z, dshape_z); 08377 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l); 08378 08379 int n = 0; 08380 for (int k = 0; k <= pm1; k++) 08381 for (int j = 0; j + k <= pm1; j++) 08382 for (int i = 0; i + j + k <= pm1; i++) 08383 { 08384 int l = pm1-i-j-k; 08385 const double dx = (dshape_x(i)*shape_l(l) - 08386 shape_x(i)*dshape_l(l))*shape_y(j)*shape_z(k); 08387 const double dy = (dshape_y(j)*shape_l(l) - 08388 shape_y(j)*dshape_l(l))*shape_x(i)*shape_z(k); 08389 const double dz = (dshape_z(k)*shape_l(l) - 08390 shape_z(k)*dshape_l(l))*shape_x(i)*shape_y(j); 08391 08392 u(n,0) = 0.; u(n,1) = dz; u(n,2) = -dy; n++; 08393 u(n,0) = -dz; u(n,1) = 0.; u(n,2) = dx; n++; 08394 u(n,0) = dy; u(n,1) = -dx; u(n,2) = 0.; n++; 08395 } 08396 for (int k = 0; k <= pm1; k++) 08397 for (int j = 0; j + k <= pm1; j++) 08398 { 08399 int i = pm1 - j - k; 08400 // s = shape_x(i)*shape_y(j)*shape_z(k); 08401 // curl of s*(ip.y - c, -(ip.x - c), 0): 08402 u(n,0) = shape_x(i)*(ip.x - c)*shape_y(j)*dshape_z(k); 08403 u(n,1) = shape_x(i)*shape_y(j)*(ip.y - c)*dshape_z(k); 08404 u(n,2) = 08405 -((dshape_x(i)*(ip.x - c) + shape_x(i))*shape_y(j)*shape_z(k) + 08406 (dshape_y(j)*(ip.y - c) + shape_y(j))*shape_x(i)*shape_z(k)); 08407 n++; 08408 // curl of s*(ip.z - c, 0, -(ip.x - c)): 08409 u(n,0) = -shape_x(i)*(ip.x - c)*dshape_y(j)*shape_z(k); 08410 u(n,1) = (shape_x(i)*shape_y(j)*(dshape_z(k)*(ip.z - c) + shape_z(k)) + 08411 (dshape_x(i)*(ip.x - c) + shape_x(i))*shape_y(j)*shape_z(k)); 08412 u(n,2) = -shape_x(i)*dshape_y(j)*shape_z(k)*(ip.z - c); 08413 n++; 08414 } 08415 for (int k = 0; k <= pm1; k++) 08416 { 08417 int j = pm1 - k; 08418 // curl of shape_y(j)*shape_z(k)*(0, ip.z - c, -(ip.y - c)): 08419 u(n,0) = -((dshape_y(j)*(ip.y - c) + shape_y(j))*shape_z(k) + 08420 shape_y(j)*(dshape_z(k)*(ip.z - c) + shape_z(k))); 08421 u(n,1) = 0.; 08422 u(n,2) = 0.; n++; 08423 } 08424 08425 Mult(T, u, curl_shape); 08426 } 08427 08428 08429 const double ND_TriangleElement::tk[8] = 08430 { 1.,0., -1.,1., 0.,-1., 0.,1. }; 08431 08432 const double ND_TriangleElement::c = 1./3.; 08433 08434 ND_TriangleElement::ND_TriangleElement(const int p) 08435 : VectorFiniteElement(2, Geometry::TRIANGLE, p*(p + 2), p, 08436 FunctionSpace::Pk), dof2tk(Dof), T(Dof) 08437 { 08438 const double *eop = poly1d.OpenPoints(p - 1); 08439 const double *iop = (p > 1) ? poly1d.OpenPoints(p - 2) : NULL; 08440 08441 const int pm1 = p - 1, pm2 = p - 2; 08442 08443 #ifndef MFEM_USE_OPENMP 08444 shape_x.SetSize(p); 08445 shape_y.SetSize(p); 08446 shape_l.SetSize(p); 08447 dshape_x.SetSize(p); 08448 dshape_y.SetSize(p); 08449 dshape_l.SetSize(p); 08450 u.SetSize(Dof, Dim); 08451 #else 08452 Vector shape_x(p), shape_y(p), shape_l(p); 08453 #endif 08454 08455 int n = 0; 08456 // edges 08457 for (int i = 0; i < p; i++) // (0,1) 08458 { 08459 Nodes.IntPoint(n).Set2(eop[i], 0.); 08460 dof2tk[n++] = 0; 08461 } 08462 for (int i = 0; i < p; i++) // (1,2) 08463 { 08464 Nodes.IntPoint(n).Set2(eop[pm1-i], eop[i]); 08465 dof2tk[n++] = 1; 08466 } 08467 for (int i = 0; i < p; i++) // (2,0) 08468 { 08469 Nodes.IntPoint(n).Set2(0., eop[pm1-i]); 08470 dof2tk[n++] = 2; 08471 } 08472 08473 // interior 08474 for (int j = 0; j <= pm2; j++) 08475 for (int i = 0; i + j <= pm2; i++) 08476 { 08477 double w = iop[i] + iop[j] + iop[pm2-i-j]; 08478 Nodes.IntPoint(n).Set2(iop[i]/w, iop[j]/w); 08479 dof2tk[n++] = 0; 08480 Nodes.IntPoint(n).Set2(iop[i]/w, iop[j]/w); 08481 dof2tk[n++] = 3; 08482 } 08483 08484 for (int m = 0; m < Dof; m++) 08485 { 08486 const IntegrationPoint &ip = Nodes.IntPoint(m); 08487 const double *tm = tk + 2*dof2tk[m]; 08488 n = 0; 08489 08490 poly1d.CalcBasis(pm1, ip.x, shape_x); 08491 poly1d.CalcBasis(pm1, ip.y, shape_y); 08492 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l); 08493 08494 for (int j = 0; j <= pm1; j++) 08495 for (int i = 0; i + j <= pm1; i++) 08496 { 08497 double s = shape_x(i)*shape_y(j)*shape_l(pm1-i-j); 08498 T(n++, m) = s * tm[0]; 08499 T(n++, m) = s * tm[1]; 08500 } 08501 for (int j = 0; j <= pm1; j++) 08502 { 08503 T(n++ ,m) = 08504 shape_x(pm1-j)*shape_y(j)*((ip.y - c)*tm[0] - (ip.x - c)*tm[1]); 08505 } 08506 } 08507 08508 T.Invert(); 08509 // cout << "ND_TriangleElement(" << p << ") : "; T.TestInversion(); 08510 } 08511 08512 void ND_TriangleElement::CalcVShape(const IntegrationPoint &ip, 08513 DenseMatrix &shape) const 08514 { 08515 const int pm1 = Order - 1; 08516 08517 #ifdef MFEM_USE_OPENMP 08518 const int p = Order; 08519 Vector shape_x(p), shape_y(p), shape_l(p); 08520 DenseMatrix u(Dof, Dim); 08521 #endif 08522 08523 poly1d.CalcBasis(pm1, ip.x, shape_x); 08524 poly1d.CalcBasis(pm1, ip.y, shape_y); 08525 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l); 08526 08527 int n = 0; 08528 for (int j = 0; j <= pm1; j++) 08529 for (int i = 0; i + j <= pm1; i++) 08530 { 08531 double s = shape_x(i)*shape_y(j)*shape_l(pm1-i-j); 08532 u(n,0) = s; u(n,1) = 0.; n++; 08533 u(n,0) = 0.; u(n,1) = s; n++; 08534 } 08535 for (int j = 0; j <= pm1; j++) 08536 { 08537 double s = shape_x(pm1-j)*shape_y(j); 08538 u(n,0) = s*(ip.y - c); 08539 u(n,1) = -s*(ip.x - c); 08540 } 08541 08542 Mult(T, u, shape); 08543 } 08544 08545 void ND_TriangleElement::CalcCurlShape(const IntegrationPoint &ip, 08546 DenseMatrix &curl_shape) const 08547 { 08548 mfem_error("ND_TriangleElement::CalcCurlShape"); 08549 } 08550 08551 08552 void NURBS1DFiniteElement::CalcShape(const IntegrationPoint &ip, 08553 Vector &shape) const 08554 { 08555 kv[0]->CalcShape(shape, ijk[0], ip.x); 08556 08557 double sum = 0.0; 08558 for (int i = 0; i <= Order; i++) 08559 sum += (shape(i) *= weights(i)); 08560 08561 shape /= sum; 08562 } 08563 08564 void NURBS1DFiniteElement::CalcDShape(const IntegrationPoint &ip, 08565 DenseMatrix &dshape) const 08566 { 08567 Vector grad(dshape.Data(), Dof); 08568 08569 kv[0]->CalcShape (shape_x, ijk[0], ip.x); 08570 kv[0]->CalcDShape(grad, ijk[0], ip.x); 08571 08572 double sum = 0.0, dsum = 0.0; 08573 for (int i = 0; i <= Order; i++) 08574 { 08575 sum += (shape_x(i) *= weights(i)); 08576 dsum += ( grad(i) *= weights(i)); 08577 } 08578 08579 sum = 1.0/sum; 08580 add(sum, grad, -dsum*sum*sum, shape_x, grad); 08581 } 08582 08583 void NURBS2DFiniteElement::CalcShape(const IntegrationPoint &ip, 08584 Vector &shape) const 08585 { 08586 kv[0]->CalcShape(shape_x, ijk[0], ip.x); 08587 kv[1]->CalcShape(shape_y, ijk[1], ip.y); 08588 08589 double sum = 0.0; 08590 for (int o = 0, j = 0; j <= Order; j++) 08591 { 08592 const double sy = shape_y(j); 08593 for (int i = 0; i <= Order; i++, o++) 08594 { 08595 sum += ( shape(o) = shape_x(i)*sy*weights(o) ); 08596 } 08597 } 08598 08599 shape /= sum; 08600 } 08601 08602 void NURBS2DFiniteElement::CalcDShape(const IntegrationPoint &ip, 08603 DenseMatrix &dshape) const 08604 { 08605 double sum, dsum[2]; 08606 08607 kv[0]->CalcShape ( shape_x, ijk[0], ip.x); 08608 kv[1]->CalcShape ( shape_y, ijk[1], ip.y); 08609 08610 kv[0]->CalcDShape(dshape_x, ijk[0], ip.x); 08611 kv[1]->CalcDShape(dshape_y, ijk[1], ip.y); 08612 08613 sum = dsum[0] = dsum[1] = 0.0; 08614 for (int o = 0, j = 0; j <= Order; j++) 08615 { 08616 const double sy = shape_y(j), dsy = dshape_y(j); 08617 for (int i = 0; i <= Order; i++, o++) 08618 { 08619 sum += ( u(o) = shape_x(i)*sy*weights(o) ); 08620 08621 dsum[0] += ( dshape(o,0) = dshape_x(i)*sy *weights(o) ); 08622 dsum[1] += ( dshape(o,1) = shape_x(i)*dsy*weights(o) ); 08623 } 08624 } 08625 08626 sum = 1.0/sum; 08627 dsum[0] *= sum*sum; 08628 dsum[1] *= sum*sum; 08629 08630 for (int o = 0; o < Dof; o++) 08631 { 08632 dshape(o,0) = dshape(o,0)*sum - u(o)*dsum[0]; 08633 dshape(o,1) = dshape(o,1)*sum - u(o)*dsum[1]; 08634 } 08635 } 08636 08637 void NURBS3DFiniteElement::CalcShape(const IntegrationPoint &ip, 08638 Vector &shape) const 08639 { 08640 kv[0]->CalcShape(shape_x, ijk[0], ip.x); 08641 kv[1]->CalcShape(shape_y, ijk[1], ip.y); 08642 kv[2]->CalcShape(shape_z, ijk[2], ip.z); 08643 08644 double sum = 0.0; 08645 for (int o = 0, k = 0; k <= Order; k++) 08646 { 08647 const double sz = shape_z(k); 08648 for (int j = 0; j <= Order; j++) 08649 { 08650 const double sy_sz = shape_y(j)*sz; 08651 for (int i = 0; i <= Order; i++, o++) 08652 { 08653 sum += ( shape(o) = shape_x(i)*sy_sz*weights(o) ); 08654 } 08655 } 08656 } 08657 08658 shape /= sum; 08659 } 08660 08661 void NURBS3DFiniteElement::CalcDShape(const IntegrationPoint &ip, 08662 DenseMatrix &dshape) const 08663 { 08664 double sum, dsum[3]; 08665 08666 kv[0]->CalcShape ( shape_x, ijk[0], ip.x); 08667 kv[1]->CalcShape ( shape_y, ijk[1], ip.y); 08668 kv[2]->CalcShape ( shape_z, ijk[2], ip.z); 08669 08670 kv[0]->CalcDShape(dshape_x, ijk[0], ip.x); 08671 kv[1]->CalcDShape(dshape_y, ijk[1], ip.y); 08672 kv[2]->CalcDShape(dshape_z, ijk[2], ip.z); 08673 08674 sum = dsum[0] = dsum[1] = dsum[2] = 0.0; 08675 for (int o = 0, k = 0; k <= Order; k++) 08676 { 08677 const double sz = shape_z(k), dsz = dshape_z(k); 08678 for (int j = 0; j <= Order; j++) 08679 { 08680 const double sy_sz = shape_y(j)* sz; 08681 const double dsy_sz = dshape_y(j)* sz; 08682 const double sy_dsz = shape_y(j)*dsz; 08683 for (int i = 0; i <= Order; i++, o++) 08684 { 08685 sum += ( u(o) = shape_x(i)*sy_sz*weights(o) ); 08686 08687 dsum[0] += ( dshape(o,0) = dshape_x(i)* sy_sz *weights(o) ); 08688 dsum[1] += ( dshape(o,1) = shape_x(i)*dsy_sz *weights(o) ); 08689 dsum[2] += ( dshape(o,2) = shape_x(i)* sy_dsz*weights(o) ); 08690 } 08691 } 08692 } 08693 08694 sum = 1.0/sum; 08695 dsum[0] *= sum*sum; 08696 dsum[1] *= sum*sum; 08697 dsum[2] *= sum*sum; 08698 08699 for (int o = 0; o < Dof; o++) 08700 { 08701 dshape(o,0) = dshape(o,0)*sum - u(o)*dsum[0]; 08702 dshape(o,1) = dshape(o,1)*sum - u(o)*dsum[1]; 08703 dshape(o,2) = dshape(o,2)*sum - u(o)*dsum[2]; 08704 } 08705 }