multi_domain_linearised_axisym_navier_stokes_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// Header for an element that couples a linearised axisymmetric
27// Navier-Stokes element to a non-linear axisymmetric Navier-Stokes
28// element via a multi domain approach
29
30// oomph-lib headers
31#include "generic.h"
32#include "axisym_navier_stokes.h"
35
36// Use the oomph namespace
37using namespace oomph;
38
39
40/// //////////////////////////////////////////////////////////////////////
41/// //////////////////////////////////////////////////////////////////////
42/// //////////////////////////////////////////////////////////////////////
43
44
45//======================================================================
46/// Build a LinearisedAxisymmetricQTaylorHood element that inherits from
47/// ElementWithExternalElement so that it can "communicate" with an
48/// axisymmetric Navier-Stokes element that provides the base flow
49/// velocities and their derivatives w.r.t. global coordinates (r and z)
50//======================================================================
53 public virtual ElementWithExternalElement
54{
55public:
56 /// Constructor: call the underlying constructors
59 {
60 // There are two interactions: the base flow velocities and their
61 // derivatives w.r.t. global coordinates
62 this->set_ninteraction(2);
63
64 // Do not include any external interaction data when computing
65 // the element's Jacobian
66 ElementWithExternalElement::ignore_external_interaction_data();
67
68 /// Do not include any external geometric data when computing
69 /// the element's Jacobian.
70 ElementWithExternalElement::ignore_external_geometric_data();
71 }
72
73 /// Overload get_base_flow_u(...) to return the external
74 /// element's velocity components at the integration point
75 virtual void get_base_flow_u(const double& time,
76 const unsigned& ipt,
77 const Vector<double>& x,
78 Vector<double>& result) const
79 {
80 // Set interaction index to 0
81 const unsigned interaction = 0;
82
83 // Get a pointer to the external element that computes the base flow.
84 // We know that it's an axisymmetric Navier-Stokes element.
85 const AxisymmetricQTaylorHoodElement* base_flow_el_pt =
86 dynamic_cast<AxisymmetricQTaylorHoodElement*>(
87 external_element_pt(interaction, ipt));
88
89 // Provide storage for local coordinates in the external element
90 // which correspond to the integration point ipt
91 Vector<double> s_external(2);
92
93 // Determine local coordinates in the external element which correspond
94 // to the integration point ipt
95 s_external = external_element_local_coord(interaction, ipt);
96
97 // Get the three velocity components interpolated from the external element
98 for (unsigned i = 0; i < 3; i++)
99 {
100 result[i] = base_flow_el_pt->interpolated_u_axi_nst(s_external, i);
101 }
102
103 } // End of overloaded get_base_flow_u function
104
105 /// Overload get_base_flow_dudx(...) to return the derivatives of
106 /// the external element's velocity components w.r.t. global coordinates
107 /// at the integration point
108 virtual void get_base_flow_dudx(const double& time,
109 const unsigned& ipt,
110 const Vector<double>& x,
111 DenseMatrix<double>& result) const
112 {
113 // Set interaction index to 1
114 const unsigned interaction = 1;
115
116 // Get a pointer to the external element that computes the base flow.
117 // We know that it's an axisymmetric Navier-Stokes element.
118 const AxisymmetricQTaylorHoodElement* base_flow_el_pt =
119 dynamic_cast<AxisymmetricQTaylorHoodElement*>(
120 external_element_pt(interaction, ipt));
121
122 // Provide storage for local coordinates in the external element
123 // which correspond to the integration point ipt
124 Vector<double> s_external(2);
125
126 // Determine local coordinates in the external element which correspond
127 // to the integration point ipt
128 s_external = external_element_local_coord(interaction, ipt);
129
130 // Loop over velocity components
131 for (unsigned i = 0; i < 3; i++)
132 {
133 // Loop over coordinate directions and get derivatives of velocity
134 // components from the external element
135 for (unsigned j = 0; j < 2; j++)
136 {
137 result(i, j) =
138 base_flow_el_pt->interpolated_dudx_axi_nst(s_external, i, j);
139 }
140 }
141
142 } // End of overloaded get_base_flow_dudx function
143
144
145 /// Compute the element's residual vector and the Jacobian matrix
147 DenseMatrix<double>& jacobian)
148 {
149 // Get the analytical contribution from the basic linearised element
150 LinearisedAxisymmetricQTaylorHoodElement::fill_in_contribution_to_jacobian(
151 residuals, jacobian);
152
153 // Get the off-diagonal terms by finite differencing
154 this->fill_in_jacobian_from_external_interaction_by_fd(residuals, jacobian);
155 }
156};
157
158
159/// //////////////////////////////////////////////////////////////////////
160/// //////////////////////////////////////////////////////////////////////
161/// //////////////////////////////////////////////////////////////////////
162
163
164//======================================================================
165/// Build a LinearisedAxisymmetricQCrouzeixRaviart element that inherits
166/// from ElementWithExternalElement so that it can "communicate" with an
167/// axisymmetric Navier-Stokes element that provides the base flow
168/// velocities and their derivatives w.r.t. global coordinates (r and z)
169//======================================================================
172 public virtual ElementWithExternalElement
173{
174public:
175 /// Constructor: call the underlying constructors
179 {
180 // There are two interactions: the base flow velocities and their
181 // derivatives w.r.t. global coordinates
182 this->set_ninteraction(2);
183
184 // Do not include any external interaction data when computing
185 // the element's Jacobian
186 ElementWithExternalElement::ignore_external_interaction_data();
187
188 /// Do not include any external geometric data when computing
189 /// the element's Jacobian.
190 ElementWithExternalElement::ignore_external_geometric_data();
191 }
192
193 /// Overload get_base_flow_u(...) to return the external
194 /// element's velocity components at the integration point
195 virtual void get_base_flow_u(const double& time,
196 const unsigned& ipt,
197 const Vector<double>& x,
198 Vector<double>& result) const
199 {
200 // Set interaction index to 0
201 const unsigned interaction = 0;
202
203 // Get a pointer to the external element that computes the base flow.
204 // We know that it's an axisymmetric Navier-Stokes element.
205 const AxisymmetricQCrouzeixRaviartElement* base_flow_el_pt =
207 external_element_pt(interaction, ipt));
208
209 // Provide storage for local coordinates in the external element
210 // which correspond to the integration point ipt
211 Vector<double> s_external(2);
212
213 // Determine local coordinates in the external element which correspond
214 // to the integration point ipt
215 s_external = external_element_local_coord(interaction, ipt);
216
217 // Get the three velocity components interpolated from the external element
218 for (unsigned i = 0; i < 3; i++)
219 {
220 result[i] = base_flow_el_pt->interpolated_u_axi_nst(s_external, i);
221 }
222
223 } // End of overloaded get_base_flow_u function
224
225 /// Overload get_base_flow_dudx(...) to return the derivatives of
226 /// the external element's velocity components w.r.t. global coordinates
227 /// at the integration point
228 virtual void get_base_flow_dudx(const double& time,
229 const unsigned& ipt,
230 const Vector<double>& x,
231 DenseMatrix<double>& result) const
232 {
233 // Set interaction index to 1
234 const unsigned interaction = 1;
235
236 // Get a pointer to the external element that computes the base flow.
237 // We know that it's an axisymmetric Navier-Stokes element.
238 const AxisymmetricQCrouzeixRaviartElement* base_flow_el_pt =
240 external_element_pt(interaction, ipt));
241
242 // Provide storage for local coordinates in the external element
243 // which correspond to the integration point ipt
244 Vector<double> s_external(2);
245
246 // Determine local coordinates in the external element which correspond
247 // to the integration point ipt
248 s_external = external_element_local_coord(interaction, ipt);
249
250 // Loop over velocity components
251 for (unsigned i = 0; i < 3; i++)
252 {
253 // Loop over coordinate directions and get derivatives of velocity
254 // components from the external element
255 for (unsigned j = 0; j < 2; j++)
256 {
257 result(i, j) =
258 base_flow_el_pt->interpolated_dudx_axi_nst(s_external, i, j);
259 }
260 }
261
262 } // End of overloaded get_base_flow_dudx function
263
264
265 /// Compute the element's residual vector and the Jacobian matrix
267 DenseMatrix<double>& jacobian)
268 {
269 // Get the analytical contribution from the basic linearised element
270 LinearisedAxisymmetricQCrouzeixRaviartElement::
271 fill_in_contribution_to_jacobian(residuals, jacobian);
272
273 // Get the off-diagonal terms by finite differencing
274 this->fill_in_jacobian_from_external_interaction_by_fd(residuals, jacobian);
275 }
276};
277
278
279/// //////////////////////////////////////////////////////////////////////
280/// //////////////////////////////////////////////////////////////////////
281/// //////////////////////////////////////////////////////////////////////
282
283
284//======================================================================
285/// Build a RefineableLinearisedAxisymmetricQTaylorHood element
286/// that inherits from ElementWithExternalElement so that it can
287/// "communicate" with an axisymmetric Navier-Stokes element that
288/// provides the base flow velocities and their derivatives w.r.t.
289/// global coordinates (r and z)
290//======================================================================
293 public virtual ElementWithExternalElement
294{
295public:
296 /// Constructor: call the underlying constructors
300 {
301 // There are two interactions: the base flow velocities and their
302 // derivatives w.r.t. global coordinates
303 this->set_ninteraction(2);
304
305 // Do not include any external interaction data when computing
306 // the element's Jacobian
307 ElementWithExternalElement::ignore_external_interaction_data();
308
309 /// Do not include any external geometric data when computing
310 /// the element's Jacobian.
311 ElementWithExternalElement::ignore_external_geometric_data();
312 }
313
314 /// Overload get_base_flow_u(...) to return the external
315 /// element's velocity components at the integration point
316 virtual void get_base_flow_u(const double& time,
317 const unsigned& ipt,
318 const Vector<double>& x,
319 Vector<double>& result) const
320 {
321 // Set interaction index to 0
322 const unsigned interaction = 0;
323
324 // Get a pointer to the external element that computes the base flow.
325 // We know that it's an axisymmetric Navier-Stokes element.
326 const AxisymmetricQTaylorHoodElement* base_flow_el_pt =
327 dynamic_cast<AxisymmetricQTaylorHoodElement*>(
328 external_element_pt(interaction, ipt));
329
330 // Provide storage for local coordinates in the external element
331 // which correspond to the integration point ipt
332 Vector<double> s_external(2);
333
334 // Determine local coordinates in the external element which correspond
335 // to the integration point ipt
336 s_external = external_element_local_coord(interaction, ipt);
337
338 // Get the three velocity components interpolated from the external element
339 for (unsigned i = 0; i < 3; i++)
340 {
341 result[i] = base_flow_el_pt->interpolated_u_axi_nst(s_external, i);
342 }
343
344 } // End of overloaded get_base_flow_u function
345
346 /// Overload get_base_flow_dudx(...) to return the derivatives of
347 /// the external element's velocity components w.r.t. global coordinates
348 /// at the integration point
349 virtual void get_base_flow_dudx(const double& time,
350 const unsigned& ipt,
351 const Vector<double>& x,
352 DenseMatrix<double>& result) const
353 {
354 // Set interaction index to 1
355 const unsigned interaction = 1;
356
357 // Get a pointer to the external element that computes the base flow.
358 // We know that it's an axisymmetric Navier-Stokes element.
359 const AxisymmetricQTaylorHoodElement* base_flow_el_pt =
360 dynamic_cast<AxisymmetricQTaylorHoodElement*>(
361 external_element_pt(interaction, ipt));
362
363 // Provide storage for local coordinates in the external element
364 // which correspond to the integration point ipt
365 Vector<double> s_external(2);
366
367 // Determine local coordinates in the external element which correspond
368 // to the integration point ipt
369 s_external = external_element_local_coord(interaction, ipt);
370
371 // Loop over velocity components
372 for (unsigned i = 0; i < 3; i++)
373 {
374 // Loop over coordinate directions and get derivatives of velocity
375 // components from the external element
376 for (unsigned j = 0; j < 2; j++)
377 {
378 result(i, j) =
379 base_flow_el_pt->interpolated_dudx_axi_nst(s_external, i, j);
380 }
381 }
382
383 } // End of overloaded get_base_flow_dudx function
384
385
386 /// Compute the element's residual vector and the Jacobian matrix
388 DenseMatrix<double>& jacobian)
389 {
390 // Get the analytical contribution from the basic patricklinearised element
391 RefineableLinearisedAxisymmetricQTaylorHoodElement::
392 fill_in_contribution_to_jacobian(residuals, jacobian);
393
394 // Get the off-diagonal terms by finite differencing
395 this->fill_in_jacobian_from_external_interaction_by_fd(residuals, jacobian);
396 }
397};
398
399
400/// //////////////////////////////////////////////////////////////////////
401/// //////////////////////////////////////////////////////////////////////
402/// //////////////////////////////////////////////////////////////////////
403
404
405//======================================================================
406/// Build a RefineableLinearisedAxisymmetricQCrouzeixRaviart element
407/// that inherits from ElementWithExternalElement so that it can
408/// "communicate" with an axisymmetric Navier-Stokes element that
409/// provides the base flow velocities and their derivatives w.r.t.
410/// global coordinates (r and z)
411//======================================================================
414 public virtual ElementWithExternalElement
415{
416public:
417 /// Constructor: call the underlying constructors
421 {
422 // There are two interactions: the base flow velocities and their
423 // derivatives w.r.t. global coordinates
424 this->set_ninteraction(2);
425
426 // Do not include any external interaction data when computing
427 // the element's Jacobian
428 ElementWithExternalElement::ignore_external_interaction_data();
429
430 /// Do not include any external geometric data when computing
431 /// the element's Jacobian.
432 ElementWithExternalElement::ignore_external_geometric_data();
433 }
434
435 /// Overload get_base_flow_u(...) to return the external
436 /// element's velocity components at the integration point
437 virtual void get_base_flow_u(const double& time,
438 const unsigned& ipt,
439 const Vector<double>& x,
440 Vector<double>& result) const
441 {
442 // Set interaction index to 0
443 const unsigned interaction = 0;
444
445 // Get a pointer to the external element that computes the base flow.
446 // We know that it's an axisymmetric Navier-Stokes element.
447 const AxisymmetricQCrouzeixRaviartElement* base_flow_el_pt =
449 external_element_pt(interaction, ipt));
450
451 // Provide storage for local coordinates in the external element
452 // which correspond to the integration point ipt
453 Vector<double> s_external(2);
454
455 // Determine local coordinates in the external element which correspond
456 // to the integration point ipt
457 s_external = external_element_local_coord(interaction, ipt);
458
459 // Get the three velocity components interpolated from the external element
460 for (unsigned i = 0; i < 3; i++)
461 {
462 result[i] = base_flow_el_pt->interpolated_u_axi_nst(s_external, i);
463 }
464
465 } // End of overloaded get_base_flow_u function
466
467 /// Overload get_base_flow_dudx(...) to return the derivatives of
468 /// the external element's velocity components w.r.t. global coordinates
469 /// at the integration point
470 virtual void get_base_flow_dudx(const double& time,
471 const unsigned& ipt,
472 const Vector<double>& x,
473 DenseMatrix<double>& result) const
474 {
475 // Set interaction index to 1
476 const unsigned interaction = 1;
477
478 // Get a pointer to the external element that computes the base flow.
479 // We know that it's an axisymmetric Navier-Stokes element.
480 const AxisymmetricQCrouzeixRaviartElement* base_flow_el_pt =
482 external_element_pt(interaction, ipt));
483
484 // Provide storage for local coordinates in the external element
485 // which correspond to the integration point ipt
486 Vector<double> s_external(2);
487
488 // Determine local coordinates in the external element which correspond
489 // to the integration point ipt
490 s_external = external_element_local_coord(interaction, ipt);
491
492 // Loop over velocity components
493 for (unsigned i = 0; i < 3; i++)
494 {
495 // Loop over coordinate directions and get derivatives of velocity
496 // components from the external element
497 for (unsigned j = 0; j < 2; j++)
498 {
499 result(i, j) =
500 base_flow_el_pt->interpolated_dudx_axi_nst(s_external, i, j);
501 }
502 }
503
504 } // End of overloaded get_base_flow_dudx function
505
506
507 /// Compute the element's residual vector and the Jacobian matrix
509 DenseMatrix<double>& jacobian)
510 {
511 // Get the analytical contribution from the basic patricklinearised element
512 RefineableLinearisedAxisymmetricQCrouzeixRaviartElement::
513 fill_in_contribution_to_jacobian(residuals, jacobian);
514
515 // Get the off-diagonal terms by finite differencing
516 this->fill_in_jacobian_from_external_interaction_by_fd(residuals, jacobian);
517 }
518};
cstr elem_len * i
Definition: cfortran.h:603
////////////////////////////////////////////////////////////////////// //////////////////////////////...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute the element's residual vector and the Jacobian matrix.
LinearisedAxisymmetricQCrouzeixRaviartMultiDomainElement()
Constructor: call the underlying constructors.
virtual void get_base_flow_dudx(const double &time, const unsigned &ipt, const Vector< double > &x, DenseMatrix< double > &result) const
Overload get_base_flow_dudx(...) to return the derivatives of the external element's velocity compone...
virtual void get_base_flow_u(const double &time, const unsigned &ipt, const Vector< double > &x, Vector< double > &result) const
Overload get_base_flow_u(...) to return the external element's velocity components at the integration...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
virtual void get_base_flow_u(const double &time, const unsigned &ipt, const Vector< double > &x, Vector< double > &result) const
Overload get_base_flow_u(...) to return the external element's velocity components at the integration...
LinearisedAxisymmetricQTaylorHoodMultiDomainElement()
Constructor: call the underlying constructors.
virtual void get_base_flow_dudx(const double &time, const unsigned &ipt, const Vector< double > &x, DenseMatrix< double > &result) const
Overload get_base_flow_dudx(...) to return the derivatives of the external element's velocity compone...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute the element's residual vector and the Jacobian matrix.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute the element's residual vector and the Jacobian matrix.
virtual void get_base_flow_u(const double &time, const unsigned &ipt, const Vector< double > &x, Vector< double > &result) const
Overload get_base_flow_u(...) to return the external element's velocity components at the integration...
virtual void get_base_flow_dudx(const double &time, const unsigned &ipt, const Vector< double > &x, DenseMatrix< double > &result) const
Overload get_base_flow_dudx(...) to return the derivatives of the external element's velocity compone...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute the element's residual vector and the Jacobian matrix.
virtual void get_base_flow_u(const double &time, const unsigned &ipt, const Vector< double > &x, Vector< double > &result) const
Overload get_base_flow_u(...) to return the external element's velocity components at the integration...
virtual void get_base_flow_dudx(const double &time, const unsigned &ipt, const Vector< double > &x, DenseMatrix< double > &result) const
Overload get_base_flow_dudx(...) to return the derivatives of the external element's velocity compone...
double interpolated_dudx_axi_nst(const Vector< double > &s, const unsigned &i, const unsigned &j) const
Return FE interpolated derivatives of velocity component u[i] w.r.t spatial global coordinate directi...
void interpolated_u_axi_nst(const Vector< double > &s, Vector< double > &veloc) const
Compute vector of FE interpolated velocity u at local coordinate s.
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////
This is a base class for all elements that require external sources (e.g. FSI, multi-domain problems ...
Vector< double > & external_element_local_coord(const unsigned &interaction_index, const unsigned &ipt)
Access function to get source element's local coords for specified interaction index at specified int...
void set_ninteraction(const unsigned &n_interaction)
Set the number of interactions in the element This function is usually called in the specific element...
void fill_in_jacobian_from_external_interaction_by_fd(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the contributions to the jacobian from all external interaction degrees of freedom (geometr...
FiniteElement *& external_element_pt(const unsigned &interaction_index, const unsigned &ipt)
Access function to source element for specified interaction index at specified integration point.
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...