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-2025 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
30#ifdef HAVE_CONFIG_H
31#include <oomph-lib-config.h>
32#endif
33
35#include "generic/Telements.h"
36
37namespace oomph
38{
39 /// Element which solves the Darcy equations using TElements
40 template<unsigned ORDER>
41 class TPoroelasticityElement : public TElement<2, 3>,
43 {
44 private:
45 /// The number of values stored at each node
46 static const unsigned Initial_Nvalue[];
47
48 /// Conversion scheme from an edge degree of freedom to the node it's stored
49 /// at
50 static const unsigned Q_edge_conv[];
51
52 /// The points along each edge where the fluxes are taken to be
53 static const double Gauss_point[];
54
55 /// The internal data index where the internal q degrees of freedom are
56 /// stored
58
59 /// The internal data index where the p degrees of freedom are stored
61
62 /// Unit normal signs associated with each edge to ensure
63 /// inter-element continuity of the flux
64 std::vector<short> Sign_edge;
65
66 public:
67 /// Constructor
69
70 /// Destructor
72
73 /// Number of values required at node n
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
95 /// Return the equation number of the n-th edge (flux) degree of freedom
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
112 /// Return the equation number of the n-th internal (moment) degree of
113 /// freedom
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
130 /// Return the index of the internal data where the q_internal
131 /// degrees of freedom are stored
132 unsigned q_internal_index() const
133 {
135 }
136
137 /// Return the nodal index at which the nth edge unknown is stored
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
154 /// Return the number of the node where the nth edge unknown is stored
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
171 /// Return the values of the edge (flux) degrees of freedom
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
188 /// Return the values of the edge (flux) degrees of freedom at time
189 /// history level t
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
206 /// Return the values of the internal (moment) degrees of freedom
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
223 /// Return the values of the internal (moment) degrees of freedom at
224 /// time history level t
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
242 /// Return the total number of computational basis functions for u
243 unsigned nq_basis() const;
244
245 /// Return the number of edge basis functions for u
246 unsigned nq_basis_edge() const;
247
248 /// Returns the local form of the q basis at local coordinate s
250
251 /// Returns the local form of the q basis and dbasis/ds at local coordinate
252 /// s
254 Shape& div_q_basis_ds) const;
255
256 /// Returns the number of gauss points along each edge of the element
257 unsigned nedge_gauss_point() const;
258
259 /// Returns the nth gauss point along an edge: if sign_edge(edge)==1,
260 /// returns regular gauss point; if sign_edge(edge)==-1, returns 1-(gauss
261 /// point)
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
287 /// Returns the global coordinates of the nth gauss point along an edge
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
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
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
344 }
345
346 /// Pin the nth internal q value
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
363 /// Return the equation number of the n-th pressure degree of freedom
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
380 /// Return the nth pressure value
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
397 /// Return the total number of pressure basis functions
398 unsigned np_basis() const;
399
400 /// Return the pressure basis
402
403 /// Pin the nth pressure value
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
421 /// Scale the edge basis to allow arbitrary edge mappings
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
462 /// Accessor for the unit normal sign of edge n (const version)
463 const short& sign_edge(const unsigned& n) const
464 {
465 return Sign_edge[n];
466 }
467
468 /// Accessor for the unit normal sign of edge n
469 short& sign_edge(const unsigned& n)
470 {
471 return Sign_edge[n];
472 }
473
474 /// Output with default number of plot points
475 void output(std::ostream& outfile)
476 {
478 }
479
480 /// Output FE representation of soln: x,y,u1,u2,div_q,p at
481 /// Nplot^DIM plot points
482 void output(std::ostream& outfile, const unsigned& Nplot)
483 {
485 }
486
487 protected:
488 /// Returns the geometric basis, and the u, p and divergence basis
489 /// functions and test functions at local coordinate s
491 Shape& psi,
492 DShape& dpsi,
493 Shape& u_basis,
494 Shape& u_test,
497 Shape& q_basis,
498 Shape& q_test,
499 Shape& p_basis,
500 Shape& p_test,
502 Shape& div_q_test_ds) const
503 {
504 const unsigned n_q_basis = this->nq_basis();
505
508 this->get_p_basis(s, p_basis);
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;
516
517 u_test = psi;
519
520 q_test = q_basis;
521 p_test = p_basis;
523
524 return J;
525 }
526
527 /// Returns the geometric basis, and the u, p and divergence basis
528 /// functions and test functions at integration point ipt
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,
536 Shape& q_basis,
537 Shape& q_test,
538 Shape& p_basis,
539 Shape& p_test,
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
550 psi,
551 dpsi,
552 u_basis,
553 u_test,
556 q_basis,
557 q_test,
558 p_basis,
559 p_test,
562 }
563 };
564
565 /// Face geometry for TPoroelasticityElement<0>
566 template<>
567 class FaceGeometry<TPoroelasticityElement<0>> : public virtual TElement<1, 3>
568 {
569 public:
570 /// Constructor: Call constructor of base
571 FaceGeometry() : TElement<1, 3>() {}
572 };
573
574 /// Face geometry for TPoroelasticityElement<1>
575 template<>
576 class FaceGeometry<TPoroelasticityElement<1>> : public virtual TElement<1, 3>
577 {
578 public:
579 /// Constructor: Call constructor of base class
580 FaceGeometry() : TElement<1, 3>() {}
581 };
582
583} // namespace oomph
584
585#endif
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
char t
Definition cfortran.h:568
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
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_)
Set the i-th stored data value to specified value. The only reason that we require an explicit set fu...
Definition nodes.h:271
double value(const unsigned &i) const
Return i-th stored value. This function is not virtual so that it can be inlined. This means that if ...
Definition nodes.h:293
FaceGeometry()
Constructor: Call constructor of base.
FaceGeometry()
Constructor: Call constructor of base class.
FaceGeometry class definition: This policy class is used to allow construction of face elements that ...
Definition elements.h:5002
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition elements.h:1967
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
Definition elements.h:2597
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:3992
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Return the local equation number corresponding to the i-th value at the n-th local node.
Definition elements.h:1436
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
Definition elements.h:605
int internal_local_eqn(const unsigned &i, const unsigned &j) const
Return the local equation number corresponding to the j-th value stored at the i-th internal data.
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
An OomphLibError object which should be thrown when an run-time error is encountered....
Class implementing the generic maths of the poroelasticity equations: linear elasticity coupled with ...
double transform_basis(const Vector< double > &s, const Shape &q_basis_local, Shape &psi, DShape &dpsi, Shape &q_basis) const
Performs a div-conserving transformation of the vector basis functions from the reference element to ...
void output(std::ostream &outfile)
Output with default number of plot points.
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Definition shape.h:76
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
General TElement class.
Definition Telements.h:1208
Element which solves the Darcy equations using TElements.
double q_edge(const unsigned &n) const
Return the values of the edge (flux) degrees of freedom.
unsigned required_nvalue(const unsigned &n) const
Number of values required at node n.
void pin_p_value(const unsigned &n, const double &p)
Pin the nth pressure value.
TPoroelasticityElement()
Constructor.
double edge_gauss_point(const unsigned &edge, const unsigned &n) const
Returns the nth gauss point along an edge: if sign_edge(edge)==1, returns regular gauss point; if sig...
unsigned Q_internal_data_index
The internal data index where the internal q degrees of freedom are stored.
void get_div_q_basis_local(const Vector< double > &s, Shape &div_q_basis_ds) const
Returns the local form of the q basis and dbasis/ds at local coordinate s.
static const unsigned Q_edge_conv[]
Conversion scheme from an edge degree of freedom to the node it's stored at.
unsigned u_index(const unsigned &n) const
Return the nodal index of the n-th solid displacement unknown.
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
Returns the geometric basis, and the u, p and divergence basis functions and test functions at integr...
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
Returns the geometric basis, and the u, p and divergence basis functions and test functions at local ...
unsigned q_edge_index(const unsigned &n) const
Return the nodal index at which the nth edge unknown is stored.
short & sign_edge(const unsigned &n)
Accessor for the unit normal sign of edge n.
std::vector< short > Sign_edge
Unit normal signs associated with each edge to ensure inter-element continuity of the flux.
void output(std::ostream &outfile)
Output with default number of plot points.
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.
void pin_q_internal_value(const unsigned &n)
Pin the nth internal q value.
unsigned q_internal_index() const
Return the index of the internal data where the q_internal degrees of freedom are stored.
int p_local_eqn(const unsigned &n) const
Return the equation number of the n-th pressure degree of freedom.
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.
unsigned np_basis() const
Return the total number of pressure basis functions.
const short & sign_edge(const unsigned &n) const
Accessor for the unit normal sign of edge n (const version)
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.
double q_internal(const unsigned &t, const unsigned &n) const
Return the values of the internal (moment) degrees of freedom at time history level t.
int q_internal_local_eqn(const unsigned &n) const
Return the equation number of the n-th internal (moment) degree of freedom.
double p_value(unsigned &n) const
Return the nth pressure value.
unsigned P_internal_data_index
The internal data index where the p degrees of freedom are stored.
void output(std::ostream &outfile, const unsigned &Nplot)
Output FE representation of soln: x,y,u1,u2,div_q,p at Nplot^DIM plot points.
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.
~TPoroelasticityElement()
Destructor.
double q_edge(const unsigned &t, const unsigned &n) const
Return the values of the edge (flux) degrees of freedom at time history level t.
unsigned q_edge_node_number(const unsigned &n) const
Return the number of the node where the nth edge unknown is stored.
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.
double q_internal(const unsigned &n) const
Return the values of the internal (moment) degrees of freedom.
unsigned nq_basis() const
Return the total number of computational basis functions for u.
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).