time_harmonic_fourier_decomposed_linear_elasticity_traction_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 file for elements that are used to apply surface loads to
27 // the equations of time-harmonic Fourier decomposed linear elasticity
28 
29 #ifndef OOMPH_FOURIER_DECOMPOSED_TIME_HARMONIC_LINEAR_ELASTICITY_TRACTION_ELEMENTS_HEADER
30 #define OOMPH_FOURIER_DECOMPOSED_TIME_HARMONIC_LINEAR_ELASTICITY_TRACTION_ELEMENTS_HEADER
31 
32 // Config header generated by autoconfig
33 #ifdef HAVE_CONFIG_H
34 #include <oomph-lib-config.h>
35 #endif
36 
37 
38 // OOMPH-LIB headers
39 //#include "../generic/Qelements.h"
40 #include "src/generic/Qelements.h"
41 
42 namespace oomph
43 {
44  //=======================================================================
47  //=======================================================================
48  namespace TimeHarmonicFourierDecomposedLinearElasticityTractionElementHelper
49  {
50  //=======================================================================
52  //=======================================================================
54  const Vector<double>& N,
55  Vector<std::complex<double>>& load)
56  {
57  unsigned n_dim = load.size();
58  for (unsigned i = 0; i < n_dim; i++)
59  {
60  load[i] = std::complex<double>(0.0, 0.0);
61  }
62  }
63 
64  } // namespace
65  // TimeHarmonicFourierDecomposedLinearElasticityTractionElementHelper
66 
67 
68  //======================================================================
74  //======================================================================
75  template<class ELEMENT>
77  : public virtual FaceGeometry<ELEMENT>,
78  public virtual FaceElement
79  {
80  protected:
84 
91  const Vector<double>& n,
93 
94 
100  virtual void get_traction(const unsigned& intpt,
101  const Vector<double>& x,
102  const Vector<double>& n,
103  Vector<std::complex<double>>& traction)
104  {
106  }
107 
108 
110  // This small level of indirection is required to avoid calling
111  // fill_in_contribution_to_residuals in fill_in_contribution_to_jacobian
112  // which causes all kinds of pain if overloading later on
114  Vector<double>& residuals);
115 
116 
117  public:
121  FiniteElement* const& element_pt, const int& face_index)
122  : FaceGeometry<ELEMENT>(), FaceElement()
123  {
124  // Attach the geometrical information to the element. N.B. This function
125  // also assigns nbulk_value from the required_nvalue of the bulk element
126  element_pt->build_face_element(face_index, this);
127 
128  // Find the dimension of the problem
129  unsigned n_dim = element_pt->nodal_dimension();
130 
131  // Find the index at which the displacement unknowns are stored
132  ELEMENT* cast_element_pt = dynamic_cast<ELEMENT*>(element_pt);
134  .resize(n_dim + 1);
135  for (unsigned i = 0; i < n_dim + 1; i++)
136  {
137  // this->
138  // U_index_time_harmonic_fourier_decomposed_linear_elasticity_traction[i].real()
139  // = cast_element_pt->
140  // u_index_time_harmonic_fourier_decomposed_linear_elasticity(i).real();
141  //
142  // this->
143  // U_index_time_harmonic_fourier_decomposed_linear_elasticity_traction[i].imag()
144  // = cast_element_pt->
145  // u_index_time_harmonic_fourier_decomposed_linear_elasticity(i).imag();
146 
147  this
148  ->U_index_time_harmonic_fourier_decomposed_linear_elasticity_traction
149  [i] =
150  cast_element_pt
151  ->u_index_time_harmonic_fourier_decomposed_linear_elasticity(i);
152  }
153 
154  // Zero traction
158  }
159 
160 
162  void (*&traction_fct_pt())(const Vector<double>& x,
163  const Vector<double>& n,
165  {
166  return Traction_fct_pt;
167  }
168 
169 
172  {
174  residuals);
175  }
176 
177 
180  DenseMatrix<double>& jacobian)
181  {
182  // Call the residuals
184  residuals);
185  }
186 
192  double zeta_nodal(const unsigned& n,
193  const unsigned& k,
194  const unsigned& i) const
195  {
196  return FaceElement::zeta_nodal(n, k, i);
197  }
198 
200  void output(std::ostream& outfile)
201  {
202  FiniteElement::output(outfile);
203  }
204 
206  void output(std::ostream& outfile, const unsigned& n_plot)
207  {
208  FiniteElement::output(outfile, n_plot);
209  }
210 
212  void output(FILE* file_pt)
213  {
214  FiniteElement::output(file_pt);
215  }
216 
218  void output(FILE* file_pt, const unsigned& n_plot)
219  {
220  FiniteElement::output(file_pt, n_plot);
221  }
222 
223 
227  void traction(const Vector<double>& s,
228  Vector<std::complex<double>>& traction);
229  };
230 
234 
235  //=====================================================================
239  //=====================================================================
240  template<class ELEMENT>
241  void TimeHarmonicFourierDecomposedLinearElasticityTractionElement<
242  ELEMENT>::traction(const Vector<double>& s,
243  Vector<std::complex<double>>& traction)
244  {
245  unsigned n_dim = this->nodal_dimension();
246 
247  // Position vector
248  Vector<double> x(n_dim);
249  interpolated_x(s, x);
250 
251  // Outer unit normal (only in r and z direction!)
252  Vector<double> unit_normal(n_dim);
253  outer_unit_normal(s, unit_normal);
254 
255  // Dummy
256  unsigned ipt = 0;
257 
258  // Traction vector
259  get_traction(ipt, x, unit_normal, traction);
260  }
261 
262 
263  //=====================================================================
266  //=====================================================================
267  template<class ELEMENT>
270  Vector<double>& residuals)
271  {
272  // Find out how many nodes there are
273  unsigned n_node = nnode();
274 
275 #ifdef PARANOID
276  // Find out how many positional dofs there are
277  unsigned n_position_type = this->nnodal_position_type();
278  if (n_position_type != 1)
279  {
280  throw OomphLibError("TimeHarmonicFourierDecomposedLinearElasticity is "
281  "not yet implemented for more than one position type",
284  }
285 #endif
286 
287  // Find out the dimension of the node
288  const unsigned n_dim = this->nodal_dimension();
289 
290  // Cache the nodal indices at which the displacement components are stored
291  std::vector<std::complex<unsigned>> u_nodal_index(n_dim + 1);
292  for (unsigned i = 0; i < n_dim + 1; i++)
293  {
294  // u_nodal_index[i].real() =
295  // this->
296  // U_index_time_harmonic_fourier_decomposed_linear_elasticity_traction[i].real();
297  //
298  // u_nodal_index[i].imag() =
299  // this->
300  // U_index_time_harmonic_fourier_decomposed_linear_elasticity_traction[i].imag();
301 
302  u_nodal_index[i] =
303  this
304  ->U_index_time_harmonic_fourier_decomposed_linear_elasticity_traction
305  [i];
306  }
307 
308  // Integer to hold the local equation number
309  int local_eqn = 0;
310 
311  // Set up memory for the shape functions
312  // Note that in this case, the number of lagrangian coordinates is always
313  // equal to the dimension of the nodes
314  Shape psi(n_node);
315  DShape dpsids(n_node, n_dim - 1);
316 
317  // Set the value of n_intpt
318  unsigned n_intpt = integral_pt()->nweight();
319 
320  // Loop over the integration points
321  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
322  {
323  // Get the integral weight
324  double w = integral_pt()->weight(ipt);
325 
326  // Only need to call the local derivatives
327  dshape_local_at_knot(ipt, psi, dpsids);
328 
329  // Calculate the Eulerian and Lagrangian coordinates
330  Vector<double> interpolated_x(n_dim, 0.0);
331 
332  // Also calculate the surface Vectors (derivatives wrt local coordinates)
333  DenseMatrix<double> interpolated_A(n_dim - 1, n_dim, 0.0);
334 
335  // Calculate displacements and derivatives
336  for (unsigned l = 0; l < n_node; l++)
337  {
338  // Loop over directions
339  for (unsigned i = 0; i < n_dim; i++)
340  {
341  // Calculate the Eulerian coords
342  const double x_local = nodal_position(l, i);
343  interpolated_x[i] += x_local * psi(l);
344 
345  // Loop over LOCAL derivative directions, to calculate the tangent(s)
346  for (unsigned j = 0; j < n_dim - 1; j++)
347  {
348  interpolated_A(j, i) += x_local * dpsids(l, j);
349  }
350  }
351  }
352 
353  // Now find the local metric tensor from the tangent Vectors
354  DenseMatrix<double> A(n_dim - 1);
355  for (unsigned i = 0; i < n_dim - 1; i++)
356  {
357  for (unsigned j = 0; j < n_dim - 1; j++)
358  {
359  // Initialise surface metric tensor to zero
360  A(i, j) = 0.0;
361 
362  // Take the dot product
363  for (unsigned k = 0; k < n_dim; k++)
364  {
365  A(i, j) += interpolated_A(i, k) * interpolated_A(j, k);
366  }
367  }
368  }
369 
370  // Get the outer unit normal
371  Vector<double> interpolated_normal(n_dim);
372  outer_unit_normal(ipt, interpolated_normal);
373 
374  // Find the determinant of the metric tensor
375  double Adet = 0.0;
376  switch (n_dim)
377  {
378  case 2:
379  Adet = A(0, 0);
380  break;
381  case 3:
382  Adet = A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0);
383  break;
384  default:
385  throw OomphLibError(
386  "Wrong dimension in "
387  "TimeHarmonicFourierDecomposedLinearElasticityTractionElement",
388  "TimeHarmonicFourierDecomposedLinearElasticityTractionElement::"
389  "fill_in_contribution_to_residuals()",
391  }
392 
393  // Premultiply the weights and the square-root of the determinant of
394  // the metric tensor
395  double W = w * sqrt(Adet);
396 
397  // Now calculate the load
398  Vector<std::complex<double>> traction(n_dim + 1);
399  get_traction(ipt, interpolated_x, interpolated_normal, traction);
400 
401  // Loop over the test functions, nodes of the element
402  for (unsigned l = 0; l < n_node; l++)
403  {
404  // Loop over the displacement components
405  for (unsigned i = 0; i < n_dim + 1; i++)
406  {
407  // Real eqn
408  local_eqn = this->nodal_local_eqn(l, u_nodal_index[i].real());
409  /*IF it's not a boundary condition*/
410  if (local_eqn >= 0)
411  {
412  // Add the loading terms to the residuals
413  residuals[local_eqn] -=
414  traction[i].real() * psi(l) * interpolated_x[0] * W;
415  }
416 
417  // Imag eqn
418  local_eqn = this->nodal_local_eqn(l, u_nodal_index[i].imag());
419  /*IF it's not a boundary condition*/
420  if (local_eqn >= 0)
421  {
422  // Add the loading terms to the residuals
423  residuals[local_eqn] -=
424  traction[i].imag() * psi(l) * interpolated_x[0] * W;
425  }
426  }
427  } // End of loop over shape functions
428  } // End of loop over integration points
429  }
430 
431 
432 } // namespace oomph
433 
434 #endif
AnnoyingScalar imag(const AnnoyingScalar &)
Definition: AnnoyingScalar.h:132
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
RowVector3d w
Definition: Matrix_resize_int.cpp:3
void load(Archive &ar, ParticleHandler &handl)
Definition: Particles.h:21
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:47
Definition: shape.h:278
Definition: elements.h:4338
int & face_index()
Definition: elements.h:4626
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
Definition: elements.h:4497
Definition: elements.h:4998
Definition: elements.h:1313
virtual void output(std::ostream &outfile)
Definition: elements.h:3050
virtual void build_face_element(const int &face_index, FaceElement *face_element_pt)
Definition: elements.cc:5132
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
Definition: elements.h:2484
Definition: oomph_definitions.h:222
Definition: shape.h:76
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:79
void traction(const Vector< double > &s, Vector< std::complex< double >> &traction)
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:242
void output(FILE *file_pt, const unsigned &n_plot)
C-style output function.
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:218
TimeHarmonicFourierDecomposedLinearElasticityTractionElement(FiniteElement *const &element_pt, const int &face_index)
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:120
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Fill in contribution from Jacobian.
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:179
void output(std::ostream &outfile)
Output function.
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:200
Vector< std::complex< unsigned > > U_index_time_harmonic_fourier_decomposed_linear_elasticity_traction
Index at which the i-th displacement component is stored.
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:83
void(*&)(const Vector< double > &x, const Vector< double > &n, Vector< std::complex< double >> &traction) traction_fct_pt()
Reference to the traction function pointer.
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:162
void fill_in_contribution_to_residuals_time_harmonic_fourier_decomposed_linear_elasticity_traction(Vector< double > &residuals)
Helper function that actually calculates the residuals.
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:269
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:192
void output(FILE *file_pt)
C_style output function.
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:212
void output(std::ostream &outfile, const unsigned &n_plot)
Output function.
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:206
virtual void get_traction(const unsigned &intpt, const Vector< double > &x, const Vector< double > &n, Vector< std::complex< double >> &traction)
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:100
void(* Traction_fct_pt)(const Vector< double > &x, const Vector< double > &n, Vector< std::complex< double >> &result)
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:90
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Return the residuals.
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:171
@ N
Definition: constructor.cpp:22
float real
Definition: datatypes.h:10
RealScalar s
Definition: level1_cplx_impl.h:130
char char char int int * k
Definition: level2_impl.h:374
@ W
Definition: quadtree.h:63
void Zero_traction_fct(const Vector< double > &x, const Vector< double > &N, Vector< std::complex< double >> &load)
Default load function (zero traction)
Definition: time_harmonic_fourier_decomposed_linear_elasticity_traction_elements.h:53
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2