Toggle navigation
Documentation
Big picture
The finite element method
The data structure
Not-so-quick guide
Optimisation
Order of action functions
Example codes and tutorials
List of example codes and tutorials
Meshing
Solvers
MPI parallel processing
Post-processing/visualisation
Other
Change log
Creating documentation
Coding conventions
Index
FAQ
About
People
Contact/Get involved
Publications
Acknowledgements
Copyright
Picture show
Go
src
biharmonic
biharmonic_flux_elements.cc
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
// Config header
27
#ifdef HAVE_CONFIG_H
28
#include <oomph-lib-config.h>
29
#endif
30
31
// oomph-lib includes
32
#include "
biharmonic_flux_elements.h
"
33
34
35
namespace
oomph
36
{
37
//=============================================================================
38
/// Constructor, takes the pointer to the "bulk" element, the
39
/// index of the fixed local coordinate and its value represented
40
/// by an integer (+/- 1), indicating that the face is located
41
/// at the max. or min. value of the "fixed" local coordinate
42
/// in the bulk element. And the macro element position of the flux element
43
/// along the edge of the problem
44
//=============================================================================
45
template
<>
46
BiharmonicFluxElement<2>::BiharmonicFluxElement
(
47
FiniteElement
*
const
&
bulk_el_pt
,
const
int
& face_index,
const
unsigned
& b)
48
:
FaceGeometry
<
BiharmonicElement
<2>>(),
FaceElement
()
49
{
50
// Let the bulk element build the FaceElement, i.e. setup the pointers
51
// to its nodes (by referring to the appropriate nodes in the bulk
52
// element), etc.
53
bulk_el_pt
->
build_face_element
(
face_index
,
this
);
54
55
// Initialise the prescribed-flux function pointer to zero
56
Flux0_fct_pt
= 0;
57
Flux1_fct_pt
= 0;
58
59
// set the number of nodal degrees of freedom for the face element
60
Nface_nodal_dof
= 2;
61
62
//
63
Boundary
= b;
64
}
65
66
67
//=============================================================================
68
/// Calculate the Jacobian of the mapping between local and global
69
/// coordinates at the position s for face elements for two dimensional
70
/// problems
71
/// The jacobian of the 1D face element is computed which is dt/ds_t
72
//=============================================================================
73
template
<>
74
double
BiharmonicFluxElement<2>::J_eulerian
(
const
Vector<double>
&
s
)
const
75
{
76
// Find the number of nodes
77
unsigned
n_node
= this->
nnode
();
78
79
// Set up dummy memory for the shape functions
80
Shape
psi
(
n_node
, Nface_nodal_dof);
81
DShape
dpsids
(
n_node
, Nface_nodal_dof, 1);
82
83
// Get the shape functions and local derivatives
84
this->
dshape_local
(s,
psi
,
dpsids
);
85
86
// computed dx_i/ds_t along edge element
87
Vector<double>
interpolated_dxds_t
(2);
88
89
// Get the bulk position type corresponding to the slope
90
const
unsigned
slope_index
= this->bulk_position_type(1);
91
for
(
unsigned
l
= 0;
l
<
n_node
;
l
++)
92
{
93
for
(
unsigned
d = 0; d < 2; d++)
94
{
95
interpolated_dxds_t
[d] +=
96
this->
node_pt
(
l
)->
x_gen
(0, d) *
dpsids
(
l
, 0, 0) +
97
this->
node_pt
(
l
)->
x_gen
(
slope_index
, d) *
dpsids
(
l
, 1, 0);
98
}
99
}
100
101
// dt/ds_t = dx_0/ds_t*t_0 + dx_1/ds_t*t_1
102
//
103
// given : t_0 = dx_0/ds_t / ( (dx_0/ds_t)^2 + (dx_1/ds_t)^2 )^0.5
104
// t_1 = dx_1/ds_t / ( (dx_0/ds_t)^2 + (dx_1/ds_t)^2 )^0.5
105
//
106
// then : dt/ds_t = ( (dx_0/ds_t)^2 + (dx_1/ds_t)^2 )^0.5
107
//
108
// (note : it is gaurantee that dt/ds_t is +ve, therefore do not need
109
// PARANOID
110
// check of jacobian)
111
double
dtds_t
=
sqrt
(
interpolated_dxds_t
[0] *
interpolated_dxds_t
[0] +
112
interpolated_dxds_t
[1] *
interpolated_dxds_t
[1]);
113
114
// Return the Jacobian
115
return
dtds_t
;
116
}
117
118
119
//=============================================================================
120
/// Compute the elemental contribution to the residual vector for 2D
121
/// problem type 0 biharmonic flux elements
122
//=============================================================================
123
template
<>
124
void
BiharmonicFluxElement
<
125
2>::fill_in_generic_residual_contribution_biharmonic_flux(
Vector<double>
&
126
residual)
127
{
128
// Find out how many nodes there are in the face element
129
unsigned
n_node
= this->nnode();
130
131
// set up memory for shape functions
132
Shape
psi
(
n_node
, Nface_nodal_dof);
133
134
// setup memory for derivative of shape functions
135
DShape
dpsi
(
n_node
, Nface_nodal_dof, 1);
136
137
// Set the value of Nintpt
138
unsigned
n_intpt
= this->integral_pt()->nweight();
139
140
// local coordinate position of integration point in face element
141
Vector<double>
s
(1);
142
143
// edge sign adjust
144
int
edge_sign
=
//-int(this->s_fixed_value())*int((s_fixed_index-0.5)*2);
145
-this->normal_sign();
146
147
// Flip for the different normal conventions (TIDY THIS UP)
148
if
((this->face_index() == 2) || (this->face_index() == -2))
149
{
150
edge_sign
*= -1;
151
}
152
153
// Get the bulk position type corresponding to the slope
154
const
unsigned
slope_index
= this->bulk_position_type(1);
155
156
// Ge the position type corresponding to the outer slope
157
const
unsigned
outer_slope_index
= 3 -
slope_index
;
158
159
// Loop over the integration points
160
//--------------------------------
161
for
(
unsigned
ipt
= 0;
ipt
<
n_intpt
;
ipt
++)
162
{
163
// Get the integral weight
164
double
w = this->integral_pt()->weight(
ipt
);
165
166
// value of local coordinate s at integration point
167
s
[0] = this->integral_pt()->knot(
ipt
, 0);
168
169
// get the (1D) shape fn
170
this->dshape_local(
s
,
psi
,
dpsi
);
171
172
// compute dx_i/ds_t and dx_i/ds_n at ipt
173
Vector<double>
dxds_t
(2, 0.0);
174
Vector<double>
dxds_n
(2, 0.0);
175
for
(
unsigned
n
= 0;
n
<
n_node
;
n
++)
176
{
177
for
(
unsigned
d = 0; d < 2; d++)
178
{
179
for
(
unsigned
k
= 0;
k
< Nface_nodal_dof;
k
++)
180
{
181
dxds_t
[d] +=
dpsi
(
n
,
k
, 0) * node_pt(
n
)->x_gen(
slope_index
*
k
, d);
182
dxds_n
[d] +=
psi
(
n
,
k
) * node_pt(
n
)->x_gen(
183
outer_slope_index
+
slope_index
*
k
, d);
184
}
185
}
186
}
187
188
// compute ds_n/dn
189
double
ds_ndn
= -
edge_sign
*
190
sqrt
(
dxds_t
[0] *
dxds_t
[0] +
dxds_t
[1] *
dxds_t
[1]) /
191
(-
dxds_n
[0] *
dxds_t
[1] +
dxds_t
[0] *
dxds_n
[1]);
192
193
// compute ds_t/dn
194
double
ds_tdn
=
edge_sign
*
195
(
dxds_t
[1] *
dxds_n
[1] +
dxds_t
[0] *
dxds_n
[0]) /
196
(
sqrt
(
dxds_t
[0] *
dxds_t
[0] +
dxds_t
[1] *
dxds_t
[1]) *
197
(-
dxds_n
[0] *
dxds_t
[1] +
dxds_t
[0] *
dxds_n
[1]));
198
199
// compute interpolated_m at s
200
double
interpolated_m
= 0.0;
201
Vector<double>
m
(2);
202
for
(
unsigned
n
= 0;
n
<
n_node
;
n
++)
203
{
204
this->node_pt(
n
)->get_coordinates_on_boundary(Boundary,
m
);
205
for
(
unsigned
k
= 0;
k
< Nface_nodal_dof;
k
++)
206
{
207
interpolated_m
+=
psi
(
n
,
k
) *
m
[
k
];
208
}
209
}
210
211
// get the fluxes
212
double
flux0
= 0.0;
213
get_flux0(
interpolated_m
,
flux0
);
214
double
flux1
= 0.0;
215
get_flux1(
interpolated_m
,
flux1
);
216
217
// get J
218
double
J
= J_eulerian(
s
);
219
220
// Premultiply the weights and the Jacobian
221
double
W = w *
J
;
222
223
// Now add to the appropriate equations
224
225
226
// Loop over the test function nodes
227
for
(
unsigned
n
= 0;
n
<
n_node
;
n
++)
228
{
229
// loop over the face element position types
230
for
(
unsigned
k
= 0;
k
< Nface_nodal_dof;
k
++)
231
{
232
// apply contribution for flux0
233
234
// determine bulk position type
235
unsigned
bulk_p_type
=
slope_index
*
k
;
236
237
// local equation number
238
int
local_eqn
= this->nodal_local_eqn(
n
,
bulk_p_type
);
239
240
// if node not pinned
241
if
(
local_eqn
>= 0)
242
{
243
// add contribution to residual
244
residual[
local_eqn
] +=
flux1
*
psi
(
n
,
k
) * W;
245
}
246
247
// apply first contribution for flux1
248
249
// if node not pinned
250
if
(
local_eqn
>= 0)
251
{
252
// add contribution to residual
253
residual[
local_eqn
] -=
flux0
*
dpsi
(
n
,
k
, 0) *
ds_tdn
* W;
254
}
255
256
// apply second contribution for flux1
257
258
// determine bulk position type
259
bulk_p_type
=
outer_slope_index
+
slope_index
*
k
;
260
261
// local equation number
262
local_eqn
= this->nodal_local_eqn(
n
,
bulk_p_type
);
263
264
// if node not pinned
265
if
(
local_eqn
>= 0)
266
{
267
// add contribution to residual
268
residual[
local_eqn
] -=
flux0
*
psi
(
n
,
k
) *
ds_ndn
* W;
269
}
270
}
271
}
272
}
273
}
274
275
// Ensure Flux elements are build
276
template
class
BiharmonicFluxElement<2>
;
277
278
}
// namespace oomph
biharmonic_flux_elements.h
s
static char t char * s
Definition
cfortran.h:568
oomph::BiharmonicElement
biharmonic element class
Definition
biharmonic_elements.h:527
oomph::BiharmonicFluxElement
Biharmonic Flux Element.
Definition
biharmonic_flux_elements.h:84
oomph::BiharmonicFluxElement::Nface_nodal_dof
unsigned Nface_nodal_dof
the number of nodal degrees of freedom for the face element basis functions
Definition
biharmonic_flux_elements.h:237
oomph::BiharmonicFluxElement::J_eulerian
double J_eulerian(const Vector< double > &s) const
Calculate the Jacobian of the mapping between local and global coordinates at the position s for face...
oomph::BiharmonicFluxElement::Flux1_fct_pt
FluxFctPt Flux1_fct_pt
Function pointer to the prescribed flux.
Definition
biharmonic_flux_elements.h:233
oomph::BiharmonicFluxElement::Boundary
unsigned Boundary
Boundary ID.
Definition
biharmonic_flux_elements.h:240
oomph::BiharmonicFluxElement::Flux0_fct_pt
FluxFctPt Flux0_fct_pt
Function pointer to the prescribed flux.
Definition
biharmonic_flux_elements.h:230
oomph::BiharmonicFluxElement::BiharmonicFluxElement
BiharmonicFluxElement()
Broken empty constructor.
Definition
biharmonic_flux_elements.h:97
oomph::DShape
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Definition
shape.h:278
oomph::FaceElement
FaceElements are elements that coincide with the faces of higher-dimensional "bulk" elements....
Definition
elements.h:4342
oomph::FaceElement::face_index
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
Definition
elements.h:4630
oomph::FaceGeometry
FaceGeometry class definition: This policy class is used to allow construction of face elements that ...
Definition
elements.h:5002
oomph::FiniteElement
A general Finite Element class.
Definition
elements.h:1317
oomph::FiniteElement::nnode
unsigned nnode() const
Return the number of nodes.
Definition
elements.h:2214
oomph::FiniteElement::node_pt
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition
elements.h:2179
oomph::FiniteElement::dshape_local
virtual void dshape_local(const Vector< double > &s, Shape &psi, DShape &dpsids) const
Function to compute the geometric shape functions and derivatives w.r.t. local coordinates at local c...
Definition
elements.h:1985
oomph::FiniteElement::build_face_element
virtual void build_face_element(const int &face_index, FaceElement *face_element_pt)
Function for building a lower dimensional FaceElement on the specified face of the FiniteElement....
Definition
elements.cc:5163
oomph::Node::x_gen
double & x_gen(const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i). ‘Type’: k; Coordinate direction: i.
Definition
nodes.h:1126
oomph::Shape
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Definition
shape.h:76
oomph::TAdvectionDiffusionReactionElement
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
Definition
Tadvection_diffusion_reaction_elements.h:66
oomph::TAdvectionDiffusionReactionElement::TAdvectionDiffusionReactionElement
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
Definition
Tadvection_diffusion_reaction_elements.h:70
oomph
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition
advection_diffusion_elements.cc:30