Tporoelasticity_elements.h
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2022 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 #ifndef OOMPH_TPOROELASTICITY_ELEMENTS_HEADER
27 #define OOMPH_TPOROELASTICITY_ELEMENTS_HEADER
28 
29 // Config header generated by autoconfig
30 #ifdef HAVE_CONFIG_H
31 #include <oomph-lib-config.h>
32 #endif
33 
35 #include "../generic/Telements.h"
36 
37 namespace oomph
38 {
40  template<unsigned ORDER>
41  class TPoroelasticityElement : public TElement<2, 3>,
42  public PoroelasticityEquations<2>
43  {
44  private:
46  static const unsigned Initial_Nvalue[];
47 
50  static const unsigned Q_edge_conv[];
51 
53  static const double Gauss_point[];
54 
58 
61 
64  std::vector<short> Sign_edge;
65 
66  public:
69 
72 
74  unsigned required_nvalue(const unsigned& n) const
75  {
76  return Initial_Nvalue[n];
77  }
78 
79  unsigned u_index(const unsigned& n) const
80  {
81 #ifdef RANGE_CHECKING
82  if (n >= 2)
83  {
84  std::ostringstream error_message;
85  error_message << "Range Error: n " << n << " is not in the range (0,1)";
86  throw OomphLibError(error_message.str(),
89  }
90 #endif
91 
92  return n;
93  }
94 
96  int q_edge_local_eqn(const unsigned& n) const
97  {
98 #ifdef RANGE_CHECKING
99  if (n >= nq_basis_edge())
100  {
101  std::ostringstream error_message;
102  error_message << "Range Error: n " << n << " is not in the range (0,"
103  << nq_basis_edge() - 1 << ")";
104  throw OomphLibError(error_message.str(),
107  }
108 #endif
110  }
111 
114  int q_internal_local_eqn(const unsigned& n) const
115  {
116 #ifdef RANGE_CHECKING
117  if (n >= (nq_basis() - nq_basis_edge()))
118  {
119  std::ostringstream error_message;
120  error_message << "Range Error: n " << n << " is not in the range (0,"
121  << (nq_basis() - nq_basis_edge()) - 1 << ")";
122  throw OomphLibError(error_message.str(),
125  }
126 #endif
128  }
129 
132  unsigned q_internal_index() const
133  {
134  return Q_internal_data_index;
135  }
136 
138  unsigned q_edge_index(const unsigned& n) const
139  {
140 #ifdef RANGE_CHECKING
141  if (n >= (nq_basis_edge()))
142  {
143  std::ostringstream error_message;
144  error_message << "Range Error: n " << n << " is not in the range (0,"
145  << nq_basis_edge() - 1 << ")";
146  throw OomphLibError(error_message.str(),
149  }
150 #endif
151  return n % (ORDER + 1) + 2;
152  }
153 
155  unsigned q_edge_node_number(const unsigned& n) const
156  {
157 #ifdef RANGE_CHECKING
158  if (n >= (nq_basis_edge()))
159  {
160  std::ostringstream error_message;
161  error_message << "Range Error: n " << n << " is not in the range (0,"
162  << nq_basis_edge() - 1 << ")";
163  throw OomphLibError(error_message.str(),
166  }
167 #endif
168  return Q_edge_conv[n / (ORDER + 1)];
169  }
170 
172  double q_edge(const unsigned& n) const
173  {
174 #ifdef RANGE_CHECKING
175  if (n >= (nq_basis_edge()))
176  {
177  std::ostringstream error_message;
178  error_message << "Range Error: n " << n << " is not in the range (0,"
179  << nq_basis_edge() - 1 << ")";
180  throw OomphLibError(error_message.str(),
183  }
184 #endif
186  }
187 
190  double q_edge(const unsigned& t, const unsigned& n) const
191  {
192 #ifdef RANGE_CHECKING
193  if (n >= (nq_basis_edge()))
194  {
195  std::ostringstream error_message;
196  error_message << "Range Error: n " << n << " is not in the range (0,"
197  << nq_basis_edge() - 1 << ")";
198  throw OomphLibError(error_message.str(),
201  }
202 #endif
204  }
205 
207  double q_internal(const unsigned& n) const
208  {
209 #ifdef RANGE_CHECKING
210  if (n >= (nq_basis() - nq_basis_edge()))
211  {
212  std::ostringstream error_message;
213  error_message << "Range Error: n " << n << " is not in the range (0,"
214  << (nq_basis() - nq_basis_edge()) - 1 << ")";
215  throw OomphLibError(error_message.str(),
218  }
219 #endif
220  return this->internal_data_pt(q_internal_index())->value(n);
221  }
222 
225  double q_internal(const unsigned& t, const unsigned& n) const
226  {
227 #ifdef RANGE_CHECKING
228  // mjr TODO add time history level range checking
229  if (n >= (nq_basis() - nq_basis_edge()))
230  {
231  std::ostringstream error_message;
232  error_message << "Range Error: n " << n << " is not in the range (0,"
233  << (nq_basis() - nq_basis_edge()) - 1 << ")";
234  throw OomphLibError(error_message.str(),
237  }
238 #endif
239  return this->internal_data_pt(q_internal_index())->value(t, n);
240  }
241 
243  unsigned nq_basis() const;
244 
246  unsigned nq_basis_edge() const;
247 
249  void get_q_basis_local(const Vector<double>& s, Shape& q_basis) const;
250 
254  Shape& div_q_basis_ds) const;
255 
257  unsigned nedge_gauss_point() const;
258 
262  double edge_gauss_point(const unsigned& edge, const unsigned& n) const
263  {
264 #ifdef RANGE_CHECKING
265  if (edge >= 3)
266  {
267  std::ostringstream error_message;
268  error_message << "Range Error: edge " << edge
269  << " is not in the range (0,2)";
270  throw OomphLibError(error_message.str(),
273  }
274  if (n >= nedge_gauss_point())
275  {
276  std::ostringstream error_message;
277  error_message << "Range Error: n " << n << " is not in the range (0,"
278  << nedge_gauss_point() - 1 << ")";
279  throw OomphLibError(error_message.str(),
282  }
283 #endif
284  return (1 - sign_edge(edge)) / 2.0 + sign_edge(edge) * Gauss_point[n];
285  }
286 
288  void edge_gauss_point_global(const unsigned& edge,
289  const unsigned& n,
290  Vector<double>& x) const
291  {
292 #ifdef RANGE_CHECKING
293  if (edge >= 3)
294  {
295  std::ostringstream error_message;
296  error_message << "Range Error: edge " << edge
297  << " is not in the range (0,2)";
298  throw OomphLibError(error_message.str(),
301  }
302  if (n >= nedge_gauss_point())
303  {
304  std::ostringstream error_message;
305  error_message << "Range Error: n " << n << " is not in the range (0,"
306  << nedge_gauss_point() - 1 << ")";
307  throw OomphLibError(error_message.str(),
310  }
311 #endif
312 
313  // Get the location of the n-th gauss point along the edge in terms of the
314  // distance along the edge itself
315  double gauss_point = edge_gauss_point(edge, n);
316 
317  // Convert the edge number to the number of the mid-edge node along that
318  // edge
319  unsigned node_number = Q_edge_conv[edge];
320 
321  // Storage for the local coords of the gauss point
322  Vector<double> s_gauss(2, 0);
323 
324  // The edge basis functions are defined in a clockwise manner, so we have
325  // to effectively "flip" the coordinates along edges 0 and 1 to match this
326  switch (node_number)
327  {
328  case 3:
329  s_gauss[0] = 1 - gauss_point;
330  s_gauss[1] = gauss_point;
331  break;
332  case 4:
333  s_gauss[0] = 0;
334  s_gauss[1] = 1 - gauss_point;
335  break;
336  case 5:
337  s_gauss[0] = gauss_point;
338  s_gauss[1] = 0;
339  break;
340  }
341 
342  // Calculate the global coordinates from the local ones
343  interpolated_x(s_gauss, x);
344  }
345 
347  void pin_q_internal_value(const unsigned& n)
348  {
349 #ifdef RANGE_CHECKING
350  if (n >= (nq_basis() - nq_basis_edge()))
351  {
352  std::ostringstream error_message;
353  error_message << "Range Error: n " << n << " is not in the range (0,"
354  << (nq_basis() - nq_basis_edge()) - 1 << ")";
355  throw OomphLibError(error_message.str(),
358  }
359 #endif
361  }
362 
364  int p_local_eqn(const unsigned& n) const
365  {
366 #ifdef RANGE_CHECKING
367  if (n >= np_basis())
368  {
369  std::ostringstream error_message;
370  error_message << "Range Error: n " << n << " is not in the range (0,"
371  << np_basis() - 1 << ")";
372  throw OomphLibError(error_message.str(),
375  }
376 #endif
377  return this->internal_local_eqn(P_internal_data_index, n);
378  }
379 
381  double p_value(unsigned& n) const
382  {
383 #ifdef RANGE_CHECKING
384  if (n >= np_basis())
385  {
386  std::ostringstream error_message;
387  error_message << "Range Error: n " << n << " is not in the range (0,"
388  << np_basis() - 1 << ")";
389  throw OomphLibError(error_message.str(),
392  }
393 #endif
394  return this->internal_data_pt(P_internal_data_index)->value(n);
395  }
396 
398  unsigned np_basis() const;
399 
401  void get_p_basis(const Vector<double>& s, Shape& p_basis) const;
402 
404  void pin_p_value(const unsigned& n, const double& p)
405  {
406 #ifdef RANGE_CHECKING
407  if (n >= np_basis())
408  {
409  std::ostringstream error_message;
410  error_message << "Range Error: n " << n << " is not in the range (0,"
411  << np_basis() - 1 << ")";
412  throw OomphLibError(error_message.str(),
415  }
416 #endif
417  this->internal_data_pt(P_internal_data_index)->pin(n);
418  this->internal_data_pt(P_internal_data_index)->set_value(n, p);
419  }
420 
422  void scale_basis(Shape& basis) const
423  {
424  // Storage for the lengths of the edges of the element
425  Vector<double> length(3, 0.0);
426 
427  // Temporary storage for the vertex positions
428  double x0, y0, x1, y1;
429 
430  // loop over the edges of the element and calculate their lengths (in x-y
431  // space)
432  for (unsigned i = 0; i < 3; i++)
433  {
434  x0 = this->node_pt(i)->x(0);
435  y0 = this->node_pt(i)->x(1);
436  x1 = this->node_pt((i + 1) % 3)->x(0);
437  y1 = this->node_pt((i + 1) % 3)->x(1);
438 
439  length[i] = std::sqrt(std::pow(y1 - y0, 2) + std::pow(x1 - x0, 2));
440  }
441 
442  // lengths of the sides of the reference element (in the same order as the
443  // basis functions)
444  const double ref_length[3] = {std::sqrt(2.0), 1, 1};
445 
446  // get the number of basis functions associated with the edges
447  unsigned n_q_basis_edge = nq_basis_edge();
448 
449  // rescale the edge basis functions to allow arbitrary edge mappings from
450  // element to ref. element
451  const unsigned n_index2 = basis.nindex2();
452  for (unsigned i = 0; i < n_index2; i++)
453  {
454  for (unsigned l = 0; l < n_q_basis_edge; l++)
455  {
456  basis(l, i) *=
457  (length[l / (ORDER + 1)] / ref_length[l / (ORDER + 1)]);
458  }
459  }
460  }
461 
463  const short& sign_edge(const unsigned& n) const
464  {
465  return Sign_edge[n];
466  }
467 
469  short& sign_edge(const unsigned& n)
470  {
471  return Sign_edge[n];
472  }
473 
475  void output(std::ostream& outfile)
476  {
478  }
479 
482  void output(std::ostream& outfile, const unsigned& Nplot)
483  {
484  PoroelasticityEquations<2>::output(outfile, Nplot);
485  }
486 
487  protected:
491  Shape& psi,
492  DShape& dpsi,
493  Shape& u_basis,
494  Shape& u_test,
495  DShape& du_basis_dx,
496  DShape& du_test_dx,
497  Shape& q_basis,
498  Shape& q_test,
499  Shape& p_basis,
500  Shape& p_test,
501  Shape& div_q_basis_ds,
502  Shape& div_q_test_ds) const
503  {
504  const unsigned n_q_basis = this->nq_basis();
505 
506  Shape q_basis_local(n_q_basis, 2);
507  this->get_q_basis_local(s, q_basis_local);
508  this->get_p_basis(s, p_basis);
509  this->get_div_q_basis_local(s, div_q_basis_ds);
510 
511  double J = this->transform_basis(s, q_basis_local, psi, dpsi, q_basis);
512 
513  // u_basis consists of the normal Lagrangian shape functions
514  u_basis = psi;
515  du_basis_dx = dpsi;
516 
517  u_test = psi;
518  du_test_dx = dpsi;
519 
520  q_test = q_basis;
521  p_test = p_basis;
522  div_q_test_ds = div_q_basis_ds;
523 
524  return J;
525  }
526 
529  double shape_basis_test_local_at_knot(const unsigned& ipt,
530  Shape& psi,
531  DShape& dpsi,
532  Shape& u_basis,
533  Shape& u_test,
534  DShape& du_basis_dx,
535  DShape& du_test_dx,
536  Shape& q_basis,
537  Shape& q_test,
538  Shape& p_basis,
539  Shape& p_test,
540  Shape& div_q_basis_ds,
541  Shape& div_q_test_ds) const
542  {
543  Vector<double> s(2);
544  for (unsigned i = 0; i < 2; i++)
545  {
546  s[i] = this->integral_pt()->knot(ipt, i);
547  }
548 
549  return shape_basis_test_local(s,
550  psi,
551  dpsi,
552  u_basis,
553  u_test,
554  du_basis_dx,
555  du_test_dx,
556  q_basis,
557  q_test,
558  p_basis,
559  p_test,
560  div_q_basis_ds,
561  div_q_test_ds);
562  }
563  };
564 
566  template<>
567  class FaceGeometry<TPoroelasticityElement<0>> : public virtual TElement<1, 3>
568  {
569  public:
571  FaceGeometry() : TElement<1, 3>() {}
572  };
573 
575  template<>
576  class FaceGeometry<TPoroelasticityElement<1>> : public virtual TElement<1, 3>
577  {
578  public:
580  FaceGeometry() : TElement<1, 3>() {}
581  };
582 
583 } // namespace oomph
584 
585 #endif
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
JacobiRotation< float > J
Definition: Jacobi_makeJacobi.cpp:3
float * p
Definition: Tutorial_Map_using.cpp:9
Definition: shape.h:278
void pin(const unsigned &i)
Pin the i-th stored variable.
Definition: nodes.h:385
void set_value(const unsigned &i, const double &value_)
Definition: nodes.h:271
double value(const unsigned &i) const
Definition: nodes.h:293
FaceGeometry()
Constructor: Call constructor of base.
Definition: Tporoelasticity_elements.h:571
FaceGeometry()
Constructor: Call constructor of base class.
Definition: Tporoelasticity_elements.h:580
Definition: elements.h:4998
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
double nodal_value(const unsigned &n, const unsigned &i) const
Definition: elements.h:2593
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
Definition: elements.cc:3962
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Definition: elements.h:1432
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1963
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
Definition: elements.h:622
int internal_local_eqn(const unsigned &i, const unsigned &j) const
Definition: elements.h:267
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
Definition: oomph_definitions.h:222
Definition: poroelasticity_elements.h:46
double transform_basis(const Vector< double > &s, const Shape &q_basis_local, Shape &psi, DShape &dpsi, Shape &q_basis) const
Definition: poroelasticity_elements.cc:196
void output(std::ostream &outfile)
Output with default number of plot points.
Definition: poroelasticity_elements.h:706
Definition: shape.h:76
unsigned nindex2() const
Return the range of index 2 of the shape function object.
Definition: shape.h:265
Definition: Telements.h:1208
Element which solves the Darcy equations using TElements.
Definition: Tporoelasticity_elements.h:43
double q_edge(const unsigned &n) const
Return the values of the edge (flux) degrees of freedom.
Definition: Tporoelasticity_elements.h:172
short & sign_edge(const unsigned &n)
Accessor for the unit normal sign of edge n.
Definition: Tporoelasticity_elements.h:469
unsigned required_nvalue(const unsigned &n) const
Number of values required at node n.
Definition: Tporoelasticity_elements.h:74
void pin_p_value(const unsigned &n, const double &p)
Pin the nth pressure value.
Definition: Tporoelasticity_elements.h:404
TPoroelasticityElement()
Constructor.
double edge_gauss_point(const unsigned &edge, const unsigned &n) const
Definition: Tporoelasticity_elements.h:262
unsigned Q_internal_data_index
Definition: Tporoelasticity_elements.h:57
void get_div_q_basis_local(const Vector< double > &s, Shape &div_q_basis_ds) const
static const unsigned Q_edge_conv[]
Definition: Tporoelasticity_elements.h:50
unsigned u_index(const unsigned &n) const
Return the nodal index of the n-th solid displacement unknown.
Definition: Tporoelasticity_elements.h:79
double shape_basis_test_local_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsi, Shape &u_basis, Shape &u_test, DShape &du_basis_dx, DShape &du_test_dx, Shape &q_basis, Shape &q_test, Shape &p_basis, Shape &p_test, Shape &div_q_basis_ds, Shape &div_q_test_ds) const
Definition: Tporoelasticity_elements.h:529
double shape_basis_test_local(const Vector< double > &s, Shape &psi, DShape &dpsi, Shape &u_basis, Shape &u_test, DShape &du_basis_dx, DShape &du_test_dx, Shape &q_basis, Shape &q_test, Shape &p_basis, Shape &p_test, Shape &div_q_basis_ds, Shape &div_q_test_ds) const
Definition: Tporoelasticity_elements.h:490
unsigned q_edge_index(const unsigned &n) const
Return the nodal index at which the nth edge unknown is stored.
Definition: Tporoelasticity_elements.h:138
std::vector< short > Sign_edge
Definition: Tporoelasticity_elements.h:64
void output(std::ostream &outfile)
Output with default number of plot points.
Definition: Tporoelasticity_elements.h:475
unsigned nedge_gauss_point() const
Returns the number of gauss points along each edge of the element.
void scale_basis(Shape &basis) const
Scale the edge basis to allow arbitrary edge mappings.
Definition: Tporoelasticity_elements.h:422
void pin_q_internal_value(const unsigned &n)
Pin the nth internal q value.
Definition: Tporoelasticity_elements.h:347
unsigned q_internal_index() const
Definition: Tporoelasticity_elements.h:132
int p_local_eqn(const unsigned &n) const
Return the equation number of the n-th pressure degree of freedom.
Definition: Tporoelasticity_elements.h:364
void get_p_basis(const Vector< double > &s, Shape &p_basis) const
Return the pressure basis.
static const double Gauss_point[]
The points along each edge where the fluxes are taken to be.
Definition: Tporoelasticity_elements.h:53
unsigned np_basis() const
Return the total number of pressure basis functions.
unsigned nq_basis_edge() const
Return the number of edge basis functions for u.
int q_edge_local_eqn(const unsigned &n) const
Return the equation number of the n-th edge (flux) degree of freedom.
Definition: Tporoelasticity_elements.h:96
double q_internal(const unsigned &t, const unsigned &n) const
Definition: Tporoelasticity_elements.h:225
int q_internal_local_eqn(const unsigned &n) const
Definition: Tporoelasticity_elements.h:114
double p_value(unsigned &n) const
Return the nth pressure value.
Definition: Tporoelasticity_elements.h:381
unsigned P_internal_data_index
The internal data index where the p degrees of freedom are stored.
Definition: Tporoelasticity_elements.h:60
void output(std::ostream &outfile, const unsigned &Nplot)
Definition: Tporoelasticity_elements.h:482
void get_q_basis_local(const Vector< double > &s, Shape &q_basis) const
Returns the local form of the q basis at local coordinate s.
static const unsigned Initial_Nvalue[]
The number of values stored at each node.
Definition: Tporoelasticity_elements.h:46
~TPoroelasticityElement()
Destructor.
double q_edge(const unsigned &t, const unsigned &n) const
Definition: Tporoelasticity_elements.h:190
unsigned q_edge_node_number(const unsigned &n) const
Return the number of the node where the nth edge unknown is stored.
Definition: Tporoelasticity_elements.h:155
void edge_gauss_point_global(const unsigned &edge, const unsigned &n, Vector< double > &x) const
Returns the global coordinates of the nth gauss point along an edge.
Definition: Tporoelasticity_elements.h:288
const short & sign_edge(const unsigned &n) const
Accessor for the unit normal sign of edge n (const version)
Definition: Tporoelasticity_elements.h:463
double q_internal(const unsigned &n) const
Return the values of the internal (moment) degrees of freedom.
Definition: Tporoelasticity_elements.h:207
unsigned nq_basis() const
Return the total number of computational basis functions for u.
RealScalar s
Definition: level1_cplx_impl.h:130
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
Vector< double > x1(const Vector< double > &coord)
Cartesian coordinates centered at the point (0.5,1)
Definition: poisson/poisson_with_singularity/two_d_poisson.cc:86
Vector< double > x0(2, 0.0)
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
t
Definition: plotPSD.py:36
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86