euler_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-2026 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 scalar advection elements
27
28#ifndef OOMPH_EULER_ELEMENTS_HEADER
29#define OOMPH_EULER_ELEMENTS_HEADER
30
31// Config header
32#ifdef HAVE_CONFIG_H
33#include <oomph-lib-config.h>
34#endif
35
38#include "generic/dg_elements.h"
39
40namespace oomph
41{
42 //==============================================================
43 /// Base class for Euler equations
44 //=============================================================
45 template<unsigned DIM>
47 {
48 // Default value for gamma (initialised to 1.4)
49 static double Default_Gamma_Value;
50
51 // Pointer to the specific gas constant
52 double* Gamma_pt;
53
54 /// Storage for the average primitive values
56
57 /// Storage for the approximated gradients
59
60 protected:
61 /// DIM momentum-components, a density and an energy are transported
62 inline unsigned nflux() const
63 {
64 return DIM + 2;
65 }
66
67 /// Return the flux as a function of the unknown
68 void flux(const Vector<double>& u, DenseMatrix<double>& f);
69
70 /// Return the flux derivatives as a function of the unknowns
71 // void dflux_du(const Vector<double> &u, RankThreeTensor<double> &df_du);
72
73 public:
74 /// Constructor
79 {
80 // Set the default value of gamma
82 }
83
84 /// Destructor
86 {
87 if (this->Average_prim_value != 0)
88 {
89 delete[] Average_prim_value;
91 }
92 if (this->Average_gradient != 0)
93 {
94 delete[] Average_gradient;
96 }
97 }
98
99 /// Calculate the pressure from the unknowns
100 double pressure(const Vector<double>& u) const;
101
102 /// Return the value of gamma
103 double gamma() const
104 {
105 return *Gamma_pt;
106 }
107
108 /// Access function for the pointer to gamma
109 double*& gamma_pt()
110 {
111 return Gamma_pt;
112 }
113
114 /// Access function for the pointer to gamma (const version)
115 double* const& gamma_pt() const
116 {
117 return Gamma_pt;
118 }
119
120 /// The number of unknowns at each node is the number of flux
121 /// components
122 inline unsigned required_nvalue(const unsigned& n) const
123 {
124 return DIM + 2;
125 }
126
127 /// Compute the error and norm of solution integrated over the element
128 /// Does not plot the error in the outfile
130 std::ostream& outfile,
132 const double& t,
134 Vector<double>& norm)
135 {
136 // Find the number of fluxes
137 const unsigned n_flux = this->nflux();
138 // Find the number of nodes
139 const unsigned n_node = this->nnode();
140 // Storage for the shape function and derivatives of shape function
143
144 // Find the number of integration points
145 unsigned n_intpt = this->integral_pt()->nweight();
146
147 error.resize(n_flux);
148 norm.resize(n_flux);
149 for (unsigned i = 0; i < n_flux; i++)
150 {
151 error[i] = 0.0;
152 norm[i] = 0.0;
153 }
154
156
157 // Loop over the integration points
158 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
159 {
160 // Get the shape functions at the knot
161 double J = this->dshape_eulerian_at_knot(ipt, psi, dpsidx);
162
163 // Get the integral weight
164 double W = this->integral_pt()->weight(ipt) * J;
165
166 // Storage for the local functions
168 Vector<double> interpolated_u(n_flux, 0.0);
169
170 // Loop over the shape functions
171 for (unsigned l = 0; l < n_node; l++)
172 {
173 // Locally cache the shape function
174 const double psi_ = psi(l);
175 for (unsigned i = 0; i < DIM; i++)
176 {
177 interpolated_x[i] += this->nodal_position(l, i) * psi_;
178 }
179
180 for (unsigned i = 0; i < n_flux; i++)
181 {
182 // Calculate the velocity and tangent vector
183 interpolated_u[i] += this->nodal_value(l, i) * psi_;
184 }
185 }
186
187 // Now get the exact solution at this value of x and t
189 (*exact_solution_pt)(t, interpolated_x, exact_u);
190
191 // Loop over the unknowns
192 for (unsigned i = 0; i < n_flux; i++)
193 {
194 error[i] += pow((interpolated_u[i] - exact_u[i]), 2.0) * W;
195 norm[i] += interpolated_u[i] * interpolated_u[i] * W;
196 }
197 }
198 }
199
200
201 /// Output function:
202 /// x,y,u or x,y,z,u
203 void output(std::ostream& outfile)
204 {
205 unsigned nplot = 5;
207 }
208
209 /// Output function:
210 /// x,y,u or x,y,z,u at n_plot^DIM plot points
211 void output(std::ostream& outfile, const unsigned& n_plot);
212
214 {
215 // Find the number of fluxes
216 const unsigned n_flux = this->nflux();
217 // Resize the memory if necessary
218 if (this->Average_prim_value == 0)
219 {
220 this->Average_prim_value = new double[n_flux];
221 }
222 // Will move this one day
223 if (this->Average_gradient == 0)
224 {
225 this->Average_gradient = new double[n_flux * DIM];
226 }
227 }
228
229 /// Return access to the average gradient
230 double& average_gradient(const unsigned& i, const unsigned& j)
231 {
232 if (Average_gradient == 0)
233 {
234 throw OomphLibError("Averages not calculated yet",
237 }
238 return Average_gradient[DIM * i + j];
239 }
240
241 /// Return the average values
242 double& average_prim_value(const unsigned& i)
243 {
244 if (Average_prim_value == 0)
245 {
246 throw OomphLibError("Averages not calculated yet",
249 }
250 return Average_prim_value[i];
251 }
252 };
253
254
255 template<unsigned DIM, unsigned NNODE_1D>
256 class QSpectralEulerElement : public virtual QSpectralElement<DIM, NNODE_1D>,
257 public virtual EulerEquations<DIM>
258 {
259 public:
260 /// Constructor: Call constructors for QElement and
261 /// Advection Diffusion equations
266
267 /// Broken copy constructor
269 delete;
270
271 /// Broken assignment operator
272 // Commented out broken assignment operator because this can lead to a
273 // conflict warning when used in the virtual inheritence hierarchy.
274 // Essentially the compiler doesn't realise that two separate
275 // implementations of the broken function are the same and so, quite
276 // rightly, it shouts.
277 /*void operator=(
278 const QSpectralEulerElement<DIM,NNODE_1D>&) = delete;*/
279
280
281 /// Output function:
282 /// x,y,u or x,y,z,u
283 void output(std::ostream& outfile)
284 {
286 }
287
288 /// Output function:
289 /// x,y,u or x,y,z,u at n_plot^DIM plot points
290 void output(std::ostream& outfile, const unsigned& n_plot)
291 {
293 }
294
295
296 /*/// C-style output function:
297 /// x,y,u or x,y,z,u
298 void output(FILE* file_pt)
299 {
300 EulerEquations<NFLUX,DIM>::output(file_pt);
301 }
302
303 /// C-style output function:
304 /// x,y,u or x,y,z,u at n_plot^DIM plot points
305 void output(FILE* file_pt, const unsigned &n_plot)
306 {
307 EulerEquations<NFLUX,DIM>::output(file_pt,n_plot);
308 }
309
310 /// Output function for an exact solution:
311 /// x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot points
312 void output_fct(std::ostream &outfile, const unsigned &n_plot,
313 FiniteElement::SteadyExactSolutionFctPt
314 exact_soln_pt)
315 {
316 EulerEquations<NFLUX,DIM>::
317 output_fct(outfile,n_plot,exact_soln_pt);}
318
319
320 /// Output function for a time-dependent exact solution.
321 /// x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot points
322 /// (Calls the steady version)
323 void output_fct(std::ostream &outfile, const unsigned &n_plot,
324 const double& time,
325 FiniteElement::UnsteadyExactSolutionFctPt
326 exact_soln_pt)
327 {
328 EulerEquations<NFLUX,DIM>::
329 output_fct(outfile,n_plot,time,exact_soln_pt);
330 }*/
331
332
333 protected:
334 /// Shape, test functions & derivs. w.r.t. to global coords. Return
335 /// Jacobian.
337 const Vector<double>& s,
338 Shape& psi,
339 DShape& dpsidx,
340 Shape& test,
341 DShape& dtestdx) const;
342
343 /// Shape, test functions & derivs. w.r.t. to global coords. at
344 /// integration point ipt. Return Jacobian.
346 const unsigned& ipt,
347 Shape& psi,
348 DShape& dpsidx,
349 Shape& test,
350 DShape& dtestdx) const;
351 };
352
353 // Inline functions:
354
355
356 //======================================================================
357 /// Define the shape functions and test functions and derivatives
358 /// w.r.t. global coordinates and return Jacobian of mapping.
359 ///
360 /// Galerkin: Test functions = shape functions
361 //======================================================================
362 template<unsigned DIM, unsigned NNODE_1D>
365 Shape& psi,
366 DShape& dpsidx,
367 Shape& test,
368 DShape& dtestdx) const
369 {
370 // Call the geometrical shape functions and derivatives
371 double J = this->dshape_eulerian(s, psi, dpsidx);
372
373 // Set the test functions equal to the shape functions
374 test.shallow_copy_from(psi);
375 dtestdx.shallow_copy_from(dpsidx);
376
377 // Return the jacobian
378 return J;
379 }
380
381
382 //======================================================================
383 /// Define the shape functions and test functions and derivatives
384 /// w.r.t. global coordinates and return Jacobian of mapping.
385 ///
386 /// Galerkin: Test functions = shape functions
387 //======================================================================
388 template<unsigned DIM, unsigned NNODE_1D>
391 Shape& psi,
392 DShape& dpsidx,
393 Shape& test,
394 DShape& dtestdx) const
395 {
396 // Call the geometrical shape functions and derivatives
397 double J = this->dshape_eulerian_at_knot(ipt, psi, dpsidx);
398
399 // Set the test functions equal to the shape functions (pointer copy)
400 test.shallow_copy_from(psi);
401 dtestdx.shallow_copy_from(dpsidx);
402
403 // Return the jacobian
404 return J;
405 }
406
407
408 ////////////////////////////////////////////////////////////////////////
409 ////////////////////////////////////////////////////////////////////////
410 ////////////////////////////////////////////////////////////////////////
411
412
413 //=======================================================================
414 /// Face geometry for the QEulerElement elements:
415 /// The spatial dimension of the face elements is one lower than that
416 /// of the bulk element but they have the same number of points along
417 /// their 1D edges.
418 //=======================================================================
419 template<unsigned DIM, unsigned NNODE_1D>
421 : public virtual QSpectralElement<DIM - 1, NNODE_1D>
422 {
423 public:
424 /// Constructor: Call the constructor for the
425 /// appropriate lower-dimensional QElement
427 };
428
429
430 //======================================================================
431 /// FaceElement for Discontinuous Galerkin Problems
432 //======================================================================
433 template<class ELEMENT>
434 class DGEulerFaceElement : public virtual FaceGeometry<ELEMENT>,
435 public virtual DGFaceElement
436 {
437 unsigned Nflux;
438
440
441 public:
442 /// Constructor
443 DGEulerFaceElement(FiniteElement* const& element_pt, const int& face_index)
444 : FaceGeometry<ELEMENT>(), DGFaceElement()
445 {
446 // Attach geometric information to the element
447 // N.B. This function also assigns nbulk_value from required_nvalue
448 // of the bulk element.
449 element_pt->build_face_element(face_index, this);
450 // Set the value of the flux
451 Nflux = 2 + element_pt->dim();
452 // Use the Face integration scheme of the element for 2D elements
453 if (Nflux > 3)
454 {
456 dynamic_cast<ELEMENT*>(element_pt)->face_integration_pt());
457 }
458 }
459
460 /// Specify the value of nodal zeta from the face geometry
461 /// The "global" intrinsic coordinate of the element when
462 /// viewed as part of a geometric object should be given by
463 /// the FaceElement representation, by default (needed to break
464 /// indeterminacy if bulk element is SolidElement)
465 double zeta_nodal(const unsigned& n,
466 const unsigned& k,
467 const unsigned& i) const
468 {
469 return FaceElement::zeta_nodal(n, k, i);
470 }
471
472
473 // There is a single required n_flux
474 unsigned required_nflux()
475 {
476 return Nflux;
477 }
478
479 /// Calculate the normal flux, so this is the dot product of the
480 /// numerical flux with n_out
482 const Vector<double>& u_int,
483 const Vector<double>& u_ext,
484 Vector<double>& flux)
485 {
486 // Let's follow the yellow book and use local Lax-Friedrichs
487 // This is almost certainly not the best flux to use ---
488 // further investigation is required here.
489 // Cache the bulk element
490 ELEMENT* cast_bulk_element_pt =
491 dynamic_cast<ELEMENT*>(this->bulk_element_pt());
492
493 // Find the dimension of the problem
494 const unsigned dim = cast_bulk_element_pt->dim();
495 // Find the number of variables
496 const unsigned n_flux = this->Nflux;
497
498 const double gamma = cast_bulk_element_pt->gamma();
499
500 // Now let's find the fluxes
503
506
508 for (unsigned i = 0; i < n_flux; i++)
509 {
510 for (unsigned j = 0; j < dim; j++)
511 {
512 flux_av(i, j) = 0.5 * (flux_int(i, j) + flux_ext(i, j));
513 }
514 }
515
516 flux.initialise(0.0);
517 // Now set the first part of the numerical flux
518 for (unsigned i = 0; i < n_flux; i++)
519 {
520 for (unsigned j = 0; j < dim; j++)
521 {
522 flux[i] += flux_av(i, j) * n_out[j];
523 }
524 }
525
526 // Now let's find the normal jumps in the fluxes
528 // Now we take the normal jump in the quantities
529 // The first two are scalars
530 for (unsigned i = 0; i < 2; i++)
531 {
532 jump[i] = u_int[i] - u_ext[i];
533 }
534
535 // The next are vectors so treat them accordingly ??
536 // By taking the component dotted with the normal component
537 double velocity_jump = 0.0;
538 for (unsigned j = 0; j < dim; j++)
539 {
540 velocity_jump += (u_int[2 + j] - u_ext[2 + j]) * n_out[j];
541 }
542 // Now we multiply by the outer normal to get the vector flux
543 for (unsigned j = 0; j < dim; j++)
544 {
545 jump[2 + j] = velocity_jump * n_out[j];
546 }
547
548
549 // Let's find the Roe average
550 /* Vector<double> u_average(n_flux);
551 double sum = sqrt(u_int[0]) + sqrt(u_ext[0]);
552 for(unsigned i=0;i<n_flux;i++)
553 {
554 u_average[i] = (sqrt(u_int[0])*u_int[i] + sqrt(u_ext[0])*u_ext[i])/sum;
555 }
556
557 //Find the average pressure
558 double p = cast_bulk_element_pt->pressure(u_average);
559
560 //Now do the normal velocity
561 double vel = 0.0;
562 for(unsigned j=0;j<dim;j++)
563 {
564 //vel += u_average[2+j]*u_average[2+j];
565 vel += u_average[2+j]*n_out[j];
566 }
567 //vel = sqrt(vel)/u_average[0];
568 vel /= u_average[0];
569
570 double arg = std::fabs(gamma*p/u_average[0]);*/
571
572 // Let's calculate the internal and external pressures and then enthalpies
573 double p_int = cast_bulk_element_pt->pressure(u_int);
574 double p_ext = cast_bulk_element_pt->pressure(u_ext);
575
576 // Limit the pressures to zero if necessary, but keep the energy the
577 // same
578 if (p_int < 0)
579 {
580 oomph_info << "Negative int pressure" << p_int << "\n";
581 p_int = 0.0;
582 }
583 if (p_ext < 0)
584 {
585 oomph_info << "Negative ext pressure " << p_ext << "\n";
586 p_ext = 0.0;
587 }
588
589 double H_int = (u_int[1] + p_int) / u_int[0];
590 double H_ext = (u_ext[1] + p_ext) / u_ext[0];
591
592 // Also calculate the velocities
594 for (unsigned j = 0; j < dim; j++)
595 {
596 vel_int[j] = u_int[2 + j] / u_int[0];
597 vel_ext[j] = u_ext[2 + j] / u_ext[0];
598 }
599
600 // Now we calculate the Roe averaged values
602 double s_int = sqrt(u_int[0]);
603 double s_ext = sqrt(u_ext[0]);
604 double sum = s_int + s_ext;
605
606 // Velocities
607 for (unsigned j = 0; j < dim; j++)
608 {
609 vel_average[j] = (s_int * vel_int[j] + s_ext * vel_ext[j]) / sum;
610 }
611
612 // The enthalpy
613 double H_average = (s_int * H_int + s_ext * H_ext) / sum;
614
615 // Now calculate the square of the sound speed
616 double arg = H_average;
617 for (unsigned j = 0; j < dim; j++)
618 {
619 arg -= 0.5 * vel_average[j];
620 }
621 arg *= (gamma - 1.0);
622 // Get the local sound speed
623 if (arg < 0.0)
624 {
625 oomph_info << "Square of sound speed is negative!\n";
626 arg = 0.0;
627 }
628 double a = sqrt(arg);
629
630 // Calculate the normal average velocity
631 // Now do the normal velocity
632 double vel = 0.0;
633 for (unsigned j = 0; j < dim; j++)
634 {
635 vel += vel_average[j] * n_out[j];
636 }
637
638 Vector<double> eigA(3, 0.0);
639
640 eigA[0] = vel - a;
641 eigA[1] = vel;
642 eigA[2] = vel + a;
643
644 double lambda = std::fabs(eigA[0]);
645 for (unsigned i = 1; i < 3; i++)
646 {
647 if (std::fabs(eigA[i]) > lambda)
648 {
649 lambda = std::fabs(eigA[i]);
650 }
651 }
652
653
654 // Find the magnitude of the external velocity
655 /*double vel_mag = 0.0;
656 for(unsigned j=0;j<dim;j++) {vel_mag += u_ext[2+j]*u_ext[2+j];}
657 vel_mag = sqrt(vel_mag)/u_ext[0];
658
659 //Get the pressure
660 double p = cast_bulk_element_pt->pressure(u_ext);
661 double lambda_ext = vel_mag + sqrt(std::fabs(gamma*p/u_ext[0]));
662
663 //Let's do the same for the internal one
664 vel_mag = 0.0;
665 for(unsigned j=0;j<dim;j++) {vel_mag += u_int[2+j]*u_int[2+j];}
666 vel_mag = sqrt(vel_mag)/u_int[0];
667
668 //Get the pressure
669 p = cast_bulk_element_pt->pressure(u_int);
670 double lambda_int = vel_mag + sqrt(std::fabs(gamma*p/u_int[0]));
671
672 //Now take the largest
673 double lambda = lambda_int;
674 if(lambda_ext > lambda) {lambda = lambda_ext;}*/
675
676 for (unsigned i = 0; i < n_flux; i++)
677 {
678 flux[i] += 0.5 * lambda * jump[i];
679 }
680 }
681 };
682
683
684 //======================================================================
685 /// FaceElement for Discontinuous Galerkin Problems with reflection
686 /// boundary conditions
687 //======================================================================
688 template<class ELEMENT>
689 class DGEulerFaceReflectionElement : public virtual FaceGeometry<ELEMENT>,
690 public virtual DGFaceElement
691 {
692 unsigned Nflux;
693
694 public:
695 /// Constructor
697 const int& face_index)
698 : FaceGeometry<ELEMENT>(), DGFaceElement()
699 {
700 // Attach geometric information to the element
701 // N.B. This function also assigns nbulk_value from required_nvalue
702 // of the bulk element.
703 element_pt->build_face_element(face_index, this);
704 // Set the value of the flux
705 Nflux = 2 + element_pt->dim();
706 }
707
708
709 /// Specify the value of nodal zeta from the face geometry
710 /// The "global" intrinsic coordinate of the element when
711 /// viewed as part of a geometric object should be given by
712 /// the FaceElement representation, by default (needed to break
713 /// indeterminacy if bulk element is SolidElement)
714 double zeta_nodal(const unsigned& n,
715 const unsigned& k,
716 const unsigned& i) const
717 {
718 return FaceElement::zeta_nodal(n, k, i);
719 }
720
721 // There is a single required n_flux
722 unsigned required_nflux()
723 {
724 return Nflux;
725 }
726
727 /// We overload interpolated_u to reflect
729 {
730 // Get the standard interpolated_u
732
733 // Now do the reflection condition for the velocities
734 // Find dot product of normal and velocities
735 const unsigned nodal_dim = this->nodal_dimension();
737 this->outer_unit_normal(s, n);
738
739 double dot = 0.0;
740 for (unsigned j = 0; j < nodal_dim; j++)
741 {
742 dot += n[j] * u[2 + j];
743 }
744
745 // Now subtract
746 for (unsigned j = 0; j < nodal_dim; j++)
747 {
748 u[2 + j] -= 2.0 * dot * n[j];
749 }
750 }
751 };
752
753
754 //=================================================================
755 /// General DGEulerClass. Establish the template parameters
756 //===================================================================
757 template<unsigned DIM, unsigned NNODE_1D>
759 {
760 };
761
762
763 //==================================================================
764 // Specialization for 1D DG Advection element
765 //==================================================================
766 template<unsigned NNODE_1D>
768 : public QSpectralEulerElement<1, NNODE_1D>, public DGElement
769 {
771
773
774 public:
775 /// Overload the required number of fluxes for the DGElement
776 unsigned required_nflux()
777 {
778 return this->nflux();
779 }
780
781 // Calculate averages
782 void calculate_element_averages(double*& average_value)
783 {
785 }
786
787
788 // Constructor
790 {
791 // Need to up the order of integration for the accurate resolution
792 // of the quadratic non-linearities
793 this->set_integration_scheme(new Gauss<1, NNODE_1D>);
794 }
795
796 // Dummy
798 {
799 return 0;
800 }
801
802
804
806 {
807 // Make the two faces
808 Face_element_pt.resize(2);
809 // Make the face on the left
810 Face_element_pt[0] =
812 // Make the face on the right
813 Face_element_pt[1] =
815 }
816
817
818 /// Compute the residuals for the Navier--Stokes equations;
819 /// flag=1(or 0): do (or don't) compute the Jacobian as well.
832
833
834 //============================================================================
835 /// Function that returns the current value of the residuals
836 /// multiplied by the inverse mass matrix (virtual so that it can be
837 /// overloaded specific elements in which time and memory saving tricks can
838 /// be applied)
839 //============================================================================
840 /* void get_inverse_mass_matrix_times_residuals(Vector<double> &minv_res)
841 {
842 //Now let's assemble stuff
843 const unsigned n_dof = this->ndof();
844
845 //Resize and initialise the vector that will holds the residuals
846 minv_res.resize(n_dof);
847 for(unsigned n=0;n<n_dof;n++) {minv_res[n] = 0.0;}
848
849 //If we are recycling the mass matrix
850 if(Mass_matrix_reuse_is_enabled && Mass_matrix_has_been_computed)
851 {
852 //Get the residuals
853 this->fill_in_contribution_to_residuals(minv_res);
854 }
855 //Otherwise
856 else
857 {
858 //Temporary mass matrix
859 DenseDoubleMatrix M(n_dof,n_dof,0.0);
860
861 //Get the local mass matrix and residuals
862 this->fill_in_contribution_to_mass_matrix(minv_res,M);
863
864 //Store the diagonal entries
865 Inverse_mass_diagonal.clear();
866 for(unsigned n=0;n<n_dof;n++)
867 {Inverse_mass_diagonal.push_back(1.0/M(n,n));}
868
869 //The mass matrix has been computed
870 Mass_matrix_has_been_computed=true;
871 }
872
873 for(unsigned n=0;n<n_dof;n++) {minv_res[n] *= Inverse_mass_diagonal[n];}
874
875 }*/
876 };
877
878
879 //=======================================================================
880 /// Face geometry of the 1D DG elements
881 //=======================================================================
882 template<unsigned NNODE_1D>
884 : public virtual PointElement
885 {
886 public:
888 };
889
890
891 //==================================================================
892 /// Specialisation for 2D DG Elements
893 //==================================================================
894 template<unsigned NNODE_1D>
896 : public QSpectralEulerElement<2, NNODE_1D>, public DGElement
897 {
899
901
902 public:
903 /// Overload the required number of fluxes for the DGElement
904 unsigned required_nflux()
905 {
906 return this->nflux();
907 }
908
909 // Calculate averages
910 void calculate_element_averages(double*& average_value)
911 {
913 }
914
915 // Constructor
917 {
918 // Need to up the order of integration for the accurate resolution
919 // of the quadratic non-linearities
920 this->set_integration_scheme(
922 }
923
925
927 {
928 return &Default_face_integration_scheme;
929 }
930
932 {
933 Face_element_pt.resize(4);
934 Face_element_pt[0] =
936 Face_element_pt[1] =
938 Face_element_pt[2] =
940 Face_element_pt[3] =
942 }
943
944
945 /// Compute the residuals for the Navier--Stokes equations;
946 /// flag=1(or 0): do (or don't) compute the Jacobian as well.
959 };
960
961
962 //=======================================================================
963 /// Face geometry of the DG elements
964 //=======================================================================
965 template<unsigned NNODE_1D>
967 : public virtual QSpectralElement<1, NNODE_1D>
968 {
969 public:
971 };
972
973
974} // namespace oomph
975
976#endif
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
char t
Definition cfortran.h:568
A Base class for DGElements.
FaceElement for Discontinuous Galerkin Problems.
void numerical_flux(const Vector< double > &n_out, const Vector< double > &u_int, const Vector< double > &u_ext, Vector< double > &flux)
Calculate the normal flux, so this is the dot product of the numerical flux with n_out.
unsigned required_nflux()
Set the number of flux components.
DGEulerFaceElement(FiniteElement *const &element_pt, const int &face_index)
Constructor.
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
Specify the value of nodal zeta from the face geometry The "global" intrinsic coordinate of the eleme...
FaceElement for Discontinuous Galerkin Problems with reflection boundary conditions.
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
Specify the value of nodal zeta from the face geometry The "global" intrinsic coordinate of the eleme...
void interpolated_u(const Vector< double > &s, Vector< double > &u)
We overload interpolated_u to reflect.
unsigned required_nflux()
Set the number of flux components.
DGEulerFaceReflectionElement(FiniteElement *const &element_pt, const int &face_index)
Constructor.
Base class for Discontinuous Galerkin Faces. These are responsible for calculating the normal fluxes ...
Definition dg_elements.h:50
virtual void interpolated_u(const Vector< double > &s, Vector< double > &f)
Return the interpolated values of the unknown fluxes.
void calculate_element_averages(double *&average_value)
Calculate the averages in the element.
unsigned required_nflux()
Overload the required number of fluxes for the DGElement.
void fill_in_generic_residual_contribution_flux_transport(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, unsigned flag)
Compute the residuals for the Navier–Stokes equations; flag=1(or 0): do (or don't) compute the Jacobi...
unsigned required_nflux()
Overload the required number of fluxes for the DGElement.
void calculate_element_averages(double *&average_value)
Calculate the averages in the element.
static Gauss< 1, NNODE_1D > Default_face_integration_scheme
void fill_in_generic_residual_contribution_flux_transport(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, unsigned flag)
Compute the residuals for the Navier–Stokes equations; flag=1(or 0): do (or don't) compute the Jacobi...
General DGEulerClass. Establish the template parameters.
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Definition shape.h:359
Base class for Euler equations.
virtual ~EulerEquations()
Destructor.
double & average_prim_value(const unsigned &i)
Return the average values.
double pressure(const Vector< double > &u) const
Calculate the pressure from the unknowns.
void flux(const Vector< double > &u, DenseMatrix< double > &f)
Return the flux as a function of the unknown.
double * Average_prim_value
Storage for the average primitive values.
void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_solution_pt, const double &t, Vector< double > &error, Vector< double > &norm)
Compute the error and norm of solution integrated over the element Does not plot the error in the out...
void output(std::ostream &outfile)
Output function: x,y,u or x,y,z,u.
double gamma() const
Return the value of gamma.
double & average_gradient(const unsigned &i, const unsigned &j)
Return access to the average gradient.
unsigned nflux() const
DIM momentum-components, a density and an energy are transported.
double * Average_gradient
Storage for the approximated gradients.
double *& gamma_pt()
Access function for the pointer to gamma.
unsigned required_nvalue(const unsigned &n) const
The number of unknowns at each node is the number of flux components.
double *const & gamma_pt() const
Access function for the pointer to gamma (const version)
static double Default_Gamma_Value
EulerEquations()
Return the flux derivatives as a function of the unknowns.
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
Definition elements.h:4630
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
Definition elements.cc:6037
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
In a FaceElement, the "global" intrinsic coordinate of the element along the boundary,...
Definition elements.h:4501
FiniteElement *& bulk_element_pt()
Pointer to higher-dimensional "bulk" element.
Definition elements.h:4739
FaceGeometry()
Constructor: Call the constructor for the appropriate lower-dimensional QElement.
FaceGeometry class definition: This policy class is used to allow construction of face elements that ...
Definition elements.h:5002
A general Finite Element class.
Definition elements.h:1317
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition elements.h:1967
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
Definition elements.h:2597
virtual double dshape_eulerian_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsidx) const
Return the geometric shape functions and also first derivatives w.r.t. global coordinates at the ipt-...
Definition elements.cc:3355
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
Definition elements.cc:3992
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition elements.h:2615
unsigned nnode() const
Return the number of nodes.
Definition elements.h:2214
double nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. If the node is hanging, the appropriate interpolation is ...
Definition elements.h:2321
double dshape_eulerian(const Vector< double > &s, Shape &psi, DShape &dpsidx) const
Compute the geometric shape functions and also first derivatives w.r.t. global coordinates at local c...
Definition elements.cc:3328
virtual void build_face_element(const int &face_index, FaceElement *face_element_pt)
Function for building a lower dimensional FaceElement on the specified face of the FiniteElement....
Definition elements.cc:5163
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
Definition elements.h:2488
virtual void set_integration_scheme(Integral *const &integral_pt)
Set the spatial integration scheme.
Definition elements.cc:3240
void(* UnsteadyExactSolutionFctPt)(const double &, const Vector< double > &, Vector< double > &)
Function pointer for function that computes Vector-valued time-dependent function as .
Definition elements.h:1769
Base class for the flux transport equations templated by the dimension DIM. The equations that are so...
virtual void fill_in_generic_residual_contribution_flux_transport(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, unsigned flag)
Compute the residuals for the Navier–Stokes equations; flag=1(or 0): do (or don't) compute the Jacobi...
void calculate_element_averages(double *&average_values)
Compute the average values of the fluxes.
Generic class for numerical integration schemes:
Definition integral.h:49
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
An OomphLibError object which should be thrown when an run-time error is encountered....
Point element has just a single node and a single shape function which is identically equal to one.
Definition elements.h:3443
General QElement class.
Definition Qelements.h:459
General QLegendreElement class.
void output(std::ostream &outfile, const unsigned &n_plot)
Output function: x,y,u or x,y,z,u at n_plot^DIM plot points.
double dshape_and_dtest_eulerian_at_knot_flux_transport(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Shape, test functions & derivs. w.r.t. to global coords. at integration point ipt....
double dshape_and_dtest_eulerian_flux_transport(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Shape, test functions & derivs. w.r.t. to global coords. Return Jacobian.
QSpectralEulerElement()
Constructor: Call constructors for QElement and Advection Diffusion equations.
QSpectralEulerElement(const QSpectralEulerElement< DIM, NNODE_1D > &dummy)=delete
Broken copy constructor.
void output(std::ostream &outfile)
Broken assignment operator.
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Definition shape.h:77
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...