pml_time_harmonic_linear_elasticity_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// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 // Non-inline functions for elements that solve the equations of linear
31 // elasticity in cartesian coordinates
32 
34 #include "../generic/complex_matrices.h"
35 
36 namespace oomph
37 {
38 
39 /// Static default value for square of frequency
40  template <unsigned DIM,class PML_ELEMENT>
41  double PMLTimeHarmonicLinearElasticityEquationsBase<DIM,PML_ELEMENT>::
42  Default_omega_sq_value=1.0;
43 
44 
45 //////////////////////////////////////////////////////////////////
46 //////////////////////////////////////////////////////////////////
47 //////////////////////////////////////////////////////////////////
48 
49 //======================================================================
50 /// Compute the strain tensor at local coordinate s
51 //======================================================================
52  template<unsigned DIM, class PML_ELEMENT>
54  const Vector<double> &s,
55  DenseMatrix<std::complex<double> >& strain) const
56  {
57 #ifdef PARANOID
58  if ((strain.ncol()!=DIM)||(strain.nrow()!=DIM))
59  {
60  std::ostringstream error_message;
61  error_message << "Strain matrix is " << strain.ncol() << " x "
62  << strain.nrow() << ", but dimension of the equations is "
63  << DIM << std::endl;
64  throw OomphLibError(error_message.str(),
65  OOMPH_CURRENT_FUNCTION,
66  OOMPH_EXCEPTION_LOCATION);
67  }
68 
69  //Find out how many position types there are
70  unsigned n_position_type = this->nnodal_position_type();
71 
72  if(n_position_type != 1)
73  {
74  std::ostringstream error_message;
75  error_message << "PMLTimeHarmonicLinearElasticity is not yet "
76  << "implemented for more than one position type"
77  << std::endl;
78  throw OomphLibError(error_message.str(),
79  OOMPH_CURRENT_FUNCTION,
80  OOMPH_EXCEPTION_LOCATION);
81  }
82 #endif
83 
84 
85  //Find out how many nodes there are in the element
86  unsigned n_node = nnode();
87 
88  //Find the indices at which the local velocities are stored
89  std::complex<unsigned> u_nodal_index[DIM];
90  for(unsigned i=0;i<DIM;i++)
91  {
92  u_nodal_index[i] = u_index_time_harmonic_linear_elasticity(i);
93  }
94 
95  //Set up memory for the shape and derivative functions
96  Shape psi(n_node);
97  DShape dpsidx(n_node,DIM);
98 
99  //Call the derivatives of the shape functions
100  (void) dshape_eulerian(s,psi,dpsidx);
101 
102  //Calculate interpolated values of the derivative of global position
104  interpolated_dudx(DIM,DIM,std::complex<double>(0.0,0.0));
105 
106  //Loop over nodes
107  for(unsigned l=0;l<n_node;l++)
108  {
109  //Loop over velocity components
110  for(unsigned i=0;i<DIM;i++)
111  {
112  //Get the nodal value
113  const std::complex<double> u_value=
114  std::complex<double>(this->nodal_value(l,u_nodal_index[i].real()),
115  this->nodal_value(l,u_nodal_index[i].imag()));
116 
117  //Loop over derivative directions
118  for(unsigned j=0;j<DIM;j++)
119  {
120  interpolated_dudx(i,j) += u_value*dpsidx(l,j);
121  }
122  }
123  }
124 
125  ///Now fill in the entries of the strain tensor
126  for(unsigned i=0;i<DIM;i++)
127  {
128  //Do upper half of matrix
129  //Note that j must be signed here for the comparison test to work
130  //Also i must be cast to an int
131  for(int j=(DIM-1);j>=static_cast<int>(i);j--)
132  {
133  //Off diagonal terms
134  if(static_cast<int>(i)!=j)
135  {
136  strain(i,j) =
137  0.5*(interpolated_dudx(i,j) + interpolated_dudx(j,i));
138  }
139  //Diagonal terms will including growth factor when it comes back in
140  else
141  {
142  strain(i,i) = interpolated_dudx(i,i);
143  }
144  }
145  //Matrix is symmetric so just copy lower half
146  for(int j=(i-1);j>=0;j--)
147  {
148  strain(i,j) = strain(j,i);
149  }
150  }
151  }
152 
153 
154 
155 
156 
157 //======================================================================
158 /// Compute the Cauchy stress tensor at local coordinate s for
159 /// displacement formulation.
160 //======================================================================
161 template<unsigned DIM, class PML_ELEMENT>
164  DenseMatrix<std::complex<double> >&stress) const
165 {
166 #ifdef PARANOID
167  if ((stress.ncol()!=DIM)||(stress.nrow()!=DIM))
168  {
169  std::ostringstream error_message;
170  error_message << "Stress matrix is " << stress.ncol() << " x "
171  << stress.nrow() << ", but dimension of the equations is "
172  << DIM << std::endl;
173  throw OomphLibError(error_message.str(),
174  OOMPH_CURRENT_FUNCTION,
175  OOMPH_EXCEPTION_LOCATION);
176  }
177 #endif
178 
179  // Get strain
180  DenseMatrix<std::complex<double> > strain(DIM,DIM);
181  this->get_strain(s,strain);
182 
183  // Now fill in the entries of the stress tensor without exploiting
184  // symmetry -- sorry too lazy. This fct is only used for
185  // postprocessing anyway...
186  for(unsigned i=0;i<DIM;i++)
187  {
188  for(unsigned j=0;j<DIM;j++)
189  {
190  stress(i,j) = 0.0;
191  for (unsigned k=0;k<DIM;k++)
192  {
193  for (unsigned l=0;l<DIM;l++)
194  {
195  stress(i,j)+=this->E(i,j,k,l)*strain(k,l);
196  }
197  }
198  }
199  }
200 }
201 
202 
203 //=======================================================================
204 /// Compute the residuals for the linear elasticity equations in
205 /// cartesian coordinates. Flag indicates if we want Jacobian too.
206 //=======================================================================
207 template <unsigned DIM, class PML_ELEMENT>
210  Vector<double> &residuals, DenseMatrix<double> &jacobian,unsigned flag)
211 {
212  //Find out how many nodes there are
213  unsigned n_node = this->nnode();
214 
215 #ifdef PARANOID
216  //Find out how many positional dofs there are
217  unsigned n_position_type = this->nnodal_position_type();
218 
219  if(n_position_type != 1)
220  {
221  std::ostringstream error_message;
222  error_message << "PMLTimeHarmonicLinearElasticity is not yet "
223  << "implemented for more than one position type"
224  << std::endl;
225  throw OomphLibError(error_message.str(),
226  OOMPH_CURRENT_FUNCTION,
227  OOMPH_EXCEPTION_LOCATION);
228  }
229 
230  //Throw and error if an elasticity tensor has not been set
231  if(this->Elasticity_tensor_pt==0)
232  {
233  throw OomphLibError(
234  "No elasticity tensor set.",
235  OOMPH_CURRENT_FUNCTION,
236  OOMPH_EXCEPTION_LOCATION);
237  }
238 #endif
239 
240  //Find the indices at which the local velocities are stored
241  std::complex<unsigned> u_nodal_index[DIM];
242  for(unsigned i=0;i<DIM;i++)
243  {
244  u_nodal_index[i] = this->u_index_time_harmonic_linear_elasticity(i);
245  }
246 
247 
248  // Square of non-dimensional frequency
249  const double omega_sq_local = this->omega_sq();
250 
251  //Set up memory for the shape functions
252  Shape psi(n_node);
253  DShape dpsidx(n_node,DIM);
254 
255  //Set the value of Nintpt -- the number of integration points
256  unsigned n_intpt = this->integral_pt()->nweight();
257 
258  //Set the vector to hold the local coordinates in the element
259  Vector<double> s(DIM);
260 
261  //Integers to store the local equation numbers
262  int local_eqn_real=0, local_unknown_real=0;
263  int local_eqn_imag=0, local_unknown_imag=0;
264 
265  //Loop over the integration points
266  for(unsigned ipt=0;ipt<n_intpt;ipt++)
267  {
268  //Assign the values of s
269  for(unsigned i=0;i<DIM;++i)
270  {
271  s[i] = this->integral_pt()->knot(ipt,i);
272  }
273 
274  //Get the integral weight
275  double w = this->integral_pt()->weight(ipt);
276 
277  //Call the derivatives of the shape functions (and get Jacobian)
278  double J = this->dshape_eulerian_at_knot(ipt,psi,dpsidx);
279 
280  //Storage for Eulerian coordinates (initialised to zero)
281  Vector<double> interpolated_x(DIM,0.0);
282 
283  // Displacement
285  interpolated_u(DIM,std::complex<double>(0.0,0.0));
286 
287  //Calculate interpolated values of the derivative of global position
288  //wrt lagrangian coordinates
290  interpolated_dudx(DIM,DIM,std::complex<double>(0.0,0.0));
291 
292  //Calculate displacements and derivatives
293  for(unsigned l=0;l<n_node;l++)
294  {
295  //Loop over displacement components (deformed position)
296  for(unsigned i=0;i<DIM;i++)
297  {
298  //Calculate the Lagrangian coordinates and the accelerations
299  interpolated_x[i] += this->raw_nodal_position(l,i)*psi(l);
300 
301 
302  //Get the nodal displacements
303  const std::complex<double> u_value
304  = std::complex<double>(
305  this->raw_nodal_value(l,u_nodal_index[i].real()),
306  this->raw_nodal_value(l,u_nodal_index[i].imag()));
307 
308  interpolated_u[i]+=u_value*psi(l);
309 
310  //Loop over derivative directions
311  for(unsigned j=0;j<DIM;j++)
312  {
313  interpolated_dudx(i,j) += u_value*dpsidx(l,j);
314  }
315  }
316  }
317 
318  //Get body force
319  Vector<std::complex<double> > body_force_vec(DIM);
320  this->body_force(interpolated_x,body_force_vec);
321 
322  //Premultiply the weights and the Jacobian
323  double W = w*J;
324 
325 
326  /// \short All the PML weights that participate in the assemby process
327  /// are computed here. pml_inverse_jacobian_diagonals are are used to
328  /// transform derivatives in real x to derivatives in transformed space
329  /// \f$\tilde x \f$.
330  /// pml_jacobian_det allows us to transform volume integrals in
331  /// transformed space to real space.
332  /// If the PML is not enabled via enable_pml, both default to 1.0.
333  DiagonalComplexMatrix pml_jacobian(DIM);
334  this->pml_transformation_jacobian(ipt, s, interpolated_x,
335  pml_jacobian);
336 
337  std::complex<double> pml_jacobian_det;
338  DiagonalComplexMatrix pml_jacobian_inverse(DIM);
339  this->compute_jacobian_inverse_and_det(pml_jacobian, pml_jacobian_inverse,
340  pml_jacobian_det);
341 
342 
343  //Loop over the test functions, nodes of the element
344  for(unsigned l=0;l<n_node;l++)
345  {
346  //Loop over the displacement components
347  for(unsigned a=0;a<DIM;a++)
348  {
349  //Get real and imaginary equation numbers
350  local_eqn_real = this->nodal_local_eqn(l,u_nodal_index[a].real());
351  local_eqn_imag = this->nodal_local_eqn(l,u_nodal_index[a].imag());
352 
353  //===== EQUATIONS OF PML TIME HARMONIC LINEAR ELASTICITY ========
354  // (This is where the maths happens)
355 
356  // Calculate jacobian and residual contributions from acceleration and
357  // body force
358  std::complex<double> mass_jacobian_contribution =
359  -omega_sq_local*pml_jacobian_det;
360  std::complex<double> mass_residual_contribution =
361  (-omega_sq_local*interpolated_u[a]-body_force_vec[a])*pml_jacobian_det;
362 
363  // Calculate jacobian and residual contributions from stress term
364  std::complex<double> stress_jacobian_contributions[DIM][DIM][DIM];
365  std::complex<double> stress_residual_contributions[DIM];
366  for(unsigned b=0;b<DIM;b++)
367  {
368  stress_residual_contributions[b] = 0.0;
369  for(unsigned c=0;c<DIM;c++)
370  {
371  for(unsigned d=0;d<DIM;d++)
372  {
373  stress_jacobian_contributions[b][c][d] =
374  this->E(a,b,c,d)*pml_jacobian_det
375  *pml_jacobian_inverse(b,b)
376  *pml_jacobian_inverse(d,d);
377 
378  stress_residual_contributions[b] +=
379  stress_jacobian_contributions[b][c][d]*interpolated_dudx(c,d);
380  }
381  }
382  }
383 
384  //===== ADD CONTRIBUTIONS TO GLOBAL RESIDUALS AND JACOBIAN ========
385 
386  /*IF it's not a boundary condition*/
387  if(local_eqn_real >= 0)
388  {
389  // Acceleration and body force
390  residuals[local_eqn_real] += mass_residual_contribution.real()
391  *psi(l)*W;
392 
393  // Stress term
394  for(unsigned b=0;b<DIM;b++)
395  {
396  //Add the stress terms to the residuals
397  residuals[local_eqn_real] += stress_residual_contributions[b].real()
398  *dpsidx(l,b)*W;
399  }
400 
401  //Jacobian entries
402  if(flag)
403  {
404  //Loop over the displacement basis functions again
405  for(unsigned l2=0;l2<n_node;l2++)
406  {
407  //Loop over the displacement components again
408  for(unsigned c=0;c<DIM;c++)
409  {
410  local_unknown_real=
411  this->nodal_local_eqn(l2,u_nodal_index[c].real());
412  local_unknown_imag=
413  this->nodal_local_eqn(l2,u_nodal_index[c].imag());
414  //If it's not pinned
415  if(local_unknown_real >= 0)
416  {
417  // Inertial term
418  if (a==c)
419  {
420  jacobian(local_eqn_real,local_unknown_real) +=
421  mass_jacobian_contribution.real()*psi(l)*psi(l2)*W;
422  }
423 
424  // Stress term
425  for(unsigned b=0;b<DIM;b++)
426  {
427  for(unsigned d=0;d<DIM;d++)
428  {
429  //Add the contribution to the Jacobian matrix
430  jacobian(local_eqn_real,local_unknown_real) +=
431  stress_jacobian_contributions[b][c][d].real()
432  *dpsidx(l2,d)*dpsidx(l,b)*W;
433  }
434  }
435  } //End of if not boundary condition
436 
437  if(local_unknown_imag >= 0)
438  {
439  // Inertial term
440  if (a==c)
441  {
442  jacobian(local_eqn_real,local_unknown_imag) -=
443  mass_jacobian_contribution.imag()*psi(l)*psi(l2)*W;
444  }
445 
446  // Stress term
447  for(unsigned b=0;b<DIM;b++)
448  {
449  for(unsigned d=0;d<DIM;d++)
450  {
451  //Add the contribution to the Jacobian matrix
452  jacobian(local_eqn_real,local_unknown_imag) -=
453  stress_jacobian_contributions[b][c][d].imag()
454  *dpsidx(l2,d)*dpsidx(l,b)*W;
455  }
456  }
457  } //End of if not boundary condition
458 
459  }
460  }
461  } //End of jacobian calculation
462 
463  } //End of if not boundary condition for real eqn
464 
465 
466  /*IF it's not a boundary condition*/
467  if(local_eqn_imag >= 0)
468  {
469  // Acceleration and body force
470  residuals[local_eqn_imag] += mass_residual_contribution.imag()
471  *psi(l)*W;
472 
473  // Stress term
474  for(unsigned b=0;b<DIM;b++)
475  {
476  //Add the stress terms to the residuals
477  residuals[local_eqn_imag] += stress_residual_contributions[b].imag()
478  *dpsidx(l,b)*W;
479  }
480 
481  //Jacobian entries
482  if(flag)
483  {
484  //Loop over the displacement basis functions again
485  for(unsigned l2=0;l2<n_node;l2++)
486  {
487  //Loop over the displacement components again
488  for(unsigned c=0;c<DIM;c++)
489  {
490  local_unknown_imag=
491  this->nodal_local_eqn(l2,u_nodal_index[c].imag());
492  local_unknown_real=
493  this->nodal_local_eqn(l2,u_nodal_index[c].real());
494  //If it's not pinned
495  if(local_unknown_imag >= 0)
496  {
497  // Inertial term
498  if (a==c)
499  {
500  jacobian(local_eqn_imag,local_unknown_imag) +=
501  mass_jacobian_contribution.real()*psi(l)*psi(l2)*W;
502  }
503 
504  // Stress term
505  for(unsigned b=0;b<DIM;b++)
506  {
507  for(unsigned d=0;d<DIM;d++)
508  {
509  //Add the contribution to the Jacobian matrix
510  jacobian(local_eqn_imag,local_unknown_imag) +=
511  stress_jacobian_contributions[b][c][d].real()
512  *dpsidx(l2,d)*dpsidx(l,b)*W;
513  }
514  }
515  } //End of if not boundary condition
516 
517  if(local_unknown_real >= 0)
518  {
519  // Inertial term
520  if (a==c)
521  {
522  jacobian(local_eqn_imag,local_unknown_real) +=
523  mass_jacobian_contribution.imag()*psi(l)*psi(l2)*W;
524  }
525 
526  // Stress term
527  for(unsigned b=0;b<DIM;b++)
528  {
529  for(unsigned d=0;d<DIM;d++)
530  {
531  //Add the contribution to the Jacobian matrix
532  jacobian(local_eqn_imag,local_unknown_real) +=
533  stress_jacobian_contributions[b][c][d].imag()
534  *dpsidx(l2,d)*dpsidx(l,b)*W;
535  }
536  }
537  } //End of if not boundary condition
538 
539  }
540  }
541  } //End of jacobian calculation
542 
543  } //End of if not boundary condition for imag eqn
544 
545  } //End of loop over coordinate directions
546  } //End of loop over shape functions
547  } //End of loop over integration points
548 
549  }
550 
551 //=======================================================================
552 /// Output exact solution x,y,[z],u_r,v_r,[w_r],u_i,v_i,[w_i]
553 //=======================================================================
554  template <unsigned DIM, class PML_ELEMENT>
556  std::ostream &outfile,
557  const unsigned &nplot,
559  {
560  //Vector of local coordinates
561  Vector<double> s(DIM);
562 
563  // Vector for coordintes
564  Vector<double> x(DIM);
565 
566  // Tecplot header info
567  outfile << this->tecplot_zone_string(nplot);
568 
569  // Exact solution Vector
570  Vector<double> exact_soln(2*DIM);
571 
572  // Loop over plot points
573  unsigned num_plot_points=this->nplot_points(nplot);
574  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
575  {
576 
577  // Get local coordinates of plot point
578  this->get_s_plot(iplot,nplot,s);
579 
580  // Get x position as Vector
581  this->interpolated_x(s,x);
582 
583  // Get exact solution at this point
584  (*exact_soln_pt)(x,exact_soln);
585 
586  //Output x,y,...,u_exact,...
587  for(unsigned i=0;i<DIM;i++)
588  {
589  outfile << x[i] << " ";
590  }
591  for(unsigned i=0;i<2*DIM;i++)
592  {
593  outfile << exact_soln[i] << " ";
594  }
595  outfile << std::endl;
596  }
597 
598  // Write tecplot footer (e.g. FE connectivity lists)
599  this->write_tecplot_zone_footer(outfile,nplot);
600 
601  }
602 
603 
604 
605 //=======================================================================
606 /// Output: x,y,[z],u,v,[w]
607 //=======================================================================
608  template <unsigned DIM, class PML_ELEMENT>
610  std::ostream &outfile, const unsigned &nplot)
611  {
612  // Initialise local coord, global coord and solution vectors
613  Vector<double> s(DIM);
614  Vector<double> x(DIM);
616 
617  // Tecplot header info
618  outfile << this->tecplot_zone_string(nplot);
619 
620  // Loop over plot points
621  unsigned num_plot_points=this->nplot_points(nplot);
622  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
623  {
624 
625  // Get local coordinates of plot point
626  this->get_s_plot(iplot,nplot,s);
627 
628  // Get Eulerian coordinates and displacements
629  this->interpolated_x(s,x);
630  this->interpolated_u_time_harmonic_linear_elasticity(s,u);
631 
632  //Output the x,y,..
633  for(unsigned i=0;i<DIM;i++)
634  {outfile << x[i] << " ";}
635 
636  // Output u,v,..
637  for(unsigned i=0;i<DIM;i++)
638  {outfile << u[i].real() << " ";}
639 
640  // Output u,v,..
641  for(unsigned i=0;i<DIM;i++)
642  {outfile << u[i].imag() << " ";}
643 
644  outfile << std::endl;
645  }
646 
647  // Write tecplot footer (e.g. FE connectivity lists)
648  this->write_tecplot_zone_footer(outfile,nplot);
649  }
650 
651 
652 //======================================================================
653 /// Output function for real part of full time-dependent solution
654 /// constructed by adding the scattered field
655 ///
656 /// u = Re( (u_r +i u_i) exp(-i omega t)
657 ///
658 /// at phase angle omega t = phi computed here, to the corresponding
659 /// incoming wave specified via the function pointer.
660 ///
661 /// x,y,u or x,y,z,u
662 ///
663 /// Output at nplot points in each coordinate direction
664 //======================================================================
665 template <unsigned DIM, class PML_ELEMENT>
667  std::ostream &outfile,
668  FiniteElement::SteadyExactSolutionFctPt incoming_wave_fct_pt,
669  const double& phi,
670  const unsigned &nplot)
671 {
672 
673  // Initialise local coord, global coord and solution vectors
674  Vector<double> s(DIM);
675  Vector<double> x(DIM);
677 
678  // Real and imag part of incoming wave
679  Vector<double> incoming_soln(2*DIM);
680 
681  // Tecplot header info
682  outfile << this->tecplot_zone_string(nplot);
683 
684  // Loop over plot points
685  unsigned num_plot_points=this->nplot_points(nplot);
686  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
687  {
688  // Get local coordinates of plot point
689  this->get_s_plot(iplot,nplot,s);
690 
691  // Get Eulerian coordinates and displacements
692  this->interpolated_x(s,x);
693  this->interpolated_u_time_harmonic_linear_elasticity(s,u);
694 
695  // Get exact solution at this point
696  (*incoming_wave_fct_pt)(x,incoming_soln);
697 
698  //Output the x,y,..
699  for(unsigned i=0;i<DIM;i++)
700  {outfile << x[i] << " ";}
701 
702  // Output u,v,..
703  for(unsigned i=0;i<DIM;i++)
704  {
705  outfile << (u[i].real()+incoming_soln[2*i])*cos(phi)+
706  (u[i].imag()+incoming_soln[2*i+1])*sin(phi) << " ";
707  }
708 
709  outfile << std::endl;
710 
711  }
712 
713  // Write tecplot footer (e.g. FE connectivity lists)
714  this->write_tecplot_zone_footer(outfile,nplot);
715 
716 }
717 
718 //======================================================================
719 /// Output function for imaginary part of full time-dependent solution
720 ///
721 /// u = Im( (u_r +i u_i) exp(-i omega t))
722 ///
723 /// at phase angle omega t = phi.
724 ///
725 /// x,y,u or x,y,z,u
726 ///
727 /// Output at nplot points in each coordinate direction
728 //======================================================================
729 template <unsigned DIM, class PML_ELEMENT>
731  ::output_real(std::ostream &outfile,
732  const double& phi,
733  const unsigned &nplot)
734 {
735 
736  // Initialise local coord, global coord and solution vectors
737  Vector<double> s(DIM);
738  Vector<double> x(DIM);
740 
741  // Tecplot header info
742  outfile << this->tecplot_zone_string(nplot);
743 
744  // Loop over plot points
745  unsigned num_plot_points=this->nplot_points(nplot);
746  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
747  {
748 
749  // Get local coordinates of plot point
750  this->get_s_plot(iplot,nplot,s);
751 
752  // Get Eulerian coordinates and displacements
753  this->interpolated_x(s,x);
754  this->interpolated_u_time_harmonic_linear_elasticity(s,u);
755 
756  //Output the x,y,..
757  for(unsigned i=0;i<DIM;i++)
758  {outfile << x[i] << " ";}
759 
760  // Output u,v,..
761  for(unsigned i=0;i<DIM;i++)
762  {
763  outfile << u[i].real()*cos(phi)+ u[i].imag()*sin(phi) << " ";
764  }
765 
766  outfile << std::endl;
767 
768  }
769 
770  // Write tecplot footer (e.g. FE connectivity lists)
771  this->write_tecplot_zone_footer(outfile,nplot);
772 
773 }
774 
775 //======================================================================
776 /// Output function for imaginary part of full time-dependent solution
777 ///
778 /// u = Im( (u_r +i u_i) exp(-i omega t))
779 ///
780 /// at phase angle omega t = phi.
781 ///
782 /// x,y,u or x,y,z,u
783 ///
784 /// Output at nplot points in each coordinate direction
785 //======================================================================
786 template <unsigned DIM, class PML_ELEMENT>
788  ::output_imag(std::ostream &outfile,
789  const double& phi,
790  const unsigned &nplot)
791 {
792 
793  // Initialise local coord, global coord and solution vectors
794  Vector<double> s(DIM);
795  Vector<double> x(DIM);
797 
798  // Tecplot header info
799  outfile << this->tecplot_zone_string(nplot);
800 
801  // Loop over plot points
802  unsigned num_plot_points=this->nplot_points(nplot);
803  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
804  {
805 
806  // Get local coordinates of plot point
807  this->get_s_plot(iplot,nplot,s);
808 
809  // Get Eulerian coordinates and displacements
810  this->interpolated_x(s,x);
811  this->interpolated_u_time_harmonic_linear_elasticity(s,u);
812 
813  //Output the x,y,..
814  for(unsigned i=0;i<DIM;i++)
815  {outfile << x[i] << " ";}
816 
817  // Output u,v,..
818  for(unsigned i=0;i<DIM;i++)
819  {
820  outfile << u[i].imag()*cos(phi)- u[i].real()*sin(phi) << " ";
821  }
822 
823  outfile << std::endl;
824 
825  }
826 
827  // Write tecplot footer (e.g. FE connectivity lists)
828  this->write_tecplot_zone_footer(outfile,nplot);
829 
830 }
831 
832 
833 //=======================================================================
834 /// C-style output: x,y,[z],u,v,[w]
835 //=======================================================================
836 template <unsigned DIM, class PML_ELEMENT>
838  FILE* file_pt, const unsigned &nplot)
839 {
840  //Vector of local coordinates
841  Vector<double> s(DIM);
842 
843  // Tecplot header info
844  fprintf(file_pt,"%s",this->tecplot_zone_string(nplot).c_str());
845 
846  // Loop over plot points
847  unsigned num_plot_points=this->nplot_points(nplot);
848  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
849  {
850  // Get local coordinates of plot point
851  this->get_s_plot(iplot,nplot,s);
852 
853  // Coordinates
854  for(unsigned i=0;i<DIM;i++)
855  {
856  fprintf(file_pt,"%g ",this->interpolated_x(s,i));
857  }
858 
859  // Displacement
860  for(unsigned i=0;i<DIM;i++)
861  {
862  fprintf(file_pt,"%g ",
863  this->interpolated_u_time_harmonic_linear_elasticity(s,i).real());
864  }
865  for(unsigned i=0;i<DIM;i++)
866  {
867  fprintf(file_pt,"%g ",
868  this->interpolated_u_time_harmonic_linear_elasticity(s,i).imag());
869  }
870  }
871  fprintf(file_pt,"\n");
872 
873  // Write tecplot footer (e.g. FE connectivity lists)
874  this->write_tecplot_zone_footer(file_pt,nplot);
875 
876 }
877 
878 
879 //=======================================================================
880 /// Compute norm of the solution
881 //=======================================================================
882 template <unsigned DIM, class PML_ELEMENT>
884  double& norm)
885 {
886 
887  // Initialise
888  norm=0.0;
889 
890  //Vector of local coordinates
891  Vector<double> s(DIM);
892 
893  // Vector for coordintes
894  Vector<double> x(DIM);
895 
896  // Displacement vector
897  Vector<std::complex<double> > disp(DIM);
898 
899  //Find out how many nodes there are in the element
900  unsigned n_node = this->nnode();
901 
902  Shape psi(n_node);
903 
904  //Set the value of n_intpt
905  unsigned n_intpt = this->integral_pt()->nweight();
906 
907  //Loop over the integration points
908  for(unsigned ipt=0;ipt<n_intpt;ipt++)
909  {
910 
911  //Assign values of s
912  for(unsigned i=0;i<DIM;i++)
913  {
914  s[i] = this->integral_pt()->knot(ipt,i);
915  }
916 
917  //Get the integral weight
918  double w = this->integral_pt()->weight(ipt);
919 
920  // Get jacobian of mapping
921  double J = this->J_eulerian(s);
922 
923  //Premultiply the weights and the Jacobian
924  double W = w*J;
925 
926  // Get FE function value
927  this->interpolated_u_time_harmonic_linear_elasticity(s,disp);
928 
929  // Add to norm
930  for (unsigned ii=0;ii<DIM;ii++)
931  {
932  norm+=(disp[ii].real()*disp[ii].real()+disp[ii].imag()*disp[ii].imag())*W;
933  }
934  }
935 }
936 
937 //======================================================================
938  /// Validate against exact solution
939  ///
940  /// Solution is provided via function pointer.
941  ///
942 //======================================================================
943 template <unsigned DIM, class PML_ELEMENT>
945  std::ostream &outfile,
947  double& error, double& norm)
948 {
949 
950  // Initialise
951  error=0.0;
952  norm=0.0;
953 
954  //Vector of local coordinates
955  Vector<double> s(DIM);
956 
957  // Vector for coordintes
958  Vector<double> x(DIM);
959 
960  // Displacement vector
961  Vector<std::complex<double> > disp(DIM);
962 
963  //Find out how many nodes there are in the element
964  unsigned n_node = this->nnode();
965 
966  Shape psi(n_node);
967 
968  //Set the value of n_intpt
969  unsigned n_intpt = this->integral_pt()->nweight();
970 
971  // Exact solution Vector
972  Vector<double> exact_soln(2*DIM);
973 
974  //Loop over the integration points
975  for(unsigned ipt=0;ipt<n_intpt;ipt++)
976  {
977 
978  //Assign values of s
979  for(unsigned i=0;i<DIM;i++)
980  {
981  s[i] = this->integral_pt()->knot(ipt,i);
982  }
983 
984  //Get the integral weight
985  double w = this->integral_pt()->weight(ipt);
986 
987  // Get jacobian of mapping
988  double J = this->J_eulerian(s);
989 
990  //Premultiply the weights and the Jacobian
991  double W = w*J;
992 
993  // Get x position as Vector
994  this->interpolated_x(s,x);
995 
996  // Get exact solution at this point
997  (*exact_soln_pt)(x,exact_soln);
998 
999  // Get FE function value
1000  this->interpolated_u_time_harmonic_linear_elasticity(s,disp);
1001 
1002  // Add to norm
1003  for (unsigned ii=0;ii<DIM;ii++)
1004  {
1005  // Add to error and norm
1006  error+=((exact_soln[ii]-disp[ii].real())
1007  *(exact_soln[ii]-disp[ii].real())+
1008  (exact_soln[ii+DIM]-disp[ii].imag())
1009  *(exact_soln[ii+DIM]-disp[ii].imag()))*W;
1010  norm+=(disp[ii].real()*disp[ii].real()+disp[ii].imag()*disp[ii].imag())*W;
1011  }
1012  }
1013 }
1014 
1015 template<unsigned DIM, class PML_ELEMENT>
1017 
1018 //Instantiate the required elements
1021 
1025 
1026 }
void output_fct(std::ostream &outfile, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact solution x,y,[z],u_r,v_r,[w_r],u_i,v_i,[w_i].
cstr elem_len * i
Definition: cfortran.h:607
void get_stress(const Vector< double > &s, DenseMatrix< std::complex< double > > &sigma) const
Return the Cauchy stress tensor, as calculated from the elasticity tensor at specified local coordina...
void compute_norm(double &norm)
Compute norm of solution: square of the L2 norm.
void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Get error against and norm of exact solution.
void output_real(std::ostream &outfile, const double &phi, const unsigned &n_plot)
Output function for real part of full time-dependent solution u = Re( (u_r +i u_i) exp(-i omega t)) a...
virtual void fill_in_generic_contribution_to_residuals_time_harmonic_linear_elasticity(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Private helper function to compute residuals and (if requested via flag) also the Jacobian matrix...
void output(std::ostream &outfile)
Output: x,y,[z],u_r,v_r,[w_r],u_i,v_i,[w_i].
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as ...
Definition: elements.h:1723
static char t char * s
Definition: cfortran.h:572
void get_strain(const Vector< double > &s, DenseMatrix< std::complex< double > > &strain) const
Return the strain tensor.
void output_total_real(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt incoming_wave_fct_pt, const double &phi, const unsigned &nplot)
void output_imag(std::ostream &outfile, const double &phi, const unsigned &n_plot)
Output function for imaginary part of full time-dependent solution u = Im( (u_r +i u_i) exp(-i omega ...
Class for dense matrices, storing all the values of the matrix as a pointer to a pointer with assorte...
Definition: communicator.h:50