[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
exact_solution.cpp
1 #include <deal.II/base/function.h>
2 #include "exact_solution.h"
3 #include <deal.II/base/utilities.h>
4 #include <deal.II/base/mpi.h>
5 
6 namespace PHiLiP {
7 
8 // ========================================================
9 // ZERO -- Returns zero everywhere; used a placeholder when no exact solution is defined.
10 // ========================================================
11 template <int dim, int nstate, typename real>
13 ::ExactSolutionFunction_Zero(double time_compare)
14  : ExactSolutionFunction<dim,nstate,real>()
15  , t(time_compare)
16 {
17 }
18 
19 template <int dim, int nstate, typename real>
21 ::value(const dealii::Point<dim,real> &/*point*/, const unsigned int /*istate*/) const
22 {
23  real value = 0;
24  return value;
25 }
26 
27 // ========================================================
28 // 1D SINE -- Exact solution for advection_explicit_time_study
29 // ========================================================
30 template <int dim, int nstate, typename real>
32 ::ExactSolutionFunction_1DSine (double time_compare)
33  : ExactSolutionFunction<dim,nstate,real>()
34  , t(time_compare)
35 {
36 }
37 
38 template <int dim, int nstate, typename real>
40 ::value(const dealii::Point<dim,real> &point, const unsigned int /*istate*/) const
41 {
42  double x_adv_speed = 1.0;
43 
44  real value = 0;
45  real pi = dealii::numbers::PI;
46  if(point[0] >= 0.0 && point[0] <= 2.0){
47  value = sin(2*pi*(point[0] - x_adv_speed * t)/2.0);
48  }
49  return value;
50 }
51 
52 // ========================================================
53 // 1D SINE -- Exact solution for burgers 1D sine manufactured solution
54 // ========================================================
55 template <int dim, int nstate, typename real>
58  : ExactSolutionFunction<dim,nstate,real>()
59  , t(time_compare)
60 {
61 }
62 
63 template <int dim, int nstate, typename real>
65 ::value(const dealii::Point<dim,real> &point, const unsigned int /*istate*/) const
66 {
67  real value = 0;
68  real pi = dealii::numbers::PI;
69  if(point[0] >= 0.0 && point[0] <= 2.0){
70  value = cos(pi*(point[0] - t));
71  }
72  return value;
73 }
74 
75 // ========================================================
76 // Inviscid Isentropic Vortex
77 // ========================================================
78 template <int dim, int nstate, typename real>
81  : ExactSolutionFunction<dim,nstate,real>()
82  , t(time_compare)
83 {
84  // Nothing to do here yet
85 }
86 
87 template <int dim, int nstate, typename real>
89 ::value(const dealii::Point<dim,real> &point, const unsigned int istate) const
90 {
91  // Setting constants
92  const double L = 10.0; // half-width of domain
93  const double pi = dealii::numbers::PI;
94  const double gam = 1.4;
95  const double M_infty = sqrt(2/gam);
96  const double R = 1;
97  const double sigma = 1;
98  const double beta = M_infty * 5 * sqrt(2.0)/4.0/pi * exp(1.0/2.0);
99  const double alpha = pi/4; //rad
100 
101  // Centre of the vortex at t
102  const double x_travel = M_infty * t * cos(alpha);
103  const double x0 = 0.0 + x_travel;
104  const double y_travel = M_infty * t * sin(alpha);
105  const double y0 = 0.0 + y_travel;
106  const double x = std::fmod(point[0] - x0-L, 2*L)+L;
107  const double y = std::fmod(point[1] - y0-L, 2*L)+L;
108 
109  const double Omega = beta * exp(-0.5/sigma/sigma* (x/R * x/R + y/R * y/R));
110  const double delta_Ux = -y/R * Omega;
111  const double delta_Uy = x/R * Omega;
112  const double delta_T = -(gam-1.0)/2.0 * Omega * Omega;
113 
114  // Primitive
115  const double rho = pow((1 + delta_T), 1.0/(gam-1.0));
116  const double Ux = M_infty * cos(alpha) + delta_Ux;
117  const double Uy = M_infty * sin(alpha) + delta_Uy;
118  const double Uz = 0;
119  const double p = 1.0/gam*pow(1+delta_T, gam/(gam-1.0));
120 
121  //Convert to conservative variables
122  if (istate == 0) return rho; //density
123  else if (istate == nstate-1) return p/(gam-1.0) + 0.5 * rho * (Ux*Ux + Uy*Uy + Uz*Uz); //total energy
124  else if (istate == 1) return rho * Ux; //x-momentum
125  else if (istate == 2) return rho * Uy; //y-momentum
126  else if (istate == 3) return rho * Uz; //z-momentum
127  else return 0;
128 
129 }
130 
131 //=========================================================
132 // FLOW SOLVER -- Exact Solution Base Class + Factory
133 //=========================================================
134 template <int dim, int nstate, typename real>
137  : dealii::Function<dim,real>(nstate)
138 {
139  //do nothing
140 }
141 
142 template <int dim, int nstate, typename real>
143 std::shared_ptr<ExactSolutionFunction<dim, nstate, real>>
145  const Parameters::FlowSolverParam& flow_solver_parameters,
146  const double time_compare)
147 {
148  // Get the flow case type
149  const FlowCaseEnum flow_type = flow_solver_parameters.flow_case_type;
150  if (flow_type == FlowCaseEnum::periodic_1D_unsteady){
151  if constexpr (dim==1 && nstate==dim) return std::make_shared<ExactSolutionFunction_1DSine<dim,nstate,real> > (time_compare);
152  } else if (flow_type == FlowCaseEnum::isentropic_vortex){
153  if constexpr (dim>1 && nstate==dim+2) return std::make_shared<ExactSolutionFunction_IsentropicVortex<dim,nstate,real> > (time_compare);
154  } else if (flow_type == FlowCaseEnum::burgers_inviscid){
155  if constexpr (dim==1 && nstate==dim) return std::make_shared<ExactSolutionFunction_BurgersInviscidManufactured<dim,nstate,real> > (time_compare);
156  } else {
157  // Select zero function if there is no exact solution defined
158  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
159  pcout << "Warning: Returning zero for the exact solution." << std::endl
160  << "This may be unintentional!" << std::endl;
161  return std::make_shared<ExactSolutionFunction_Zero<dim,nstate,real>> (time_compare);
162  }
163  return nullptr;
164 }
165 
170 #if PHILIP_DIM>1
172 #endif
178 
179 #if PHILIP_DIM>1
181 #endif
182 } // PHiLiP namespace
FlowCaseType
Selects the flow case to be simulated.
FlowCaseType flow_case_type
Selected FlowCaseType from the input file.
Files for the baseline physics.
Definition: ADTypes.hpp:10
static std::shared_ptr< ExactSolutionFunction< dim, nstate, real > > create_ExactSolutionFunction(const Parameters::FlowSolverParam &flow_solver_parameters, const double time_compare)
Construct ExactSolutionFunction object from global parameter file.
real value(const dealii::Point< dim, real > &point, const unsigned int istate=0) const override
Value of the exact solution at a point.
Exact Solution Function: Zero Function; used as a placeholder when there is no exact solution...
ExactSolutionFunction()
< dealii::Function we are templating on
ExactSolutionFunction_BurgersInviscidManufactured(double time_compare)
< dealii::Function we are templating on
Parameters related to the flow solver.
real value(const dealii::Point< dim, real > &point, const unsigned int istate=0) const override
Value of the exact solution at a point.
Exact solution function factory.
ExactSolutionFunction_IsentropicVortex(double time_compare)
< dealii::Function we are templating on
ExactSolutionFunction_Zero(double time_compare)
< dealii::Function we are templating on
Exact solution function used for a particular flow setup/case.
ExactSolutionFunction_1DSine(double time_compare)
< dealii::Function we are templating on
real value(const dealii::Point< dim, real > &point, const unsigned int istate=0) const override
Value of the exact solution at a point.
Exact Solution Function: Isentropic vortex.
real value(const dealii::Point< dim, real > &point, const unsigned int istate=0) const override
Value of the exact solution at a point.