MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
hyperbolic.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12// Implementation of hyperbolic conservation laws
13
14#include "hyperbolic.hpp"
15#include "nonlinearform.hpp"
16#include "pnonlinearform.hpp"
17
18namespace mfem
19{
20
23 const Vector &elfun,
24 Vector &elvect)
25{
26 // current element's the number of degrees of freedom
27 // does not consider the number of equations
28 const int dof = el.GetDof();
29
30#ifdef MFEM_THREAD_SAFE
31 // Local storage for element integration
32
33 // shape function value at an integration point
34 Vector shape(dof);
35 // derivative of shape function at an integration point
36 DenseMatrix dshape(dof, el.GetDim());
37 // state value at an integration point
38 Vector state(num_equations);
39 // flux value at an integration point
41#else
42 // resize shape and gradient shape storage
43 shape.SetSize(dof);
44 dshape.SetSize(dof, el.GetDim());
45#endif
46
47 // setDegree-up output vector
48 elvect.SetSize(dof * num_equations);
49 elvect = 0.0;
50
51 // make state variable and output dual vector matrix form.
52 const DenseMatrix elfun_mat(elfun.GetData(), dof, num_equations);
53 DenseMatrix elvect_mat(elvect.GetData(), dof, num_equations);
54
55 // obtain integration rule. If integration is rule is given, then use it.
56 // Otherwise, get (2*p + IntOrderOffset) order integration rule
57 const IntegrationRule *ir = IntRule;
58 if (!ir)
59 {
60 const int order = el.GetOrder()*2 + IntOrderOffset;
61 ir = &IntRules.Get(Tr.GetGeometryType(), order);
62 }
63
64 // loop over integration points
65 for (int i = 0; i < ir->GetNPoints(); i++)
66 {
67 const IntegrationPoint &ip = ir->IntPoint(i);
68 Tr.SetIntPoint(&ip);
69
70 el.CalcShape(ip, shape);
71 el.CalcPhysDShape(Tr, dshape);
72 // compute current state value with given shape function values
73 elfun_mat.MultTranspose(shape, state);
74 // compute F(u,x) and point maximum characteristic speed
75
76 const real_t mcs = fluxFunction.ComputeFlux(state, Tr, flux);
77 // update maximum characteristic speed
78 max_char_speed = std::max(mcs, max_char_speed);
79 // integrate (F(u,x), grad v)
80 AddMult_a_ABt(ip.weight * Tr.Weight(), dshape, flux, elvect_mat);
81 }
82}
83
85 const FiniteElement &el1, const FiniteElement &el2,
86 FaceElementTransformations &Tr, const Vector &elfun, Vector &elvect)
87{
88 // current elements' the number of degrees of freedom
89 // does not consider the number of equations
90 const int dof1 = el1.GetDof();
91 const int dof2 = el2.GetDof();
92
93#ifdef MFEM_THREAD_SAFE
94 // Local storage for element integration
95
96 // shape function value at an integration point - first elem
97 Vector shape1(dof1);
98 // shape function value at an integration point - second elem
99 Vector shape2(dof2);
100 // normal vector (usually not a unit vector)
101 Vector nor(el1.GetDim());
102 // state value at an integration point - first elem
103 Vector state1(num_equations);
104 // state value at an integration point - second elem
105 Vector state2(num_equations);
106 // hat(F)(u,x)
107 Vector fluxN(num_equations);
108#else
109 shape1.SetSize(dof1);
110 shape2.SetSize(dof2);
111#endif
112
113 elvect.SetSize((dof1 + dof2) * num_equations);
114 elvect = 0.0;
115
116 const DenseMatrix elfun1_mat(elfun.GetData(), dof1, num_equations);
117 const DenseMatrix elfun2_mat(elfun.GetData() + dof1 * num_equations, dof2,
119
120 DenseMatrix elvect1_mat(elvect.GetData(), dof1, num_equations);
121 DenseMatrix elvect2_mat(elvect.GetData() + dof1 * num_equations, dof2,
123
124 // Obtain integration rule. If integration is rule is given, then use it.
125 // Otherwise, get (2*p + IntOrderOffset) order integration rule
126 const IntegrationRule *ir = IntRule;
127 if (!ir)
128 {
129 const int order = 2*std::max(el1.GetOrder(), el2.GetOrder()) + IntOrderOffset;
130 ir = &IntRules.Get(Tr.GetGeometryType(), order);
131 }
132 // loop over integration points
133 for (int i = 0; i < ir->GetNPoints(); i++)
134 {
135 const IntegrationPoint &ip = ir->IntPoint(i);
136
137 Tr.SetAllIntPoints(&ip); // set face and element int. points
138
139 // Calculate basis functions on both elements at the face
140 el1.CalcShape(Tr.GetElement1IntPoint(), shape1);
141 el2.CalcShape(Tr.GetElement2IntPoint(), shape2);
142
143 // Interpolate elfun at the point
144 elfun1_mat.MultTranspose(shape1, state1);
145 elfun2_mat.MultTranspose(shape2, state2);
146
147 // Get the normal vector and the flux on the face
148 if (nor.Size() == 1) // if 1D, use 1 or -1.
149 {
150 // This assume the 1D integration point is in (0,1). This may not work
151 // if this changes.
152 nor(0) = (Tr.GetElement1IntPoint().x - 0.5) * 2.0;
153 }
154 else
155 {
156 CalcOrtho(Tr.Jacobian(), nor);
157 }
158 // Compute F(u+, x) and F(u-, x) with maximum characteristic speed
159 // Compute hat(F) using evaluated quantities
160 const real_t speed = rsolver.Eval(state1, state2, nor, Tr, fluxN);
161
162 // Update the global max char speed
163 max_char_speed = std::max(speed, max_char_speed);
164
165 // pre-multiply integration weight to flux
166 AddMult_a_VWt(-ip.weight, shape1, fluxN, elvect1_mat);
167 AddMult_a_VWt(+ip.weight, shape2, fluxN, elvect2_mat);
168 }
169}
170
172 const RiemannSolver &rsolver,
173 const int IntOrderOffset)
175 rsolver(rsolver),
176 fluxFunction(rsolver.GetFluxFunction()),
177 IntOrderOffset(IntOrderOffset),
178 num_equations(fluxFunction.num_equations)
179{
180#ifndef MFEM_THREAD_SAFE
181 state.SetSize(num_equations);
182 flux.SetSize(num_equations, fluxFunction.dim);
183 state1.SetSize(num_equations);
184 state2.SetSize(num_equations);
185 fluxN.SetSize(num_equations);
186 nor.SetSize(fluxFunction.dim);
187#endif
188}
189
191 const Vector &normal,
193 Vector &FUdotN) const
194{
195#ifdef MFEM_THREAD_SAFE
197#endif
198 real_t val = ComputeFlux(U, Tr, flux);
199 flux.Mult(normal, FUdotN);
200 return val;
201}
202
203
204real_t RusanovFlux::Eval(const Vector &state1, const Vector &state2,
205 const Vector &nor, FaceElementTransformations &Tr,
206 Vector &flux) const
207{
208#ifdef MFEM_THREAD_SAFE
210#endif
211 const real_t speed1 = fluxFunction.ComputeFluxDotN(state1, nor, Tr, fluxN1);
212 const real_t speed2 = fluxFunction.ComputeFluxDotN(state2, nor, Tr, fluxN2);
213 // NOTE: nor in general is not a unit normal
214 const real_t maxE = std::max(speed1, speed2);
215 // here, std::sqrt(nor*nor) is multiplied to match the scale with fluxN
216 const real_t scaledMaxE = maxE*std::sqrt(nor*nor);
217 for (int i=0; i<state1.Size(); i++)
218 {
219 flux[i] = 0.5*(scaledMaxE*(state1[i] - state2[i]) + (fluxN1[i] + fluxN2[i]));
220 }
221 return std::max(speed1, speed2);
222}
223
224
227 DenseMatrix &FU) const
228{
229#ifdef MFEM_THREAD_SAFE
230 Vector bval(b.GetVDim());
231#endif
232 b.Eval(bval, Tr, Tr.GetIntPoint());
233 MultVWt(U, bval, FU);
234 return bval.Norml2();
235}
236
237
240 DenseMatrix &FU) const
241{
242 FU = U * U * 0.5;
243 return std::fabs(U(0));
244}
245
246
249 DenseMatrix &FU) const
250{
251 const real_t height = U(0);
252 const Vector h_vel(U.GetData() + 1, dim);
253
254 const real_t energy = 0.5 * g * (height * height);
255
256 MFEM_ASSERT(height >= 0, "Negative Height");
257
258 for (int d = 0; d < dim; d++)
259 {
260 FU(0, d) = h_vel(d);
261 for (int i = 0; i < dim; i++)
262 {
263 FU(1 + i, d) = h_vel(i) * h_vel(d) / height;
264 }
265 FU(1 + d, d) += energy;
266 }
267
268 const real_t sound = std::sqrt(g * height);
269 const real_t vel = std::sqrt(h_vel * h_vel) / height;
270
271 return vel + sound;
272}
273
274
276 const Vector &normal,
278 Vector &FUdotN) const
279{
280 const real_t height = U(0);
281 const Vector h_vel(U.GetData() + 1, dim);
282
283 const real_t energy = 0.5 * g * (height * height);
284
285 MFEM_ASSERT(height >= 0, "Negative Height");
286 FUdotN(0) = h_vel * normal;
287 const real_t normal_vel = FUdotN(0) / height;
288 for (int i = 0; i < dim; i++)
289 {
290 FUdotN(1 + i) = normal_vel * h_vel(i) + energy * normal(i);
291 }
292
293 const real_t sound = std::sqrt(g * height);
294 const real_t vel = std::fabs(normal_vel) / std::sqrt(normal*normal);
295
296 return vel + sound;
297}
298
299
302 DenseMatrix &FU) const
303{
304 // 1. Get states
305 const real_t density = U(0); // ρ
306 const Vector momentum(U.GetData() + 1, dim); // ρu
307 const real_t energy = U(1 + dim); // E, internal energy ρe
308 const real_t kinetic_energy = 0.5 * (momentum*momentum) / density;
309 // pressure, p = (γ-1)*(E - ½ρ|u|^2)
310 const real_t pressure = (specific_heat_ratio - 1.0) *
311 (energy - kinetic_energy);
312
313 // Check whether the solution is physical only in debug mode
314 MFEM_ASSERT(density >= 0, "Negative Density");
315 MFEM_ASSERT(pressure >= 0, "Negative Pressure");
316 MFEM_ASSERT(energy >= 0, "Negative Energy");
317
318 // 2. Compute Flux
319 for (int d = 0; d < dim; d++)
320 {
321 FU(0, d) = momentum(d); // ρu
322 for (int i = 0; i < dim; i++)
323 {
324 // ρuuᵀ
325 FU(1 + i, d) = momentum(i) * momentum(d) / density;
326 }
327 // (ρuuᵀ) + p
328 FU(1 + d, d) += pressure;
329 }
330 // enthalpy H = e + p/ρ = (E + p)/ρ
331 const real_t H = (energy + pressure) / density;
332 for (int d = 0; d < dim; d++)
333 {
334 // u(E+p) = ρu*(E + p)/ρ = ρu*H
335 FU(1 + dim, d) = momentum(d) * H;
336 }
337
338 // 3. Compute maximum characteristic speed
339
340 // sound speed, √(γ p / ρ)
341 const real_t sound = std::sqrt(specific_heat_ratio * pressure / density);
342 // fluid speed |u|
343 const real_t speed = std::sqrt(2.0 * kinetic_energy / density);
344 // max characteristic speed = fluid speed + sound speed
345 return speed + sound;
346}
347
348
350 const Vector &normal,
352 Vector &FUdotN) const
353{
354 // 1. Get states
355 const real_t density = x(0); // ρ
356 const Vector momentum(x.GetData() + 1, dim); // ρu
357 const real_t energy = x(1 + dim); // E, internal energy ρe
358 const real_t kinetic_energy = 0.5 * (momentum*momentum) / density;
359 // pressure, p = (γ-1)*(E - ½ρ|u|^2)
360 const real_t pressure = (specific_heat_ratio - 1.0) *
361 (energy - kinetic_energy);
362
363 // Check whether the solution is physical only in debug mode
364 MFEM_ASSERT(density >= 0, "Negative Density");
365 MFEM_ASSERT(pressure >= 0, "Negative Pressure");
366 MFEM_ASSERT(energy >= 0, "Negative Energy");
367
368 // 2. Compute normal flux
369
370 FUdotN(0) = momentum * normal; // ρu⋅n
371 // u⋅n
372 const real_t normal_velocity = FUdotN(0) / density;
373 for (int d = 0; d < dim; d++)
374 {
375 // (ρuuᵀ + pI)n = ρu*(u⋅n) + pn
376 FUdotN(1 + d) = normal_velocity * momentum(d) + pressure * normal(d);
377 }
378 // (u⋅n)(E + p)
379 FUdotN(1 + dim) = normal_velocity * (energy + pressure);
380
381 // 3. Compute maximum characteristic speed
382
383 // sound speed, √(γ p / ρ)
384 const real_t sound = std::sqrt(specific_heat_ratio * pressure / density);
385 // fluid speed |u|
386 const real_t speed = std::fabs(normal_velocity) / std::sqrt(normal*normal);
387 // max characteristic speed = fluid speed + sound speed
388 return speed + sound;
389}
390
391} // namespace mfem
real_t ComputeFlux(const Vector &state, ElementTransformation &Tr, DenseMatrix &flux) const override
Compute F(u)
real_t ComputeFlux(const Vector &state, ElementTransformation &Tr, DenseMatrix &flux) const override
Compute F(u)
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication.
Definition densemat.cpp:220
void MultTranspose(const real_t *x, real_t *y) const
Multiply a vector with the transpose matrix.
Definition densemat.cpp:262
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition densemat.hpp:105
Geometry::Type GetGeometryType() const
Return the Geometry::Type of the reference element.
Definition eltrans.hpp:162
const IntegrationPoint & GetIntPoint()
Get a const reference to the currently set integration point. This will return NULL if no integration...
Definition eltrans.hpp:98
real_t Weight()
Return the weight of the Jacobian matrix of the transformation at the currently set IntegrationPoint....
Definition eltrans.hpp:131
const DenseMatrix & Jacobian()
Return the Jacobian matrix of the transformation at the currently set IntegrationPoint,...
Definition eltrans.hpp:119
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition eltrans.hpp:93
real_t ComputeFlux(const Vector &state, ElementTransformation &Tr, DenseMatrix &flux) const override
Compute F(ρ, ρu, E)
real_t ComputeFluxDotN(const Vector &x, const Vector &normal, FaceElementTransformations &Tr, Vector &fluxN) const override
Compute normal flux, F(ρ, ρu, E)n.
A specialized ElementTransformation class representing a face and its two neighboring elements.
Definition eltrans.hpp:484
const IntegrationPoint & GetElement1IntPoint()
Get a const reference to the integration point in neighboring element 1 corresponding to the currentl...
Definition eltrans.hpp:580
const IntegrationPoint & GetElement2IntPoint()
Get a const reference to the integration point in neighboring element 2 corresponding to the currentl...
Definition eltrans.hpp:590
void SetAllIntPoints(const IntegrationPoint *face_ip)
Set the integration point in the Face and the two neighboring elements, if present.
Definition eltrans.hpp:569
Abstract class for all finite elements.
Definition fe_base.hpp:239
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition fe_base.hpp:333
void CalcPhysDShape(ElementTransformation &Trans, DenseMatrix &dshape) const
Evaluate the gradients of all shape functions of a scalar finite element in physical space at the poi...
Definition fe_base.cpp:192
int GetDim() const
Returns the reference space dimension for the finite element.
Definition fe_base.hpp:316
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const =0
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:329
const int num_equations
virtual real_t ComputeFlux(const Vector &state, ElementTransformation &Tr, DenseMatrix &flux) const =0
Compute flux F(u, x) for given state u and physical point x.
virtual real_t ComputeFluxDotN(const Vector &state, const Vector &normal, FaceElementTransformations &Tr, Vector &fluxDotN) const
Compute normal flux. Optionally overloaded in the derived class to avoid creating full dense matrix f...
HyperbolicFormIntegrator(const RiemannSolver &rsolver, const int IntOrderOffset=0)
Construct a new Hyperbolic Form Integrator object.
void AssembleFaceVector(const FiniteElement &el1, const FiniteElement &el2, FaceElementTransformations &Tr, const Vector &elfun, Vector &elvect) override
implement <-hat(F)(u,x) n, [[v]]> with abstract hat(F) computed by ComputeFluxDotN and numerical flux...
void AssembleElementVector(const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun, Vector &elvect) override
implement (F(u), grad v) with abstract F computed by ComputeFlux
Class for integration point with weight.
Definition intrules.hpp:35
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:100
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:256
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:259
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
This class is used to express the local action of a general nonlinear finite element operator....
const IntegrationRule * IntRule
Abstract class for numerical flux for a system of hyperbolic conservation laws on a face with states,...
virtual real_t Eval(const Vector &state1, const Vector &state2, const Vector &nor, FaceElementTransformations &Tr, Vector &flux) const =0
Evaluates numerical flux for given states and fluxes. Must be overloaded in a derived class.
const FluxFunction & fluxFunction
real_t Eval(const Vector &state1, const Vector &state2, const Vector &nor, FaceElementTransformations &Tr, Vector &flux) const override
hat(F)n = ½(F(u⁺,x)n + F(u⁻,x)n) - ½λ(u⁺ - u⁻)
real_t ComputeFluxDotN(const Vector &state, const Vector &normal, FaceElementTransformations &Tr, Vector &fluxN) const override
Compute normal flux, F(h, hu)
real_t ComputeFlux(const Vector &state, ElementTransformation &Tr, DenseMatrix &flux) const override
Compute F(h, hu)
int GetVDim()
Returns dimension of the vector.
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
Vector data type.
Definition vector.hpp:80
real_t Norml2() const
Returns the l2 norm of the vector.
Definition vector.cpp:832
int Size() const
Returns the size of the vector.
Definition vector.hpp:218
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:538
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:227
void CalcOrtho(const DenseMatrix &J, Vector &n)
void AddMult_a_ABt(real_t a, const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += a * A * B^t.
void MultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
void AddMult_a_VWt(const real_t a, const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += a * v w^t.
float real_t
Definition config.hpp:43
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:486
void vel(const Vector &x, real_t t, Vector &u)