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
33
34
35namespace 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<>
47 FiniteElement* const& bulk_el_pt, const int& face_index, const unsigned& b)
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.
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
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<>
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
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 {
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)
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<>
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(
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
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
static char t char * s
Definition cfortran.h:568
biharmonic element class
unsigned Nface_nodal_dof
the number of nodal degrees of freedom for the face element basis functions
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...
FluxFctPt Flux1_fct_pt
Function pointer to the prescribed flux.
FluxFctPt Flux0_fct_pt
Function pointer to the prescribed flux.
BiharmonicFluxElement()
Broken empty constructor.
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Definition shape.h:278
FaceElements are elements that coincide with the faces of higher-dimensional "bulk" elements....
Definition elements.h:4342
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
Definition elements.h:4630
FaceGeometry class definition: This policy class is used to allow construction of face elements that ...
Definition elements.h:5002
A general Finite Element class.
Definition elements.h:1317
unsigned nnode() const
Return the number of nodes.
Definition elements.h:2214
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
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
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
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
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...
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).