HyPar  1.0
Finite-Difference Hyperbolic-Parabolic PDE Solver on Cartesian Grids
FirstDerivativeSecondOrderNoGhosts.c File Reference

Second order finite-difference approximation to first derivative. More...

#include <stdio.h>
#include <stdlib.h>
#include <basic.h>
#include <arrayfunctions.h>
#include <firstderivative.h>
#include <mpivars.h>

Go to the source code of this file.

Macros

#define _MINIMUM_GHOSTS_   1
 

Typedefs

typedef MPIVariables MPIContext
 

Functions

int FirstDerivativeSecondOrderCentralNoGhosts (double *Df, double *f, int dir, int bias, int ndims, int *dim, int ghosts, int nvars, void *m)
 

Detailed Description

Second order finite-difference approximation to first derivative.

Author
Ping-Hsuan Tsai

Definition in file FirstDerivativeSecondOrderNoGhosts.c.

Macro Definition Documentation

◆ _MINIMUM_GHOSTS_

#define _MINIMUM_GHOSTS_   1

Minimum number of ghost points required.

Definition at line 19 of file FirstDerivativeSecondOrderNoGhosts.c.

Typedef Documentation

◆ MPIContext

Definition at line 13 of file FirstDerivativeSecondOrderNoGhosts.c.

Function Documentation

◆ FirstDerivativeSecondOrderCentralNoGhosts()

int FirstDerivativeSecondOrderCentralNoGhosts ( double *  Df,
double *  f,
int  dir,
int  bias,
int  ndims,
int *  dim,
int  ghosts,
int  nvars,
void *  m 
)

Computes the second-order finite-difference approximation to the first derivative (Note: not divided by the grid spacing):

\begin{equation} \left(\partial f\right)_i = \left\{ \begin{array}{ll} \frac{1}{2}\left(-3f_i+4f_{i+1}-f_{i+2}\right) & i = -g \\ \frac{1}{2}\left( f_{i+1} - f_{i-1} \right) & -g+1 \leq i \leq N+g-2 \\ \frac{1}{2}\left( f_{i-2} -4f_{i-1}+3f_i \right) & i = N+g-1 \end{array}\right. \end{equation}

where \(i\) is the grid index along the spatial dimension of the derivative, \(g\) is the number of ghost points, and \(N\) is the number of grid points (not including the ghost points) in the spatial dimension of the derivative.

Notes:

  • The first derivative is computed at the grid points or the cell centers.
  • Df and f are serialized 1D arrays containing the function and its computed derivatives on a multi-dimensional grid. The derivative along the specified dimension dir is computed by looping through all grid lines along dir.
  • Df and f must have the same number of ghost points.
  • Biased stencils are used at the physical boundaries and ghost point values of f are not used. So this function can be used when the ghost values at physical boundaries are not filled. The ghost values at internal (MPI) boundaries are still needed.
Parameters
DfArray to hold the computed first derivative (with ghost points)
fArray containing the grid point function values whose first derivative is to be computed (with ghost points)
dirThe spatial dimension along which the derivative is computed
biasForward or backward differencing for non-central finite-difference schemes (-1: backward, 1: forward)
ndimsNumber of spatial/coordinate dimensions
dimLocal dimensions
ghostsNumber of ghost points
nvarsNumber of vector components at each grid points
mMPI object of type MPIContext

Definition at line 42 of file FirstDerivativeSecondOrderNoGhosts.c.

53 {
54  MPIContext* mpi = (MPIContext*) m;
55  int i, j, v;
56 
57  if ((!Df) || (!f)) {
58  fprintf(stderr, "Error in FirstDerivativeSecondOrder(): input arrays not allocated.\n");
59  return(1);
60  }
61  if (ghosts < _MINIMUM_GHOSTS_) {
62  fprintf(stderr, "Error in FirstDerivativeSecondOrderCentralNoGhosts(): insufficient number of ghosts.\n");
63  return(1);
64  }
65 
66  /* create index and bounds for the outer loop, i.e., to loop over all 1D lines along
67  dimension "dir" */
68  int indexC[ndims], index_outer[ndims], bounds_outer[ndims];
69  _ArrayCopy1D_(dim,bounds_outer,ndims); bounds_outer[dir] = 1;
70  int N_outer; _ArrayProduct1D_(bounds_outer,ndims,N_outer);
71 
72 #pragma omp parallel for schedule(auto) default(shared) private(i,j,v,index_outer,indexC)
73  for (j=0; j<N_outer; j++) {
74  _ArrayIndexnD_(ndims,j,bounds_outer,index_outer,0);
75  _ArrayCopy1D_(index_outer,indexC,ndims);
76  for (i = 0; i < dim[dir]; i++) {
77  int qC, qL, qR;
78  indexC[dir] = i-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qL);
79  indexC[dir] = i ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qC );
80  indexC[dir] = i+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qR);
81  for (v=0; v<nvars; v++) Df[qC*nvars+v] = 0.5 * (f[qR*nvars+v]-f[qL*nvars+v]);
82  }
83  }
84 
85  if (mpi->ip[dir] == 0) {
86  /* left physical boundary: overwrite the leftmost value with biased finite-difference */
87 #pragma omp parallel for schedule(auto) default(shared) private(i,j,v,index_outer,indexC)
88  for (j=0; j<N_outer; j++) {
89  _ArrayIndexnD_(ndims,j,bounds_outer,index_outer,0);
90  _ArrayCopy1D_(index_outer,indexC,ndims);
91  i = 0;
92  int qC, qR, qR2;
93  indexC[dir] = i ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qC );
94  indexC[dir] = i+1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qR);
95  indexC[dir] = i+2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qR2);
96  for (v=0; v<nvars; v++) Df[qC*nvars+v] = (-0.5*f[qR2*nvars+v]+2*f[qR*nvars+v]-1.5*f[qC*nvars+v]);
97  }
98  }
99 
100  if (mpi->ip[dir] == (mpi->iproc[dir]-1)) {
101  /* right physical boundary: overwrite the rightmost value with biased finite-difference */
102 #pragma omp parallel for schedule(auto) default(shared) private(i,j,v,index_outer,indexC)
103  for (j=0; j<N_outer; j++) {
104  _ArrayIndexnD_(ndims,j,bounds_outer,index_outer,0);
105  _ArrayCopy1D_(index_outer,indexC,ndims);
106  i = dim[dir] - 1;
107  int qC, qL, qL2;
108  indexC[dir] = i-2; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qL2);
109  indexC[dir] = i-1; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qL);
110  indexC[dir] = i ; _ArrayIndex1D_(ndims,dim,indexC,ghosts,qC );
111  for (v=0; v<nvars; v++) Df[qC*nvars+v] = (0.5*f[qL2*nvars+v]-2*f[qL*nvars+v]+1.5*f[qC*nvars+v]);
112  }
113  }
114 
115  return 0;
116 }
#define _ArrayIndexnD_(N, index, imax, i, ghost)
#define _ArrayIndex1D_(N, imax, i, ghost, index)
Structure of MPI-related variables.
#define _ArrayCopy1D_(x, y, size)
#define _ArrayProduct1D_(x, size, p)