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-2024 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
37 using 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 {
55 public:
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.
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
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 {
173 public:
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.
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
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 {
292 public:
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.
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
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 {
411 public:
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.
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
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 ...
void ignore_external_geometric_data()
Do not include any external geometric data when computing the element's Jacobian. This function shoul...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Add the elemental contribution to the jacobian matrix. and the residuals vector. Note that this funct...
Definition: elements.h:1739
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
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...
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...