multi_domain_linearised_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 "navier_stokes.h"
35
36// Use the oomph namespace
37using namespace oomph;
38
39
40/// //////////////////////////////////////////////////////////////////////
41/// //////////////////////////////////////////////////////////////////////
42/// //////////////////////////////////////////////////////////////////////
43
44
45//======================================================================
46/// Build a LinearisedQTaylorHood 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//======================================================================
52 : public virtual LinearisedQTaylorHoodElement,
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 QTaylorHoodElement<DIM>* base_flow_el_pt =
86 dynamic_cast<QTaylorHoodElement<DIM>*>(
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 DIM velocity components interpolated from the external element
98 for (unsigned i = 0; i < DIM; i++)
99 {
100 result[i] = base_flow_el_pt->interpolated_u_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 QTaylorHoodElement<DIM>* base_flow_el_pt =
119 dynamic_cast<QTaylorHoodElement<DIM>*>(
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 < DIM; i++)
132 {
133 // Loop over coordinate directions and get derivatives of velocity
134 // components from the external element
135 for (unsigned j = 0; j < DIM; j++)
136 {
137 result(i, j) = base_flow_el_pt->interpolated_dudx_nst(s_external, i, j);
138 }
139 }
140
141 } // End of overloaded get_base_flow_dudx function
142
143
144 /// Compute the element's residual vector and the Jacobian matrix
146 DenseMatrix<double>& jacobian)
147 {
148 // Get the analytical contribution from the basic linearised element
149 LinearisedQTaylorHoodElement::fill_in_contribution_to_jacobian(residuals,
150 jacobian);
151
152 // Get the off-diagonal terms by finite differencing
153 this->fill_in_jacobian_from_external_interaction_by_fd(residuals, jacobian);
154 }
155};
156
157
158/// //////////////////////////////////////////////////////////////////////
159/// //////////////////////////////////////////////////////////////////////
160/// //////////////////////////////////////////////////////////////////////
161
162
163//======================================================================
164/// Build a LinearisedQCrouzeixRaviart element that inherits
165/// from ElementWithExternalElement so that it can "communicate" with an
166/// axisymmetric Navier-Stokes element that provides the base flow
167/// velocities and their derivatives w.r.t. global coordinates (r and z)
168//======================================================================
170 : public virtual LinearisedQCrouzeixRaviartElement,
171 public virtual ElementWithExternalElement
172{
173public:
174 /// Constructor: call the underlying constructors
177 {
178 // There are two interactions: the base flow velocities and their
179 // derivatives w.r.t. global coordinates
180 this->set_ninteraction(2);
181
182 // Do not include any external interaction data when computing
183 // the element's Jacobian
184 // ElementWithExternalElement::ignore_external_interaction_data();
185
186 /// Do not include any external geometric data when computing
187 /// the element's Jacobian.
188 ElementWithExternalElement::ignore_external_geometric_data();
189 }
190
191 /// Overload get_base_flow_u(...) to return the external
192 /// element's velocity components at the integration point
193 virtual void get_base_flow_u(const double& time,
194 const unsigned& ipt,
195 const Vector<double>& x,
196 Vector<double>& result) const
197 {
198 // Set interaction index to 0
199 const unsigned interaction = 0;
200
201 // Get a pointer to the external element that computes the base flow.
202 // We know that it's an axisymmetric Navier-Stokes element.
203 const QCrouzeixRaviartElement<DIM>* base_flow_el_pt =
204 dynamic_cast<QCrouzeixRaviartElement<DIM>*>(
205 external_element_pt(interaction, ipt));
206
207 // Provide storage for local coordinates in the external element
208 // which correspond to the integration point ipt
209 Vector<double> s_external(2);
210
211 // Determine local coordinates in the external element which correspond
212 // to the integration point ipt
213 s_external = external_element_local_coord(interaction, ipt);
214
215 // Get the DIM velocity components interpolated from the external element
216 for (unsigned i = 0; i < DIM; i++)
217 {
218 result[i] = base_flow_el_pt->interpolated_u_nst(s_external, i);
219 }
220
221 } // End of overloaded get_base_flow_u function
222
223 /// Overload get_base_flow_dudx(...) to return the derivatives of
224 /// the external element's velocity components w.r.t. global coordinates
225 /// at the integration point
226 virtual void get_base_flow_dudx(const double& time,
227 const unsigned& ipt,
228 const Vector<double>& x,
229 DenseMatrix<double>& result) const
230 {
231 // Set interaction index to 1
232 const unsigned interaction = 1;
233
234 // Get a pointer to the external element that computes the base flow.
235 // We know that it's an axisymmetric Navier-Stokes element.
236 const QCrouzeixRaviartElement<DIM>* base_flow_el_pt =
237 dynamic_cast<QCrouzeixRaviartElement<DIM>*>(
238 external_element_pt(interaction, ipt));
239
240 // Provide storage for local coordinates in the external element
241 // which correspond to the integration point ipt
242 Vector<double> s_external(2);
243
244 // Determine local coordinates in the external element which correspond
245 // to the integration point ipt
246 s_external = external_element_local_coord(interaction, ipt);
247
248 // Loop over velocity components
249 for (unsigned i = 0; i < DIM; i++)
250 {
251 // Loop over coordinate directions and get derivatives of velocity
252 // components from the external element
253 for (unsigned j = 0; j < DIM; j++)
254 {
255 result(i, j) = base_flow_el_pt->interpolated_dudx_nst(s_external, i, j);
256 }
257 }
258
259 } // End of overloaded get_base_flow_dudx function
260
261
262 /// Compute the element's residual vector and the Jacobian matrix
264 DenseMatrix<double>& jacobian)
265 {
266 // Get the analytical contribution from the basic linearised element
267 LinearisedQCrouzeixRaviartElement::fill_in_contribution_to_jacobian(
268 residuals, jacobian);
269
270 // Get the off-diagonal terms by finite differencing
271 this->fill_in_jacobian_from_external_interaction_by_fd(residuals, jacobian);
272 }
273};
274
275
276/// //////////////////////////////////////////////////////////////////////
277/// //////////////////////////////////////////////////////////////////////
278/// //////////////////////////////////////////////////////////////////////
279
280
281//======================================================================
282/// Build a RefineableLinearisedQTaylorHood element
283/// that inherits from ElementWithExternalElement so that it can
284/// "communicate" with an axisymmetric Navier-Stokes element that
285/// provides the base flow velocities and their derivatives w.r.t.
286/// global coordinates (r and z)
287//======================================================================
290 public virtual ElementWithExternalElement
291{
292public:
293 /// Constructor: call the underlying constructors
296 {
297 // There are two interactions: the base flow velocities and their
298 // derivatives w.r.t. global coordinates
299 this->set_ninteraction(2);
300
301 // Do not include any external interaction data when computing
302 // the element's Jacobian
303 // ElementWithExternalElement::ignore_external_interaction_data();
304
305 /// Do not include any external geometric data when computing
306 /// the element's Jacobian.
307 ElementWithExternalElement::ignore_external_geometric_data();
308 }
309
310 /// Overload get_base_flow_u(...) to return the external
311 /// element's velocity components at the integration point
312 virtual void get_base_flow_u(const double& time,
313 const unsigned& ipt,
314 const Vector<double>& x,
315 Vector<double>& result) const
316 {
317 // Set interaction index to 0
318 const unsigned interaction = 0;
319
320 // Get a pointer to the external element that computes the base flow.
321 // We know that it's an axisymmetric Navier-Stokes element.
322 const QTaylorHoodElement<DIM>* base_flow_el_pt =
323 dynamic_cast<QTaylorHoodElement<DIM>*>(
324 external_element_pt(interaction, ipt));
325
326 // Provide storage for local coordinates in the external element
327 // which correspond to the integration point ipt
328 Vector<double> s_external(2);
329
330 // Determine local coordinates in the external element which correspond
331 // to the integration point ipt
332 s_external = external_element_local_coord(interaction, ipt);
333
334 // Get the three velocity components interpolated from the external element
335 for (unsigned i = 0; i < DIM; i++)
336 {
337 result[i] = base_flow_el_pt->interpolated_u_nst(s_external, i);
338 }
339
340 } // End of overloaded get_base_flow_u function
341
342 /// Overload get_base_flow_dudx(...) to return the derivatives of
343 /// the external element's velocity components w.r.t. global coordinates
344 /// at the integration point
345 virtual void get_base_flow_dudx(const double& time,
346 const unsigned& ipt,
347 const Vector<double>& x,
348 DenseMatrix<double>& result) const
349 {
350 // Set interaction index to 1
351 const unsigned interaction = 1;
352
353 // Get a pointer to the external element that computes the base flow.
354 // We know that it's an axisymmetric Navier-Stokes element.
355 const QTaylorHoodElement<DIM>* base_flow_el_pt =
356 dynamic_cast<QTaylorHoodElement<DIM>*>(
357 external_element_pt(interaction, ipt));
358
359 // Provide storage for local coordinates in the external element
360 // which correspond to the integration point ipt
361 Vector<double> s_external(2);
362
363 // Determine local coordinates in the external element which correspond
364 // to the integration point ipt
365 s_external = external_element_local_coord(interaction, ipt);
366
367 // Loop over velocity components
368 for (unsigned i = 0; i < DIM; i++)
369 {
370 // Loop over coordinate directions and get derivatives of velocity
371 // components from the external element
372 for (unsigned j = 0; j < DIM; j++)
373 {
374 result(i, j) = base_flow_el_pt->interpolated_dudx_nst(s_external, i, j);
375 }
376 }
377
378 } // End of overloaded get_base_flow_dudx function
379
380
381 /// Compute the element's residual vector and the Jacobian matrix
383 DenseMatrix<double>& jacobian)
384 {
385 // Get the analytical contribution from the basic patricklinearised element
386 RefineableLinearisedQTaylorHoodElement::fill_in_contribution_to_jacobian(
387 residuals, jacobian);
388
389 // Get the off-diagonal terms by finite differencing
390 this->fill_in_jacobian_from_external_interaction_by_fd(residuals, jacobian);
391 }
392};
393
394
395/// //////////////////////////////////////////////////////////////////////
396/// //////////////////////////////////////////////////////////////////////
397/// //////////////////////////////////////////////////////////////////////
398
399
400//======================================================================
401/// Build a RefineableLinearisedQCrouzeixRaviart element
402/// that inherits from ElementWithExternalElement so that it can
403/// "communicate" with an axisymmetric Navier-Stokes element that
404/// provides the base flow velocities and their derivatives w.r.t.
405/// global coordinates (r and z)
406//======================================================================
409 public virtual ElementWithExternalElement
410{
411public:
412 /// Constructor: call the underlying constructors
416 {
417 // There are two interactions: the base flow velocities and their
418 // derivatives w.r.t. global coordinates
419 this->set_ninteraction(2);
420
421 // Do not include any external interaction data when computing
422 // the element's Jacobian
423 // ElementWithExternalElement::ignore_external_interaction_data();
424
425 /// Do not include any external geometric data when computing
426 /// the element's Jacobian.
427 ElementWithExternalElement::ignore_external_geometric_data();
428 }
429
430 /// Overload get_base_flow_u(...) to return the external
431 /// element's velocity components at the integration point
432 virtual void get_base_flow_u(const double& time,
433 const unsigned& ipt,
434 const Vector<double>& x,
435 Vector<double>& result) const
436 {
437 // Set interaction index to 0
438 const unsigned interaction = 0;
439
440 // Get a pointer to the external element that computes the base flow.
441 // We know that it's an axisymmetric Navier-Stokes element.
442 const QCrouzeixRaviartElement<DIM>* base_flow_el_pt =
443 dynamic_cast<QCrouzeixRaviartElement<DIM>*>(
444 external_element_pt(interaction, ipt));
445
446 // Provide storage for local coordinates in the external element
447 // which correspond to the integration point ipt
448 Vector<double> s_external(2);
449
450 // Determine local coordinates in the external element which correspond
451 // to the integration point ipt
452 s_external = external_element_local_coord(interaction, ipt);
453
454 // Get the three velocity components interpolated from the external element
455 for (unsigned i = 0; i < DIM; i++)
456 {
457 result[i] = base_flow_el_pt->interpolated_u_nst(s_external, i);
458 }
459
460 } // End of overloaded get_base_flow_u function
461
462 /// Overload get_base_flow_dudx(...) to return the derivatives of
463 /// the external element's velocity components w.r.t. global coordinates
464 /// at the integration point
465 virtual void get_base_flow_dudx(const double& time,
466 const unsigned& ipt,
467 const Vector<double>& x,
468 DenseMatrix<double>& result) const
469 {
470 // Set interaction index to 1
471 const unsigned interaction = 1;
472
473 // Get a pointer to the external element that computes the base flow.
474 // We know that it's an axisymmetric Navier-Stokes element.
475 const QCrouzeixRaviartElement<DIM>* base_flow_el_pt =
476 dynamic_cast<QCrouzeixRaviartElement<DIM>*>(
477 external_element_pt(interaction, ipt));
478
479 // Provide storage for local coordinates in the external element
480 // which correspond to the integration point ipt
481 Vector<double> s_external(2);
482
483 // Determine local coordinates in the external element which correspond
484 // to the integration point ipt
485 s_external = external_element_local_coord(interaction, ipt);
486
487 // Loop over velocity components
488 for (unsigned i = 0; i < DIM; i++)
489 {
490 // Loop over coordinate directions and get derivatives of velocity
491 // components from the external element
492 for (unsigned j = 0; j < DIM; j++)
493 {
494 result(i, j) = base_flow_el_pt->interpolated_dudx_nst(s_external, i, j);
495 }
496 }
497
498 } // End of overloaded get_base_flow_dudx function
499
500
501 /// Compute the element's residual vector and the Jacobian matrix
503 DenseMatrix<double>& jacobian)
504 {
505 // Get the analytical contribution from the basic patricklinearised element
506 RefineableLinearisedQCrouzeixRaviartElement::
507 fill_in_contribution_to_jacobian(residuals, jacobian);
508
509 // Get the off-diagonal terms by finite differencing
510 this->fill_in_jacobian_from_external_interaction_by_fd(residuals, jacobian);
511 }
512};
cstr elem_len * i
Definition: cfortran.h:603
////////////////////////////////////////////////////////////////////// //////////////////////////////...
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.
LinearisedQCrouzeixRaviartMultiDomainElement()
Constructor: call the underlying constructors.
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...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
LinearisedQTaylorHoodMultiDomainElement()
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...
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...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute the element's residual vector and the Jacobian matrix.
RefineableLinearisedQCrouzeixRaviartMultiDomainElement()
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...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
RefineableLinearisedQTaylorHoodMultiDomainElement()
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...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute the element's residual vector and the Jacobian matrix.
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.
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
void interpolated_u_nst(const Vector< double > &s, Vector< double > &veloc) const
Compute vector of FE interpolated velocity u at local coordinate s.
double interpolated_dudx_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...
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...