HyPar  1.0
Finite-Difference Hyperbolic-Parabolic PDE Solver on Cartesian Grids
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
interpolation.h File Reference

Definitions for the functions computing the interpolated value of the primitive at the cell interfaces from the cell-centered values. More...

#include "basic.h"

Go to the source code of this file.

Data Structures

struct  MUSCLParameters
 Structure of variables/parameters needed by the MUSCL scheme. More...
 
struct  WENOParameters
 Structure of variables/parameters needed by the WENO-type scheme. More...
 
struct  CompactScheme
 Structure of variables/parameters needed by the compact schemes. More...
 

Macros

#define _FIRST_ORDER_UPWIND_   "1"
 
#define _SECOND_ORDER_CENTRAL_   "2"
 
#define _SECOND_ORDER_MUSCL_   "muscl2"
 
#define _THIRD_ORDER_MUSCL_   "muscl3"
 
#define _FOURTH_ORDER_CENTRAL_   "4"
 
#define _FIFTH_ORDER_UPWIND_   "upw5"
 
#define _FIFTH_ORDER_COMPACT_UPWIND_   "cupw5"
 
#define _FIFTH_ORDER_WENO_   "weno5"
 
#define _FIFTH_ORDER_CRWENO_   "crweno5"
 
#define _FIFTH_ORDER_HCWENO_   "hcweno5"
 
#define _CHARACTERISTIC_   "characteristic"
 
#define _COMPONENTS_   "components"
 
#define _WENO_OPTIMAL_WEIGHT_1_   0.1
 
#define _WENO_OPTIMAL_WEIGHT_2_   0.6
 
#define _WENO_OPTIMAL_WEIGHT_3_   0.3
 
#define _CRWENO_OPTIMAL_WEIGHT_1_   0.2
 
#define _CRWENO_OPTIMAL_WEIGHT_2_   0.5
 
#define _CRWENO_OPTIMAL_WEIGHT_3_   0.3
 
#define _WENOWeights_v_JS_(w1, w2, w3, c1, c2, c3, m3, m2, m1, p1, p2, eps, N)
 
#define _WENOWeights_v_M_(w1, w2, w3, c1, c2, c3, m3, m2, m1, p1, p2, eps, N)
 
#define _WENOWeights_v_M_Scalar_(w1, w2, w3, c1, c2, c3, m3, m2, m1, p1, p2, eps, idx)
 
#define _WENOWeights_v_Z_(w1, w2, w3, c1, c2, c3, m3, m2, m1, p1, p2, eps, N)
 
#define _WENOWeights_v_YC_(w1, w2, w3, c1, c2, c3, m3, m2, m1, p1, p2, eps, N)
 
#define _WENOWeights_v_YC_Scalar_(w1, w2, w3, c1, c2, c3, m3, m2, m1, p1, p2, eps, idx)
 

Functions

int Interp1PrimFirstOrderUpwind (double *, double *, double *, double *, int, int, void *, void *, int)
 1st order upwind reconstruction (component-wise) on a uniform grid More...
 
int Interp1PrimSecondOrderCentral (double *, double *, double *, double *, int, int, void *, void *, int)
 2nd order central reconstruction (component-wise) on a uniform grid More...
 
int Interp1PrimSecondOrderMUSCL (double *, double *, double *, double *, int, int, void *, void *, int)
 2nd order MUSCL scheme (component-wise) on a uniform grid More...
 
int Interp1PrimThirdOrderMUSCL (double *, double *, double *, double *, int, int, void *, void *, int)
 3rd order MUSCL scheme with Koren's limiter (component-wise) on a uniform grid More...
 
int Interp1PrimFourthOrderCentral (double *, double *, double *, double *, int, int, void *, void *, int)
 4th order central reconstruction (component-wise) on a uniform grid More...
 
int Interp1PrimFifthOrderUpwind (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order upwind reconstruction (component-wise) on a uniform grid More...
 
int Interp1PrimFifthOrderCompactUpwind (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order compact upwind reconstruction (component-wise) on a uniform grid More...
 
int Interp1PrimFifthOrderWENO (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order WENO reconstruction (component-wise) on a uniform grid More...
 
int Interp1PrimFifthOrderCRWENO (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order CRWENO reconstruction (component-wise) on a uniform grid More...
 
int Interp1PrimFifthOrderHCWENO (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order hybrid compact-WENO reconstruction (component-wise) on a uniform grid More...
 
int gpuInterp1PrimFifthOrderWENO (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order WENO reconstruction (component-wise) on a uniform grid More...
 
int Interp1PrimFirstOrderUpwindChar (double *, double *, double *, double *, int, int, void *, void *, int)
 1st order upwind reconstruction (characteristic-based) on a uniform grid More...
 
int Interp1PrimSecondOrderCentralChar (double *, double *, double *, double *, int, int, void *, void *, int)
 2nd order central reconstruction (characteristic-based) on a uniform grid More...
 
int Interp1PrimSecondOrderMUSCLChar (double *, double *, double *, double *, int, int, void *, void *, int)
 2nd order MUSCL scheme (characteristic-based) on a uniform grid More...
 
int Interp1PrimThirdOrderMUSCLChar (double *, double *, double *, double *, int, int, void *, void *, int)
 3rd order MUSCL scheme with Koren's limiter (characteristic-based) on a uniform grid More...
 
int Interp1PrimFourthOrderCentralChar (double *, double *, double *, double *, int, int, void *, void *, int)
 4th order central reconstruction (characteristic-based) on a uniform grid More...
 
int Interp1PrimFifthOrderUpwindChar (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order upwind reconstruction (characteristic-based) on a uniform grid More...
 
int Interp1PrimFifthOrderCompactUpwindChar (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order compact upwind reconstruction (characteristic-based) on a uniform grid More...
 
int Interp1PrimFifthOrderWENOChar (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order WENO reconstruction (characteristic-based) on a uniform grid More...
 
int Interp1PrimFifthOrderCRWENOChar (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order CRWENO reconstruction (characteristic-based) on a uniform grid More...
 
int Interp1PrimFifthOrderHCWENOChar (double *, double *, double *, double *, int, int, void *, void *, int)
 5th order hybrid compact-WENO reconstruction (characteristic-based) on a uniform grid More...
 
int Interp2PrimSecondOrder (double *, double *, int, void *, void *)
 2nd order component-wise interpolation of the 2nd primitive on a uniform grid More...
 
int InterpSetLimiterVar (double *, double *, double *, int, void *, void *)
 
int MUSCLInitialize (void *, void *)
 
int WENOInitialize (void *, void *, char *, char *)
 
int WENOCleanup (void *, int)
 
int CompactSchemeInitialize (void *, void *, char *)
 
int CompactSchemeCleanup (void *)
 

Detailed Description

Definitions for the functions computing the interpolated value of the primitive at the cell interfaces from the cell-centered values.

Author
Debojyoti Ghosh

Definition in file interpolation.h.


Data Structure Documentation

struct WENOParameters

Structure of variables/parameters needed by the WENO-type scheme.

This structure contains the variables/parameters needed by the WENO-type scheme (_FIFTH_ORDER_WENO_, _FIFTH_ORDER_CRWENO_, _FIFTH_ORDER_HCWENO_).

Definition at line 194 of file interpolation.h.

Data Fields
int mapped

Use mapped weights? (Henrick, Aslam, J. Comput. Phys., 2005)

int borges

Use Borges' implementation of weights? (Borges, et. al, J. Comput. Phys., 2008)

int yc

Use Yamaleev-Carpenter implementation of weights? (Yamaleev, Carpenter, J. Comput. Phys., 2009)

int no_limiting

Remove limiting -> 5th order polynomial interpolation (freeze the WENO weights to the optimal coefficients)

double eps

epsilon parameter

double p

p parameter

double tol

a general tolerance parameter

double rc

Parameter for the hybrid compact-WENO scheme

double xi

Parameter for the hybrid compact-WENO scheme

double * w1

Array to save the first WENO weight

double * w2

Array to save the second WENO weight

double * w3

Array to save the third WENO weight

int * offset

Array containing the offset information for the WENO weights

int size

Size of the WENO weights array

struct CompactScheme

Structure of variables/parameters needed by the compact schemes.

This structure contains the variables/parameters needed by a compact scheme (_FIFTH_ORDER_COMPACT_UPWIND_, _FIFTH_ORDER_CRWENO_, _FIFTH_ORDER_HCWENO_).

Definition at line 560 of file interpolation.h.

Data Fields
double * A

Array to save the sub-diagonal of the tridiagonal system resulting from the fifth-order CRWENO scheme

double * B

Array to save the diagonal of the tridiagonal system resulting from the fifth-order CRWENO scheme

double * C

Array to save the super-diagonal of the tridiagonal system resulting from the fifth-order CRWENO scheme

double * R

Array to save the right-hand-side of the tridiagonal system resulting from the fifth-order CRWENO scheme

double * sendbuf

Buffer array to send data across processors

double * recvbuf

Buffer array to receive data across processors

Macro Definition Documentation

#define _FIRST_ORDER_UPWIND_   "1"

First order upwind scheme: Interp1PrimFirstOrderUpwind(), Interp1PrimFirstOrderUpwindChar()

Definition at line 12 of file interpolation.h.

#define _SECOND_ORDER_CENTRAL_   "2"

Second order central scheme: Interp1PrimSecondOrderCentral(), Interp1PrimSecondOrderCentralChar()

Definition at line 14 of file interpolation.h.

#define _SECOND_ORDER_MUSCL_   "muscl2"

Second order MUSCL scheme: Interp1PrimSecondOrderMUSCL(), Interp1PrimSecondOrderMUSCLChar()

Definition at line 16 of file interpolation.h.

#define _THIRD_ORDER_MUSCL_   "muscl3"

Third order MUSCL scheme with Koren's limiter: Interp1PrimThirdOrderMUSCL(), Interp1PrimThirdOrderMUSCLChar()

Definition at line 18 of file interpolation.h.

#define _FOURTH_ORDER_CENTRAL_   "4"

Fourth order central scheme: Interp1PrimFourthOrderCentral(), Interp1PrimFourthOrderCentralChar()

Definition at line 20 of file interpolation.h.

#define _FIFTH_ORDER_UPWIND_   "upw5"

Fifth order upwind scheme: Interp1PrimFifthOrderUpwind(), Interp1PrimFifthOrderUpwindChar()

Definition at line 22 of file interpolation.h.

#define _FIFTH_ORDER_COMPACT_UPWIND_   "cupw5"

Fifth order compact upwind scheme: Interp1PrimFifthOrderCompactUpwind(), Interp1PrimFifthOrderCompactUpwindChar()

Definition at line 24 of file interpolation.h.

#define _FIFTH_ORDER_WENO_   "weno5"

Fifth order Weighted Essentially Non-Oscillatory (WENO) scheme: Interp1PrimFifthOrderWENO(), Interp1PrimFifthOrderWENOChar()

Definition at line 26 of file interpolation.h.

#define _FIFTH_ORDER_CRWENO_   "crweno5"

Fifth order Compact Reconstruction Weighted Essentially Non-Oscillatory (CRWENO) scheme: Interp1PrimFifthOrderCRWENO(), Interp1PrimFifthOrderCRWENOChar()

Definition at line 28 of file interpolation.h.

#define _FIFTH_ORDER_HCWENO_   "hcweno5"

Fifth order hybrid compact-WENO scheme: Interp1PrimFifthOrderHCWENO(), Interp1PrimFifthOrderHCWENOChar()

Definition at line 30 of file interpolation.h.

#define _CHARACTERISTIC_   "characteristic"

Characteristic-based interpolation of vectors (Physical model must define left and right eigenvectors)

Definition at line 33 of file interpolation.h.

#define _COMPONENTS_   "components"

Component-wise interpolation of vectors

Definition at line 34 of file interpolation.h.

#define _WENO_OPTIMAL_WEIGHT_1_   0.1

Optimal value for the first fifth-order WENO weight

Definition at line 228 of file interpolation.h.

#define _WENO_OPTIMAL_WEIGHT_2_   0.6

Optimal value for the second fifth-order WENO weight

Definition at line 230 of file interpolation.h.

#define _WENO_OPTIMAL_WEIGHT_3_   0.3

Optimal value for the third fifth-order WENO weight

Definition at line 232 of file interpolation.h.

#define _CRWENO_OPTIMAL_WEIGHT_1_   0.2

Optimal value for the first fifth-order CRWENO weight

Definition at line 234 of file interpolation.h.

#define _CRWENO_OPTIMAL_WEIGHT_2_   0.5

Optimal value for the second fifth-order CRWENO weight

Definition at line 236 of file interpolation.h.

#define _CRWENO_OPTIMAL_WEIGHT_3_   0.3

Optimal value for the third fifth-order CRWENO weight

Definition at line 238 of file interpolation.h.

#define _WENOWeights_v_JS_ (   w1,
  w2,
  w3,
  c1,
  c2,
  c3,
  m3,
  m2,
  m1,
  p1,
  p2,
  eps,
 
)
Value:
{ \
int idx; \
/* calculate smoothness indicators and the WENO weights */\
double b1, b2, b3, a1, a2, a3, a_sum_inv; \
for (idx=0; idx<N; idx++) { \
b1 = thirteen_by_twelve*(m3[idx]-2*m2[idx]+m1[idx])*(m3[idx]-2*m2[idx]+m1[idx]) \
+ one_fourth*(m3[idx]-4*m2[idx]+3*m1[idx])*(m3[idx]-4*m2[idx]+3*m1[idx]); \
a1 = c1 / ( (b1+eps) * (b1+eps) ); \
b2 = thirteen_by_twelve*(m2[idx]-2*m1[idx]+p1[idx])*(m2[idx]-2*m1[idx]+p1[idx]) \
+ one_fourth*(m2[idx]-p1[idx])*(m2[idx]-p1[idx]); \
a2 = c2 / ( (b2+eps) * (b2+eps) ); \
b3 = thirteen_by_twelve*(m1[idx]-2*p1[idx]+p2[idx])*(m1[idx]-2*p1[idx]+p2[idx]) \
+ one_fourth*(3*m1[idx]-4*p1[idx]+p2[idx])*(3*m1[idx]-4*p1[idx]+p2[idx]); \
a3 = c3 / ( (b3+eps) * (b3+eps) ); \
a_sum_inv = 1.0 / (a1 + a2 + a3); \
w1[idx] = a1 * a_sum_inv; \
w2[idx] = a2 * a_sum_inv; \
w3[idx] = a3 * a_sum_inv; \
} \
}

Compute the WENO weights according the the Jiang & Shu formulation:

\begin{equation} \omega_k = \frac {a_k} {\sum_{j=1}^3 a_j },\ a_k = \frac {c_k} {\left(\beta_k+\epsilon\right)^p},\ k = 1,2,3, \end{equation}

where \(c_k\) are the optimal weights, \(p\) is hardcoded to \(2\), and \(\epsilon\) is an input parameter (WENOParameters::eps) (typically \(10^{-6}\)). The smoothness indicators \(\beta_k\) are given by:

\begin{eqnarray} \beta_1 &=& \frac{13}{12} \left(f_{j-2}-2f_{j-1}+f_j\right)^2 + \frac{1}{4}\left(f_{j-2}-4f_{j-1}+3f_j\right)^2 \\ \beta_2 &=& \frac{13}{12} \left(f_{j-1}-2f_j+f_{j+1}\right)^2 + \frac{1}{4}\left(f_{j-1}-f_{j+1}\right)^2 \\ \beta_3 &=& \frac{13}{12} \left(f_j-2f_{j+1}+f_{j+2}\right)^2 + \frac{1}{4}\left(3f_j-4f_{j+1}+f_{j+2}\right)^2 \end{eqnarray}

Notes:

  • This macro computes the weights for one variable along one grid line.

Arguments:

  • w1, w2,w3 are the nonlinear WENO weights.
  • c1, c2,c3 are optimal coefficients.
  • m3, m2,m1,p1,p2 are the function values at stencil points corresponding to the interface j+1/2: j-2,j-1,j,j+1,j+2
  • weno is an object of type WENOParameters containing parameters for the WENO method.

Reference:

Definition at line 265 of file interpolation.h.

#define _WENOWeights_v_M_ (   w1,
  w2,
  w3,
  c1,
  c2,
  c3,
  m3,
  m2,
  m1,
  p1,
  p2,
  eps,
 
)
Value:
{ \
int idx; \
/* calculate smoothness indicators and the WENO weights */\
double b1, b2, b3, a1, a2, a3, a_sum_inv; \
for (idx=0; idx<N; idx++) { \
b1 = thirteen_by_twelve*(m3[idx]-2*m2[idx]+m1[idx])*(m3[idx]-2*m2[idx]+m1[idx]) \
+ one_fourth*(m3[idx]-4*m2[idx]+3*m1[idx])*(m3[idx]-4*m2[idx]+3*m1[idx]); \
a1 = c1 / ( (b1+eps) * (b1+eps) ); \
b2 = thirteen_by_twelve*(m2[idx]-2*m1[idx]+p1[idx])*(m2[idx]-2*m1[idx]+p1[idx]) \
+ one_fourth*(m2[idx]-p1[idx])*(m2[idx]-p1[idx]); \
a2 = c2 / ( (b2+eps) * (b2+eps) ); \
b3 = thirteen_by_twelve*(m1[idx]-2*p1[idx]+p2[idx])*(m1[idx]-2*p1[idx]+p2[idx]) \
+ one_fourth*(3*m1[idx]-4*p1[idx]+p2[idx])*(3*m1[idx]-4*p1[idx]+p2[idx]); \
a3 = c3 / ( (b3+eps) * (b3+eps) ); \
a_sum_inv = 1.0 / (a1 + a2 + a3); \
w1[idx] = a1 * a_sum_inv; \
w2[idx] = a2 * a_sum_inv; \
w3[idx] = a3 * a_sum_inv; \
a1 = w1[idx] * (c1 + c1*c1 - 3*c1*w1[idx] + w1[idx]*w1[idx]) / (c1*c1 + w1[idx]*(1.0-2.0*c1)); \
a2 = w2[idx] * (c2 + c2*c2 - 3*c2*w2[idx] + w2[idx]*w2[idx]) / (c2*c2 + w2[idx]*(1.0-2.0*c2)); \
a3 = w3[idx] * (c3 + c3*c3 - 3*c3*w3[idx] + w3[idx]*w3[idx]) / (c3*c3 + w3[idx]*(1.0-2.0*c3)); \
a_sum_inv = 1.0 / (a1 + a2 + a3); \
w1[idx] = a1 * a_sum_inv; \
w2[idx] = a2 * a_sum_inv; \
w3[idx] = a3 * a_sum_inv; \
} \
}

Compute the WENO weights according the the Mapped-WENO formulation:

\begin{eqnarray} \omega_k &=& \frac {a_k} {\sum_{j=1}^3 a_j },\ a_k = \frac {\tilde{\omega}_k \left( c_k + c_k^2 - 3c_k\tilde{\omega}_k + \tilde{\omega}_k^2\right)} {c_k^2 + \tilde{\omega}_k\left(1-2c_k\right)}, \\ \tilde{\omega}_k &=& \frac {\tilde{a}_k} {\sum_{j=1}^3 \tilde{a}_j },\ \tilde{a}_k = \frac {c_k} {\left(\beta_k+\epsilon\right)^p},\ k = 1,2,3, \end{eqnarray}

where \(c_k\) are the optimal weights, \(p\) is hardcoded to \(2\), and \(\epsilon\) is an input parameter (WENOParameters::eps) (typically \(10^{-6}\)). The smoothness indicators \(\beta_k\) are given by:

\begin{eqnarray} \beta_1 &=& \frac{13}{12} \left(f_{j-2}-2f_{j-1}+f_j\right)^2 + \frac{1}{4}\left(f_{j-2}-4f_{j-1}+3f_j\right)^2 \\ \beta_2 &=& \frac{13}{12} \left(f_{j-1}-2f_j+f_{j+1}\right)^2 + \frac{1}{4}\left(f_{j-1}-f_{j+1}\right)^2 \\ \beta_3 &=& \frac{13}{12} \left(f_j-2f_{j+1}+f_{j+2}\right)^2 + \frac{1}{4}\left(3f_j-4f_{j+1}+f_{j+2}\right)^2 \end{eqnarray}

Notes:

  • This macro computes the weights for one variable along one grid line.

Arguments:-

  • w1, w2,w3 are the nonlinear WENO weights.
  • c1, c2,c3 are optimal coefficients.
  • m3, m2,m1,p1,p2 are the function values at stencil points corresponding to the interface j+1/2: j-2,j-1,j,j+1,j+2
  • weno is an object of type WENOParameters containing parameters for the WENO method.
  • N is the number of interfaces along the grid line on which this WENO-type reconstruction is happening.

Reference:

Definition at line 314 of file interpolation.h.

#define _WENOWeights_v_M_Scalar_ (   w1,
  w2,
  w3,
  c1,
  c2,
  c3,
  m3,
  m2,
  m1,
  p1,
  p2,
  eps,
  idx 
)
Value:
{ \
/* calculate smoothness indicators and the WENO weights */\
double b1, b2, b3, a1, a2, a3, a_sum_inv; \
b1 = thirteen_by_twelve*(m3[idx]-2*m2[idx]+m1[idx])*(m3[idx]-2*m2[idx]+m1[idx]) \
+ one_fourth*(m3[idx]-4*m2[idx]+3*m1[idx])*(m3[idx]-4*m2[idx]+3*m1[idx]); \
a1 = c1 / ( (b1+eps) * (b1+eps) ); \
b2 = thirteen_by_twelve*(m2[idx]-2*m1[idx]+p1[idx])*(m2[idx]-2*m1[idx]+p1[idx]) \
+ one_fourth*(m2[idx]-p1[idx])*(m2[idx]-p1[idx]); \
a2 = c2 / ( (b2+eps) * (b2+eps) ); \
b3 = thirteen_by_twelve*(m1[idx]-2*p1[idx]+p2[idx])*(m1[idx]-2*p1[idx]+p2[idx]) \
+ one_fourth*(3*m1[idx]-4*p1[idx]+p2[idx])*(3*m1[idx]-4*p1[idx]+p2[idx]); \
a3 = c3 / ( (b3+eps) * (b3+eps) ); \
a_sum_inv = 1.0 / (a1 + a2 + a3); \
w1[idx] = a1 * a_sum_inv; \
w2[idx] = a2 * a_sum_inv; \
w3[idx] = a3 * a_sum_inv; \
a1 = w1[idx] * (c1 + c1*c1 - 3*c1*w1[idx] + w1[idx]*w1[idx]) / (c1*c1 + w1[idx]*(1.0-2.0*c1)); \
a2 = w2[idx] * (c2 + c2*c2 - 3*c2*w2[idx] + w2[idx]*w2[idx]) / (c2*c2 + w2[idx]*(1.0-2.0*c2)); \
a3 = w3[idx] * (c3 + c3*c3 - 3*c3*w3[idx] + w3[idx]*w3[idx]) / (c3*c3 + w3[idx]*(1.0-2.0*c3)); \
a_sum_inv = 1.0 / (a1 + a2 + a3); \
w1[idx] = a1 * a_sum_inv; \
w2[idx] = a2 * a_sum_inv; \
w3[idx] = a3 * a_sum_inv; \
}

Compute the WENO weights according the the Mapped-WENO formulation:

\begin{eqnarray} \omega_k &=& \frac {a_k} {\sum_{j=1}^3 a_j },\ a_k = \frac {\tilde{\omega}_k \left( c_k + c_k^2 - 3c_k\tilde{\omega}_k + \tilde{\omega}_k^2\right)} {c_k^2 + \tilde{\omega}_k\left(1-2c_k\right)}, \\ \tilde{\omega}_k &=& \frac {\tilde{a}_k} {\sum_{j=1}^3 \tilde{a}_j },\ \tilde{a}_k = \frac {c_k} {\left(\beta_k+\epsilon\right)^p},\ k = 1,2,3, \end{eqnarray}

where \(c_k\) are the optimal weights, \(p\) is hardcoded to \(2\), and \(\epsilon\) is an input parameter (WENOParameters::eps) (typically \(10^{-6}\)). The smoothness indicators \(\beta_k\) are given by:

\begin{eqnarray} \beta_1 &=& \frac{13}{12} \left(f_{j-2}-2f_{j-1}+f_j\right)^2 + \frac{1}{4}\left(f_{j-2}-4f_{j-1}+3f_j\right)^2 \\ \beta_2 &=& \frac{13}{12} \left(f_{j-1}-2f_j+f_{j+1}\right)^2 + \frac{1}{4}\left(f_{j-1}-f_{j+1}\right)^2 \\ \beta_3 &=& \frac{13}{12} \left(f_j-2f_{j+1}+f_{j+2}\right)^2 + \frac{1}{4}\left(3f_j-4f_{j+1}+f_{j+2}\right)^2 \end{eqnarray}

Notes:

  • This macro computes the weights for one variable along one grid line.

Arguments:-

  • w1, w2,w3 are the nonlinear WENO weights.
  • c1, c2,c3 are optimal coefficients.
  • m3, m2,m1,p1,p2 are the function values at stencil points corresponding to the interface j+1/2: j-2,j-1,j,j+1,j+2
  • weno is an object of type WENOParameters containing parameters for the WENO method.
  • N is the number of interfaces along the grid line on which this WENO-type reconstruction is happening.

Reference:

Definition at line 370 of file interpolation.h.

#define _WENOWeights_v_Z_ (   w1,
  w2,
  w3,
  c1,
  c2,
  c3,
  m3,
  m2,
  m1,
  p1,
  p2,
  eps,
 
)
Value:
{ \
int idx; \
/* calculate smoothness indicators and the WENO weights */\
double b1, b2, b3, a1, a2, a3, a_sum_inv, tau; \
for (idx=0; idx<N; idx++) { \
b1 = thirteen_by_twelve*(m3[idx]-2*m2[idx]+m1[idx])*(m3[idx]-2*m2[idx]+m1[idx]) \
+ one_fourth*(m3[idx]-4*m2[idx]+3*m1[idx])*(m3[idx]-4*m2[idx]+3*m1[idx]); \
b2 = thirteen_by_twelve*(m2[idx]-2*m1[idx]+p1[idx])*(m2[idx]-2*m1[idx]+p1[idx]) \
+ one_fourth*(m2[idx]-p1[idx])*(m2[idx]-p1[idx]); \
b3 = thirteen_by_twelve*(m1[idx]-2*p1[idx]+p2[idx])*(m1[idx]-2*p1[idx]+p2[idx]) \
+ one_fourth*(3*m1[idx]-4*p1[idx]+p2[idx])*(3*m1[idx]-4*p1[idx]+p2[idx]); \
tau = absolute(b3 - b1); \
a1 = c1 * (1.0 + (tau/(b1+eps)) * (tau/(b1+eps)) ); \
a2 = c2 * (1.0 + (tau/(b2+eps)) * (tau/(b2+eps)) ); \
a3 = c3 * (1.0 + (tau/(b3+eps)) * (tau/(b3+eps)) ); \
a_sum_inv = 1.0 / (a1 + a2 + a3); \
w1[idx] = a1 * a_sum_inv; \
w2[idx] = a2 * a_sum_inv; \
w3[idx] = a3 * a_sum_inv; \
} \
}
#define absolute(a)
Definition: math_ops.h:32

Compute the WENO weights according the the WENO-Z formulation:

\begin{equation} \omega_k = \frac {a_k} {\sum_{j=1}^3 a_j },\ a_k = c_k \left( 1 + \frac{\tau_5}{\beta_k+\epsilon} \right)^p,\ k = 1,2,3, \end{equation}

where \(c_k\) are the optimal weights, \(p\) is hardcoded to \(2\), and \(\epsilon\) is an input parameter (WENOParameters::eps) (typically \(10^{-6}\)). The smoothness indicators \(\beta_k\) are given by:

\begin{eqnarray} \beta_1 &=& \frac{13}{12} \left(f_{j-2}-2f_{j-1}+f_j\right)^2 + \frac{1}{4}\left(f_{j-2}-4f_{j-1}+3f_j\right)^2 \\ \beta_2 &=& \frac{13}{12} \left(f_{j-1}-2f_j+f_{j+1}\right)^2 + \frac{1}{4}\left(f_{j-1}-f_{j+1}\right)^2 \\ \beta_3 &=& \frac{13}{12} \left(f_j-2f_{j+1}+f_{j+2}\right)^2 + \frac{1}{4}\left(3f_j-4f_{j+1}+f_{j+2}\right)^2, \end{eqnarray}

and \(\tau_5 = \left|\beta_1 - \beta_3 \right|\).

Notes:

  • This macro computes the weights for one variable along one grid line.

Arguments:

  • w1, w2,w3 are the nonlinear WENO weights.
  • c1, c2,c3 are optimal coefficients.
  • m3, m2,m1,p1,p2 are the function values at stencil points corresponding to the interface j+1/2: j-2,j-1,j,j+1,j+2
  • weno is an object of type WENOParameters containing parameters for the WENO method.
  • N is the number of interfaces along the grid line on which this WENO-type reconstruction is happening.

Reference:

Definition at line 426 of file interpolation.h.

#define _WENOWeights_v_YC_ (   w1,
  w2,
  w3,
  c1,
  c2,
  c3,
  m3,
  m2,
  m1,
  p1,
  p2,
  eps,
 
)
Value:
{ \
int idx; \
/* calculate smoothness indicators and the WENO weights */\
double b1, b2, b3, a1, a2, a3, a_sum_inv, tau; \
for (idx=0; idx<N; idx++) { \
b1 = thirteen_by_twelve*(m3[idx]-2*m2[idx]+m1[idx])*(m3[idx]-2*m2[idx]+m1[idx]) \
+ one_fourth*(m3[idx]-4*m2[idx]+3*m1[idx])*(m3[idx]-4*m2[idx]+3*m1[idx]); \
b2 = thirteen_by_twelve*(m2[idx]-2*m1[idx]+p1[idx])*(m2[idx]-2*m1[idx]+p1[idx]) \
+ one_fourth*(m2[idx]-p1[idx])*(m2[idx]-p1[idx]); \
b3 = thirteen_by_twelve*(m1[idx]-2*p1[idx]+p2[idx])*(m1[idx]-2*p1[idx]+p2[idx]) \
+ one_fourth*(3*m1[idx]-4*p1[idx]+p2[idx])*(3*m1[idx]-4*p1[idx]+p2[idx]); \
tau = (m3[idx]-4*m2[idx]+6*m1[idx]-4*p1[idx]+p2[idx])*(m3[idx]-4*m2[idx]+6*m1[idx]-4*p1[idx]+p2[idx]); \
a1 = c1 * (1.0 + (tau/(b1+eps)) * (tau/(b1+eps)) ); \
a2 = c2 * (1.0 + (tau/(b2+eps)) * (tau/(b2+eps)) ); \
a3 = c3 * (1.0 + (tau/(b3+eps)) * (tau/(b3+eps)) ); \
a_sum_inv = 1.0 / (a1 + a2 + a3); \
w1[idx] = a1 * a_sum_inv; \
w2[idx] = a2 * a_sum_inv; \
w3[idx] = a3 * a_sum_inv; \
} \
}

Compute the WENO weights according the the ESWENO formulation of Yamaleev & Carpenter. Note that only the formulation for the nonlinear weights is adopted and implemented here, not the ESWENO scheme as a whole.

\begin{equation} \omega_k = \frac {a_k} {\sum_{j=1}^3 a_j },\ a_k = c_k \left( 1 + \frac{\tau_5}{\beta_k+\epsilon} \right)^p,\ k = 1,2,3, \end{equation}

where \(c_k\) are the optimal weights, \(p\) is hardcoded to \(2\), and \(\epsilon\) is an input parameter (WENOParameters::eps) (typically \(10^{-6}\)). The smoothness indicators \(\beta_k\) are given by:

\begin{eqnarray} \beta_1 &=& \frac{13}{12} \left(f_{j-2}-2f_{j-1}+f_j\right)^2 + \frac{1}{4}\left(f_{j-2}-4f_{j-1}+3f_j\right)^2 \\ \beta_2 &=& \frac{13}{12} \left(f_{j-1}-2f_j+f_{j+1}\right)^2 + \frac{1}{4}\left(f_{j-1}-f_{j+1}\right)^2 \\ \beta_3 &=& \frac{13}{12} \left(f_j-2f_{j+1}+f_{j+2}\right)^2 + \frac{1}{4}\left(3f_j-4f_{j+1}+f_{j+2}\right)^2, \end{eqnarray}

and \(\tau_5 = \left( f_{j-2}-4f_{j-1}+6f_j-4f_{j+1}+f_{j+2} \right)^2\).

Notes:

  • This macro computes the weights for one variable along one grid line.

Arguments:

  • w1, w2,w3 are the nonlinear WENO weights.
  • c1, c2,c3 are optimal coefficients.
  • m3, m2,m1,p1,p2 are the function values at stencil points corresponding to the interface j+1/2: j-2,j-1,j,j+1,j+2
  • weno is an object of type WENOParameters containing parameters for the WENO method.
  • N is the number of interfaces along the grid line on which this WENO-type reconstruction is happening.
    Reference:

Definition at line 479 of file interpolation.h.

#define _WENOWeights_v_YC_Scalar_ (   w1,
  w2,
  w3,
  c1,
  c2,
  c3,
  m3,
  m2,
  m1,
  p1,
  p2,
  eps,
  idx 
)
Value:
{ \
/* calculate smoothness indicators and the WENO weights */\
double b1, b2, b3, a1, a2, a3, a_sum_inv, tau; \
b1 = thirteen_by_twelve*(m3[idx]-2*m2[idx]+m1[idx])*(m3[idx]-2*m2[idx]+m1[idx]) \
+ one_fourth*(m3[idx]-4*m2[idx]+3*m1[idx])*(m3[idx]-4*m2[idx]+3*m1[idx]); \
b2 = thirteen_by_twelve*(m2[idx]-2*m1[idx]+p1[idx])*(m2[idx]-2*m1[idx]+p1[idx]) \
+ one_fourth*(m2[idx]-p1[idx])*(m2[idx]-p1[idx]); \
b3 = thirteen_by_twelve*(m1[idx]-2*p1[idx]+p2[idx])*(m1[idx]-2*p1[idx]+p2[idx]) \
+ one_fourth*(3*m1[idx]-4*p1[idx]+p2[idx])*(3*m1[idx]-4*p1[idx]+p2[idx]); \
tau = (m3[idx]-4*m2[idx]+6*m1[idx]-4*p1[idx]+p2[idx])*(m3[idx]-4*m2[idx]+6*m1[idx]-4*p1[idx]+p2[idx]); \
a1 = c1 * (1.0 + (tau/(b1+eps)) * (tau/(b1+eps)) ); \
a2 = c2 * (1.0 + (tau/(b2+eps)) * (tau/(b2+eps)) ); \
a3 = c3 * (1.0 + (tau/(b3+eps)) * (tau/(b3+eps)) ); \
a_sum_inv = 1.0 / (a1 + a2 + a3); \
w1[idx] = a1 * a_sum_inv; \
w2[idx] = a2 * a_sum_inv; \
w3[idx] = a3 * a_sum_inv; \
}

Compute the WENO weights according the the ESWENO formulation of Yamaleev & Carpenter. Note that only the formulation for the nonlinear weights is adopted and implemented here, not the ESWENO scheme as a whole.

\begin{equation} \omega_k = \frac {a_k} {\sum_{j=1}^3 a_j },\ a_k = c_k \left( 1 + \frac{\tau_5}{\beta_k+\epsilon} \right)^p,\ k = 1,2,3, \end{equation}

where \(c_k\) are the optimal weights, \(p\) is hardcoded to \(2\), and \(\epsilon\) is an input parameter (WENOParameters::eps) (typically \(10^{-6}\)). The smoothness indicators \(\beta_k\) are given by:

\begin{eqnarray} \beta_1 &=& \frac{13}{12} \left(f_{j-2}-2f_{j-1}+f_j\right)^2 + \frac{1}{4}\left(f_{j-2}-4f_{j-1}+3f_j\right)^2 \\ \beta_2 &=& \frac{13}{12} \left(f_{j-1}-2f_j+f_{j+1}\right)^2 + \frac{1}{4}\left(f_{j-1}-f_{j+1}\right)^2 \\ \beta_3 &=& \frac{13}{12} \left(f_j-2f_{j+1}+f_{j+2}\right)^2 + \frac{1}{4}\left(3f_j-4f_{j+1}+f_{j+2}\right)^2, \end{eqnarray}

and \(\tau_5 = \left( f_{j-2}-4f_{j-1}+6f_j-4f_{j+1}+f_{j+2} \right)^2\).

Notes:

  • This macro computes the weights for one variable along one grid line.

Arguments:

  • w1, w2,w3 are the nonlinear WENO weights.
  • c1, c2,c3 are optimal coefficients.
  • m3, m2,m1,p1,p2 are the function values at stencil points corresponding to the interface j+1/2: j-2,j-1,j,j+1,j+2
  • weno is an object of type WENOParameters containing parameters for the WENO method.
  • N is the number of interfaces along the grid line on which this WENO-type reconstruction is happening.
    Reference:

Definition at line 532 of file interpolation.h.

Function Documentation

int Interp1PrimFirstOrderUpwind ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

1st order upwind reconstruction (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the first-order upwind scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 1st order upwind scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 1st order upwind numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{equation} \hat{\bf f}_{j+1/2} = \left\{\begin{array}{cc} {\bf f}_{j} & {\rm upw} > 0 \\ {\bf f}_{j+1} & {\rm upw} \le 0 \end{array}\right.. \end{equation}

Implementation Notes:

  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 61 of file Interp1PrimFirstOrderUpwind.c.

72 {
73  HyPar *solver = (HyPar*) s;
74 
75  int ghosts = solver->ghosts;
76  int ndims = solver->ndims;
77  int nvars = solver->nvars;
78  int *dim = solver->dim_local;
79 
80  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
81  dimension "dir" */
82  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
83  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
84  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
85  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
86 
87  int i;
88 #pragma omp parallel for schedule(auto) default(shared) private(i,index_outer,indexC,indexI)
89  for (i=0; i<N_outer; i++) {
90  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
91  _ArrayCopy1D_(index_outer,indexC,ndims);
92  _ArrayCopy1D_(index_outer,indexI,ndims);
93  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
94  indexC[dir] = (upw > 0 ? indexI[dir]-1 : indexI[dir]);
95  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0 ,p);
96  int q; _ArrayIndex1D_(ndims,dim ,indexC,ghosts,q);
97  int v; for (v=0; v<nvars; v++) fI[p*nvars+v] = fC[q*nvars+v];
98  }
99  }
100 
101  return(0);
102 }
#define _ArrayIndexnD_(N, index, imax, i, ghost)
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
int ndims
Definition: hypar.h:26
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int Interp1PrimSecondOrderCentral ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

2nd order central reconstruction (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the second-order central scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 2nd order central scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 2nd order central numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{equation} \hat{\bf f}_{j+1/2} = \frac{1}{2}\left( {\bf f}_{j} + {\bf f}_{j+1} \right). \end{equation}

Implementation Notes:

  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • Since this is a central scheme, the input argument upw has no effect.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 62 of file Interp1PrimSecondOrderCentral.c.

73 {
74  HyPar *solver = (HyPar*) s;
75 
76  int ghosts = solver->ghosts;
77  int ndims = solver->ndims;
78  int nvars = solver->nvars;
79  int *dim = solver->dim_local;
80 
81  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
82  dimension "dir" */
83  int indexL[ndims], indexR[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
84  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
85  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
86  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
87 
88  int i;
89 #pragma omp parallel for schedule(auto) default(shared) private(i,index_outer,indexL,indexR,indexI)
90  for (i=0; i<N_outer; i++) {
91  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
92  _ArrayCopy1D_(index_outer,indexL,ndims);
93  _ArrayCopy1D_(index_outer,indexR,ndims);
94  _ArrayCopy1D_(index_outer,indexI,ndims);
95  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
96  indexL[dir] = indexI[dir]-1;
97  indexR[dir] = indexI[dir];
98  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0 ,p);
99  int qL; _ArrayIndex1D_(ndims,dim ,indexL,ghosts,qL);
100  int qR; _ArrayIndex1D_(ndims,dim ,indexR,ghosts,qR);
101  int v; for (v=0; v<nvars; v++) fI[p*nvars+v] = 0.5*(fC[qL*nvars+v]+fC[qR*nvars+v]);
102  }
103  }
104 
105  return(0);
106 }
#define _ArrayIndexnD_(N, index, imax, i, ghost)
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
int ndims
Definition: hypar.h:26
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int Interp1PrimSecondOrderMUSCL ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

2nd order MUSCL scheme (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the second-order MUSCL scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 2nd order MUSCL scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as: using the 2nd order MUSCL scheme:

\begin{equation} \hat{\bf f}_{j+1/2} = {\bf f}_{j} + \frac{1}{2} \phi\left(r_j\right) \left[{\bf f}_{j+1}-{\bf f}_{j}\right] \end{equation}

where

\begin{equation} r_j = \left( f_j - f_{j-1} \right) / \left( f_{j+1} - f_j \right) \end{equation}

and \(\phi\left(r\right)\) is a limiter (minmod, mc, generalized minmod, etc.)

Implementation Notes:

  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

  • van Leer, B. (1979), Towards the Ultimate Conservative Difference Scheme, V. A Second Order Sequel to Godunov's Method, J. Com. Phys., 32, 101–136.
  • Nessyahu, H. and E. Tadmor (1990), Non-oscillatory central differencing for hyperbolic conservation laws, J. Comput. Phys., 87, 408–463.
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 76 of file Interp1PrimSecondOrderMUSCL.c.

87 {
88  HyPar *solver = (HyPar*) s;
89  MUSCLParameters *muscl = (MUSCLParameters*) solver->interp;
90 
91  int ghosts = solver->ghosts;
92  int ndims = solver->ndims;
93  int nvars = solver->nvars;
94  int *dim = solver->dim_local;
95 
96  /* define some constants */
97  double half = 1.0/2.0;
98 
99  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
100  dimension "dir" */
101  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
102  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
103  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
104  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
105 
106  int i;
107  if (upw > 0) {
108 #pragma omp parallel for schedule(auto) default(shared) private(i,index_outer,indexC,indexI)
109  for (i=0; i<N_outer; i++) {
110  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
111  _ArrayCopy1D_(index_outer,indexC,ndims);
112  _ArrayCopy1D_(index_outer,indexI,ndims);
113  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
114  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
115  int qm2,qm1,qp1,v;
116  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
117  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
118  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
119  for (v=0; v<nvars; v++) {
120  /* Defining stencil points */
121  double m2, m1, p1;
122  m2 = fC[qm2*nvars+v];
123  m1 = fC[qm1*nvars+v];
124  p1 = fC[qp1*nvars+v];
125 
126  double slope_ratio = (m1 - m2) / ((p1 - m1) + 1e-40);
127  double phi = muscl->LimiterFunction(slope_ratio);
128  fI[p*nvars+v] = m1 + 0.5 * phi * (p1-m1);
129  }
130  }
131  }
132  } else {
133 #pragma omp parallel for schedule(auto) default(shared) private(i,index_outer,indexC,indexI)
134  for (i=0; i<N_outer; i++) {
135  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
136  _ArrayCopy1D_(index_outer,indexC,ndims);
137  _ArrayCopy1D_(index_outer,indexI,ndims);
138  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
139  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
140  int qm1,qp1,qp2,v;
141  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
142  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
143  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
144  for (v=0; v<nvars; v++) {
145  /* Defining stencil points */
146  double m1, p1, p2;
147  m1 = fC[qm1*nvars+v];
148  p1 = fC[qp1*nvars+v];
149  p2 = fC[qp2*nvars+v];
150 
151  double slope_ratio = (p1 - m1) / ((p2 - p1) + 1e-40);
152  double phi = muscl->LimiterFunction(slope_ratio);
153  fI[p*nvars+v] = p1 + 0.5 * phi * (p1-p2);
154  }
155  }
156  }
157  }
158 
159  return(0);
160 }
void * interp
Definition: hypar.h:362
#define _ArrayIndexnD_(N, index, imax, i, ghost)
int * dim_local
Definition: hypar.h:37
double(* LimiterFunction)(double)
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
Structure of variables/parameters needed by the MUSCL scheme.
int ndims
Definition: hypar.h:26
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int Interp1PrimThirdOrderMUSCL ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

3rd order MUSCL scheme with Koren's limiter (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the third-order MUSCL scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 3rd order MUSCL scheme with Koren's limiter on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as: using the 3rd order MUSCL scheme with Koren's limiter as follows:

\begin{equation} \hat{\bf f}_{j+1/2} = {\bf f}_{j-1} + \phi \left[\frac{1}{3}\left({\bf f}_j-{\bf f}_{j-1}\right) + \frac{1}{6}\left({\bf f}_{j-1}-{\bf f}_{j-2}\right)\right] \end{equation}

where

\begin{equation} \phi = \frac {3\left({\bf f}_j-{\bf f}_{j-1}\right)\left({\bf f}_{j-1}-{\bf f}_{j-2}\right) + \epsilon} {2\left[\left({\bf f}_j-{\bf f}_{j-1}\right)-\left({\bf f}_{j-1}-{\bf f}_{j-2}\right)\right]^2 + 3\left({\bf f}_j-{\bf f}_{j-1}\right)\left({\bf f}_{j-1}-{\bf f}_{j-2}\right) + \epsilon}. \end{equation}

and \(\epsilon\) is a small constant (typically \(10^{-3}\)).

Implementation Notes:

  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

  • van Leer, B., Towards the Ultimate Conservative Difference Scheme. 2: Monotonicity and Conservation Combined in a Second-Order Scheme, J. of Comput. Phys., 14 (4), 1974, pp.361-370, http://dx.doi.org/10.1016/0021-9991(74)90019-9
  • Koren, B., A Robust Upwind Discretization Method for Advection, Diffusion and Source Terms, Centrum voor Wiskunde en Informatica, Amsterdam, 1993
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 75 of file Interp1PrimThirdOrderMUSCL.c.

86 {
87  HyPar *solver = (HyPar*) s;
88  MUSCLParameters *muscl = (MUSCLParameters*) solver->interp;
89 
90  int ghosts = solver->ghosts;
91  int ndims = solver->ndims;
92  int nvars = solver->nvars;
93  int *dim = solver->dim_local;
94 
95  /* define some constants */
96  double one_third = 1.0/3.0;
97  double one_sixth = 1.0/6.0;
98 
99  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
100  dimension "dir" */
101  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
102  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
103  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
104  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
105 
106  int i;
107  if (upw > 0) {
108 #pragma omp parallel for schedule(auto) default(shared) private(i,index_outer,indexC,indexI)
109  for (i=0; i<N_outer; i++) {
110  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
111  _ArrayCopy1D_(index_outer,indexC,ndims);
112  _ArrayCopy1D_(index_outer,indexI,ndims);
113  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
114  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
115  int qm1,qm2,qp1,v;
116  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
117  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
118  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
119  for (v=0; v<nvars; v++) {
120  /* Defining stencil points */
121  double m2, m1, p1;
122  m2 = fC[qm2*nvars+v];
123  m1 = fC[qm1*nvars+v];
124  p1 = fC[qp1*nvars+v];
125 
126  double fdiff = p1 - m1;
127  double bdiff = m1 - m2;
128  double limit = (3*fdiff*bdiff + muscl->eps)
129  / (2*(fdiff-bdiff)*(fdiff-bdiff) + 3*fdiff*bdiff + muscl->eps);
130 
131  fI[p*nvars+v] = m1 + limit * (one_third*fdiff + one_sixth*bdiff);
132  }
133  }
134  }
135  } else {
136 #pragma omp parallel for schedule(auto) default(shared) private(i,index_outer,indexC,indexI)
137  for (i=0; i<N_outer; i++) {
138  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
139  _ArrayCopy1D_(index_outer,indexC,ndims);
140  _ArrayCopy1D_(index_outer,indexI,ndims);
141  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
142  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
143  int qm1,qp1,qp2,v;
144  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
145  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
146  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
147  for (v=0; v<nvars; v++) {
148  /* Defining stencil points */
149  double m1, p1, p2;
150  m1 = fC[qm1*nvars+v];
151  p1 = fC[qp1*nvars+v];
152  p2 = fC[qp2*nvars+v];
153 
154  double fdiff = p2 - p1;
155  double bdiff = p1 - m1;
156  double limit = (3*fdiff*bdiff + muscl->eps)
157  / (2*(fdiff-bdiff)*(fdiff-bdiff) + 3*fdiff*bdiff + muscl->eps);
158 
159  fI[p*nvars+v] = p1 - limit * (one_third*fdiff + one_sixth*bdiff);
160  }
161  }
162  }
163  }
164 
165  return(0);
166 }
void * interp
Definition: hypar.h:362
#define _ArrayIndexnD_(N, index, imax, i, ghost)
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
Structure of variables/parameters needed by the MUSCL scheme.
int ndims
Definition: hypar.h:26
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int Interp1PrimFourthOrderCentral ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

4th order central reconstruction (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the fourth-order central scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 4th order central scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 4th order central numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{equation} \hat{\bf f}_{j+1/2} = -\frac{1}{12} {\bf f}_{j-1} + \frac{7}{12} {\bf f}_{j} + \frac{7}{12} {\bf f}_{j+1} - \frac{1}{12} {\bf f}_{j+2}. \end{equation}

Implementation Notes:

  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • Since this is a central scheme, the input argument upw has no effect.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 62 of file Interp1PrimFourthOrderCentral.c.

73 {
74  HyPar *solver = (HyPar*) s;
75 
76  int ghosts = solver->ghosts;
77  int ndims = solver->ndims;
78  int nvars = solver->nvars;
79  int *dim = solver->dim_local;
80 
81  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
82  dimension "dir" */
83  int indexL[ndims],
84  indexR[ndims],
85  indexLL[ndims],
86  indexRR[ndims],
87  indexI[ndims],
88  index_outer[ndims],
89  bounds_outer[ndims],
90  bounds_inter[ndims];
91 
92  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
93  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
94  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
95 
96  static const double c1 = 7.0 / 12.0;
97  static const double c2 = -1.0 / 12.0;
98 
99  int i;
100 #pragma omp parallel for schedule(auto) default(shared) private(i,index_outer,indexL,indexR,indexI)
101  for (i=0; i<N_outer; i++) {
102  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
103  _ArrayCopy1D_(index_outer,indexL,ndims);
104  _ArrayCopy1D_(index_outer,indexLL,ndims);
105  _ArrayCopy1D_(index_outer,indexR,ndims);
106  _ArrayCopy1D_(index_outer,indexRR,ndims);
107  _ArrayCopy1D_(index_outer,indexI,ndims);
108  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
109  indexLL[dir] = indexI[dir]-2;
110  indexL[dir] = indexI[dir]-1;
111  indexR[dir] = indexI[dir];
112  indexRR[dir] = indexI[dir]+1;
113 
114  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI ,0 ,p);
115  int qLL; _ArrayIndex1D_(ndims,dim ,indexLL,ghosts,qLL);
116  int qL; _ArrayIndex1D_(ndims,dim ,indexL ,ghosts,qL );
117  int qR; _ArrayIndex1D_(ndims,dim ,indexR ,ghosts,qR );
118  int qRR; _ArrayIndex1D_(ndims,dim ,indexRR,ghosts,qRR);
119 
120  int v; for (v=0; v<nvars; v++) {
121  fI[p*nvars+v] = c2 * fC[qLL*nvars+v]
122  + c1 * fC[qL *nvars+v]
123  + c1 * fC[qR *nvars+v]
124  + c2 * fC[qRR*nvars+v];
125  }
126  }
127  }
128 
129  return(0);
130 }
#define _ArrayIndexnD_(N, index, imax, i, ghost)
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
int ndims
Definition: hypar.h:26
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int Interp1PrimFifthOrderUpwind ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order upwind reconstruction (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the fifth-order upwind scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order upwind scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 5th order upwind numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{align} \hat{\bf f}_{j+1/2} = \frac{1}{30} {\bf f}_{j-2} - \frac{13}{60}{\bf f}_{j-1} + \frac{47}{60}{\bf f}_j + \frac{27}{60}{\bf f}_{j+1} - \frac{1}{20}{\bf f}_{j+2}. \end{align}

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 68 of file Interp1PrimFifthOrderUpwind.c.

79 {
80  HyPar *solver = (HyPar*) s;
81 
82  int ghosts = solver->ghosts;
83  int ndims = solver->ndims;
84  int nvars = solver->nvars;
85  int *dim = solver->dim_local;
86  int *stride= solver->stride_with_ghosts;
87 
88  /* define some constants */
89  static const double one_by_thirty = 1.0/30.0,
90  thirteen_by_sixty = 13.0/60.0,
91  fortyseven_by_sixty = 47.0/60.0,
92  twentyseven_by_sixty = 27.0/60.0,
93  one_by_twenty = 1.0/20.0;
94 
95  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
96  dimension "dir" */
97  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
98  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
99  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
100  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
101 
102  int i;
103 #pragma omp parallel for schedule(auto) default(shared) private(i,index_outer,indexC,indexI)
104  for (i=0; i<N_outer; i++) {
105  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
106  _ArrayCopy1D_(index_outer,indexC,ndims);
107  _ArrayCopy1D_(index_outer,indexI,ndims);
108  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
109  int qm1,qm2,qm3,qp1,qp2,p;
110  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
111  if (upw > 0) {
112  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
113  qm3 = qm1 - 2*stride[dir];
114  qm2 = qm1 - stride[dir];
115  qp1 = qm1 + stride[dir];
116  qp2 = qm1 + 2*stride[dir];
117  } else {
118  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
119  qm3 = qm1 + 2*stride[dir];
120  qm2 = qm1 + stride[dir];
121  qp1 = qm1 - stride[dir];
122  qp2 = qm1 - 2*stride[dir];
123  }
124 
125  /* Defining stencil points */
126  double *fm3, *fm2, *fm1, *fp1, *fp2;
127  fm3 = (fC+qm3*nvars);
128  fm2 = (fC+qm2*nvars);
129  fm1 = (fC+qm1*nvars);
130  fp1 = (fC+qp1*nvars);
131  fp2 = (fC+qp2*nvars);
132 
133  int v;
134  for (v=0; v<nvars; v++) {
135  (fI+p*nvars)[v] = one_by_thirty * fm3[v]
136  - thirteen_by_sixty * fm2[v]
137  + fortyseven_by_sixty * fm1[v]
138  + twentyseven_by_sixty * fp1[v]
139  - one_by_twenty * fp2[v];
140  }
141  }
142  }
143 
144  return(0);
145 }
#define _ArrayIndexnD_(N, index, imax, i, ghost)
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int * stride_with_ghosts
Definition: hypar.h:414
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
int ndims
Definition: hypar.h:26
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int Interp1PrimFifthOrderCompactUpwind ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order compact upwind reconstruction (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the fifth-order compact upwind scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order compact upwind scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 5th order compact upwind numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{align} \frac{3}{10}\hat{\bf f}_{j-1/2} + \frac{6}{10}\hat{\bf f}_{j+1/2} + \frac{1}{10}\hat{\bf f}_{j+3/2} = \frac{1}{30}{\bf f}_{j-1} + \frac{19}{30}{\bf f}_j + \frac{1}{3}{\bf f}_{j+1}. \end{align}

The resulting tridiagonal system is solved using tridiagLU() (see also TridiagLU, tridiagLU.h).

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

  • Ghosh, D., Baeder, J. D., Compact Reconstruction Schemes with Weighted ENO Limiting for Hyperbolic Conservation Laws, SIAM Journal on Scientific Computing, 34 (3), 2012, A1678–A1706, http://dx.doi.org/10.1137/110857659
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 72 of file Interp1PrimFifthOrderCompactUpwind.c.

83 {
84  HyPar *solver = (HyPar*) s;
85  MPIVariables *mpi = (MPIVariables*) m;
86  CompactScheme *compact= (CompactScheme*) solver->compact;
87  TridiagLU *lu = (TridiagLU*) solver->lusolver;
88  int sys,Nsys,d,v;
90 
91  int ghosts = solver->ghosts;
92  int ndims = solver->ndims;
93  int nvars = solver->nvars;
94  int *dim = solver->dim_local;
95  int *stride= solver->stride_with_ghosts;
96 
97  /* define some constants */
98  static const double one_third = 1.0/3.0,
99  thirteen_by_sixty = 13.0/60.0,
100  fortyseven_by_sixty = 47.0/60.0,
101  twentyseven_by_sixty = 27.0/60.0,
102  one_by_twenty = 1.0/20.0,
103  one_by_thirty = 1.0/30.0,
104  nineteen_by_thirty = 19.0/30.0,
105  three_by_ten = 3.0/10.0,
106  six_by_ten = 6.0/10.0,
107  one_by_ten = 1.0/10.0;
108 
109  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
110  dimension "dir" */
111  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
112  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
113  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
114  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
115 
116  /* calculate total number of tridiagonal systems to solve */
117  _ArrayProduct1D_(bounds_outer,ndims,Nsys); Nsys *= nvars;
118 
119  /* Allocate arrays for tridiagonal system */
120  double *A = compact->A;
121  double *B = compact->B;
122  double *C = compact->C;
123  double *R = compact->R;
124 
125 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,index_outer,indexC,indexI)
126  for (sys=0; sys < N_outer; sys++) {
127  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
128  _ArrayCopy1D_(index_outer,indexC,ndims);
129  _ArrayCopy1D_(index_outer,indexI,ndims);
130  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
131  int qm1,qm2,qm3,qp1,qp2,p;
132  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
133  if (upw > 0) {
134  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
135  qm3 = qm1 - 2*stride[dir];
136  qm2 = qm1 - stride[dir];
137  qp1 = qm1 + stride[dir];
138  qp2 = qm1 + 2*stride[dir];
139  } else {
140  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
141  qm3 = qm1 + 2*stride[dir];
142  qm2 = qm1 + stride[dir];
143  qp1 = qm1 - stride[dir];
144  qp2 = qm1 - 2*stride[dir];
145  }
146 
147  /* Defining stencil points */
148  double *fm3, *fm2, *fm1, *fp1, *fp2;
149  fm3 = fC+qm3*nvars;
150  fm2 = fC+qm2*nvars;
151  fm1 = fC+qm1*nvars;
152  fp1 = fC+qp1*nvars;
153  fp2 = fC+qp2*nvars;
154 
155  if ( ((mpi->ip[dir] == 0 ) && (indexI[dir] == 0 ))
156  || ((mpi->ip[dir] == mpi->iproc[dir]-1) && (indexI[dir] == dim[dir])) ) {
157 
158  /* Use 5th order upwind at the physical boundaries */
159  _ArraySetValue_((A+Nsys*indexI[dir]+sys*nvars),nvars,0.0)
160  _ArraySetValue_((B+Nsys*indexI[dir]+sys*nvars),nvars,1.0)
161  _ArraySetValue_((C+Nsys*indexI[dir]+sys*nvars),nvars,0.0)
162  for (v=0; v<nvars; v++) {
163  (R+Nsys*indexI[dir]+sys*nvars)[v] = one_by_thirty * fm3[v]
164  - thirteen_by_sixty * fm2[v]
165  + fortyseven_by_sixty * fm1[v]
166  + twentyseven_by_sixty * fp1[v]
167  - one_by_twenty * fp2[v];
168  }
169 
170  } else {
171 
172  /* Use 5th order upwind at the physical boundaries */
173  if (upw > 0) {
174  _ArraySetValue_((A+Nsys*indexI[dir]+sys*nvars),nvars,three_by_ten);
175  _ArraySetValue_((B+Nsys*indexI[dir]+sys*nvars),nvars,six_by_ten );
176  _ArraySetValue_((C+Nsys*indexI[dir]+sys*nvars),nvars,one_by_ten );
177  } else {
178  _ArraySetValue_((C+Nsys*indexI[dir]+sys*nvars),nvars,three_by_ten);
179  _ArraySetValue_((B+Nsys*indexI[dir]+sys*nvars),nvars,six_by_ten );
180  _ArraySetValue_((A+Nsys*indexI[dir]+sys*nvars),nvars,one_by_ten );
181  }
182  for (v=0; v<nvars; v++) {
183  (R+Nsys*indexI[dir]+sys*nvars)[v] = one_by_thirty * fm2[v]
184  + nineteen_by_thirty * fm1[v]
185  + one_third * fp1[v];
186  }
187  }
188  }
189  }
190 
191 #ifdef serial
192 
193  /* Solve the tridiagonal system */
194  IERR tridiagLU(A,B,C,R,dim[dir]+1,Nsys,lu,NULL); CHECKERR(ierr);
195 
196 #else
197 
198  /* Solve the tridiagonal system */
199  /* all processes except the last will solve without the last interface to avoid overlap */
200  if (mpi->ip[dir] != mpi->iproc[dir]-1) { IERR tridiagLU(A,B,C,R,dim[dir] ,Nsys,lu,&mpi->comm[dir]); CHECKERR(ierr); }
201  else { IERR tridiagLU(A,B,C,R,dim[dir]+1,Nsys,lu,&mpi->comm[dir]); CHECKERR(ierr); }
202 
203  /* Now get the solution to the last interface from the next proc */
204  double *sendbuf = compact->sendbuf;
205  double *recvbuf = compact->recvbuf;
206  MPI_Request req[2] = {MPI_REQUEST_NULL,MPI_REQUEST_NULL};
207  if (mpi->ip[dir]) for (d=0; d<Nsys; d++) sendbuf[d] = R[d];
208  if (mpi->ip[dir] != mpi->iproc[dir]-1) MPI_Irecv(recvbuf,Nsys,MPI_DOUBLE,mpi->ip[dir]+1,214,mpi->comm[dir],&req[0]);
209  if (mpi->ip[dir]) MPI_Isend(sendbuf,Nsys,MPI_DOUBLE,mpi->ip[dir]-1,214,mpi->comm[dir],&req[1]);
210  MPI_Status status_arr[2];
211  MPI_Waitall(2,&req[0],status_arr);
212  if (mpi->ip[dir] != mpi->iproc[dir]-1) for (d=0; d<Nsys; d++) R[d+Nsys*dim[dir]] = recvbuf[d];
213 
214 #endif
215 
216  /* save the solution to fI */
217 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,index_outer,indexC,indexI)
218  for (sys=0; sys < N_outer; sys++) {
219  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
220  _ArrayCopy1D_(index_outer,indexI,ndims);
221  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
222  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
223  _ArrayCopy1D_((R+sys*nvars+Nsys*indexI[dir]),(fI+nvars*p),nvars);
224  }
225  }
226 
227  return(0);
228 }
MPI_Comm * comm
#define _ArraySetValue_(x, size, value)
#define _ArrayIndexnD_(N, index, imax, i, ghost)
int tridiagLU(double *, double *, double *, double *, int, int, void *, void *)
Definition: tridiagLU.c:83
int * dim_local
Definition: hypar.h:37
double * recvbuf
Structure of variables/parameters needed by the compact schemes.
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
void * compact
Definition: hypar.h:364
int * stride_with_ghosts
Definition: hypar.h:414
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure of MPI-related variables.
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
double * sendbuf
void * lusolver
Definition: hypar.h:368
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimFifthOrderWENO ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order WENO reconstruction (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the fifth-order WENO scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order WENO scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 5th order WENO numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as the convex combination of three 3rd order methods:

\begin{align} &\ \omega_1\ \times\ \left[ \hat{\bf f}_{j+1/2}^1 = \frac{1}{3} {\bf f}_{j-2} - \frac{7}{6} {\bf f}_{j-1} + \frac{11}{6} {\bf f}_j \right]\\ + &\ \omega_2\ \times\ \left[ \hat{\bf f}_{j+1/2}^2 = -\frac{1}{6} {\bf f}_{j-1} + \frac{5}{6} {\bf f}_j + \frac{1}{3} {\bf f}_{j+1} \right]\\ + &\ \omega_3\ \times\ \left[ \hat{\bf f}_{j+1/2}^3 = \frac{1}{3} {\bf f}_j + \frac{5}{6} {\bf f}_{j+1} - \frac{1}{6} {\bf f}_{j+2} \right]\\ \Rightarrow &\ \hat{\bf f}_{j+1/2} = \frac{\omega_1}{3} {\bf f}_{j-2} - \frac{1}{6}(7\omega_1+\omega_2){\bf f}_{j-1} + \frac{1}{6}(11\omega_1+5\omega_2+2\omega_3){\bf f}_j + \frac{1}{6}(2\omega_2+5\omega_3){\bf f}_{j+1} - \frac{\omega_3}{6}{\bf f}_{j+2}, \end{align}

where \(\omega_k; k=1,2,3\) are the nonlinear WENO weights computed in WENOFifthOrderCalculateWeights() (note that the \(\omega\) are different for each component of the vector \(\hat{\bf f}\)).

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 74 of file Interp1PrimFifthOrderWENO.c.

85 {
86  HyPar *solver = (HyPar*) s;
87  WENOParameters *weno = (WENOParameters*) solver->interp;
88 
89  int ghosts = solver->ghosts;
90  int ndims = solver->ndims;
91  int nvars = solver->nvars;
92  int *dim = solver->dim_local;
93  int *stride= solver->stride_with_ghosts;
94 
95  /* define some constants */
96  static const double one_sixth = 1.0/6.0;
97 
98  double *ww1, *ww2, *ww3;
99  ww1 = weno->w1 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
100  ww2 = weno->w2 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
101  ww3 = weno->w3 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
102 
103  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
104  dimension "dir" */
105  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
106  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
107  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
108  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
109 
110 #if defined(CPU_STAT)
111  clock_t cpu_start, cpu_end;
112  cpu_start = clock();
113 #endif
114 
115  int i;
116 #pragma omp parallel for schedule(auto) default(shared) private(i,index_outer,indexC,indexI)
117  for (i=0; i<N_outer; i++) {
118  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
119  _ArrayCopy1D_(index_outer,indexC,ndims);
120  _ArrayCopy1D_(index_outer,indexI,ndims);
121  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
122  int qm1,qm2,qm3,qp1,qp2,p;
123  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
124  if (upw > 0) {
125  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
126  qm3 = qm1 - 2*stride[dir];
127  qm2 = qm1 - stride[dir];
128  qp1 = qm1 + stride[dir];
129  qp2 = qm1 + 2*stride[dir];
130  } else {
131  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
132  qm3 = qm1 + 2*stride[dir];
133  qm2 = qm1 + stride[dir];
134  qp1 = qm1 - stride[dir];
135  qp2 = qm1 - 2*stride[dir];
136  }
137 
138  /* Defining stencil points */
139  double *fm3, *fm2, *fm1, *fp1, *fp2;
140  fm3 = (fC+qm3*nvars);
141  fm2 = (fC+qm2*nvars);
142  fm1 = (fC+qm1*nvars);
143  fp1 = (fC+qp1*nvars);
144  fp2 = (fC+qp2*nvars);
145 
146  /* Candidate stencils and their optimal weights*/
147  double f1[nvars], f2[nvars], f3[nvars];
148  _ArrayAXBYCZ_(f1,(2*one_sixth),fm3,(-7*one_sixth) ,fm2,(11*one_sixth) ,fm1,nvars);
149  _ArrayAXBYCZ_(f2,(-one_sixth) ,fm2,(5*one_sixth) ,fm1,(2*one_sixth) ,fp1,nvars);
150  _ArrayAXBYCZ_(f3,(2*one_sixth),fm1,(5*one_sixth) ,fp1,(-one_sixth) ,fp2,nvars);
151 
152  /* calculate WENO weights */
153  double *w1,*w2,*w3;
154  w1 = (ww1+p*nvars);
155  w2 = (ww2+p*nvars);
156  w3 = (ww3+p*nvars);
157 
158  _ArrayMultiply3Add1D_((fI+p*nvars),w1,f1,w2,f2,w3,f3,nvars);
159  }
160  }
161 
162 #if defined(CPU_STAT)
163  cpu_end = clock();
164  printf("Interp1PrimFifthOrderWENO CPU time = %8.6lf dir = %d\n", (double)(cpu_end - cpu_start) / CLOCKS_PER_SEC, dir);
165 #endif
166 
167  return(0);
168 }
void * interp
Definition: hypar.h:362
#define _ArrayIndexnD_(N, index, imax, i, ghost)
int * dim_local
Definition: hypar.h:37
Structure of variables/parameters needed by the WENO-type scheme.
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
#define _ArrayMultiply3Add1D_(x, a, b, c, d, e, f, size)
int * stride_with_ghosts
Definition: hypar.h:414
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define _ArrayAXBYCZ_(w, a, x, b, y, c, z, size)
int ndims
Definition: hypar.h:26
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int Interp1PrimFifthOrderCRWENO ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order CRWENO reconstruction (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the fifth-order CRWENO scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order CRWENO scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 5th order CRWENO numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as the convex combination of three 3rd order methods:

\begin{align} &\ \omega_1\ \times\ \left[ \frac{2}{3}\hat{\bf f}_{j-1/2} + \frac{1}{3}\hat{\bf f}_{j+1/2} = \frac{1}{6} \left( f_{j-1} + 5f_j \right) \right]\\ + &\ \omega_2\ \times\ \left[ \frac{1}{3}\hat{\bf f}_{j-1/2}+\frac{2}{3}\hat{\bf f}_{j+1/2} = \frac{1}{6} \left( 5f_j + f_{j+1} \right) \right] \\ + &\ \omega_3\ \times\ \left[ \frac{2}{3}\hat{\bf f}_{j+1/2} + \frac{1}{3}\hat{\bf f}_{j+3/2} = \frac{1}{6} \left( f_j + 5f_{j+1} \right) \right] \\ \Rightarrow &\ \left(\frac{2}{3}\omega_1+\frac{1}{3}\omega_2\right)\hat{\bf f}_{j-1/2} + \left[\frac{1}{3}\omega_1+\frac{2}{3}(\omega_2+\omega_3)\right]\hat{\bf f}_{j+1/2} + \frac{1}{3}\omega_3\hat{\bf f}_{j+3/2} = \frac{\omega_1}{6}{\bf f}_{j-1} + \frac{5(\omega_1+\omega_2)+\omega_3}{6}{\bf f}_j + \frac{\omega_2+5\omega_3}{6}{\bf f}_{j+1}, \end{align}

where \(\omega_k; k=1,2,3\) are the nonlinear WENO weights computed in WENOFifthOrderCalculateWeights() (note that the \(\omega\) are different for each component of the vector \(\hat{\bf f}\)). The resulting tridiagonal system is solved using tridiagLU() (see also TridiagLU, tridiagLU.h).

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

  • Ghosh, D., Baeder, J. D., Compact Reconstruction Schemes with Weighted ENO Limiting for Hyperbolic Conservation Laws, SIAM Journal on Scientific Computing, 34 (3), 2012, A1678–A1706, http://dx.doi.org/10.1137/110857659
  • Ghosh, D., Constantinescu, E. M., Brown, J., Efficient Implementation of Nonlinear Compact Schemes on Massively Parallel Platforms, SIAM Journal on Scientific Computing, 37 (3), 2015, C354–C383, http://dx.doi.org/10.1137/140989261
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 78 of file Interp1PrimFifthOrderCRWENO.c.

89 {
90  HyPar *solver = (HyPar*) s;
91  MPIVariables *mpi = (MPIVariables*) m;
92  CompactScheme *compact= (CompactScheme*) solver->compact;
93  WENOParameters *weno = (WENOParameters*) solver->interp;
94  TridiagLU *lu = (TridiagLU*) solver->lusolver;
95  int sys,Nsys,d;
97 
98  int ghosts = solver->ghosts;
99  int ndims = solver->ndims;
100  int nvars = solver->nvars;
101  int *dim = solver->dim_local;
102  int *stride= solver->stride_with_ghosts;
103 
104  /* define some constants */
105  static const double one_third = 1.0/3.0;
106  static const double one_sixth = 1.0/6.0;
107 
108  double *ww1, *ww2, *ww3;
109  ww1 = weno->w1 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
110  ww2 = weno->w2 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
111  ww3 = weno->w3 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
112 
113  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
114  dimension "dir" */
115  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
116  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
117  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
118  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
119 
120  /* calculate total number of tridiagonal systems to solve */
121  _ArrayProduct1D_(bounds_outer,ndims,Nsys); Nsys *= nvars;
122 
123  /* Allocate arrays for tridiagonal system */
124  double *A = compact->A;
125  double *B = compact->B;
126  double *C = compact->C;
127  double *R = compact->R;
128 
129 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,index_outer,indexC,indexI)
130  for (sys=0; sys < N_outer; sys++) {
131  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
132  _ArrayCopy1D_(index_outer,indexC,ndims);
133  _ArrayCopy1D_(index_outer,indexI,ndims);
134  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
135  int qm1,qm2,qm3,qp1,qp2,p;
136  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
137  if (upw > 0) {
138  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
139  qm3 = qm1 - 2*stride[dir];
140  qm2 = qm1 - stride[dir];
141  qp1 = qm1 + stride[dir];
142  qp2 = qm1 + 2*stride[dir];
143  } else {
144  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
145  qm3 = qm1 + 2*stride[dir];
146  qm2 = qm1 + stride[dir];
147  qp1 = qm1 - stride[dir];
148  qp2 = qm1 - 2*stride[dir];
149  }
150 
151  /* Defining stencil points */
152  double *fm3, *fm2, *fm1, *fp1, *fp2;
153  fm3 = fC+qm3*nvars;
154  fm2 = fC+qm2*nvars;
155  fm1 = fC+qm1*nvars;
156  fp1 = fC+qp1*nvars;
157  fp2 = fC+qp2*nvars;
158 
159  /* Candidate stencils and their optimal weights*/
160  double f1[nvars], f2[nvars], f3[nvars];
161  if ( ((mpi->ip[dir] == 0 ) && (indexI[dir] == 0 ))
162  || ((mpi->ip[dir] == mpi->iproc[dir]-1) && (indexI[dir] == dim[dir])) ) {
163  /* Use WENO5 at the physical boundaries */
164  _ArrayAXBYCZ_(f1,(2*one_sixth),fm3,(-7*one_sixth) ,fm2,(11*one_sixth) ,fm1,nvars);
165  _ArrayAXBYCZ_(f2,(-one_sixth) ,fm2,(5*one_sixth) ,fm1,(2*one_sixth) ,fp1,nvars);
166  _ArrayAXBYCZ_(f3,(2*one_sixth),fm1,(5*one_sixth) ,fp1,(-one_sixth) ,fp2,nvars);
167  } else {
168  /* CRWENO5 at the interior points */
169  _ArrayAXBY_(f1,(one_sixth) ,fm2,(5*one_sixth),fm1,nvars);
170  _ArrayAXBY_(f2,(5*one_sixth),fm1,(one_sixth) ,fp1,nvars);
171  _ArrayAXBY_(f3,(one_sixth) ,fm1,(5*one_sixth),fp1,nvars);
172  }
173 
174  /* retrieve the WENO weights */
175  double *w1, *w2, *w3;
176  w1 = (ww1+p*nvars);
177  w2 = (ww2+p*nvars);
178  w3 = (ww3+p*nvars);
179 
180  if ( ((mpi->ip[dir] == 0 ) && (indexI[dir] == 0 ))
181  || ((mpi->ip[dir] == mpi->iproc[dir]-1) && (indexI[dir] == dim[dir])) ) {
182  _ArraySetValue_ ((A+Nsys*indexI[dir]+sys*nvars),nvars,0.0)
183  _ArraySetValue_ ((B+Nsys*indexI[dir]+sys*nvars),nvars,1.0)
184  _ArraySetValue_ ((C+Nsys*indexI[dir]+sys*nvars),nvars,0.0)
185  } else {
186  if (upw > 0) {
187  _ArrayAXBY_ ((A+Nsys*indexI[dir]+sys*nvars),(2*one_third) ,w1,(one_third) ,w2,nvars);
188  _ArrayAXBYCZ_ ((B+Nsys*indexI[dir]+sys*nvars),(one_third) ,w1,(2*one_third),w2,(2*one_third),w3,nvars);
189  _ArrayScaleCopy1D_(w3,(one_third),(C+Nsys*indexI[dir]+sys*nvars),nvars);
190  } else {
191  _ArrayAXBY_ ((C+Nsys*indexI[dir]+sys*nvars),(2*one_third) ,w1,(one_third) ,w2,nvars);
192  _ArrayAXBYCZ_ ((B+Nsys*indexI[dir]+sys*nvars),(one_third) ,w1,(2*one_third),w2,(2*one_third),w3,nvars);
193  _ArrayScaleCopy1D_(w3,(one_third),(A+Nsys*indexI[dir]+sys*nvars),nvars);
194  }
195  }
196  _ArrayMultiply3Add1D_ ((R+Nsys*indexI[dir]+sys*nvars),w1,f1,w2,f2,w3,f3,nvars);
197  }
198  }
199 
200 #ifdef serial
201 
202  /* Solve the tridiagonal system */
203  IERR tridiagLU(A,B,C,R,dim[dir]+1,Nsys,lu,NULL); CHECKERR(ierr);
204 
205 #else
206 
207  /* Solve the tridiagonal system */
208  /* all processes except the last will solve without the last interface to avoid overlap */
209  if (mpi->ip[dir] != mpi->iproc[dir]-1) { IERR tridiagLU(A,B,C,R,dim[dir] ,Nsys,lu,&mpi->comm[dir]); CHECKERR(ierr); }
210  else { IERR tridiagLU(A,B,C,R,dim[dir]+1,Nsys,lu,&mpi->comm[dir]); CHECKERR(ierr); }
211 
212  /* Now get the solution to the last interface from the next proc */
213  double *sendbuf = compact->sendbuf;
214  double *recvbuf = compact->recvbuf;
215  MPI_Request req[2] = {MPI_REQUEST_NULL,MPI_REQUEST_NULL};
216  if (mpi->ip[dir]) for (d=0; d<Nsys; d++) sendbuf[d] = R[d];
217  if (mpi->ip[dir] != mpi->iproc[dir]-1) MPI_Irecv(recvbuf,Nsys,MPI_DOUBLE,mpi->ip[dir]+1,214,mpi->comm[dir],&req[0]);
218  if (mpi->ip[dir]) MPI_Isend(sendbuf,Nsys,MPI_DOUBLE,mpi->ip[dir]-1,214,mpi->comm[dir],&req[1]);
219  MPI_Status status_arr[2];
220  MPI_Waitall(2,&req[0],status_arr);
221  if (mpi->ip[dir] != mpi->iproc[dir]-1) for (d=0; d<Nsys; d++) R[d+Nsys*dim[dir]] = recvbuf[d];
222 
223 #endif
224 
225  /* save the solution to fI */
226 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,index_outer,indexC,indexI)
227  for (sys=0; sys < N_outer; sys++) {
228  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
229  _ArrayCopy1D_(index_outer,indexI,ndims);
230  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
231  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
232  _ArrayCopy1D_((R+sys*nvars+Nsys*indexI[dir]),(fI+nvars*p),nvars);
233  }
234  }
235 
236  return(0);
237 }
void * interp
Definition: hypar.h:362
MPI_Comm * comm
#define _ArraySetValue_(x, size, value)
#define _ArrayAXBY_(z, a, x, b, y, size)
#define _ArrayIndexnD_(N, index, imax, i, ghost)
#define _ArrayScaleCopy1D_(x, a, y, size)
int tridiagLU(double *, double *, double *, double *, int, int, void *, void *)
Definition: tridiagLU.c:83
int * dim_local
Definition: hypar.h:37
double * recvbuf
Structure of variables/parameters needed by the WENO-type scheme.
Structure of variables/parameters needed by the compact schemes.
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
#define _ArrayMultiply3Add1D_(x, a, b, c, d, e, f, size)
void * compact
Definition: hypar.h:364
int * stride_with_ghosts
Definition: hypar.h:414
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
#define _ArrayAXBYCZ_(w, a, x, b, y, c, z, size)
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure of MPI-related variables.
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
double * sendbuf
void * lusolver
Definition: hypar.h:368
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimFifthOrderHCWENO ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order hybrid compact-WENO reconstruction (component-wise) on a uniform grid

Component-wise interpolation of the first primitive at the cell interfaces using the fifth-order hybrid-compact WENO scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order hybrid compact-WENO scheme on a uniform grid. The tridiagonal system is solved using tridiagLU() (see also TridiagLU, tridiagLU.h). See references below for a complete description of the method implemented here.

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The WENO weights are computed in WENOFifthOrderCalculateWeights().
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 63 of file Interp1PrimFifthOrderHCWENO.c.

74 {
75  HyPar *solver = (HyPar*) s;
76  MPIVariables *mpi = (MPIVariables*) m;
77  CompactScheme *compact= (CompactScheme*) solver->compact;
78  WENOParameters *weno = (WENOParameters*) solver->interp;
79  TridiagLU *lu = (TridiagLU*) solver->lusolver;
80  int sys,Nsys,d;
82 
83  int ghosts = solver->ghosts;
84  int ndims = solver->ndims;
85  int nvars = solver->nvars;
86  int *dim = solver->dim_local;
87 
88  /* define some constants */
89  static const double one_half = 1.0/2.0;
90  static const double one_third = 1.0/3.0;
91  static const double one_sixth = 1.0/6.0;
92 
93  double *ww1, *ww2, *ww3;
94  ww1 = weno->w1 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
95  ww2 = weno->w2 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
96  ww3 = weno->w3 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
97 
98  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
99  dimension "dir" */
100  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
101  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
102  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
103  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
104 
105  /* calculate total number of tridiagonal systems to solve */
106  _ArrayProduct1D_(bounds_outer,ndims,Nsys); Nsys *= nvars;
107 
108  /* Allocate arrays for tridiagonal system */
109  double *A = compact->A;
110  double *B = compact->B;
111  double *C = compact->C;
112  double *R = compact->R;
113 
114 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,index_outer,indexC,indexI)
115  for (sys=0; sys < N_outer; sys++) {
116  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
117  _ArrayCopy1D_(index_outer,indexC,ndims);
118  _ArrayCopy1D_(index_outer,indexI,ndims);
119  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
120  int qm1,qm2,qm3,qp1,qp2,p;
121  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
122  if (upw > 0) {
123  indexC[dir] = indexI[dir]-3; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
124  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
125  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
126  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
127  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
128  } else {
129  indexC[dir] = indexI[dir]+2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
130  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
131  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
132  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
133  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
134  }
135  int v;
136  for (v=0; v<nvars; v++) {
137  /* Defining stencil points */
138  double fm3, fm2, fm1, fp1, fp2;
139  fm3 = fC[qm3*nvars+v];
140  fm2 = fC[qm2*nvars+v];
141  fm1 = fC[qm1*nvars+v];
142  fp1 = fC[qp1*nvars+v];
143  fp2 = fC[qp2*nvars+v];
144 
145  /* Candidate stencils and their optimal weights*/
146  double f1, f2, f3;
147  f1 = (2*one_sixth)*fm3 - (7.0*one_sixth)*fm2 + (11.0*one_sixth)*fm1;
148  f2 = (-one_sixth)*fm2 + (5.0*one_sixth)*fm1 + (2*one_sixth)*fp1;
149  f3 = (2*one_sixth)*fm1 + (5*one_sixth)*fp1 - (one_sixth)*fp2;
150 
151  /* calculate WENO weights */
152  double w1,w2,w3;
153  w1 = *(ww1+p*nvars+v);
154  w2 = *(ww2+p*nvars+v);
155  w3 = *(ww3+p*nvars+v);
156 
157  /* calculate the hybridization parameter */
158  double sigma;
159  if ( ((mpi->ip[dir] == 0 ) && (indexI[dir] == 0 ))
160  || ((mpi->ip[dir] == mpi->iproc[dir]-1) && (indexI[dir] == dim[dir])) ) {
161  /* Standard WENO at physical boundaries */
162  sigma = 0.0;
163  } else {
164  double cuckoo, df_jm12, df_jp12, df_jp32, r_j, r_jp1, r_int;
165  cuckoo = (0.9*weno->rc / (1.0-0.9*weno->rc)) * weno->xi * weno->xi;
166  df_jm12 = fm1 - fm2;
167  df_jp12 = fp1 - fm1;
168  df_jp32 = fp2 - fp1;
169  r_j = (absolute(2*df_jp12*df_jm12)+cuckoo)/(df_jp12*df_jp12+df_jm12*df_jm12+cuckoo);
170  r_jp1 = (absolute(2*df_jp32*df_jp12)+cuckoo)/(df_jp32*df_jp32+df_jp12*df_jp12+cuckoo);
171  r_int = min(r_j, r_jp1);
172  sigma = min((r_int/weno->rc), 1.0);
173  }
174 
175  if (upw > 0) {
176  A[sys*nvars+v+Nsys*indexI[dir]] = one_half * sigma;
177  B[sys*nvars+v+Nsys*indexI[dir]] = 1.0;
178  C[sys*nvars+v+Nsys*indexI[dir]] = one_sixth * sigma;
179  } else {
180  C[sys*nvars+v+Nsys*indexI[dir]] = one_half * sigma;
181  B[sys*nvars+v+Nsys*indexI[dir]] = 1.0;
182  A[sys*nvars+v+Nsys*indexI[dir]] = one_sixth * sigma;
183  }
184 
185  double fWENO, fCompact;
186  fWENO = w1*f1 + w2*f2 + w3*f3;
187  fCompact = one_sixth * (one_third*fm2 + 19.0*one_third*fm1 + 10.0*one_third*fp1);
188  R[sys*nvars+v+Nsys*indexI[dir]] = sigma*fCompact + (1.0-sigma)*fWENO;
189  }
190  }
191  }
192 
193 #ifdef serial
194 
195  /* Solve the tridiagonal system */
196  IERR tridiagLU(A,B,C,R,dim[dir]+1,Nsys,lu,NULL); CHECKERR(ierr);
197 
198 #else
199 
200  /* Solve the tridiagonal system */
201  /* all processes except the last will solve without the last interface to avoid overlap */
202  if (mpi->ip[dir] != mpi->iproc[dir]-1) { IERR tridiagLU(A,B,C,R,dim[dir] ,Nsys,lu,&mpi->comm[dir]); CHECKERR(ierr); }
203  else { IERR tridiagLU(A,B,C,R,dim[dir]+1,Nsys,lu,&mpi->comm[dir]); CHECKERR(ierr); }
204 
205  /* Now get the solution to the last interface from the next proc */
206  double *sendbuf = compact->sendbuf;
207  double *recvbuf = compact->recvbuf;
208  MPI_Request req[2] = {MPI_REQUEST_NULL,MPI_REQUEST_NULL};
209  if (mpi->ip[dir]) for (d=0; d<Nsys; d++) sendbuf[d] = R[d];
210  if (mpi->ip[dir] != mpi->iproc[dir]-1) MPI_Irecv(recvbuf,Nsys,MPI_DOUBLE,mpi->ip[dir]+1,214,mpi->comm[dir],&req[0]);
211  if (mpi->ip[dir]) MPI_Isend(sendbuf,Nsys,MPI_DOUBLE,mpi->ip[dir]-1,214,mpi->comm[dir],&req[1]);
212  MPI_Status status_arr[2];
213  MPI_Waitall(2,&req[0],status_arr);
214  if (mpi->ip[dir] != mpi->iproc[dir]-1) for (d=0; d<Nsys; d++) R[d+Nsys*dim[dir]] = recvbuf[d];
215 
216 #endif
217 
218  /* save the solution to fI */
219 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,index_outer,indexC,indexI)
220  for (sys=0; sys < N_outer; sys++) {
221  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
222  _ArrayCopy1D_(index_outer,indexI,ndims);
223  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
224  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
225  _ArrayCopy1D_((R+sys*nvars+Nsys*indexI[dir]),(fI+nvars*p),nvars);
226  }
227  }
228 
229  return(0);
230 }
void * interp
Definition: hypar.h:362
MPI_Comm * comm
#define _ArrayIndexnD_(N, index, imax, i, ghost)
int tridiagLU(double *, double *, double *, double *, int, int, void *, void *)
Definition: tridiagLU.c:83
int * dim_local
Definition: hypar.h:37
double * recvbuf
Structure of variables/parameters needed by the WENO-type scheme.
Structure of variables/parameters needed by the compact schemes.
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
void * compact
Definition: hypar.h:364
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define absolute(a)
Definition: math_ops.h:32
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure of MPI-related variables.
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
double * sendbuf
void * lusolver
Definition: hypar.h:368
#define min(a, b)
Definition: math_ops.h:14
#define _DECLARE_IERR_
Definition: basic.h:17
int gpuInterp1PrimFifthOrderWENO ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order WENO reconstruction (component-wise) on a uniform grid

GPU implementation of component-wise interpolation of the first primitive at the cell interfaces using the fifth-order WENO scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order WENO scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 5th order WENO numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as the convex combination of three 3rd order methods:

\begin{align} &\ \omega_1\ \times\ \left[ \hat{\bf f}_{j+1/2}^1 = \frac{1}{3} {\bf f}_{j-2} - \frac{7}{6} {\bf f}_{j-1} + \frac{11}{6} {\bf f}_j \right]\\ + &\ \omega_2\ \times\ \left[ \hat{\bf f}_{j+1/2}^2 = -\frac{1}{6} {\bf f}_{j-1} + \frac{5}{6} {\bf f}_j + \frac{1}{3} {\bf f}_{j+1} \right]\\ + &\ \omega_3\ \times\ \left[ \hat{\bf f}_{j+1/2}^3 = \frac{1}{3} {\bf f}_j + \frac{5}{6} {\bf f}_{j+1} - \frac{1}{6} {\bf f}_{j+2} \right]\\ \Rightarrow &\ \hat{\bf f}_{j+1/2} = \frac{\omega_1}{3} {\bf f}_{j-2} - \frac{1}{6}(7\omega_1+\omega_2){\bf f}_{j-1} + \frac{1}{6}(11\omega_1+5\omega_2+2\omega_3){\bf f}_j + \frac{1}{6}(2\omega_2+5\omega_3){\bf f}_{j+1} - \frac{\omega_3}{6}{\bf f}_{j+2}, \end{align}

where \(\omega_k; k=1,2,3\) are the nonlinear WENO weights computed in WENOFifthOrderCalculateWeights() (note that the \(\omega\) are different for each component of the vector \(\hat{\bf f}\)).

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 352 of file Interp1PrimFifthOrderWENO_GPU.cu.

363 {
364  HyPar *solver = (HyPar*) s;
365  WENOParameters *weno = (WENOParameters*) solver->interp;
366 
367  int ghosts = solver->ghosts;
368  int ndims = solver->ndims;
369  int nvars = solver->nvars;
370  int *dim = solver->dim_local;
371  int *stride= solver->stride_with_ghosts;
372 
373  /* calculate dimension offset */
374  int offset = weno->offset[dir];
375  int bounds_inter[ndims];
376  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
377  int npoints_grid; _ArrayProduct1D_(bounds_inter,ndims,npoints_grid);
378  int nblocks = (npoints_grid - 1) / GPU_THREADS_PER_BLOCK + 1;
379 
380 #if defined(GPU_STAT)
381  cudaEvent_t start, stop;
382  float milliseconds = 0;
383  checkCuda( cudaEventCreate(&start) );
384  checkCuda( cudaEventCreate(&stop) );
385 
386 
387  int weno_memory_accessed = 3*npoints_grid*nvars*sizeof(double);
388  int fI_memory_accessed = npoints_grid*nvars*sizeof(double);
389  int fC_memory_accessed = 1;
390  for (int d=0; d<ndims; d++) {
391  if (d == dir) fC_memory_accessed *= (dim[d]+2*ghosts);
392  else fC_memory_accessed *= dim[d];
393  }
394  fC_memory_accessed *= nvars*sizeof(double);
395 
396  checkCuda( cudaEventRecord(start) );
397 #endif
398 
399  Interp1PrimFifthOrderWENO_kernel<<<nblocks, GPU_THREADS_PER_BLOCK>>>(
400  npoints_grid, solver->npoints_local_wghosts, ndims, dir, ghosts, nvars, weno->size, offset, stride[dir], upw, uflag,
401  solver->gpu_dim_local, fC, weno->w1, weno->w2, weno->w3, fI
402  );
403 #if defined(GPU_STAT)
404  checkCuda( cudaEventRecord(stop) );
405  checkCuda( cudaEventSynchronize(stop) );
406 #endif
407 
408  cudaDeviceSynchronize();
409 
410 #if defined(GPU_STAT)
411  checkCuda( cudaEventElapsedTime(&milliseconds, start, stop) );
412 
413  printf("%-50s GPU time (secs) = %.6f dir = %d bandwidth (GB/s) = %6.2f\n",
414  "Interp1PrimFifthOrderWENO2", milliseconds*1e-3, dir,
415  (1e-6*(weno_memory_accessed+fI_memory_accessed+fC_memory_accessed))/milliseconds);
416 
417  checkCuda( cudaEventDestroy(start) );
418  checkCuda( cudaEventDestroy(stop) );
419 #endif
420 
421  return 0;
422 }
void * interp
Definition: hypar.h:362
int npoints_local_wghosts
Definition: hypar.h:42
int * dim_local
Definition: hypar.h:37
#define GPU_THREADS_PER_BLOCK
Definition: basic_gpu.h:7
Structure of variables/parameters needed by the WENO-type scheme.
int ghosts
Definition: hypar.h:52
int * gpu_dim_local
Definition: hypar.h:455
int * stride_with_ghosts
Definition: hypar.h:414
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
int ndims
Definition: hypar.h:26
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int Interp1PrimFirstOrderUpwindChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

1st order upwind reconstruction (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the first-order upwind scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 1st order upwind scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 1st order upwind numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{equation} \hat{\alpha}^k_{j+1/2} = \left\{\begin{array}{cc} {\alpha}^k_{j} & {\rm upw} > 0 \\ {\alpha}^k_{j+1} & {\rm upw} \le 0 \end{array}\right.. \end{equation}

where

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n \end{equation}

is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

Implementation Notes:

  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 77 of file Interp1PrimFirstOrderUpwindChar.c.

88 {
89  HyPar *solver = (HyPar*) s;
90  int i, k, v;
92 
93  int ghosts = solver->ghosts;
94  int ndims = solver->ndims;
95  int nvars = solver->nvars;
96  int *dim = solver->dim_local;
97 
98  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
99  dimension "dir" */
100  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
101  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
102  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
103  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
104 
105  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
106  double R[nvars*nvars], L[nvars*nvars], uavg[nvars], fchar[nvars];
107 
108 #pragma omp parallel for schedule(auto) default(shared) private(i,k,v,R,L,uavg,fchar,index_outer,indexC,indexI)
109  for (i=0; i<N_outer; i++) {
110  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
111  _ArrayCopy1D_(index_outer,indexC,ndims);
112  _ArrayCopy1D_(index_outer,indexI,ndims);
113 
114  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
115 
116  int pL, pR; /* 1D index of the left and right cells */
117  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,pL);
118  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,pR);
119  int p; /* 1D index of the interface */
120  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
121 
122  /* find averaged state at this interface */
123  IERR solver->AveragingFunction(uavg,&u[nvars*pL],&u[nvars*pR],solver->physics); CHECKERR(ierr);
124 
125  /* Get the left and right eigenvectors */
126  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
127  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
128 
129  /* For each characteristic field */
130  for (v = 0; v < nvars; v++) {
131 
132  /* calculate the characteristic flux components along this characteristic */
133  double fcL = 0, fcR = 0;
134  for (k = 0; k < nvars; k++) {
135  fcL += L[v*nvars+k] * fC[pL*nvars+k];
136  fcR += L[v*nvars+k] * fC[pR*nvars+k];
137  }
138 
139  /* first order upwind approximation of the characteristic flux */
140  fchar[v] = (upw > 0 ? fcL : fcR);
141 
142  }
143 
144  /* calculate the interface u from the characteristic u */
145  IERR MatVecMult(nvars,(fI+nvars*p),R,fchar); CHECKERR(ierr);
146 
147  }
148  }
149 
150  return(0);
151 }
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
#define MatVecMult(N, y, A, x)
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimSecondOrderCentralChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

2nd order central reconstruction (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the second-order central scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 2nd order central scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 2nd order central numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{equation} \hat{\alpha}^k_{j+1/2} = \frac{1}{2} \left( {\alpha}^k_{j+1} + {\alpha}^k_j \right), \end{equation}

where

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n \end{equation}

is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • Since this is a central scheme, the input argument upw has no effect.
  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 79 of file Interp1PrimSecondOrderCentralChar.c.

90 {
91  HyPar *solver = (HyPar*) s;
92  int i, k, v;
94 
95  int ghosts = solver->ghosts;
96  int ndims = solver->ndims;
97  int nvars = solver->nvars;
98  int *dim = solver->dim_local;
99 
100  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
101  dimension "dir" */
102  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
103  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
104  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
105  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
106 
107  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
108  double R[nvars*nvars], L[nvars*nvars], uavg[nvars], fchar[nvars];
109 
110 #pragma omp parallel for schedule(auto) default(shared) private(i,k,v,R,L,uavg,fchar,index_outer,indexC,indexI)
111  for (i=0; i<N_outer; i++) {
112  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
113  _ArrayCopy1D_(index_outer,indexC,ndims);
114  _ArrayCopy1D_(index_outer,indexI,ndims);
115 
116  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
117 
118  int pL, pR; /* 1D index of the left and right cells */
119  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,pL);
120  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,pR);
121  int p; /* 1D index of the interface */
122  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
123 
124  /* find averaged state at this interface */
125  IERR solver->AveragingFunction(uavg,&u[nvars*pL],&u[nvars*pR],solver->physics); CHECKERR(ierr);
126 
127  /* Get the left and right eigenvectors */
128  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
129  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
130 
131  /* For each characteristic field */
132  for (v = 0; v < nvars; v++) {
133 
134  /* calculate the characteristic flux components along this characteristic */
135  double fcL = 0, fcR = 0;
136  for (k = 0; k < nvars; k++) {
137  fcL += L[v*nvars+k] * fC[pL*nvars+k];
138  fcR += L[v*nvars+k] * fC[pR*nvars+k];
139  }
140 
141  /* first order upwind approximation of the characteristic flux */
142  fchar[v] = 0.5 * (fcL + fcR);
143 
144  }
145 
146  /* calculate the interface u from the characteristic u */
147  IERR MatVecMult(nvars,(fI+nvars*p),R,fchar); CHECKERR(ierr);
148 
149  }
150  }
151 
152  return(0);
153 }
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
#define MatVecMult(N, y, A, x)
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimSecondOrderMUSCLChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

2nd order MUSCL scheme (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the second-order MUSCL scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 2nd order MUSCL scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as: using the 2nd order MUSCL scheme as follows:

\begin{equation} \hat{\alpha}^k_{j+1/2} = {\alpha}^k_{j} + \frac{1}{2} \phi\left(r_j\right) \left[{\alpha}^k_{j+1}-{\alpha}^k_{j}\right] \end{equation}

where

\begin{equation} r_j = \left( \alpha^k_j - \alpha^k_{j-1} \right) / \left( \alpha^k_{j+1} - \alpha^k_j \right), \end{equation}

\(\phi\left(r\right)\) is a limiter (minmod, mc, generalized minmod, etc.), and

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n \end{equation}

is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

  • van Leer, B. (1979), Towards the Ultimate Conservative Difference Scheme, V. A Second Order Sequel to Godunov's Method, J. Com. Phys., 32, 101–136.
  • Nessyahu, H. and E. Tadmor (1990), Non-oscillatory central differencing for hyperbolic conservation laws, J. Comput. Phys., 87, 408–463.
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 92 of file Interp1PrimSecondOrderMUSCLChar.c.

103 {
104  HyPar *solver = (HyPar*) s;
105  MUSCLParameters *muscl = (MUSCLParameters*) solver->interp;
106  int i, k, v;
108 
109  int ghosts = solver->ghosts;
110  int ndims = solver->ndims;
111  int nvars = solver->nvars;
112  int *dim = solver->dim_local;
113 
114  /* define some constants */
115  double one_third = 1.0/3.0;
116  double one_sixth = 1.0/6.0;
117 
118  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
119  dimension "dir" */
120  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
121  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
122  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
123  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
124 
125  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
126  double R[nvars*nvars], L[nvars*nvars], uavg[nvars], fchar[nvars];
127 
128  if (upw > 0) {
129 #pragma omp parallel for schedule(auto) default(shared) private(i,k,v,R,L,uavg,fchar,index_outer,indexC,indexI)
130  for (i=0; i<N_outer; i++) {
131  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
132  _ArrayCopy1D_(index_outer,indexC,ndims);
133  _ArrayCopy1D_(index_outer,indexI,ndims);
134 
135  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
136 
137  /* 1D indices of the stencil grid points */
138  int qm1,qm2,qp1;
139  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
140  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
141  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
142 
143  int p; /* 1D index of the interface */
144  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
145 
146  /* find averaged state at this interface */
147  IERR solver->AveragingFunction(uavg,&u[nvars*qm1],&u[nvars*qp1],solver->physics);
148  CHECKERR(ierr);
149 
150  /* Get the left and right eigenvectors */
151  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
152  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
153 
154  /* For each characteristic field */
155  for (v = 0; v < nvars; v++) {
156  /* calculate the characteristic flux components along this characteristic */
157  double m2, m1, p1;
158  m2 = m1 = p1 = 0;
159  for (k = 0; k < nvars; k++) {
160  m2 += L[v*nvars+k] * fC[qm2*nvars+k];
161  m1 += L[v*nvars+k] * fC[qm1*nvars+k];
162  p1 += L[v*nvars+k] * fC[qp1*nvars+k];
163  }
164 
165  double slope_ratio = (m1 - m2) / ((p1 - m1) + 1e-40);
166  double phi = muscl->LimiterFunction(slope_ratio);
167  fchar[v] = m1 + 0.5 * phi * (p1-m1);
168  }
169 
170  /* calculate the interface u from the characteristic u */
171  IERR MatVecMult(nvars,(fI+nvars*p),R,fchar); CHECKERR(ierr);
172  }
173  }
174  } else {
175 #pragma omp parallel for schedule(auto) default(shared) private(i,k,v,R,L,uavg,fchar,index_outer,indexC,indexI)
176  for (i=0; i<N_outer; i++) {
177  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
178  _ArrayCopy1D_(index_outer,indexC,ndims);
179  _ArrayCopy1D_(index_outer,indexI,ndims);
180 
181  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
182 
183  /* 1D indices of the stencil grid points */
184  int qm1,qp1,qp2;
185  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
186  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
187  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
188 
189  int p; /* 1D index of the interface */
190  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
191 
192  /* find averaged state at this interface */
193  IERR solver->AveragingFunction(uavg,&u[nvars*qm1],&u[nvars*qp1],solver->physics);
194  CHECKERR(ierr);
195 
196  /* Get the left and right eigenvectors */
197  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
198  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
199 
200  /* For each characteristic field */
201  for (v = 0; v < nvars; v++) {
202  /* calculate the characteristic flux components along this characteristic */
203  double m1, p1, p2;
204  m1 = p1 = p2 = 0;
205  for (k = 0; k < nvars; k++) {
206  m1 += L[v*nvars+k] * fC[qm1*nvars+k];
207  p1 += L[v*nvars+k] * fC[qp1*nvars+k];
208  p2 += L[v*nvars+k] * fC[qp2*nvars+k];
209  }
210 
211  double slope_ratio = (p1 - m1) / ((p2 - p1) + 1e-40);
212  double phi = muscl->LimiterFunction(slope_ratio);
213  fchar[v] = p1 + 0.5 * phi * (p1-p2);
214  }
215 
216  /* calculate the interface u from the characteristic u */
217  IERR MatVecMult(nvars,(fI+nvars*p),R,fchar); CHECKERR(ierr);
218  }
219  }
220  }
221 
222  return(0);
223 }
void * interp
Definition: hypar.h:362
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
double(* LimiterFunction)(double)
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
#define MatVecMult(N, y, A, x)
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
Structure of variables/parameters needed by the MUSCL scheme.
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimThirdOrderMUSCLChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

3rd order MUSCL scheme with Koren's limiter (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the third-order MUSCL scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 3rd order MUSCL scheme with Koren's limiter on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as: using the 3rd order MUSCL scheme with Koren's limiter as follows:

\begin{equation} \hat{\alpha}^k_{j+1/2} = {\alpha}^k_{j-1} + \phi \left[\frac{1}{3}\left({\alpha}^k_j-{\alpha}^k_{j-1}\right) + \frac{1}{6}\left({\alpha}^k_{j-1}-{\alpha}^k_{j-2}\right)\right] \end{equation}

where

\begin{equation} \phi = \frac {3\left({\alpha}^k_j-{\alpha}^k_{j-1}\right)\left({\alpha}^k_{j-1}-{\alpha}^k_{j-2}\right) + \epsilon} {2\left[\left({\alpha}^k_j-{\alpha}^k_{j-1}\right)-\left({\alpha}^k_{j-1}-{\alpha}^k_{j-2}\right)\right]^2 + 3\left({\alpha}^k_j-{\alpha}^k_{j-1}\right)\left({\alpha}^k_{j-1}-{\alpha}^k_{j-2}\right) + \epsilon}, \end{equation}

\(\epsilon\) is a small constant (typically \(10^{-3}\)), and

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n \end{equation}

is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

  • van Leer, B., Towards the Ultimate Conservative Difference Scheme. 2: Monotonicity and Conservation Combined in a Second-Order Scheme, J. of Comput. Phys., 14 (4), 1974, pp.361-370, http://dx.doi.org/10.1016/0021-9991(74)90019-9
  • Koren, B., A Robust Upwind Discretization Method for Advection, Diffusion and Source Terms, Centrum voor Wiskunde en Informatica, Amsterdam, 1993
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 91 of file Interp1PrimThirdOrderMUSCLChar.c.

102 {
103  HyPar *solver = (HyPar*) s;
104  MUSCLParameters *muscl = (MUSCLParameters*) solver->interp;
105  int i, k, v;
107 
108  int ghosts = solver->ghosts;
109  int ndims = solver->ndims;
110  int nvars = solver->nvars;
111  int *dim = solver->dim_local;
112 
113  /* define some constants */
114  double one_third = 1.0/3.0;
115  double one_sixth = 1.0/6.0;
116 
117  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
118  dimension "dir" */
119  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
120  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
121  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
122  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
123 
124  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
125  double R[nvars*nvars], L[nvars*nvars], uavg[nvars], fchar[nvars];
126 
127  if (upw > 0) {
128 #pragma omp parallel for schedule(auto) default(shared) private(i,k,v,R,L,uavg,fchar,index_outer,indexC,indexI)
129  for (i=0; i<N_outer; i++) {
130  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
131  _ArrayCopy1D_(index_outer,indexC,ndims);
132  _ArrayCopy1D_(index_outer,indexI,ndims);
133 
134  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
135 
136  /* 1D indices of the stencil grid points */
137  int qm1,qm2,qp1;
138  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
139  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
140  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
141 
142  int p; /* 1D index of the interface */
143  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
144 
145  /* find averaged state at this interface */
146  IERR solver->AveragingFunction(uavg,&u[nvars*qm1],&u[nvars*qp1],solver->physics);
147  CHECKERR(ierr);
148 
149  /* Get the left and right eigenvectors */
150  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
151  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
152 
153  /* For each characteristic field */
154  for (v = 0; v < nvars; v++) {
155  /* calculate the characteristic flux components along this characteristic */
156  double m2, m1, p1;
157  m2 = m1 = p1 = 0;
158  for (k = 0; k < nvars; k++) {
159  m2 += L[v*nvars+k] * fC[qm2*nvars+k];
160  m1 += L[v*nvars+k] * fC[qm1*nvars+k];
161  p1 += L[v*nvars+k] * fC[qp1*nvars+k];
162  }
163  double fdiff = p1 - m1;
164  double bdiff = m1 - m2;
165  double limit = (3*fdiff*bdiff + muscl->eps)
166  / (2*(fdiff-bdiff)*(fdiff-bdiff) + 3*fdiff*bdiff + muscl->eps);
167  fchar[v] = m1 + limit * (one_third*fdiff + one_sixth*bdiff);
168  }
169 
170  /* calculate the interface u from the characteristic u */
171  IERR MatVecMult(nvars,(fI+nvars*p),R,fchar); CHECKERR(ierr);
172  }
173  }
174  } else {
175 #pragma omp parallel for schedule(auto) default(shared) private(i,k,v,R,L,uavg,fchar,index_outer,indexC,indexI)
176  for (i=0; i<N_outer; i++) {
177  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
178  _ArrayCopy1D_(index_outer,indexC,ndims);
179  _ArrayCopy1D_(index_outer,indexI,ndims);
180 
181  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
182 
183  /* 1D indices of the stencil grid points */
184  int qm1,qp1,qp2;
185  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
186  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
187  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
188 
189  int p; /* 1D index of the interface */
190  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
191 
192  /* find averaged state at this interface */
193  IERR solver->AveragingFunction(uavg,&u[nvars*qm1],&u[nvars*qp1],solver->physics);
194  CHECKERR(ierr);
195 
196  /* Get the left and right eigenvectors */
197  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
198  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
199 
200  /* For each characteristic field */
201  for (v = 0; v < nvars; v++) {
202  /* calculate the characteristic flux components along this characteristic */
203  double m1, p1, p2;
204  m1 = p1 = p2 = 0;
205  for (k = 0; k < nvars; k++) {
206  m1 += L[v*nvars+k] * fC[qm1*nvars+k];
207  p1 += L[v*nvars+k] * fC[qp1*nvars+k];
208  p2 += L[v*nvars+k] * fC[qp2*nvars+k];
209  }
210  double fdiff = p2 - p1;
211  double bdiff = p1 - m1;
212  double limit = (3*fdiff*bdiff + muscl->eps)
213  / (2*(fdiff-bdiff)*(fdiff-bdiff) + 3*fdiff*bdiff + muscl->eps);
214  fchar[v] = p1 - limit * (one_third*fdiff + one_sixth*bdiff);
215  }
216 
217  /* calculate the interface u from the characteristic u */
218  IERR MatVecMult(nvars,(fI+nvars*p),R,fchar); CHECKERR(ierr);
219  }
220  }
221  }
222 
223  return(0);
224 }
void * interp
Definition: hypar.h:362
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
#define MatVecMult(N, y, A, x)
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
Structure of variables/parameters needed by the MUSCL scheme.
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimFourthOrderCentralChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

4th order central reconstruction (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the fourth-order central scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the 4th order central scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 4th order central numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{equation} \hat{\alpha}^k_{j+1/2} = -\frac{1}{12} {\alpha}^k_{j-1} + \frac{7}{12} {\alpha}^k_{j} + \frac{7}{12} {\alpha}^k_{j+1} - \frac{1}{12} {\alpha}^k_{j+2}, \end{equation}

where

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n \end{equation}

is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • Since this is a central scheme, the input argument upw has no effect.
  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 79 of file Interp1PrimFourthOrderCentralChar.c.

90 {
91  HyPar *solver = (HyPar*) s;
92  int i, k, v;
94 
95  int ghosts = solver->ghosts;
96  int ndims = solver->ndims;
97  int nvars = solver->nvars;
98  int *dim = solver->dim_local;
99 
100  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
101  dimension "dir" */
102  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
103  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
104  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
105  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
106 
107  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
108  double R[nvars*nvars], L[nvars*nvars], uavg[nvars], fchar[nvars];
109 
110  static const double c1 = 7.0 / 12.0;
111  static const double c2 = -1.0 / 12.0;
112 
113 #pragma omp parallel for schedule(auto) default(shared) private(i,k,v,R,L,uavg,fchar,index_outer,indexC,indexI)
114  for (i=0; i<N_outer; i++) {
115  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
116  _ArrayCopy1D_(index_outer,indexC,ndims);
117  _ArrayCopy1D_(index_outer,indexI,ndims);
118 
119  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
120 
121  int pLL, pL, pR, pRR; /* 1D index of the left and right cells */
122  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,pLL);
123  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,pL );
124  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,pR );
125  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,pRR);
126  int p; /* 1D index of the interface */
127  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
128 
129  /* find averaged state at this interface */
130  IERR solver->AveragingFunction(uavg,&u[nvars*pL],&u[nvars*pR],solver->physics); CHECKERR(ierr);
131 
132  /* Get the left and right eigenvectors */
133  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
134  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
135 
136  /* For each characteristic field */
137  for (v = 0; v < nvars; v++) {
138 
139  /* calculate the characteristic flux components along this characteristic */
140  double fcLL = 0, fcL = 0, fcR = 0, fcRR = 0;
141  for (k = 0; k < nvars; k++) {
142  fcLL += L[v*nvars+k] * fC[pLL*nvars+k];
143  fcL += L[v*nvars+k] * fC[pL *nvars+k];
144  fcR += L[v*nvars+k] * fC[pR *nvars+k];
145  fcRR += L[v*nvars+k] * fC[pRR*nvars+k];
146  }
147 
148  /* first order upwind approximation of the characteristic flux */
149  fchar[v] = c2*fcLL + c1*fcL + c1*fcR + c2*fcRR;
150 
151  }
152 
153  /* calculate the interface u from the characteristic u */
154  IERR MatVecMult(nvars,(fI+nvars*p),R,fchar); CHECKERR(ierr);
155 
156  }
157  }
158 
159  return(0);
160 }
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
#define MatVecMult(N, y, A, x)
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimFifthOrderUpwindChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order upwind reconstruction (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the fifth-order upwind scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order upwind scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 5th order upwind numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{align} \hat{\alpha}^k_{j+1/2} = \frac{1}{30} {\alpha}^k_{j-2} - \frac{13}{60}{\alpha}^k_{j-1} + \frac{47}{60}{\alpha}^k_j + \frac{27}{60}{\alpha}^k_{j+1} - \frac{1}{20}{\alpha}^k_{j+2}, \end{align}

where

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n \end{equation}

is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 84 of file Interp1PrimFifthOrderUpwindChar.c.

95 {
96  HyPar *solver = (HyPar*) s;
97  int i, k, v;
99 
100  int ghosts = solver->ghosts;
101  int ndims = solver->ndims;
102  int nvars = solver->nvars;
103  int *dim = solver->dim_local;
104 
105  /* define some constants */
106  static const double one_by_thirty = 1.0/30.0,
107  thirteen_by_sixty = 13.0/60.0,
108  fortyseven_by_sixty = 47.0/60.0,
109  twentyseven_by_sixty = 27.0/60.0,
110  one_by_twenty = 1.0/20.0;
111 
112  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
113  dimension "dir" */
114  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
115  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
116  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
117  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
118 
119  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
120  double R[nvars*nvars], L[nvars*nvars], uavg[nvars], fchar[nvars];
121 
122 #pragma omp parallel for schedule(auto) default(shared) private(i,k,v,R,L,uavg,fchar,index_outer,indexC,indexI)
123  for (i=0; i<N_outer; i++) {
124  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
125  _ArrayCopy1D_(index_outer,indexC,ndims);
126  _ArrayCopy1D_(index_outer,indexI,ndims);
127 
128  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
129 
130  /* 1D indices of the stencil grid points */
131  int qm1,qm2,qm3,qp1,qp2;
132  if (upw > 0) {
133  indexC[dir] = indexI[dir]-3; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
134  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
135  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
136  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
137  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
138  } else {
139  indexC[dir] = indexI[dir]+2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
140  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
141  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
142  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
143  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
144  }
145 
146  int p; /* 1D index of the interface */
147  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
148 
149  /* find averaged state at this interface */
150  IERR solver->AveragingFunction(uavg,&u[nvars*qm1],&u[nvars*qp1],solver->physics); CHECKERR(ierr);
151 
152  /* Get the left and right eigenvectors */
153  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
154  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
155 
156  /* For each characteristic field */
157  for (v = 0; v < nvars; v++) {
158 
159  /* calculate the characteristic flux components along this characteristic */
160  double fm3, fm2, fm1, fp1, fp2;
161  fm3 = fm2 = fm1 = fp1 = fp2 = 0;
162  for (k = 0; k < nvars; k++) {
163  fm3 += L[v*nvars+k] * fC[qm3*nvars+k];
164  fm2 += L[v*nvars+k] * fC[qm2*nvars+k];
165  fm1 += L[v*nvars+k] * fC[qm1*nvars+k];
166  fp1 += L[v*nvars+k] * fC[qp1*nvars+k];
167  fp2 += L[v*nvars+k] * fC[qp2*nvars+k];
168  }
169 
170  /* fifth order upwind approximation of the characteristic flux */
171  fchar[v] = one_by_thirty * fm3
172  - thirteen_by_sixty * fm2
173  + fortyseven_by_sixty * fm1
174  + twentyseven_by_sixty * fp1
175  - one_by_twenty * fp2;
176  }
177 
178  /* calculate the interface u from the characteristic u */
179  IERR MatVecMult(nvars,(fI+nvars*p),R,fchar); CHECKERR(ierr);
180 
181  }
182  }
183 
184  return(0);
185 }
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
#define MatVecMult(N, y, A, x)
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimFifthOrderCompactUpwindChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order compact upwind reconstruction (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the fifth-order compact upwind scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order compact upwind scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 5th order compact upwind numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{align} \frac{3}{10}\hat{\alpha}^k_{j-1/2} + \frac{6}{10}\hat{\alpha}^k_{j+1/2} + \frac{1}{10}\hat{\alpha}^k_{j+3/2} = \frac{}{30}{\alpha}^k_{j-1} + \frac{19}{30}{\alpha}^k_j + \frac{1}{3}{\alpha}^k_{j+1}, \end{align}

where

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n \end{equation}

is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The resulting block tridiagonal system is solved using blocktridiagLU() (see also TridiagLU, tridiagLU.h). The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

  • Ghosh, D., Baeder, J. D., Compact Reconstruction Schemes with Weighted ENO Limiting for Hyperbolic Conservation Laws, SIAM Journal on Scientific Computing, 34 (3), 2012, A1678–A1706, http://dx.doi.org/10.1137/110857659
  • Ghosh, D., Constantinescu, E. M., Brown, J., Efficient Implementation of Nonlinear Compact Schemes on Massively Parallel Platforms, SIAM Journal on Scientific Computing, 37 (3), 2015, C354–C383, http://dx.doi.org/10.1137/140989261
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 90 of file Interp1PrimFifthOrderCompactUpwindChar.c.

101 {
102  HyPar *solver = (HyPar*) s;
103  MPIVariables *mpi = (MPIVariables*) m;
104  CompactScheme *compact= (CompactScheme*) solver->compact;
105  TridiagLU *lu = (TridiagLU*) solver->lusolver;
106  int sys,Nsys,d,v,k;
108 
109  int ghosts = solver->ghosts;
110  int ndims = solver->ndims;
111  int nvars = solver->nvars;
112  int *dim = solver->dim_local;
113 
114  /* define some constants */
115  static const double three_by_ten = 3.0/10.0,
116  six_by_ten = 6.0/10.0,
117  one_by_ten = 1.0/10.0,
118  one_by_thirty = 1.0/30.0,
119  nineteen_by_thirty = 19.0/30.0,
120  one_third = 1.0/3.0,
121  thirteen_by_sixty = 13.0/60.0,
122  fortyseven_by_sixty = 47.0/60.0,
123  twentyseven_by_sixty = 27.0/60.0,
124  one_by_twenty = 1.0/20.0;
125 
126  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
127  dimension "dir" */
128  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
129  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
130  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
131 
132  /* calculate total number of block tridiagonal systems to solve */
133  _ArrayProduct1D_(bounds_outer,ndims,Nsys);
134 
135  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
136  double R[nvars*nvars], L[nvars*nvars], uavg[nvars];
137 
138  /* Allocate arrays for tridiagonal system */
139  double *A = compact->A;
140  double *B = compact->B;
141  double *C = compact->C;
142  double *F = compact->R;
143 
144 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,v,k,R,L,uavg,index_outer,indexC,indexI)
145  for (sys=0; sys<Nsys; sys++) {
146  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
147  _ArrayCopy1D_(index_outer,indexC,ndims);
148  _ArrayCopy1D_(index_outer,indexI,ndims);
149  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
150  int qm1,qm2,qm3,qp1,qp2;
151  if (upw > 0) {
152  indexC[dir] = indexI[dir]-3; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
153  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
154  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
155  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
156  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
157  } else {
158  indexC[dir] = indexI[dir]+2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
159  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
160  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
161  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
162  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
163  }
164 
165  int p; /* 1D index of the interface */
166  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
167 
168  /* find averaged state at this interface */
169  IERR solver->AveragingFunction(uavg,&u[nvars*qm1],&u[nvars*qp1],solver->physics); CHECKERR(ierr);
170 
171  /* Get the left and right eigenvectors */
172  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
173  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
174 
175  for (v=0; v<nvars; v++) {
176 
177  /* calculate the characteristic flux components along this characteristic */
178  double fm3, fm2, fm1, fp1, fp2;
179  fm3 = fm2 = fm1 = fp1 = fp2 = 0;
180  for (k = 0; k < nvars; k++) {
181  fm3 += L[v*nvars+k] * fC[qm3*nvars+k];
182  fm2 += L[v*nvars+k] * fC[qm2*nvars+k];
183  fm1 += L[v*nvars+k] * fC[qm1*nvars+k];
184  fp1 += L[v*nvars+k] * fC[qp1*nvars+k];
185  fp2 += L[v*nvars+k] * fC[qp2*nvars+k];
186  }
187 
188  if ( ((mpi->ip[dir] == 0 ) && (indexI[dir] == 0 ))
189  || ((mpi->ip[dir] == mpi->iproc[dir]-1) && (indexI[dir] == dim[dir])) ) {
190  /* Use 5th order upwind at the physical boundaries */
191  for (k=0; k<nvars; k++) {
192  A[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = 0.0;
193  C[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = 0.0;
194  B[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = L[v*nvars+k];
195  }
196  F[(Nsys*indexI[dir]+sys)*nvars+v] = one_by_thirty * fm3
197  - thirteen_by_sixty * fm2
198  + fortyseven_by_sixty * fm1
199  + twentyseven_by_sixty * fp1
200  - one_by_twenty * fp2;
201  } else {
202  /* 5th order compact upwind at the interior points */
203  if (upw > 0) {
204  for (k=0; k<nvars; k++) {
205  A[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = three_by_ten * L[v*nvars+k];
206  B[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = six_by_ten * L[v*nvars+k];
207  C[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = one_by_ten * L[v*nvars+k];
208  }
209  } else {
210  for (k=0; k<nvars; k++) {
211  C[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = three_by_ten * L[v*nvars+k];
212  B[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = six_by_ten * L[v*nvars+k];
213  A[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = one_by_ten * L[v*nvars+k];
214  }
215  }
216  F[(Nsys*indexI[dir]+sys)*nvars+v] = one_by_thirty * fm2
217  + nineteen_by_thirty * fm1
218  + one_third * fp1;
219  }
220  }
221  }
222  }
223 
224 #ifdef serial
225 
226  /* Solve the tridiagonal system */
227  IERR blocktridiagLU(A,B,C,F,dim[dir]+1,Nsys,nvars,lu,NULL); CHECKERR(ierr);
228 
229 #else
230 
231  /* Solve the tridiagonal system */
232  /* all processes except the last will solve without the last interface to avoid overlap */
233  if (mpi->ip[dir] != mpi->iproc[dir]-1) {
234  IERR blocktridiagLU(A,B,C,F,dim[dir] ,Nsys,nvars,lu,&mpi->comm[dir]); CHECKERR(ierr);
235  } else {
236  IERR blocktridiagLU(A,B,C,F,dim[dir]+1,Nsys,nvars,lu,&mpi->comm[dir]); CHECKERR(ierr);
237  }
238 
239  /* Now get the solution to the last interface from the next proc */
240  double *sendbuf = compact->sendbuf;
241  double *recvbuf = compact->recvbuf;
242  MPI_Request req[2] = {MPI_REQUEST_NULL,MPI_REQUEST_NULL};
243  if (mpi->ip[dir]) for (d=0; d<Nsys*nvars; d++) sendbuf[d] = F[d];
244  if (mpi->ip[dir] != mpi->iproc[dir]-1) MPI_Irecv(recvbuf,Nsys*nvars,MPI_DOUBLE,mpi->ip[dir]+1,214,mpi->comm[dir],&req[0]);
245  if (mpi->ip[dir]) MPI_Isend(sendbuf,Nsys*nvars,MPI_DOUBLE,mpi->ip[dir]-1,214,mpi->comm[dir],&req[1]);
246  MPI_Status status_arr[2];
247  MPI_Waitall(2,&req[0],status_arr);
248  if (mpi->ip[dir] != mpi->iproc[dir]-1) for (d=0; d<Nsys*nvars; d++) F[d+Nsys*nvars*dim[dir]] = recvbuf[d];
249 
250 #endif
251 
252  /* save the solution to fI */
253 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,v,k,R,L,uavg,index_outer,indexC,indexI)
254  for (sys=0; sys<Nsys; sys++) {
255  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
256  _ArrayCopy1D_(index_outer,indexI,ndims);
257  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
258  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
259  _ArrayCopy1D_((F+sys*nvars+Nsys*nvars*indexI[dir]),(fI+nvars*p),nvars);
260  }
261  }
262 
263  return(0);
264 }
MPI_Comm * comm
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
int blocktridiagLU(double *, double *, double *, double *, int, int, int, void *, void *)
double * recvbuf
Structure of variables/parameters needed by the compact schemes.
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
void * compact
Definition: hypar.h:364
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure of MPI-related variables.
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
double * sendbuf
void * lusolver
Definition: hypar.h:368
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimFifthOrderWENOChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order WENO reconstruction (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the fifth-order WENO scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order WENO scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 5th order WENO numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as the convex combination of three 3rd order methods:

\begin{align} &\ \omega_1\ \times\ \left[ \hat{\alpha}^k_{j+1/2} = \frac{1}{3} {\alpha}^k_{j-2} - \frac{7}{6} {\alpha}^k_{j-1} + \frac{11}{6} {\alpha}^k_j \right]\\ + &\ \omega_2\ \times\ \left[ \hat{\alpha}^k_{j+1/2} = -\frac{1}{6} {\alpha}^k_{j-1} + \frac{5}{6} {\alpha}^k_j + \frac{1}{3} {\alpha}^k_{j+1} \right]\\ + &\ \omega_3\ \times\ \left[ \hat{\alpha}^k_{j+1/2} = \frac{1}{3} {\alpha}^k_j + \frac{5}{6} {\alpha}^k_{j+1} - \frac{1}{6} {\alpha}^k_{j+2} \right]\\ \Rightarrow &\ \hat{\alpha}^k_{j+1/2} = \frac{\omega_1}{3} {\alpha}^k_{j-2} - \frac{1}{6}(7\omega_1+\omega_2){\alpha}^k_{j-1} + \frac{1}{6}(11\omega_1+5\omega_2+2\omega_3){\alpha}^k_j + \frac{1}{6}(2\omega_2+5\omega_3){\alpha}^k_{j+1} - \frac{\omega_3}{6}{\alpha}^k_{j+2}, \end{align}

where

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n \end{equation}

is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The nonlinear weights \(\omega_k; k=1,2,3\) are the WENO weights computed in WENOFifthOrderCalculateWeightsChar(). The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 86 of file Interp1PrimFifthOrderWENOChar.c.

97 {
98  HyPar *solver = (HyPar*) s;
99  WENOParameters *weno = (WENOParameters*) solver->interp;
100  int i, k, v;
102 
103  int ghosts = solver->ghosts;
104  int ndims = solver->ndims;
105  int nvars = solver->nvars;
106  int *dim = solver->dim_local;
107 
108  /* define some constants */
109  static const double one_sixth = 1.0/6.0;
110 
111  double *ww1, *ww2, *ww3;
112  ww1 = weno->w1 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
113  ww2 = weno->w2 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
114  ww3 = weno->w3 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
115 
116  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
117  dimension "dir" */
118  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
119  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
120  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
121  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
122 
123  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
124  double R[nvars*nvars], L[nvars*nvars], uavg[nvars], fchar[nvars];
125 
126 #pragma omp parallel for schedule(auto) default(shared) private(i,k,v,R,L,uavg,fchar,index_outer,indexC,indexI)
127  for (i=0; i<N_outer; i++) {
128  _ArrayIndexnD_(ndims,i,bounds_outer,index_outer,0);
129  _ArrayCopy1D_(index_outer,indexC,ndims);
130  _ArrayCopy1D_(index_outer,indexI,ndims);
131 
132  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
133 
134  /* 1D indices of the stencil grid points */
135  int qm1,qm2,qm3,qp1,qp2;
136  if (upw > 0) {
137  indexC[dir] = indexI[dir]-3; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
138  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
139  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
140  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
141  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
142  } else {
143  indexC[dir] = indexI[dir]+2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
144  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
145  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
146  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
147  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
148  }
149 
150  int p; /* 1D index of the interface */
151  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
152 
153  /* find averaged state at this interface */
154  IERR solver->AveragingFunction(uavg,&u[nvars*qm1],&u[nvars*qp1],solver->physics); CHECKERR(ierr);
155 
156  /* Get the left and right eigenvectors */
157  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
158  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
159 
160  /* For each characteristic field */
161  for (v = 0; v < nvars; v++) {
162 
163  /* calculate the characteristic flux components along this characteristic */
164  double fm3, fm2, fm1, fp1, fp2;
165  fm3 = fm2 = fm1 = fp1 = fp2 = 0;
166  for (k = 0; k < nvars; k++) {
167  fm3 += L[v*nvars+k] * fC[qm3*nvars+k];
168  fm2 += L[v*nvars+k] * fC[qm2*nvars+k];
169  fm1 += L[v*nvars+k] * fC[qm1*nvars+k];
170  fp1 += L[v*nvars+k] * fC[qp1*nvars+k];
171  fp2 += L[v*nvars+k] * fC[qp2*nvars+k];
172  }
173 
174  /* Candidate stencils and their optimal weights*/
175  double f1, f2, f3;
176  f1 = (2*one_sixth)*fm3 - (7.0*one_sixth)*fm2 + (11.0*one_sixth)*fm1;
177  f2 = (-one_sixth)*fm2 + (5.0*one_sixth)*fm1 + (2*one_sixth)*fp1;
178  f3 = (2*one_sixth)*fm1 + (5*one_sixth)*fp1 - (one_sixth)*fp2;
179 
180  /* calculate WENO weights */
181  double w1,w2,w3;
182  w1 = *(ww1+p*nvars+v);
183  w2 = *(ww2+p*nvars+v);
184  w3 = *(ww3+p*nvars+v);
185 
186  /* fifth order WENO approximation of the characteristic flux */
187  fchar[v] = w1*f1 + w2*f2 + w3*f3;
188 
189  }
190 
191  /* calculate the interface u from the characteristic u */
192  IERR MatVecMult(nvars,(fI+nvars*p),R,fchar); CHECKERR(ierr);
193 
194  }
195  }
196 
197  return(0);
198 }
void * interp
Definition: hypar.h:362
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
Structure of variables/parameters needed by the WENO-type scheme.
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
#define MatVecMult(N, y, A, x)
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimFifthOrderCRWENOChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order CRWENO reconstruction (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the fifth-order CRWENO scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth order CRWENO scheme on a uniform grid. The first primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x} \int_{x-\Delta x/2}^{x+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right)d\zeta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function computes the 5th order CRWENO numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as the convex combination of three 3rd order methods:

\begin{align} &\ \omega_1\ \times\ \left[ \frac{2}{3}\hat{\alpha}^k_{j-1/2} + \frac{1}{3}\hat{\alpha}^k_{j+1/2} = \frac{1}{6} \left( f_{j-1} + 5f_j \right) \right]\\ + &\ \omega_2\ \times\ \left[ \frac{1}{3}\hat{\alpha}^k_{j-1/2}+\frac{2}{3}\hat{\alpha}^k_{j+1/2} = \frac{1}{6} \left( 5f_j + f_{j+1} \right) \right] \\ + &\ \omega_3\ \times\ \left[ \frac{2}{3}\hat{\alpha}^k_{j+1/2} + \frac{1}{3}\hat{\alpha}^k_{j+3/2} = \frac{1}{6} \left( f_j + 5f_{j+1} \right) \right] \\ \Rightarrow &\ \left(\frac{2}{3}\omega_1+\frac{1}{3}\omega_2\right)\hat{\alpha}^k_{j-1/2} + \left[\frac{1}{3}\omega_1+\frac{2}{3}(\omega_2+\omega_3)\right]\hat{\alpha}^k_{j+1/2} + \frac{1}{3}\omega_3\hat{\alpha}^k_{j+3/2} = \frac{\omega_1}{6}{\alpha}^k_{j-1} + \frac{5(\omega_1+\omega_2)+\omega_3}{6}{\alpha}^k_j + \frac{\omega_2+5\omega_3}{6}{\alpha}^k_{j+1}, \end{align}

where

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n \end{equation}

is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The nonlinear weights \(\omega_k; k=1,2,3\) are the WENO weights computed in WENOFifthOrderCalculateWeightsChar(). The resulting block tridiagonal system is solved using blocktridiagLU() (see also TridiagLU, tridiagLU.h). The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

  • Ghosh, D., Baeder, J. D., Compact Reconstruction Schemes with Weighted ENO Limiting for Hyperbolic Conservation Laws, SIAM Journal on Scientific Computing, 34 (3), 2012, A1678–A1706, http://dx.doi.org/10.1137/110857659
  • Ghosh, D., Constantinescu, E. M., Brown, J., Efficient Implementation of Nonlinear Compact Schemes on Massively Parallel Platforms, SIAM Journal on Scientific Computing, 37 (3), 2015, C354–C383, http://dx.doi.org/10.1137/140989261
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 93 of file Interp1PrimFifthOrderCRWENOChar.c.

104 {
105  HyPar *solver = (HyPar*) s;
106  MPIVariables *mpi = (MPIVariables*) m;
107  CompactScheme *compact= (CompactScheme*) solver->compact;
108  WENOParameters *weno = (WENOParameters*) solver->interp;
109  TridiagLU *lu = (TridiagLU*) solver->lusolver;
110  int sys,Nsys,d,v,k;
112 
113  int ghosts = solver->ghosts;
114  int ndims = solver->ndims;
115  int nvars = solver->nvars;
116  int *dim = solver->dim_local;
117 
118  /* define some constants */
119  static const double one_third = 1.0/3.0;
120  static const double one_sixth = 1.0/6.0;
121 
122  double *ww1, *ww2, *ww3;
123  ww1 = weno->w1 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
124  ww2 = weno->w2 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
125  ww3 = weno->w3 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
126 
127  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
128  dimension "dir" */
129  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
130  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
131  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
132 
133  /* calculate total number of block tridiagonal systems to solve */
134  _ArrayProduct1D_(bounds_outer,ndims,Nsys);
135 
136  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
137  double R[nvars*nvars], L[nvars*nvars], uavg[nvars];
138 
139  /* Allocate arrays for tridiagonal system */
140  double *A = compact->A;
141  double *B = compact->B;
142  double *C = compact->C;
143  double *F = compact->R;
144 
145 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,v,k,R,L,uavg,index_outer,indexC,indexI)
146  for (sys=0; sys<Nsys; sys++) {
147  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
148  _ArrayCopy1D_(index_outer,indexC,ndims);
149  _ArrayCopy1D_(index_outer,indexI,ndims);
150  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
151  int qm1,qm2,qm3,qp1,qp2;
152  if (upw > 0) {
153  indexC[dir] = indexI[dir]-3; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
154  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
155  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
156  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
157  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
158  } else {
159  indexC[dir] = indexI[dir]+2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
160  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
161  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
162  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
163  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
164  }
165 
166  int p; /* 1D index of the interface */
167  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
168 
169  /* find averaged state at this interface */
170  IERR solver->AveragingFunction(uavg,&u[nvars*qm1],&u[nvars*qp1],solver->physics); CHECKERR(ierr);
171 
172  /* Get the left and right eigenvectors */
173  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
174  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
175 
176  for (v=0; v<nvars; v++) {
177 
178  /* calculate the characteristic flux components along this characteristic */
179  double fm3, fm2, fm1, fp1, fp2;
180  fm3 = fm2 = fm1 = fp1 = fp2 = 0;
181  for (k = 0; k < nvars; k++) {
182  fm3 += L[v*nvars+k] * fC[qm3*nvars+k];
183  fm2 += L[v*nvars+k] * fC[qm2*nvars+k];
184  fm1 += L[v*nvars+k] * fC[qm1*nvars+k];
185  fp1 += L[v*nvars+k] * fC[qp1*nvars+k];
186  fp2 += L[v*nvars+k] * fC[qp2*nvars+k];
187  }
188 
189  /* Candidate stencils and their optimal weights*/
190  double f1, f2, f3;
191  if ( ((mpi->ip[dir] == 0 ) && (indexI[dir] == 0 ))
192  || ((mpi->ip[dir] == mpi->iproc[dir]-1) && (indexI[dir] == dim[dir])) ) {
193  /* Use WENO5 at the physical boundaries */
194  f1 = (2*one_sixth)*fm3 - (7.0*one_sixth)*fm2 + (11.0*one_sixth)*fm1;
195  f2 = (-one_sixth)*fm2 + (5.0*one_sixth)*fm1 + (2*one_sixth)*fp1;
196  f3 = (2*one_sixth)*fm1 + (5*one_sixth)*fp1 - (one_sixth)*fp2;
197  } else {
198  /* CRWENO5 at the interior points */
199  f1 = (one_sixth) * (fm2 + 5*fm1);
200  f2 = (one_sixth) * (5*fm1 + fp1);
201  f3 = (one_sixth) * (fm1 + 5*fp1);
202  }
203 
204  /* calculate WENO weights */
205  double w1,w2,w3;
206  w1 = *(ww1+p*nvars+v);
207  w2 = *(ww2+p*nvars+v);
208  w3 = *(ww3+p*nvars+v);
209 
210  if ( ((mpi->ip[dir] == 0 ) && (indexI[dir] == 0 ))
211  || ((mpi->ip[dir] == mpi->iproc[dir]-1) && (indexI[dir] == dim[dir])) ) {
212  for (k=0; k<nvars; k++) {
213  A[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = 0.0;
214  C[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = 0.0;
215  B[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = L[v*nvars+k];
216  }
217  } else {
218  if (upw > 0) {
219  for (k=0; k<nvars; k++) {
220  A[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = ((2*one_third)*w1 + (one_third)*w2) * L[v*nvars+k];
221  B[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = ((one_third)*w1 + (2*one_third)*(w2+w3)) * L[v*nvars+k];
222  C[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = ((one_third)*w3) * L[v*nvars+k];
223  }
224  } else {
225  for (k=0; k<nvars; k++) {
226  C[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = ((2*one_third)*w1 + (one_third)*w2) * L[v*nvars+k];
227  B[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = ((one_third)*w1 + (2*one_third)*(w2+w3)) * L[v*nvars+k];
228  A[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = ((one_third)*w3) * L[v*nvars+k];
229  }
230  }
231  }
232  F[(Nsys*indexI[dir]+sys)*nvars+v] = w1*f1 + w2*f2 + w3*f3;
233  }
234  }
235  }
236 
237 #ifdef serial
238 
239  /* Solve the tridiagonal system */
240  IERR blocktridiagLU(A,B,C,F,dim[dir]+1,Nsys,nvars,lu,NULL); CHECKERR(ierr);
241 
242 #else
243 
244  /* Solve the tridiagonal system */
245  /* all processes except the last will solve without the last interface to avoid overlap */
246  if (mpi->ip[dir] != mpi->iproc[dir]-1) {
247  IERR blocktridiagLU(A,B,C,F,dim[dir] ,Nsys,nvars,lu,&mpi->comm[dir]); CHECKERR(ierr);
248  } else {
249  IERR blocktridiagLU(A,B,C,F,dim[dir]+1,Nsys,nvars,lu,&mpi->comm[dir]); CHECKERR(ierr);
250  }
251 
252  /* Now get the solution to the last interface from the next proc */
253  double *sendbuf = compact->sendbuf;
254  double *recvbuf = compact->recvbuf;
255  MPI_Request req[2] = {MPI_REQUEST_NULL,MPI_REQUEST_NULL};
256  if (mpi->ip[dir]) for (d=0; d<Nsys*nvars; d++) sendbuf[d] = F[d];
257  if (mpi->ip[dir] != mpi->iproc[dir]-1) MPI_Irecv(recvbuf,Nsys*nvars,MPI_DOUBLE,mpi->ip[dir]+1,214,mpi->comm[dir],&req[0]);
258  if (mpi->ip[dir]) MPI_Isend(sendbuf,Nsys*nvars,MPI_DOUBLE,mpi->ip[dir]-1,214,mpi->comm[dir],&req[1]);
259  MPI_Status status_arr[2];
260  MPI_Waitall(2,&req[0],status_arr);
261  if (mpi->ip[dir] != mpi->iproc[dir]-1) for (d=0; d<Nsys*nvars; d++) F[d+Nsys*nvars*dim[dir]] = recvbuf[d];
262 
263 #endif
264 
265  /* save the solution to fI */
266 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,v,k,R,L,uavg,index_outer,indexC,indexI)
267  for (sys=0; sys<Nsys; sys++) {
268  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
269  _ArrayCopy1D_(index_outer,indexI,ndims);
270  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
271  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
272  _ArrayCopy1D_((F+sys*nvars+Nsys*nvars*indexI[dir]),(fI+nvars*p),nvars);
273  }
274  }
275 
276  return(0);
277 }
void * interp
Definition: hypar.h:362
MPI_Comm * comm
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
int blocktridiagLU(double *, double *, double *, double *, int, int, int, void *, void *)
double * recvbuf
Structure of variables/parameters needed by the WENO-type scheme.
Structure of variables/parameters needed by the compact schemes.
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
void * compact
Definition: hypar.h:364
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure of MPI-related variables.
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
double * sendbuf
void * lusolver
Definition: hypar.h:368
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp1PrimFifthOrderHCWENOChar ( double *  fI,
double *  fC,
double *  u,
double *  x,
int  upw,
int  dir,
void *  s,
void *  m,
int  uflag 
)

5th order hybrid compact-WENO reconstruction (characteristic-based) on a uniform grid

Characteristic-based interpolation of the first primitive at the cell interfaces using the fifth-order hybrid-compact WENO scheme

Computes the interpolated values of the first primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the fifth hybrid compact-WENO order scheme on a uniform grid. The reconstruction is carried out in terms of

\begin{equation} \alpha^k = {\bf l}_k \cdot {\bf f},\ k=1,\cdots,n, \end{equation}

which is the \(k\)-th characteristic quantity, and \({\bf l}_k\) is the \(k\)-th left eigenvector, \({\bf r}_k\) is the \(k\)-th right eigenvector, and \(n\) is HyPar::nvars. The block tridiagonal system is solved using blocktridiagLU() (see also TridiagLU, tridiagLU.h). The final interpolated function is computed from the interpolated characteristic quantities as:

\begin{equation} \hat{\bf f}_{j+1/2} = \sum_{k=1}^n \alpha^k_{j+1/2} {\bf r}_k \end{equation}

See the references below for details of the hybrid compact-WENO scheme.

Implementation Notes:

  • This method assumes a uniform grid in the spatial dimension corresponding to the interpolation.
  • The method described above corresponds to a left-biased interpolation. The corresponding right-biased interpolation can be obtained by reflecting the equations about interface j+1/2.
  • The WENO weights are computed in WENOFifthOrderCalculateWeightsChar().
  • The left and right eigenvectors are computed at an averaged quantity at j+1/2. Thus, this function requires functions to compute the average state, and the left and right eigenvectors. These are provided by the physical model through

    If these functions are not provided by the physical model, then a characteristic-based interpolation cannot be used.

  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
u double* The solution array \({\bf u}\) (with ghost points). If the interpolation is characteristic based, this is needed to compute the eigendecomposition. For a multidimensional problem, the layout is as follows: u is a contiguous 1D array of size (nvars*dim[0]*dim[1]*...*dim[D-1]) corresponding to the multi-dimensional solution, with the following ordering - nvars, dim[0], dim[1], ..., dim[D-1], where nvars is the number of solution components (HyPar::nvars), dim is the local size (HyPar::dim_local), D is the number of spatial dimensions.
x double* The grid array (with ghost points). This is used only by non-uniform-grid interpolation methods. For multidimensional problems, the layout is as follows: x is a contiguous 1D array of size (dim[0]+dim[1]+...+dim[D-1]), with the spatial coordinates along dim[0] stored from 0,...,dim[0]-1, the spatial coordinates along dim[1] stored along dim[0],...,dim[0]+dim[1]-1, and so forth.
upw int Upwinding direction: if positive, a left-biased interpolant will be computed; if negative, a right-biased interpolant will be computed. If the interpolation method is central, then this has no effect.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
uflag int A flag indicating if the function being interpolated \({\bf f}\) is the solution itself \({\bf u}\) (if 1, \({\bf f}\left({\bf u}\right) \equiv {\bf u}\)).

Reference:

  • Pirozzoli, S., Conservative Hybrid Compact-WENO Schemes for Shock-Turbulence Interaction, J. Comput. Phys., 178 (1), 2002, pp. 81-117, http://dx.doi.org/10.1006/jcph.2002.7021
  • Ren, Y.-X., Liu, M., Zhang, H., A characteristic-wise hybrid compact-WENO scheme for solving hyperbolic conservation laws, J. Comput. Phys., 192 (2), 2003, pp. 365-386,
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
uArray of cell-centered values of the solution \({\bf u}\)
xGrid coordinates
upwUpwind direction (left or right biased)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables
uflagFlag to indicate if \(f(u) \equiv u\), i.e, if the solution is being reconstructed

Definition at line 79 of file Interp1PrimFifthOrderHCWENOChar.c.

90 {
91  HyPar *solver = (HyPar*) s;
92  MPIVariables *mpi = (MPIVariables*) m;
93  CompactScheme *compact= (CompactScheme*) solver->compact;
94  WENOParameters *weno = (WENOParameters*) solver->interp;
95  TridiagLU *lu = (TridiagLU*) solver->lusolver;
96  int sys,Nsys,d,v,k;
98 
99  int ghosts = solver->ghosts;
100  int ndims = solver->ndims;
101  int nvars = solver->nvars;
102  int *dim = solver->dim_local;
103 
104  /* define some constants */
105  static const double one_half = 1.0/2.0;
106  static const double one_third = 1.0/3.0;
107  static const double one_sixth = 1.0/6.0;
108 
109  double *ww1, *ww2, *ww3;
110  ww1 = weno->w1 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
111  ww2 = weno->w2 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
112  ww3 = weno->w3 + (upw < 0 ? 2*weno->size : 0) + (uflag ? weno->size : 0) + weno->offset[dir];
113 
114  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
115  dimension "dir" */
116  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
117  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
118  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
119 
120  /* calculate total number of block tridiagonal systems to solve */
121  _ArrayProduct1D_(bounds_outer,ndims,Nsys);
122 
123  /* allocate arrays for the averaged state, eigenvectors and characteristic interpolated f */
124  double R[nvars*nvars], L[nvars*nvars], uavg[nvars];
125 
126  /* Allocate arrays for tridiagonal system */
127  double *A = compact->A;
128  double *B = compact->B;
129  double *C = compact->C;
130  double *F = compact->R;
131 
132 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,v,k,R,L,uavg,index_outer,indexC,indexI)
133  for (sys=0; sys<Nsys; sys++) {
134  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
135  _ArrayCopy1D_(index_outer,indexC,ndims);
136  _ArrayCopy1D_(index_outer,indexI,ndims);
137  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
138  int qm1,qm2,qm3,qp1,qp2;
139  if (upw > 0) {
140  indexC[dir] = indexI[dir]-3; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
141  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
142  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
143  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
144  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
145  } else {
146  indexC[dir] = indexI[dir]+2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm3);
147  indexC[dir] = indexI[dir]+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm2);
148  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qm1);
149  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp1);
150  indexC[dir] = indexI[dir]-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qp2);
151  }
152 
153  int p; /* 1D index of the interface */
154  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
155 
156  /* find averaged state at this interface */
157  IERR solver->AveragingFunction(uavg,&u[nvars*qm1],&u[nvars*qp1],solver->physics); CHECKERR(ierr);
158 
159  /* Get the left and right eigenvectors */
160  IERR solver->GetLeftEigenvectors (uavg,L,solver->physics,dir); CHECKERR(ierr);
161  IERR solver->GetRightEigenvectors (uavg,R,solver->physics,dir); CHECKERR(ierr);
162 
163  for (v=0; v<nvars; v++) {
164 
165  /* calculate the characteristic flux components along this characteristic */
166  double fm3, fm2, fm1, fp1, fp2;
167  fm3 = fm2 = fm1 = fp1 = fp2 = 0;
168  for (k = 0; k < nvars; k++) {
169  fm3 += L[v*nvars+k] * fC[qm3*nvars+k];
170  fm2 += L[v*nvars+k] * fC[qm2*nvars+k];
171  fm1 += L[v*nvars+k] * fC[qm1*nvars+k];
172  fp1 += L[v*nvars+k] * fC[qp1*nvars+k];
173  fp2 += L[v*nvars+k] * fC[qp2*nvars+k];
174  }
175 
176  /* Candidate stencils and their optimal weights*/
177  double f1, f2, f3;
178  if ( ((mpi->ip[dir] == 0 ) && (indexI[dir] == 0 ))
179  || ((mpi->ip[dir] == mpi->iproc[dir]-1) && (indexI[dir] == dim[dir])) ) {
180  /* Use WENO5 at the physical boundaries */
181  f1 = (2*one_sixth)*fm3 - (7.0*one_sixth)*fm2 + (11.0*one_sixth)*fm1;
182  f2 = (-one_sixth)*fm2 + (5.0*one_sixth)*fm1 + (2*one_sixth)*fp1;
183  f3 = (2*one_sixth)*fm1 + (5*one_sixth)*fp1 - (one_sixth)*fp2;
184  } else {
185  /* HCWENO5 at the interior points */
186  f1 = (one_sixth) * (fm2 + 5*fm1);
187  f2 = (one_sixth) * (5*fm1 + fp1);
188  f3 = (one_sixth) * (fm1 + 5*fp1);
189  }
190 
191  /* calculate WENO weights */
192  double w1,w2,w3;
193  w1 = *(ww1+p*nvars+v);
194  w2 = *(ww2+p*nvars+v);
195  w3 = *(ww3+p*nvars+v);
196 
197  /* calculate the hybridization parameter */
198  double sigma;
199  if ( ((mpi->ip[dir] == 0 ) && (indexI[dir] == 0 ))
200  || ((mpi->ip[dir] == mpi->iproc[dir]-1) && (indexI[dir] == dim[dir])) ) {
201  /* Standard WENO at physical boundaries */
202  sigma = 0.0;
203  } else {
204  double cuckoo, df_jm12, df_jp12, df_jp32, r_j, r_jp1, r_int;
205  cuckoo = (0.9*weno->rc / (1.0-0.9*weno->rc)) * weno->xi * weno->xi;
206  df_jm12 = fm1 - fm2;
207  df_jp12 = fp1 - fm1;
208  df_jp32 = fp2 - fp1;
209  r_j = (absolute(2*df_jp12*df_jm12)+cuckoo)/(df_jp12*df_jp12+df_jm12*df_jm12+cuckoo);
210  r_jp1 = (absolute(2*df_jp32*df_jp12)+cuckoo)/(df_jp32*df_jp32+df_jp12*df_jp12+cuckoo);
211  r_int = min(r_j, r_jp1);
212  sigma = min((r_int/weno->rc), 1.0);
213  }
214 
215  if (upw > 0) {
216  for (k=0; k<nvars; k++) {
217  A[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = (one_half*sigma) * L[v*nvars+k];
218  B[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = (1.0) * L[v*nvars+k];
219  C[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = (one_sixth*sigma) * L[v*nvars+k];
220  }
221  } else {
222  for (k=0; k<nvars; k++) {
223  C[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = (one_half*sigma) * L[v*nvars+k];
224  B[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = (1.0) * L[v*nvars+k];
225  A[(Nsys*indexI[dir]+sys)*nvars*nvars+v*nvars+k] = (one_sixth*sigma) * L[v*nvars+k];
226  }
227  }
228  double fWENO, fCompact;
229  fWENO = w1*f1 + w2*f2 + w3*f3;
230  fCompact = one_sixth * (one_third*fm2 + 19.0*one_third*fm1 + 10.0*one_third*fp1);
231  F[(Nsys*indexI[dir]+sys)*nvars+v] = sigma*fCompact + (1.0-sigma)*fWENO;
232  }
233  }
234  }
235 
236 #ifdef serial
237 
238  /* Solve the tridiagonal system */
239  IERR blocktridiagLU(A,B,C,F,dim[dir]+1,Nsys,nvars,lu,NULL); CHECKERR(ierr);
240 
241 #else
242 
243  /* Solve the tridiagonal system */
244  /* all processes except the last will solve without the last interface to avoid overlap */
245  if (mpi->ip[dir] != mpi->iproc[dir]-1) {
246  IERR blocktridiagLU(A,B,C,F,dim[dir] ,Nsys,nvars,lu,&mpi->comm[dir]); CHECKERR(ierr);
247  } else {
248  IERR blocktridiagLU(A,B,C,F,dim[dir]+1,Nsys,nvars,lu,&mpi->comm[dir]); CHECKERR(ierr);
249  }
250 
251  /* Now get the solution to the last interface from the next proc */
252  double *sendbuf = compact->sendbuf;
253  double *recvbuf = compact->recvbuf;
254  MPI_Request req[2] = {MPI_REQUEST_NULL,MPI_REQUEST_NULL};
255  if (mpi->ip[dir]) for (d=0; d<Nsys*nvars; d++) sendbuf[d] = F[d];
256  if (mpi->ip[dir] != mpi->iproc[dir]-1) MPI_Irecv(recvbuf,Nsys*nvars,MPI_DOUBLE,mpi->ip[dir]+1,214,mpi->comm[dir],&req[0]);
257  if (mpi->ip[dir]) MPI_Isend(sendbuf,Nsys*nvars,MPI_DOUBLE,mpi->ip[dir]-1,214,mpi->comm[dir],&req[1]);
258  MPI_Status status_arr[2];
259  MPI_Waitall(2,&req[0],status_arr);
260  if (mpi->ip[dir] != mpi->iproc[dir]-1) for (d=0; d<Nsys*nvars; d++) F[d+Nsys*nvars*dim[dir]] = recvbuf[d];
261 
262 #endif
263 
264  /* save the solution to fI */
265 #pragma omp parallel for schedule(auto) default(shared) private(sys,d,v,k,R,L,uavg,index_outer,indexC,indexI)
266  for (sys=0; sys<Nsys; sys++) {
267  _ArrayIndexnD_(ndims,sys,bounds_outer,index_outer,0);
268  _ArrayCopy1D_(index_outer,indexI,ndims);
269  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
270  int p; _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
271  _ArrayCopy1D_((F+sys*nvars+Nsys*nvars*indexI[dir]),(fI+nvars*p),nvars);
272  }
273  }
274 
275  return(0);
276 }
void * interp
Definition: hypar.h:362
MPI_Comm * comm
#define _ArrayIndexnD_(N, index, imax, i, ghost)
void * physics
Definition: hypar.h:266
int(* GetRightEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:359
int * dim_local
Definition: hypar.h:37
int blocktridiagLU(double *, double *, double *, double *, int, int, int, void *, void *)
double * recvbuf
Structure of variables/parameters needed by the WENO-type scheme.
Structure of variables/parameters needed by the compact schemes.
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
int(* AveragingFunction)(double *, double *, double *, void *)
Definition: hypar.h:354
void * compact
Definition: hypar.h:364
int(* GetLeftEigenvectors)(double *, double *, void *, int)
Definition: hypar.h:357
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
#define CHECKERR(ierr)
Definition: basic.h:18
int ndims
Definition: hypar.h:26
#define absolute(a)
Definition: math_ops.h:32
#define IERR
Definition: basic.h:16
#define _ArrayProduct1D_(x, size, p)
Structure of MPI-related variables.
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
double * sendbuf
void * lusolver
Definition: hypar.h:368
#define min(a, b)
Definition: math_ops.h:14
#define _DECLARE_IERR_
Definition: basic.h:17
int Interp2PrimSecondOrder ( double *  fI,
double *  fC,
int  dir,
void *  s,
void *  m 
)

2nd order component-wise interpolation of the 2nd primitive on a uniform grid

Interpolation of the second primitive at the cell interfaces using the second-order central scheme

Computes the interpolated values of the second primitive of a function \({\bf f}\left({\bf u}\right)\) at the interfaces from the cell-centered values of the function using the second order central method on a uniform grid. The second primitive is defined as a function \({\bf h}\left({\bf u}\right)\) that satisfies:

\begin{equation} {\bf f}\left({\bf u}\left(x\right)\right) = \frac{1}{\Delta x^2} \int_{x-\Delta x/2}^{x+\Delta x/2} \left( \int_{\eta-\Delta x/2}^{\eta+\Delta x/2} {\bf h}\left({\bf u}\left(\zeta\right)\right) d\zeta \right) d\eta, \end{equation}

where \(x\) is the spatial coordinate along the dimension of the interpolation. This function the 2nd order central numerical approximation \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as \(\hat{\bf f}_{j+1/2} \approx {\bf h}_{j+1/2}\) as:

\begin{equation} \hat{\bf f}_{j+1/2} = \frac{1}{2}\left( {\bf f}_{j+1} - {\bf f}_j \right). \end{equation}

Implementation Notes:

  • The scalar interpolation method is applied to the vector function in a component-wise manner.
  • The function computes the interpolant for the entire grid in one call. It loops over all the grid lines along the interpolation direction and carries out the 1D interpolation along these grid lines.
  • Location of cell-centers and cell interfaces along the spatial dimension of the interpolation is shown in the following figure:
    chap1_1Ddomain.png

Reference:

  • Liu, Y., Shu, C.-W., Zhang, M., High Order Finite Difference WENO Schemes for Nonlinear Degenerate Parabolic Equations, SIAM J. Sci. Comput., 33 (2), 2011, pp. 939-965, http://dx.doi.org/10.1137/100791002.

Function arguments:

Argument Type Explanation
fI double* Array to hold the computed interpolant at the grid interfaces. This array must have the same layout as the solution, but with no ghost points. Its size should be the same as u in all dimensions, except dir (the dimension along which to interpolate) along which it should be larger by 1 (number of interfaces is 1 more than the number of interior cell centers).
fC double* Array with the cell-centered values of the flux function \({\bf f}\left({\bf u}\right)\). This array must have the same layout and size as the solution, with ghost points.
dir int Spatial dimension along which to interpolate (eg: 0 for 1D; 0 or 1 for 2D; 0,1 or 2 for 3D)
s void* Solver object of type HyPar: the following variables are needed - HyPar::ghosts, HyPar::ndims, HyPar::nvars, HyPar::dim_local.
m void* MPI object of type MPIVariables: this is needed only by compact interpolation method that need to solve a global implicit system across MPI ranks.
Parameters
fIArray of interpolated function values at the interfaces
fCArray of cell-centered values of the function \({\bf f}\left({\bf u}\right)\)
dirSpatial dimension along which to interpolation
sObject of type HyPar containing solver-related variables
mObject of type MPIVariables containing MPI-related variables

Definition at line 56 of file Interp2PrimSecondOrder.c.

63 {
64  HyPar *solver = (HyPar*) s;
65 
66  int ghosts = solver->ghosts;
67  int ndims = solver->ndims;
68  int nvars = solver->nvars;
69  int *dim = solver->dim_local;
70 
71  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
72  dimension "dir" */
73  int indexC[ndims], indexI[ndims], index_outer[ndims], bounds_outer[ndims], bounds_inter[ndims];
74  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
75  _ArrayCopy1D_(dim,bounds_inter,ndims); bounds_inter[dir] += 1;
76 
77  int done = 0; _ArraySetValue_(index_outer,ndims,0);
78  while (!done) {
79  _ArrayCopy1D_(index_outer,indexC,ndims);
80  _ArrayCopy1D_(index_outer,indexI,ndims);
81  for (indexI[dir] = 0; indexI[dir] < dim[dir]+1; indexI[dir]++) {
82  int p, qL, qR;
83  _ArrayIndex1D_(ndims,bounds_inter,indexI,0,p);
84  indexC[dir] = indexI[dir]-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qL);
85  indexC[dir] = indexI[dir] ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qR);
86  int v; for (v=0; v<nvars; v++) fI[p*nvars+v] = (fC[qR*nvars+v] - fC[qL*nvars+v]);
87  }
88  _ArrayIncrementIndex_(ndims,bounds_outer,index_outer,done);
89  }
90 
91  return(0);
92 }
#define _ArraySetValue_(x, size, value)
#define _ArrayIncrementIndex_(N, imax, i, done)
int * dim_local
Definition: hypar.h:37
int ghosts
Definition: hypar.h:52
#define _ArrayIndex1D_(N, imax, i, ghost, index)
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
int ndims
Definition: hypar.h:26
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int InterpSetLimiterVar ( double *  ,
double *  ,
double *  ,
int  ,
void *  ,
void *   
)

Function to calculate and save the nonlinear interpolation coefficients for a non-linear (solution-dependent) interpolation scheme (eg. _FIFTH_ORDER_WENO_, _FIFTH_ORDER_CRWENO_, _FIFTH_ORDER_HCWENO_, etc).

int MUSCLInitialize ( void *  s,
void *  m 
)

Initialize the 2nd or 3rd order MUSCL scheme.

Parameters
sSolver object of type HyPar
mMPI object of type MPIVariables

Definition at line 17 of file MUSCLInitialize.c.

21 {
22  HyPar *solver = (HyPar*) s;
23  MPIVariables *mpi = (MPIVariables*) m;
24  MUSCLParameters *muscl = (MUSCLParameters*) solver->interp;
25 
26  /* default values */
27  muscl->eps = 1e-3;
28  strcpy(muscl->limiter_type, _LIM_GM_);
29 
30  if (!mpi->rank) {
31  FILE *in;
32  int ferr;
33  in = fopen("muscl.inp","r");
34  if (!in) printf("Warning: File muscl.inp not found. Using default parameters for muscl2/muscl3 scheme.\n");
35  else {
36  printf("Reading MUSCL parameters from muscl.inp.\n");
37  char word[_MAX_STRING_SIZE_];
38  ferr = fscanf(in,"%s",word); if (ferr != 1) return(1);
39  if (!strcmp(word, "begin")){
40  while (strcmp(word, "end")){
41  ferr = fscanf(in,"%s",word); if (ferr != 1) return(1);
42  if (!strcmp(word,"epsilon")) { ferr = fscanf(in,"%lf",&muscl->eps); if (ferr != 1) return(1); }
43  else if (!strcmp(word,"limiter")) { ferr = fscanf(in,"%s" ,muscl->limiter_type); if (ferr != 1) return(1); }
44  else if (strcmp(word,"end")) {
45  char useless[_MAX_STRING_SIZE_];
46  ferr = fscanf(in,"%s",useless); if (ferr != 1) return(ferr);
47  printf("Warning: keyword %s in file \"muscl.inp\" with value %s not ",word,useless);
48  printf("recognized or extraneous. Ignoring.\n");
49  }
50  }
51  } else {
52  fprintf(stderr,"Error: Illegal format in file \"muscl.inp\".\n");
53  return(1);
54  }
55  fclose(in);
56  }
57  }
58 
59  MPIBroadcast_double(&muscl->eps, 1, 0, &mpi->world);
61 
62  if (!strcmp(muscl->limiter_type, _LIM_GM_)) {
64  } else if (!strcmp(muscl->limiter_type, _LIM_MM_)) {
66  } else if (!strcmp(muscl->limiter_type, _LIM_VANLEER_)) {
68  } else if (!strcmp(muscl->limiter_type, _LIM_SUPERBEE_)) {
70  } else {
71  if (!mpi->rank) {
72  fprintf(stderr, "Warning: %s is an invalid limiter type. Using default (Generalized MinMod).\n",
73  muscl->limiter_type);
74  }
76  }
77 
78  return(0);
79 }
void * interp
Definition: hypar.h:362
int MPIBroadcast_double(double *, int, int, void *)
Definition: MPIBroadcast.c:9
double LimiterGeneralizedMinMod(double)
double LimiterSuperBee(double)
#define _LIM_SUPERBEE_
Definition: limiters.h:16
char limiter_type[_MAX_STRING_SIZE_]
double(* LimiterFunction)(double)
double LimiterMinMod(double)
Definition: LimiterMinMod.c:16
#define _LIM_VANLEER_
Definition: limiters.h:14
MPI_Comm world
#define _MAX_STRING_SIZE_
Definition: basic.h:14
double LimiterVanLeer(double)
int MPIBroadcast_character(char *, int, int, void *)
Definition: MPIBroadcast.c:37
Structure of variables/parameters needed by the MUSCL scheme.
#define _LIM_GM_
Definition: limiters.h:10
Structure of MPI-related variables.
#define _LIM_MM_
Definition: limiters.h:12
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int WENOInitialize ( void *  s,
void *  m,
char *  scheme,
char *  type 
)

Initialize the structure containing variables and parameters for WENO-type schemes

This function initializes the WENO-type methods.

  • Sets the parameters to default values.
  • Reads in the parameters from optional input file "weno.inp", if available.
  • Allocates memory for and initializes the nonlinear weights used by WENO-type schemes.
Parameters
sSolver object of type HyPar
mMPI object of type MPIVariables
schemeName of scheme
typeType of interpolation

Definition at line 34 of file WENOInitialize.c.

40 {
41  HyPar *solver = (HyPar*) s;
42  MPIVariables *mpi = (MPIVariables*) m;
43  WENOParameters *weno = (WENOParameters*) solver->interp;
44 
45  static int count = 0;
46 
47  int nvars = solver->nvars;
48  int ndims = solver->ndims;
49 
50  /* default parameters */
51  weno->mapped = 0;
52  weno->borges = 0;
53  weno->yc = 0;
54  weno->no_limiting = 0;
55  weno->eps = 1e-6;
56  weno->p = 2.0;
57 
58  weno->rc = 0.3;
59  weno->xi = 0.001;
60  weno->tol = 1e-16;
61 
62  if (!mpi->rank) {
63  FILE *in;
64  int ferr;
65  in = fopen("weno.inp","r");
66  if (!in) printf("Warning: File weno.inp not found. Using default parameters for WENO5/CRWENO5/HCWENO5 scheme.\n");
67  else {
68  if (!count) printf("Reading WENO parameters from weno.inp.\n");
69  char word[_MAX_STRING_SIZE_];
70  ferr = fscanf(in,"%s",word); if (ferr != 1) return(1);
71  if (!strcmp(word, "begin")){
72  while (strcmp(word, "end")){
73  ferr = fscanf(in,"%s",word); if (ferr != 1) return(1);
74  if (!strcmp(word,"mapped" )) { ferr = fscanf(in,"%d" ,&weno->mapped ); if (ferr != 1) return(1); }
75  else if (!strcmp(word,"borges" )) { ferr = fscanf(in,"%d" ,&weno->borges ); if (ferr != 1) return(1); }
76  else if (!strcmp(word,"yc" )) { ferr = fscanf(in,"%d" ,&weno->yc ); if (ferr != 1) return(1); }
77  else if (!strcmp(word,"no_limiting")) { ferr = fscanf(in,"%d" ,&weno->no_limiting); if (ferr != 1) return(1); }
78  else if (!strcmp(word,"epsilon" )) { ferr = fscanf(in,"%lf",&weno->eps ); if (ferr != 1) return(1); }
79  else if (!strcmp(word,"p" )) { ferr = fscanf(in,"%lf",&weno->p ); if (ferr != 1) return(1); }
80  else if (!strcmp(word,"rc" )) { ferr = fscanf(in,"%lf",&weno->rc ); if (ferr != 1) return(1); }
81  else if (!strcmp(word,"xi" )) { ferr = fscanf(in,"%lf",&weno->xi ); if (ferr != 1) return(1); }
82  else if (!strcmp(word,"tol" )) { ferr = fscanf(in,"%lf",&weno->tol ); if (ferr != 1) return(1); }
83  else if (strcmp(word,"end")) {
84  char useless[_MAX_STRING_SIZE_];
85  ferr = fscanf(in,"%s",useless); if (ferr != 1) return(ferr);
86  printf("Warning: keyword %s in file \"weno.inp\" with value %s not ",word,useless);
87  printf("recognized or extraneous. Ignoring.\n");
88  }
89  }
90  } else {
91  fprintf(stderr,"Error: Illegal format in file \"weno.inp\".\n");
92  return(1);
93  }
94  fclose(in);
95  }
96  }
97 
98  int integer_data[4];
99  double real_data[5];
100  if (!mpi->rank) {
101  integer_data[0] = weno->mapped;
102  integer_data[1] = weno->borges;
103  integer_data[2] = weno->yc;
104  integer_data[3] = weno->no_limiting;
105  real_data[0] = weno->eps;
106  real_data[1] = weno->p;
107  real_data[2] = weno->rc;
108  real_data[3] = weno->xi;
109  real_data[4] = weno->tol;
110  }
111  MPIBroadcast_integer(integer_data,4,0,&mpi->world);
112  MPIBroadcast_double (real_data ,5,0,&mpi->world);
113 
114  weno->mapped = integer_data[0];
115  weno->borges = integer_data[1];
116  weno->yc = integer_data[2];
117  weno->no_limiting = integer_data[3];
118  weno->eps = real_data [0];
119  weno->p = real_data [1];
120  weno->rc = real_data [2];
121  weno->xi = real_data [3];
122  weno->tol = real_data [4];
123 
124  /* WENO weight calculation is hard-coded for p=2, so return error if p != 2 in
125  * user input file, so that there's no confusion */
126  if (weno->p != 2.0) {
127  if (!mpi->rank && !count) printf("Warning from WENOInitialize(): \"p\" parameter is 2.0. Any other value will be ignored!\n");
128  }
129 
130  weno->offset = NULL;
131  weno->w1 = NULL;
132  weno->w2 = NULL;
133  weno->w3 = NULL;
134 
135  weno->offset = (int*) calloc (ndims,sizeof(int));
136  int dir,d;
137  for (dir=0; dir<ndims; dir++) {
138  weno->offset[dir] = 0;
139  for (d=0; d<dir; d++) {
140  int size = nvars, i;
141  for (i=0; i<ndims; i++)
142  size *= ( i==d ? solver->dim_local[i]+1 : solver->dim_local[i] );
143  weno->offset[dir] += size;
144  }
145  }
146 
147  int total_size = 0;
148  for (d=0; d<ndims; d++) {
149  int size = nvars, i;
150  for (i=0; i<ndims; i++)
151  size *= ( i==d ? solver->dim_local[i]+1 : solver->dim_local[i] );
152  total_size += size;
153  }
154  weno->size = total_size;
155 
156  if ((!strcmp(type,_CHARACTERISTIC_)) && (nvars > 1))
158  else {
159 #if defined(HAVE_CUDA)
160  if (solver->use_gpu) {
162  } else {
163 #endif
165 #if defined(HAVE_CUDA)
166  }
167 #endif
168  }
169 
170  /* initialize WENO weights to their optimal values */
171  double* tmp_w1 = (double*) calloc (4*total_size,sizeof(double));
172  double* tmp_w2 = (double*) calloc (4*total_size,sizeof(double));
173  double* tmp_w3 = (double*) calloc (4*total_size,sizeof(double));
174  for (d=0; d<ndims; d++) WENOFifthOrderInitializeWeights( tmp_w1,
175  tmp_w2,
176  tmp_w3,
177  weno->offset,
178  d,
179  solver,
180  mpi);
181  count++;
182 
183 #if defined(HAVE_CUDA)
184  if (solver->use_gpu) {
185  //gpuMalloc((void**)&weno->gpu_offset, solver->ndims*sizeof(int));
186  gpuMalloc((void**)&weno->w1, 4*total_size*sizeof(double));
187  gpuMalloc((void**)&weno->w2, 4*total_size*sizeof(double));
188  gpuMalloc((void**)&weno->w3, 4*total_size*sizeof(double));
189 
190  //gpuMemcpy(weno->gpu_offset, weno->offset, solver->ndims*sizeof(int), gpuMemcpyHostToDevice);
191  gpuMemcpy(weno->w1, tmp_w1, 4*total_size*sizeof(double), gpuMemcpyHostToDevice);
192  gpuMemcpy(weno->w2, tmp_w2, 4*total_size*sizeof(double), gpuMemcpyHostToDevice);
193  gpuMemcpy(weno->w3, tmp_w3, 4*total_size*sizeof(double), gpuMemcpyHostToDevice);
194  } else {
195 #endif
196  weno->w1 = (double*) calloc (4*total_size,sizeof(double));
197  weno->w2 = (double*) calloc (4*total_size,sizeof(double));
198  weno->w3 = (double*) calloc (4*total_size,sizeof(double));
199 
200  _ArrayCopy1D_(tmp_w1, weno->w1, 4*total_size);
201  _ArrayCopy1D_(tmp_w2, weno->w2, 4*total_size);
202  _ArrayCopy1D_(tmp_w3, weno->w3, 4*total_size);
203 #if defined(HAVE_CUDA)
204  }
205 #endif
206 
207  free(tmp_w1);
208  free(tmp_w2);
209  free(tmp_w3);
210 
211  return 0;
212 }
void * interp
Definition: hypar.h:362
int gpuWENOFifthOrderCalculateWeights(double *fC, double *uC, double *x, int dir, void *s, void *m)
#define _CHARACTERISTIC_
Definition: interpolation.h:33
int WENOFifthOrderCalculateWeightsChar(double *fC, double *uC, double *x, int dir, void *s, void *m)
int MPIBroadcast_double(double *, int, int, void *)
Definition: MPIBroadcast.c:9
int WENOFifthOrderCalculateWeights(double *fC, double *uC, double *x, int dir, void *s, void *m)
int * dim_local
Definition: hypar.h:37
void gpuMemcpy(void *, const void *, size_t, enum gpuMemcpyKind)
int WENOFifthOrderInitializeWeights(double *const a_w1, double *const a_w2, double *const a_w3, const int *const a_offset, int dir, void *s, void *m)
Structure of variables/parameters needed by the WENO-type scheme.
int(* SetInterpLimiterVar)(double *, double *, double *, int, void *, void *)
Definition: hypar.h:234
MPI_Comm world
#define _MAX_STRING_SIZE_
Definition: basic.h:14
#define _ArrayCopy1D_(x, y, size)
int nvars
Definition: hypar.h:29
void gpuMalloc(void **, size_t)
int use_gpu
Definition: hypar.h:449
int ndims
Definition: hypar.h:26
Structure of MPI-related variables.
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int MPIBroadcast_integer(int *, int, int, void *)
Definition: MPIBroadcast.c:23
int WENOCleanup ( void *  s,
int  flag_gpu 
)

Clean up the structure containing variables and parameters for WENO-type schemes

Cleans up all allocations related to the WENO-type methods.

Parameters
sWENO object of type WENOParameters
flag_gpuflag to indicate if on GPU

Definition at line 17 of file WENOCleanup.c.

19 {
20  WENOParameters *weno = (WENOParameters*) s;
21 
22  if (weno->offset) free(weno->offset);
23 #if defined(HAVE_CUDA)
24  if (flag_gpu) {
25  if (weno->w1) gpuFree(weno->w1);
26  if (weno->w2) gpuFree(weno->w2);
27  if (weno->w3) gpuFree(weno->w3);
28  } else {
29 #endif
30  if (weno->w1) free(weno->w1);
31  if (weno->w2) free(weno->w2);
32  if (weno->w3) free(weno->w3);
33 #if defined(HAVE_CUDA)
34  }
35 #endif
36 
37  return(0);
38 }
Structure of variables/parameters needed by the WENO-type scheme.
void gpuFree(void *)
int CompactSchemeInitialize ( void *  s,
void *  m,
char *  type 
)

Initialize the structure containing variables and parameters for compact schemes

This function initializes the compact finite-difference methods: allocates the arrays to store the tridiagonal system.

Parameters
sSolver object of type HyPar
mMPI object of type MPIVariables
typeType of interpolation

Definition at line 17 of file CompactSchemeInitialize.c.

22 {
23  HyPar *solver = (HyPar*) s;
24  MPIVariables *mpi = (MPIVariables*) m;
25  CompactScheme *compact = (CompactScheme*) solver->compact;
26 
27  int nvars = solver->nvars;
28  int ndims = solver->ndims;
29 
30  int size = 1, d;
31  for (d=0; d<solver->ndims; d++) size *= (solver->dim_local[d]+1);
32  size *= solver->nvars;
33  if (!strcmp(solver->interp_type,_CHARACTERISTIC_)) size *= solver->nvars;
34 
35  compact->A = (double*) calloc (size, sizeof(double));
36  compact->B = (double*) calloc (size, sizeof(double));
37  compact->C = (double*) calloc (size, sizeof(double));
38  compact->R = (double*) calloc (size, sizeof(double));
39 
40  compact->sendbuf = (double*) calloc (size, sizeof(double));
41  compact->recvbuf = (double*) calloc (size, sizeof(double));
42 
43  return(0);
44 }
#define _CHARACTERISTIC_
Definition: interpolation.h:33
int * dim_local
Definition: hypar.h:37
double * recvbuf
Structure of variables/parameters needed by the compact schemes.
void * compact
Definition: hypar.h:364
int nvars
Definition: hypar.h:29
char interp_type[_MAX_STRING_SIZE_]
Definition: hypar.h:88
int ndims
Definition: hypar.h:26
Structure of MPI-related variables.
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
double * sendbuf
int CompactSchemeCleanup ( void *  s)

Clean up the structure containing variables and parameters for compact schemes

Cleans up all allocations related to the compact finite difference methods.

Parameters
sCompactScheme object of type CompactScheme

Definition at line 14 of file CompactSchemeCleanup.c.

15 {
16  CompactScheme *compact = (CompactScheme*) s;
17 
18  if (compact->A) free(compact->A);
19  if (compact->B) free(compact->B);
20  if (compact->C) free(compact->C);
21  if (compact->R) free(compact->R);
22 
23  if (compact->sendbuf) free(compact->sendbuf);
24  if (compact->recvbuf) free(compact->recvbuf);
25 
26  return(0);
27 }
double * recvbuf
Structure of variables/parameters needed by the compact schemes.
double * sendbuf