<|start_filename|>MacCor1d/commonlib/kernelLaunch.h<|end_filename|>
/* kernelLaunch.h
 * 1-dim. MacCormack method with global memory
 * <NAME>  <EMAIL>
 * 20161030
 */
#ifndef __KERNELLAUNCH_H__
#define __KERNELLAUNCH_H__

#include "./MacCor1d.h" 

void kernelLauncher(float *, float *, float *, dim3, dim3 ) ;

int blocksNeeded( int N_i, int M_i) ;

#endif // __KERNELLAUNCH_H__


<|start_filename|>NavSt2DIncompFiniteDiff/physlib/boundary.cu<|end_filename|>
/* boundary.cu
 * fix boundary conditions at the "boundary strip" cf. Griebel, Dornseifer, & Neunhoeffer (1997)
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161207
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/boundary.cu -o boundary.o
 * 
 */
#include "boundary.h"

/* --------------------------------------------------------------- */
/* Setting the boundary conditions at the boundary strip.      	   */
// on the host CPU memory
/* --------------------------------------------------------------- */

__host__ void set_BConditions_host( Grid2d & grid2d) {
	const int imax { grid2d.Ld[0] } ;
	const int jmax { grid2d.Ld[1] } ;

	/* western and eastern boundary, i.e. x=0, and x=L_x+1 i.e. x=imax+1 */
	
	/* no slip */
	for (auto j = 0; j<= (jmax+1);j++) { 
		/* western boundary */
		grid2d.u[grid2d.staggered_flatten( 0,j) ] = 0.0;  	   /* u = 0  	*/
		grid2d.v[grid2d.staggered_flatten( 0,j) ] = 
			(-1.0) * grid2d.v[grid2d.staggered_flatten( 1,j) ]; /* v = 0 at the boundary by averaging */

		/* eastern boundary */
		grid2d.u[grid2d.staggered_flatten( imax,j) ] = 0.0; 
		grid2d.v[grid2d.staggered_flatten( imax+1,j) ] = 
			(-1.0) * grid2d.v[grid2d.staggered_flatten( imax,j) ];
	}
	
	/* northern and southern boundary, i.e. y=0 and y=L_y+1, i.e. y=jmax+1 */ 

	/* no slip */
	for (auto i = 0; i<= (imax+1);i++) {
		/* northern boundary */
		grid2d.v[grid2d.staggered_flatten( i,jmax)] = 0.0;  /* v = 0  */
		grid2d.u[grid2d.staggered_flatten( i,jmax+1)] = 
			(-1.0)*grid2d.u[grid2d.staggered_flatten( i,jmax)]; /* u = 0 at the boundary by averaging */
	
		/* southern boundary */
		grid2d.v[grid2d.staggered_flatten( i,0) ] = 0.0;     /* v = 0 */
		grid2d.u[grid2d.staggered_flatten( i,0) ] = 
			(-1.0)*grid2d.u[grid2d.staggered_flatten( i,1) ]; /* u = 0 at the boundary by averaging */
		
	}
	return;	
} // end set_BConditions_host

/* -------------------------------------------------------------- */
/* Driven Cavity: u^x = 1.0 at the upper boundary                 */ 
// on the host CPU memory
/* -------------------------------------------------------------- */
// we set \overline{u} = 2.0, but this case be changed, i.e. how fast the lid moves to the right, or positive +x direction
__host__ void set_lidcavity_BConditions_host( Grid2d & grid2d) {
	const int imax { grid2d.Ld[0] } ;
	const int jmax { grid2d.Ld[1] } ;

	
	for (auto i = 0; i< imax+1;i++) {
		/* northern boundary */
		grid2d.u[grid2d.staggered_flatten( i,jmax+1)] = 
			2.0 - grid2d.u[grid2d.staggered_flatten( i, jmax)] ; }

	return;
}

/* --------------------------------------------------------------- */
/* Setting the boundary conditions at the boundary strip.      	   */
// on the device GPU memory
/* --------------------------------------------------------------- */

void set_BConditions( Dev_Grid2d & dev_grid2d ) {
	const int imax = dev_grid2d.Ld.x;
	const int jmax = dev_grid2d.Ld.y;
	
	/* western and eastern boundary, i.e. x=0, and x=L_x+1 i.e. x=imax+1 */

	/* no slip */
	for (auto j = 1; j<= (jmax+1);j++) { 
		/* western boundary */
		dev_grid2d.u[dev_grid2d.staggered_flatten( 0,j) ] = 0.0;  	   /* u = 0  	*/
		dev_grid2d.v[dev_grid2d.staggered_flatten( 0,j) ] = 
			(-1.0) * dev_grid2d.v[dev_grid2d.staggered_flatten( 1,j) ]; /* v = 0 at the boundary by averaging */

		/* eastern boundary */
		dev_grid2d.u[dev_grid2d.staggered_flatten( imax,j) ] = 0.0; 
		dev_grid2d.v[dev_grid2d.staggered_flatten( imax+1,j) ] = 
			(-1.0) * dev_grid2d.v[dev_grid2d.staggered_flatten( imax,j) ];
	}
	
	/* northern and southern boundary, i.e. y=0 and y=L_y+1, i.e. y=jmax+1 */ 

	/* no slip */
	for (auto i = 1; i<= (imax+1);i++) {
		/* northern boundary */
		dev_grid2d.v[dev_grid2d.staggered_flatten( i,jmax)] = 0.0;  /* v = 0  */
		dev_grid2d.u[dev_grid2d.staggered_flatten( i,jmax+1)] = 
			(-1.0)*dev_grid2d.u[dev_grid2d.staggered_flatten( i,jmax)]; /* u = 0 at the boundary by averaging */
	
		/* southern boundary */
		dev_grid2d.v[dev_grid2d.staggered_flatten( i,0) ] = 0.0;     /* v = 0 */
		dev_grid2d.u[dev_grid2d.staggered_flatten( i,0) ] = 
			(-1.0)*dev_grid2d.u[dev_grid2d.staggered_flatten( i,1) ]; /* u = 0 at the boundary by averaging */
		
	}
	return;	
} // end set_BConditions


/* -------------------------------------------------------------- */
/* Setting specific boundary conditions, depending on "problem"   */
/* -------------------------------------------------------------- */

/* -------------------------------------------------------------- */
/* Driven Cavity: u^x = 1.0 at the upper boundary                 */ 
// on the device GPU memory
/* -------------------------------------------------------------- */
// we set \overline{u} = 2.0, but this case be changed, i.e. how fast the lid moves to the right, or positive +x direction

__host__ void set_lidcavity_BConditions( Dev_Grid2d & dev_grid2d) {
	const int imax = dev_grid2d.Ld.x  ;
	const int jmax = dev_grid2d.Ld.y  ;

	for (auto i = 0; i< imax+1;i++) {
		/* northern boundary */
		dev_grid2d.u[dev_grid2d.staggered_flatten( i,jmax+1)] = 
			2.0 - dev_grid2d.u[dev_grid2d.staggered_flatten( i, jmax)] ; }

	return;
}


////////////////////////////////////////////////////////////////////////
__host__ void set_horiz_press_BCs( Dev_Grid2d & dev_grid2d) {
	const int imax = dev_grid2d.Ld.x; 
	const int jmax = dev_grid2d.Ld.y; 
	
	for (auto i = 1; i<= imax; i++) {
	/* copy values at external boundary */
	/* -------------------------------- */
	// p_i,0 = p_i,1
		dev_grid2d.p[ dev_grid2d.staggered_flatten( i, 0)] = 
			dev_grid2d.p[ dev_grid2d.staggered_flatten( i, 1)] ; 
	// p_i,jmax+1 = p_i,jmax
		dev_grid2d.p[ dev_grid2d.staggered_flatten( i, jmax+1)] = 
			dev_grid2d.p[ dev_grid2d.staggered_flatten( i, jmax)] ; 
	}
}

////////////////////////////////////////////////////////////////////////
__host__ void set_vert_press_BCs( Dev_Grid2d & dev_grid2d) {
	const int imax = dev_grid2d.Ld.x; 
	const int jmax = dev_grid2d.Ld.y; 

	for (auto j = 1; j<= jmax; j++) {
	/* copy values at external boundary */
	/* -------------------------------- */
	// p_0,j = p_1,j
		dev_grid2d.p[ dev_grid2d.staggered_flatten( 0, j)] = 
			dev_grid2d.p[ dev_grid2d.staggered_flatten( 1, j)] ; 
	// p_imax+1,j = p_imax,j
		dev_grid2d.p[ dev_grid2d.staggered_flatten( imax+1, j)] = 
			dev_grid2d.p[ dev_grid2d.staggered_flatten( imax, j)] ; 
	}
}



<|start_filename|>MacCor1d/commonlib/MacCor1d.cu<|end_filename|>
/* MacCor1d.cu
 * 1-dim. MacCormack method
 * <NAME>  <EMAIL>
 * 20161026
 * */
#include "MacCor1d.h"

__constant__ float dev_sigmaconst[1] ; // sigma

// MacCormack method

// MacCormack method, using (only) global memory
//__global__ void MacCor_global_predict(float *f, float *foverline, const float sigmaconst ) {
__global__ void MacCor_global_predict(float *f, float *foverline, const int L_x ) {

	// global indices
	const int k_x = threadIdx.x + blockDim.x * blockIdx.x;

	int right = k_x + 1; 	
		
	if ( k_x >= L_x ) {
		return; }
		
	// predictor
	float prediction;
	prediction = f[k_x] - dev_sigmaconst[0]*(f[right]-f[k_x]) ;
	foverline[k_x] = prediction;
	
}

// MacCormack method; corrector and updating steps
__global__ void MacCor_global_correctupdate( float *f_in, float *foverline, float *f_out, 
												const int L_x) {
	
	// global indices
	const int k_x = threadIdx.x + blockDim.x * blockIdx.x ;
		
	int left = k_x - 1;
	left = max( left, 0 );

	if (k_x >= L_x) {
		return ; }
	
	// boundary condition at x = 0
	if (k_x == 0 ) {
		f_out[k_x] = 0; 
		return; 
	}
	
	float fdbloverline = 0.f; // \overline{\overline{f}}
	fdbloverline = f_in[k_x] - dev_sigmaconst[0] * (foverline[k_x] - foverline[left]) ;

	__syncthreads() ;


	f_out[k_x] = 0.5f * ( foverline[k_x] + fdbloverline ) ;

	__syncthreads();

}	

__global__ void swap( float *f_in, float *f_out, const int L_x ) {
	const int k_x = threadIdx.x + blockDim.x * blockIdx.x;
	
	if (k_x >= L_x) {
		return ; }
		
	float tempval = f_out[k_x] ; 
	f_in[k_x] = tempval; 
	
}

__global__ void BoundaryCondcheck_end(float *f, const int L_x) {
	const int k_x = threadIdx.x + blockDim.x * blockDim.x;
	
	if (k_x >= L_x) {
		return ; }
		
	if (k_x == L_x - 1) {
		float tempval = 2.f*f[k_x -1] - f[k_x-2] ;
		f[k_x] = tempval; }

}


<|start_filename|>MacCor1d/commonlib/MacCor1d.h<|end_filename|>
/* MacCor1d.h
 * 1-dim. MacCormack method
 * <NAME>  <EMAIL>
 * 20161029
 * */
#ifndef __MACCOR1D_H__
#define __MACCOR1D_H__

extern __constant__ float dev_sigmaconst[1] ; // sigma

__global__ void MacCor_global_predict(float *f, float *foverline,
										const int L_x); 

__global__ void MacCor_global_correctupdate( float *f_in, float *foverline, float *f_out,
												const int L_x);

__global__ void swap( float *f_in, float *f_out, const int L_x ) ;

__global__ void BoundaryCondcheck_end(float *f, const int L_x) ;

#endif // __MACCOR1D_H__ 


<|start_filename|>lid-driven-cavity_gpu-gfx/physlib/boundary.cu<|end_filename|>
/** boundary.cu
 * \file boundary.cu
 * fix boundary conditions at the "boundary strip" cf. Griebel, Dornseifer, & Neunhoeffer (1997)
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161207
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/boundary.cu -o boundary.o
 * 
 */
#include "boundary.h"

/* --------------------------------------------------------------- */
/* Setting the boundary conditions at the boundary strip.      	   */
// on the host CPU memory
/* --------------------------------------------------------------- */
///////////////////////////////////////////////////////////////////////////////

void set_BCs_host (float* u, float* v, 
	const int imax, const int jmax) 
{
	int ind;

	// loop through rows and columns
	for (ind = 0; ind < jmax + 2; ++ind) {

		// left boundary
		u[flatten(0, ind,jmax+2)] = 0.0;
		v[flatten(0, ind,jmax+2)] = -v[flatten(1, ind,jmax+2)];

		// right boundary
		u[flatten(imax, ind,jmax+2)] = 0.0;
		v[flatten(imax + 1, ind, jmax+2)] = -v[flatten(imax, ind, jmax+2)];

		// bottom boundary
		u[flatten(ind, 0, jmax+2)] = -u[flatten(ind, 1,jmax+2)];
		v[flatten(ind, 0, jmax+2)] = 0.0;

		// top boundary
		u[flatten(ind, jmax + 1, jmax+2)] = 2.0 - u[flatten(ind, jmax,jmax+2)];
		v[flatten(ind, jmax, jmax+2)] = 0.0;

		if (ind == jmax) {
			// left boundary
			u[flatten(0, 0, jmax+2)] = 0.0;
			v[flatten(0, 0, jmax+2)] = -v[flatten(1, 0, jmax + 2)];
			u[flatten(0, jmax + 1, jmax+2)] = 0.0;
			v[flatten(0, jmax + 1, jmax+2)] = -v[flatten(1, jmax + 1, jmax+2)];

			// right boundary
			u[flatten(imax, 0, jmax)] = 0.0;
			v[flatten(imax + 1, 0, jmax)] = -v[flatten(imax, 0, jmax + 2)];
			u[flatten(imax, jmax + 1, jmax+2)] = 0.0;
			v[flatten(imax + 1, jmax + 1, jmax+2)] = -v[flatten(imax, jmax + 1, jmax + 2)];

			// bottom boundary
			u[flatten(0, 0, jmax + 2)] = -u[flatten(0, 1, jmax + 2)];
			v[flatten(0, 0, jmax +2)] = 0.0;
			u[flatten(imax + 1, 0, jmax + 2)] = -u[flatten(imax + 1, 1, jmax + 2) ];
			v[flatten(imax + 1, 0, jmax + 2) ] = 0.0;

			// top boundary
			u[flatten(0, jmax + 1, jmax + 2) ] = 2.0 - u[flatten(0, jmax, jmax + 2)];
			v[flatten(0, jmax, jmax + 2) ] = 0.0;
			u[flatten(imax + 1, jmax + 1, jmax + 2) ] = 2.0 - u[flatten(imax + 1, jmax, jmax + 2) ];
			v[ flatten(ind, jmax + 1, jmax + 2)] = 0.0;
		} // end if

	} // end for

} // end set_BCs_host


/* --------------------------------------------------------------- */
/* Setting the boundary conditions at the boundary strip.      	   */
// on the device GPU memory
/* --------------------------------------------------------------- */
///////////////////////////////////////////////////////////////////////////////
__global__
void set_BCs (float* u, float* v,
	const int imax, const int jmax) 
{
	int ind = (blockIdx.x * blockDim.x) + threadIdx.x + 1;

	// left boundary
	u[flatten(0, ind,jmax+2)] = 0.0;
	v[flatten(0, ind,jmax+2)] = -v[flatten(1, ind,jmax+2)];

	// right boundary
	u[flatten(imax, ind,jmax+2)] = 0.0;
	v[flatten(imax + 1, ind, jmax+2)] = -v[flatten(imax, ind, jmax+2)];

	// bottom boundary
	u[flatten(ind, 0, jmax+2)] = -u[flatten(ind, 1,jmax+2)];
	v[flatten(ind, 0, jmax+2)] = 0.0;

	// top boundary
	u[flatten(ind, jmax + 1, jmax+2)] = 2.0 - u[flatten(ind, jmax,jmax+2)];
	v[flatten(ind, jmax, jmax+2)] = 0.0;

	if (ind == jmax) {
		// left boundary
		u[flatten(0, 0, jmax+2)] = 0.0;
		v[flatten(0, 0, jmax+2)] = -v[flatten(1, 0, jmax + 2)];
		u[flatten(0, jmax + 1, jmax+2)] = 0.0;
		v[flatten(0, jmax + 1, jmax+2)] = -v[flatten(1, jmax + 1, jmax+2)];

		// right boundary
		u[flatten(imax, 0, jmax)] = 0.0;
		v[flatten(imax + 1, 0, jmax)] = -v[flatten(imax, 0, jmax + 2)];
		u[flatten(imax, jmax + 1, jmax+2)] = 0.0;
		v[flatten(imax + 1, jmax + 1, jmax+2)] = -v[flatten(imax, jmax + 1, jmax + 2)];

		// bottom boundary
		u[flatten(0, 0, jmax + 2)] = -u[flatten(0, 1, jmax + 2)];
		v[flatten(0, 0, jmax +2)] = 0.0;
		u[flatten(imax + 1, 0, jmax + 2)] = -u[flatten(imax + 1, 1, jmax + 2) ];
		v[flatten(imax + 1, 0, jmax + 2) ] = 0.0;

		// top boundary
		u[flatten(0, jmax + 1, jmax + 2) ] = 2.0 - u[flatten(0, jmax, jmax + 2)];
		v[flatten(0, jmax, jmax + 2) ] = 0.0;
		u[flatten(imax + 1, jmax + 1, jmax + 2) ] = 2.0 - u[flatten(imax + 1, jmax, jmax + 2) ];
		v[ flatten(ind, jmax + 1, jmax + 2)] = 0.0;
	} // end if

} // end set_BCs

///////////////////////////////////////////////////////////////////////////////
__global__ 
void set_horz_pres_BCs (float* pres_red, float* pres_black,
	const int imax, const int jmax) 
{
	int col = (blockIdx.x * blockDim.x) + threadIdx.x + 1;
	col = (col * 2) - 1;

	int NUM_2 = jmax >> 1;

	// p_i,0 = p_i,1
	pres_black[flatten(col, 0, NUM_2 + 2)] = pres_red[flatten(col, 1, NUM_2 + 2)];
	pres_red[flatten(col + 1, 0, NUM_2 + 2)] = pres_black[ flatten(col + 1, 1, NUM_2 + 2)];

	// p_i,jmax+1 = p_i,jmax
	pres_red[flatten(col, NUM_2 + 1, NUM_2 + 2)] = pres_black[flatten(col, NUM_2, NUM_2 + 2)];
	pres_black[flatten(col + 1, NUM_2 + 1, NUM_2 + 2) ] = pres_red[flatten(col + 1, NUM_2, NUM_2 + 2)];

} // end set_horz_pres_BCs

//////////////////////////////////////////////////////////////////////////////

__global__
void set_vert_pres_BCs (float* pres_red, float* pres_black,
	const int imax, const int jmax) 
{
	int row = (blockIdx.x * blockDim.x) + threadIdx.x + 1;

	int NUM_2 = jmax >> 1;

	// p_0,j = p_1,j
	pres_black[flatten(0, row, NUM_2 + 2)] = pres_red[flatten(1, row, NUM_2 + 2)];
	pres_red[flatten(0, row, NUM_2 + 2)] = pres_black[flatten(1, row, NUM_2 + 2)];

	// p_imax+1,j = p_imax,j
	pres_black[flatten(imax + 1, row, NUM_2 + 2)] = pres_red[flatten(imax, row, NUM_2 + 2)];
	pres_red[flatten(imax + 1, row, NUM_2 + 2)] = pres_black[flatten(imax, row, NUM_2 + 2)];

} // end set_pressure_BCs

///////////////////////////////////////////////////////////////////////////////


<|start_filename|>lid-driven-cavity_gpu-gfx/physlib/R2grid.cu<|end_filename|>
/* R3grid.cpp
 * R3 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20160630
 */
#include "R2grid.h"


Grid2d :: Grid2d(std::array<int,2> Ld_in, std::array<float,2> ld_in)
	: Ld(Ld_in), ld(ld_in)
{
	hd = { ld[0]/Ld[0], ld[1]/Ld[1]  };
	
	F = new float[ this->staggered_NFLAT() ];
	G = new float[ this->staggered_NFLAT() ];
	u = new float[ this->staggered_NFLAT() ];
	v = new float[ this->staggered_NFLAT() ];

	for (auto i = 0; i < this->staggered_NFLAT(); ++i ) {
		F[i] = 0.0;
		G[i] = 0.0;
		u[i] = 0.0;
		v[i] = 0.0;
	}

	int size_pres = ((Ld[0] / 2) + 2) * ( Ld[1] + 2);
	pres_red   = new float[ size_pres ];
	pres_black = new float[ size_pres ];

	for (int i = 0; i < size_pres; ++i) {
		pres_red[i] = 0.0;
		pres_black[i] = 0.0 ;
	}

}

std::array<float,2> Grid2d :: gridpt_to_space(std::array<int,2> index) {
	std::array<float,2> Xi { index[0]*hd[0], index[1]*hd[1]  } ;
	return Xi;
}

int Grid2d :: NFLAT() {
	return Ld[0]*Ld[1] ;
}	

int Grid2d :: staggered_NFLAT() {
	return (Ld[0]+2)*(Ld[1]+2) ;
}	


int Grid2d :: flatten(const int i_x, const int i_y ) {
	return i_x+i_y*Ld[0]  ;
}

int Grid2d :: staggered_flatten(const int i_x, const int i_y ) {
	return i_x+i_y*(Ld[0]+2)  ;
}


Grid2d::~Grid2d() {
	delete[] F;
	delete[] G;
	delete[] u;
	delete[] v;

	delete[] pres_red;
	delete[] pres_black;
}




<|start_filename|>lid-driven-cavity_gpu-gfx/physlib/dev_R2grid.h<|end_filename|>
/* dev_R2grid.h
 * R2 under discretization (discretize functor) to a thread block
 * <NAME>  <EMAIL>
 * 20160728
 */
#ifndef __DEV_R2GRID_H__
#define __DEV_R2GRID_H__

#include "../commonlib/checkerror.h" // checkCudaErrors(

class Dev_Grid2d
{
	public:
		dim3 Ld;

		float* F;
		float* G;
		float* u;
		float* v;
	
		float* pres_red;
		float* pres_black;
		

		// constructor
		__host__ Dev_Grid2d( dim3 );

		// destructor
//		__host__ ~dev_Grid3d();

		__host__ int NFLAT();
		
		__host__ int staggered_NFLAT();
};


#endif // __DEV_R2GRID_H__


<|start_filename|>convect2dfinitedifftex/commonlib/tex_anim2d.cu<|end_filename|>
/* tex_anim2d.cu
 * 2-dim. GPU texture animation 
 * <NAME>  <EMAIL>
 * 20160720
 */
#include "tex_anim2d.h"
  
int iterationCount = 0 ;

// interactions

void keyboard_func( unsigned char key, int x, int y) {
	if (key==27) {
		exit(0) ;
	}
	glutPostRedisplay();
}
	
void mouse_func( int button, int state, int x, int y ) {
	glutPostRedisplay();
}

void idle() {
	++iterationCount;
	glutPostRedisplay();
}

void printInstructions() {
	printf("2 dim. texture animation \n");

}

// make* functions make functions to pass into OpenGL (note OpenGL is inherently a C API

void make_draw_texture(int w, int h) {
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 
		GL_UNSIGNED_BYTE, NULL);
	glEnable(GL_TEXTURE_2D);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f); glVertex2f(0,0);
	glTexCoord2f(0.0f, 1.0f); glVertex2f(0,h);
	glTexCoord2f(1.0f, 1.0f); glVertex2f(w,h);
	glTexCoord2f(1.0f, 0.0f); glVertex2f(w,0);
	glEnd();
	glDisable(GL_TEXTURE_2D);
}	


__device__ unsigned char clip(const float val ) {
	// Set limits, range
	const float scale = 0.999f ;
	const float newval = val/scale;

	int n = 256 * newval ; 
	if (n==256) {n=256; }
	return n > 255 ? 255 : (n < 0 ? 0 : n); 
}

__global__ void float_to_char( uchar4* dev_out, const float* outSrc) {
	// map from threadIdx/BlockIdx to pixel position
	int k_x = threadIdx.x + blockIdx.x*blockDim.x ;
	int k_y = threadIdx.y + blockIdx.y*blockDim.y ;
	
	int offset = k_x + k_y*blockDim.x*gridDim.x ;

	dev_out[offset].x = 0;
	dev_out[offset].y = 0;
	dev_out[offset].z = 0;
	dev_out[offset].w = 255;
	


	float value = outSrc[offset];

	const unsigned char intensity = clip(value) ;

	dev_out[offset].x = intensity ; // higher mass density -> more red

	dev_out[offset].z = 255 - intensity ; // lower mass density -> more blue
	
}


__global__ void float_to_color3d( uchar4* optr, const float* outSrc) {
	// map from threadIdx/BlockIdx to pixel position
	int k_x = threadIdx.x + blockIdx.x*blockDim.x ;
	int k_y = threadIdx.y + blockIdx.y*blockDim.y ;

	// choose at which z coordinate to make the slice in x-y plane
	int zcoordslice = blockDim.z*gridDim.z/2*1; 

	int offset = k_x + k_y*blockDim.x*gridDim.x ;
	int fulloffset = offset + zcoordslice*blockDim.x*gridDim.x*blockDim.y*gridDim.y ;
	float value = outSrc[fulloffset];
	
	// Be aware of the "hard-coded" (numerical) constants for 
	// maximum and minimum scalar values that'll be assigned white and black, respectively
	if (value < 0.0001 ) { value = 0; }
	else if (value > 1.0 ) { value = 1.; } 

	// convert to long rainbow RGB* 
	value = value/0.20;
	int valueint  = ((int) floorf( value )); // this is the integer part 
	int valuefrac = ((int) floorf(255*(value-valueint)) );
	
	switch( valueint )
	{
		case 0:	optr[offset].x = 255; optr[offset].y = valuefrac; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 1:	optr[offset].x = 255-valuefrac; optr[offset].y = 255; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 2:	optr[offset].x = 0; optr[offset].y = 255; optr[offset].z = valuefrac; 
		optr[offset].w = 255; 
		break;
		case 3:	optr[offset].x = 0; optr[offset].y = 255-valuefrac; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 4:	optr[offset].x = valuefrac; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 5:	optr[offset].x = 255; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
	}
}





<|start_filename|>NavSt2DIncompFiniteDiff/physlib/dev_R2grid.h<|end_filename|>
/* dev_R2grid.h
 * R2 under discretization (discretize functor) to a (staggered) grid
 * <NAME>  <EMAIL>
 * 20161114
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/dev_R2grid.cu -o dev_R2grid.o
 * 
 */
#ifndef __DEV_R2GRID_H__
#define __DEV_R2GRID_H__

#include <thrust/device_vector.h>

#include "../commonlib/checkerror.h"  // checkCudaErrors

class Dev_Grid2d
{
	public:
		dim3 Ld;  // Ld.x,Ld.y = L_x, L_y or i.e. imax,jmax 
		dim3 staggered_Ld; // Ld[0]+2,Ld[1]+2 = L_x+2,L_y+2, or i.e. imax+2,jmax+2 

		// thrust::device_vector for pressure, and other scalar fields
		thrust::device_vector<float> p;
		thrust::device_vector<float> p_temp;
		thrust::device_vector<float> F;
		thrust::device_vector<float> G;
		thrust::device_vector<float> RHS;

		// thrust:device_vector for velocity
		thrust::device_vector<float> u;
		thrust::device_vector<float> v;

		float* p_arr ; 
		float* p_temp_arr ; 
		float* F_arr ; 
		float* G_arr ; 
		float* RHS_arr ; 
		float* u_arr ; 
		float* v_arr ; 
	

		// Constructor
		/* --------------------------------------------------------- */
		/* Sets the initial values for velocity u, p                 */
		/* --------------------------------------------------------- */
		__host__ Dev_Grid2d( dim3 );

		// destructor
		__host__ ~Dev_Grid2d();

		__host__ int NFLAT();
		
		// __host__ int staggered_SIZE() - returns the staggered grid size
		/* this would correspond to Griebel's notation of 
		 * (imax+1)*(jmax+1)
		 */
		__host__ int staggered_SIZE();
		
		__host__ int flatten(const int i_x, const int i_y ) ;

		__host__ int staggered_flatten(const int i_x, const int i_y ) ;

};




#endif // __DEV_R2GRID_H__


<|start_filename|>Euler2d/commonlib/finitediff.h<|end_filename|>
/* finitediff.h
 * finite difference methods on a grid
 * <NAME>  <EMAIL>
 * 20160710
 */
#ifndef __FINITEDIFF_H__
#define __FINITEDIFF_H__ 

#include "errors.h"

// I fixed the size of dev_c to be 4 because I don't anticipate that we'd need more accuracy 
extern __constant__ float2 dev_cnus[4]; // i = x,y; j = 1,2,3,4

// for the Laplacian and double derivatives
extern __constant__ float2 dev_cnus2[4]; // i = x,y; j = 1,2,3,4 

// for the divergence (and gradient)

void set1DerivativeParameters(const float hd_i[2] );

void set2DerivativeParameters(const float hd_i[2] );

void set3DerivativeParameters(const float hd_i[2] );

void set4DerivativeParameters(const float hd_i[2] );


__device__ float dev_dirder1(float stencil[1][2], float c_nus[4]);

__device__ float dev_dirder2(float stencil[2][2], float c_nus[4]);

__device__ float dev_dirder3(float stencil[3][2], float c_nus[4]);

__device__ float dev_dirder4(float stencil[4][2], float c_nus[4]);

// GRADIENT (GRAD) in 1,2,3,4 stencils, central difference

__device__ float2 dev_grad1( float2 stencil[1][2] ) ;

__device__ float2 dev_grad2( float2 stencil[2][2] ) ;

__device__ float2 dev_grad3( float2 stencil[3][2] ) ;

__device__ float2 dev_grad4( float2 stencil[4][2] ) ;


// DIVERGENCE (DIV) in 1, 2, 3, 4 stencils, central difference

__device__ float dev_div1( float2 stencil[1][2]  ) ;

__device__ float dev_div2( float2 stencil[2][2]  ) ; 

__device__ float dev_div3( float2 stencil[3][2]  ) ;

__device__ float dev_div4( float2 stencil[4][2]  ) ;

// For the Laplacian and double derivatives; central difference for order = 2 double derivatives

void set1dblDerivativeParameters(const float hd_i[2] );

void set2dblDerivativeParameters(const float hd_i[2] );

void set3dblDerivativeParameters(const float hd_i[2] );

void set4dblDerivativeParameters(const float hd_i[2] );

// For the Laplacian and double derivatives; order = 2 i.e. double derivatives

__device__ float dev_dirdblder1(float centerval, float stencil[1][2], float c_nus[4]);

__device__ float dev_dirdblder2(float centerval, float stencil[2][2], float c_nus[4]);

__device__ float dev_dirdblder3(float centerval, float stencil[3][2], float c_nus[4]);

__device__ float dev_dirdblder4(float centerval, float stencil[4][2], float c_nus[4]);

// LAPLACIAN (LAP) in 1, 2, 3, 4 stencils, central difference

__device__ float dev_lap1( float centerval, float2 stencil[1][2]  ) ;

__device__ float dev_lap2( float centerval, float2 stencil[2][2]  ) ; 

__device__ float dev_lap3( float centerval, float2 stencil[3][2]  ) ;

__device__ float dev_lap4( float centerval, float2 stencil[4][2]  ) ;


#endif // __FINITEDIFF_H__


<|start_filename|>MacCor1d/physlib/R1grid.cpp<|end_filename|>
/* R1grid.cpp
 * R1 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20161026
 * */
#include "R1grid.h"

Grid1d :: Grid1d(std::array<int,1> Ld_in, std::array<float,1> ld_in)
	: Ld(Ld_in), ld(ld_in)
{
	hd = { ld[0]/ Ld[0] }; 
	
	// Put in the desired physical objects that live on top of manifold here.
	// this has to be a pointer to a float or "old-school" float array 
	// in order to be cuda copied back to the host
	f = new float[ this->NFLAT() ];
}

std::array<float,1> Grid1d :: gridpt_to_space(std::array<int,1> index) {
	std::array<float,1> Xi { index[0]*hd[0] } ;
	return Xi;
}

int Grid1d :: NFLAT() {
	return Ld[0] ;
}

// destroy the physical quantities that sit on the R1 manifold
Grid1d::~Grid1d() {
	delete[] f ;
}



<|start_filename|>MacCor1d/physlib/dev_phys_param.cu<|end_filename|>
/* dev_phys_param.cu
 * physical parameters on the device
 * <NAME>  <EMAIL>
 * 20161027
 * */
#include "dev_phys_param.h"

__constant__ float dev_Deltat[1]; // Delta t



<|start_filename|>convect3dupwind/physlib/dev_R3grid.cu<|end_filename|>
/* dev_R3grid.cu
 * R3 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20160630
 */
#include "dev_R3grid.h"

__device__ dev_Grid3d :: dev_Grid3d(unsigned int N_x, unsigned int N_y, unsigned int N_z ) : N_is {N_x,N_y,N_z} 
{}


__device__ unsigned int dev_Grid3d :: flatten(
							unsigned int i_x, unsigned int i_y, unsigned int i_z) {
	return i_x+i_y*N_is[0]+i_z*N_is[0]*N_is[1];
}	
	


<|start_filename|>convect3dfinitedifftex/main.cu<|end_filename|>
/*
 * main.cu
 * 3-dimensional convection with time-independent velocty vector field using
 * CUDA C/C++ implementing finite difference
 * <NAME>  <EMAIL>
 * 20160723
*/
#include <functional>

#include "./commonlib/tex_anim2d.h"
#include "./commonlib/errors.h"
#include "./commonlib/finitediff.h"
#include "./commonlib/sharedmem.h"

#include "./physlib/convect.h"
#include "./physlib/R3grid.h"
#include "./physlib/dev_R3grid.h"

#include "math.h" // CUDA C/C++ math.h

#define GL_GLEXT_PROTOTYPES // needed for identifier glGenBuffer, glBindBuffer, glBufferData, glDeleteBuffers

#include <GL/glut.h>

#include <cuda_runtime.h>

#include <cuda_gl_interop.h>


const float Deltat[1] { 0.00001f } ; 

// physics
const int W { 680 } ;
const int H { 680 } ;
const int DEPTH { 320 } ;

dim3 dev_L3 { static_cast<unsigned int>(W), 
				static_cast<unsigned int>(H),
				static_cast<unsigned int>(DEPTH) };
				
dev_Grid3d dev_grid3d( dev_L3 );		


// graphics + physics

const dim3 M_i { 2, 2, 2 };

const int iters_per_render { 5 } ;


GPUAnim2dTex animtexmap( W, H );
GPUAnim2dTex* texptr = &animtexmap;


// struct DataBlock for recording, benchmarking events, iterations
struct DataBlock {
	cudaEvent_t  start, stop;
	float        totalTime;
	float        frames; 
};

DataBlock databenchmarks ; 



void make_render(int iters_per_render ) {
	uchar4* dev_out=0; 
	
	HANDLE_ERROR(
		cudaGraphicsMapResources(1, &(texptr->cuda_pixbufferObj_resource), 0 ) );
	
	HANDLE_ERROR(
		cudaGraphicsResourceGetMappedPointer((void **)&dev_out, NULL, 
			texptr->cuda_pixbufferObj_resource ) 
	);
	
	dim3 grids( (dev_L3.x+M_i.x-1)/M_i.x,(dev_L3.y+M_i.y-1)/M_i.y,(dev_L3.z+M_i.z-1)/M_i.z) ;
	
/*	
	constexpr int radius { 2 };
	const size_t smSz = (M_i.x + 2*radius)*(M_i.y + 2*radius)*(M_i.z+2*radius)*sizeof(float) ;
	*/
	
	cudaEventRecord( databenchmarks.start, 0 );
	
	for (int i = 0 ; i < iters_per_render; ++i ) {
		convect_fd_naive_sh<<<grids,M_i>>>(
			dev_grid3d.dev_rho, dev_grid3d.dev_u ); 

//		convect_sh<<<grids,M_i, smSz>>>( dev_grid3d.dev_rho, dev_grid3d.dev_u ) ;

//		float_to_color3d<<<grids,M_i>>>(dev_out, dev_grid3d.dev_rho ) ;


//		float_to_char<<<grids,M_i>>>(dev_out, dev_grid3d.dev_rho ) ;

	}
	//float_to_color3d<<<grids,M_i>>>(dev_out, dev_grid3d.dev_rho ) ;

	float_to_char<<<grids,M_i>>>(dev_out, dev_grid3d.dev_rho ) ;


	// Recording time for rough benchmarking, only
	cudaEventRecord( databenchmarks.stop, 0 );
	cudaEventSynchronize( databenchmarks.stop );

	float elapsedTime;
	cudaEventElapsedTime( &elapsedTime, databenchmarks.start, databenchmarks.stop );

	databenchmarks.totalTime += elapsedTime;
	++databenchmarks.frames;

//	printf("Iteration complete : ticks %d \n ", ticks );
	printf("Average Time per frame: %3.1f ms \n", databenchmarks.totalTime/databenchmarks.frames );
	// END of Recording time for rough benchmarking, only, END


	HANDLE_ERROR(
		cudaGraphicsUnmapResources( 1, &texptr->cuda_pixbufferObj_resource, 0 ));


	char title[128];
	sprintf(title, "mass density Visualizer - Iterations=%4d, ", iterationCount );
	
	glutSetWindowTitle(title);
}; 

std::function<void()> render = std::bind( make_render, iters_per_render ) ;



std::function<void()> draw_texture = std::bind( make_draw_texture, W,H) ;

void display() {
	render();
	draw_texture()   ;


	glutSwapBuffers();
}




int main(int argc, char** argv) {
	// physics
	constexpr float rho_0 { 0.956 };
	constexpr std::array<int,3> LdS { W, H, DEPTH} ; 
	constexpr std::array<float,3> ldS { 1.f, 1.f, 1.f };

	HANDLE_ERROR(
		cudaMemcpyToSymbol( dev_Deltat, Deltat, sizeof(float)*1,0,cudaMemcpyHostToDevice) );

	const int Ld_to_const[3] { LdS[0], LdS[1], LdS[2] };
	
	HANDLE_ERROR(
		cudaMemcpyToSymbol( dev_Ld, Ld_to_const, sizeof(int)*3,0,cudaMemcpyHostToDevice) );


	// set radius for shared memory "tiling", i.e. for the "halo" cells
	const int radius[1] { 2 };
	HANDLE_ERROR(
		cudaMemcpyToSymbol( sharedmem::RAD, radius, sizeof(int)*1,0,cudaMemcpyHostToDevice) );


	Grid3d grid3d( LdS, ldS);

	const float hds[3] { grid3d.hd[0], grid3d.hd[1], grid3d.hd[2] };

	set2DerivativeParameters(hds );

	// data benchmarking, cuda timing of events
	databenchmarks.totalTime = 0;
	databenchmarks.frames = 0 ;

	cudaEventCreate( &databenchmarks.start );
	cudaEventCreate( &databenchmarks.stop );
	


	// graphics setup
	
	texptr->initGLUT(&argc,argv) ;
	 
	glutKeyboardFunc( keyboard_func );
	glutMouseFunc( mouse_func );
	glutIdleFunc( idle );
	glutDisplayFunc( display) ;
	texptr->initPixelBuffer();
		

	// initial conditions

	for (int k=0; k<(grid3d.Ld[2]); ++k) {
		for (int j=0; j<(grid3d.Ld[1]); ++j) {
			for (int i=0;i<(grid3d.Ld[0]); ++i) {

				grid3d.u[ grid3d.flatten(i,j,k) ].x = 25.0;  // meters/second
				grid3d.u[ grid3d.flatten(i,j,k) ].y = 25.0;  // meters/second
				grid3d.u[ grid3d.flatten(i,j,k) ].z = 12.0;  // meters/second

			}
		}
	}

	std::array<int,3> ix_in { 0, 0, 0 };
	std::array<float,3> b_0 { 0.25f*grid3d.ld[0], 0.25f*grid3d.ld[1], 0.5f*grid3d.ld[2]  };
	
	for (int k=0; k<(grid3d.Ld[2]); ++k) {
		for (int j=0; j<(grid3d.Ld[1]); ++j) {
			for (int i=0; i<(grid3d.Ld[0]); ++i) {
				ix_in[0] = i;
				ix_in[1] = j;
				ix_in[2] = k;
				grid3d.rho[ grid3d.flatten(i,j,k) ] = 
						gaussian3d( rho_0, 0.05, b_0,grid3d.gridpt_to_space(ix_in));

			}
		}
	}


	HANDLE_ERROR(
		cudaMemcpy( dev_grid3d.dev_rho, grid3d.rho, grid3d.NFLAT()*sizeof(float), cudaMemcpyHostToDevice)
		);

	HANDLE_ERROR(
		cudaMemcpy( dev_grid3d.dev_u, grid3d.u, grid3d.NFLAT()*sizeof(float3), cudaMemcpyHostToDevice)
		);


	glutMainLoop();

	HANDLE_ERROR(
		cudaFree( dev_grid3d.dev_rho )  );

	HANDLE_ERROR(
		cudaFree( dev_grid3d.dev_u ) );
		
	texptr->exitfunc(); 
}
	


<|start_filename|>lid-driven-cavity_gpu-gfx/physlib/R2grid.h<|end_filename|>
/* R2grid.h
 * R2 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20160701
 */
#ifndef __R2GRID_H__
#define __R2GRID_H__

#include <array> // std::array
#include <cmath> // expf

class Grid2d
{
	public : 
		std::array<int,2> Ld;
		std::array<float,2> ld;
		std::array<float,2> hd;
		
		// arrays for pressure and velocity
		float* F;
		float* G;
		float* u;
		float* v;

		// arrays for pressure
		float* pres_red;
		float* pres_black;
		
		Grid2d(std::array<int,2> Ld_in, std::array<float,2> ld_in);
		
		std::array<float,2> gridpt_to_space(std::array<int,2> );
		
		int NFLAT();
		int staggered_NFLAT();
		
		int flatten(const int i_x, const int i_y ) ;
		int staggered_flatten(const int i_x, const int i_y);
	
	
		~Grid2d();	
};


#endif // __R2GRID_H__


<|start_filename|>Euler2d/physlib/convect.h<|end_filename|>
/* convect.h
 * 2-dim. Euler eq. (heat eq.) by finite difference with shared memory
 * <NAME>  <EMAIL>
 * 20160804
 */
#ifndef __CONVECT_H__
#define __CONVECT_H__

#include "../commonlib/finitediff.h"
#include "../commonlib/sharedmem.h" // __device__ int flatten
#include "dev_phys_param.h" // dev_Deltat, dev_phys_params
#include "dev_R2grid.h" // dev_Ld
 
// convect finite difference, for stencil of "size NU"
//__device__ float pressure(float, float, float2 );

__global__ void convect_fd( float* dev_rho, float2* dev_u ) ;

__global__ void convect_fd2( float* dev_rho, float2* dev_u ) ;

__global__ void convect_fd_sh( float* dev_rho, float2* dev_u ) ;


__global__ void Euler2dp1( float* dev_rho, float2* dev_p, float2* dev_u, float* dev_E ) ; 

__global__ void Euler2dp2( float* dev_rho, float2* dev_p, float2* dev_u, float* dev_E ) ; 

 
#endif // __CONVECT_H__


<|start_filename|>Euler2d/commonlib/sharedmem.h<|end_filename|>
/* sharedmem.h
 * shared shared memory routines
 * <NAME>  <EMAIL>
 * 20160804
 */
#ifndef __SHAREDMEM_H__
#define __SHAREDMEM_H__ 

int blocksNeeded( int N_i, int M_i); 

__device__ unsigned char clip(int n) ;  

__device__ int idxClip( int idx, int idxMax) ;

__device__ int flatten(int col, int row, int width, int height) ;

//__device__ float pressure( float energy, float rho, float2 u ) ;

__global__ void float_to_char( uchar4* dev_out, const float* outSrc) ;

#endif // __SHAREDMEM_H__


<|start_filename|>NavSt2DIncompFiniteDiff/Makefile<|end_filename|>
# <NAME>
# <EMAIL>
# 20161116
NVCC = nvcc
NVCC_FLAGS = -std=c++11

GPP = g++
GPP_FLAGS = -std=c++11

physobjects    = dev_R2grid.o R2grid.o boundary.o u_p.o

all: main.exe

main.exe: main.o $(physobjects) $(commonobjects) $(gfxobjects)
	$(NVCC) $(NVCC_FLAGS) $^ -o $@ $(GFX_FLAGS)
		
main.o: main.cu 
	$(NVCC) $(NVCC_FLAGS) -dc $< -o $@

	

# physics
dev_R2grid.o: ./physlib/dev_R2grid.cu
	$(NVCC) $(NVCC_FLAGS) -dc $< -o $@

R2grid.o: ./physlib/R2grid.cpp
#	$(GPP) $(GPP_FLAGS) -c $< -o $@  # I need float2 and so I had to use the nvcc compiler
	$(NVCC) -x cu $(NVCC_FLAGS) -dc $< -o $@  

boundary.o: ./physlib/boundary.cu  
# ./physlib/dev_R2grid.cu
	$(NVCC) $(NVCC_FLAGS) -dc $< -o $@

u_p.o: ./physlib/u_p.cu
	$(NVCC) $(NVCC_FLAGS) -dc $< -o $@

		
clean:
		rm -f *.o *.exe


<|start_filename|>NavSt2DIncompFiniteDiff/physlib/u_p.h<|end_filename|>
/* u_p.h
 * computation of u, p for 2-dim. incompressible Navier-Stokes equation with finite difference
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161209
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/u_p.cu -o u_p.o
 * 
 */
#ifndef __U_P_H__
#define __U_P_H__

#include <thrust/device_vector.h>

#include "../commonlib/checkerror.h"  // checkCudaErrors


/*------------------------------------------------------------------- */
/* Computation of tentative velocity field (F,G) -------------------- */
/*------------------------------------------------------------------- */

__global__ void compute_F(const float deltat, 
	const float* u, const float* v, float* F,
	const int imax, const int jmax, const float deltax, const float deltay,
	const float gamma, const float Re) ; 

__global__ void compute_G(const float deltat, 
	const float* u, const float* v, float* G,
	const int imax, const int jmax, const float deltax, const float deltay,
	const float gamma, const float Re) ;


////////////////////////////////////////////////////////////////////////
/* __host__ void copy_press_int( thrust::device_vector<float> p_all, 
	thrust::device_vector<float> & p_int,
	const int imax, const int jmax) ; 
void copy_press_int( const float* p_all, float* p_int,
	const int imax, const int jmax);

__global__ void sum_pressure( cudaSurfaceObject_t pSurfObj, 
	const int imax, const int jmax, float* pres_sum);
*/
/*------------------------------------------------------------------- */
/* Computation of the right hand side of the pressure equation ------ */
/*------------------------------------------------------------------- */


__global__ void compute_RHS( const float* F, const float* G, 
	float* RHS, 
	const int imax, const int jmax, 
	const float deltat, const float deltax, const float deltay);

/*------------------------------------------------------------------- */
/* SOR iteration for the Poisson equation for the pressure
/*------------------------------------------------------------------- */

__global__ void poisson( const float* p, const float* RHS, 
	float* p_temp, 
	const int imax, const int jmax,
	const float deltax, const float deltay, 
	const float omega) ;



__global__ void poisson_redblack( float* p, const float* RHS, 
	const int imax, const int jmax,
	const float deltax, const float deltay, 
	const float omega) ;

/*------------------------------------------------------------------- */
/* computation of residual */
/*------------------------------------------------------------------- */

__global__ void compute_residual( const float* p, const float* RHS, 
	const int imax, const int jmax,
	const float deltax, const float deltay, 
	float* residualsq_Array) ;

/* cannot do this:
	thrust::device_vector<float> & residualsq);
	* cf. http://stackoverflow.com/questions/5510715/thrust-inside-user-written-kernels
	* */
	
	
/*------------------------------------------------------------------- */
/* computation of new velocity values */
/*------------------------------------------------------------------- */

__global__ void calculate_u( float* u, const float* p, const float* F, 
	const int imax, const int jmax, const float deltat, const float deltax ) ;


__global__ void calculate_v( float* v, const float* p, const float* G, 
	const int imax, const int jmax, const float deltat, const float deltay ) ;

/* --------------------------------------------------------- */
/* Routines to assist in the 								 */		
/* Computation of adaptive time stepsize satisfying  		 */
/* the CFL stability criteria								 */
/* and set the flag "write" if some data has to be written   */
/* into a file.												 */
/* --------------------------------------------------------- */

/*
void calculate_max_uv( thrust::device_vector<float> & max_u_vec, thrust::device_vector<float> & max_v_vec, 
	const thrust::device_vector<float> u_vec, const thrust::device_vector<float> v_vec ); 
*/


#endif // __U_P_H__


<|start_filename|>convect2dfinitedifftex/commonlib/sharedmem.cu<|end_filename|>
/* sharedmem.cu
 * shared memory to a 1-dim. grid
 * <NAME>  <EMAIL>
 * 20160710
 */
#include "sharedmem.h"

#include "errors.h" // HANDLE_ERROR()


namespace sharedmem {

__constant__ int RAD[1] ; 
	
__device__ int idxClip( int idx, int idxMax) {
			return idx > (idxMax - 1) ? (idxMax - 1) : (idx < 0 ? 0 : idx);
}
		
__device__ int flatten(int k_x, int k_y, int k_z, int L_x, int L_y, int L_z) {
	return idxClip( k_x, L_x) + idxClip( k_y,L_y)*L_x + idxClip(k_z, L_z)*L_x*L_y ;
}	
	
__device__ void sh_dev_div1( float* dev_rho, float3* dev_u, float &result ) {
	extern __shared__ float sh_rho[ ];
	extern __shared__ float3 sh_u[ ];

	// global indices
	const int k_x = threadIdx.x + blockIdx.x * blockDim.x; 
	const int k_y = threadIdx.y + blockIdx.y * blockDim.y; 
	const int k_z = threadIdx.z + blockIdx.z * blockDim.z; 
	
	// EY : 20160718 check this; I want nothing to be done, but I return 0.f	
	if (k_x >= dev_Ld[0] || k_y >= dev_Ld[1] || k_z >= dev_Ld[2] ) { return ;  }

	const int k = flatten( k_x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2]);

	constexpr int NUS = 1;

	// local S
	const int3 S { static_cast<int>(blockDim.x + 2*RAD[0]) , 
					static_cast<int>(blockDim.y + 2*RAD[0]) , 
					static_cast<int>(blockDim.z + 2*RAD[0]) } ;

	// local s_i
	const int s_x = threadIdx.x + RAD[0];
	const int s_y = threadIdx.y + RAD[0];
	const int s_z = threadIdx.z + RAD[0];

	const int s_k = flatten( s_x,s_y,s_z, S.x, S.y, S.z );

	// Load regular cells
	sh_rho[s_k] = dev_rho[k];
	sh_u[s_k]   = dev_u[k];
	
	// Load halo cells
	if (threadIdx.x < RAD[0]) {
		sh_rho[ flatten( s_x -RAD[0],s_y,s_z,S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x-RAD[0],k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x -RAD[0],s_y,s_z,S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x-RAD[0],k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x+blockDim.x,s_y,s_z,S.x,S.y,S.z)] = 
			dev_rho[flatten(k_x+blockDim.x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x+blockDim.x,s_y,s_z,S.x,S.y,S.z)]   = 
			dev_u[flatten(k_x+blockDim.x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}
	
	if (threadIdx.y < RAD[0]) {
		sh_rho[ flatten( s_x,s_y-RAD[0],s_z,S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x,k_y-RAD[0],k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x ,s_y-RAD[0],s_z,S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x,k_y-RAD[0],k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x,s_y+blockDim.y,s_z,S.x,S.y,S.z)] 
				= dev_rho[flatten(k_x,k_y+blockDim.y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x,s_y+blockDim.y,s_z,S.x,S.y,S.z)]   = 
				dev_u[flatten(k_x,k_y+blockDim.y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}

	if (threadIdx.z < RAD[0]) {
		sh_rho[ flatten( s_x ,s_y,s_z-RAD[0],S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x,k_y,k_z-RAD[0],dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x,s_y,s_z-RAD[0],S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x,k_y,k_z-RAD[0],dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x,s_y,s_z+blockDim.z,S.x,S.y,S.z)] = 
			dev_rho[flatten(k_x,k_y,k_z+blockDim.z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x,s_y,s_z+blockDim.z,S.x,S.y,S.z)]   = 
			dev_u[flatten(k_x,k_y,k_z+blockDim.z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}

	__syncthreads();

//	__shared__ float3 stencil[NUS][2];

	float3 stencil[NUS][2];
		
	
	for (int nu = 0; nu < NUS; ++nu ) {
		stencil[nu][0].x = sh_rho[flatten(s_x-(nu+1),s_y,s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x-(nu+1),s_y,s_z,S.x,S.y,S.z)].x;
		stencil[nu][1].x = sh_rho[flatten(s_x+(nu+1),s_y,s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x+(nu+1),s_y,s_z,S.x,S.y,S.z)].x;
		stencil[nu][0].y = sh_rho[flatten(s_x,s_y-(nu+1),s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y-(nu+1),s_z,S.x,S.y,S.z)].y;
		stencil[nu][1].y = sh_rho[flatten(s_x,s_y+(nu+1),s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y+(nu+1),s_z,S.x,S.y,S.z)].y;
		stencil[nu][0].z = sh_rho[flatten(s_x,s_y,s_z-(nu+1),S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y,s_z-(nu+1),S.x,S.y,S.z)].z;
		stencil[nu][1].z = sh_rho[flatten(s_x,s_y,s_z+(nu+1),S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y,s_z+(nu+1),S.x,S.y,S.z)].z;
	}
	float div_value { dev_div1( stencil ) };
	
//	return div_value;
	result = div_value;
}

	
__device__ float sh_dev_div2( float* dev_rho, float3* dev_u ) {
	extern __shared__ float sh_rho[ ];
	extern __shared__ float3 sh_u[ ];

	// global indices
	const int k_x = threadIdx.x + blockIdx.x * blockDim.x; 
	const int k_y = threadIdx.y + blockIdx.y * blockDim.y; 
	const int k_z = threadIdx.z + blockIdx.z * blockDim.z; 
	
	// EY : 20160718 check this; I want nothing to be done, but I return 0.f	
	if (k_x >= dev_Ld[0] || k_y >= dev_Ld[1] || k_z >= dev_Ld[2] ) { return 0.f;  }

	const int k = flatten( k_x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2]);


	constexpr int NUS = 2;


	// local S
	const int3 S { static_cast<int>(blockDim.x + 2*RAD[0]) , 
					static_cast<int>(blockDim.y + 2*RAD[0]) , 
					static_cast<int>(blockDim.z + 2*RAD[0]) } ;

	// local s_i
	const int s_x = threadIdx.x + RAD[0];
	const int s_y = threadIdx.y + RAD[0];
	const int s_z = threadIdx.z + RAD[0];

	const int s_k = flatten( s_x,s_y,s_z, S.x, S.y, S.z );

	// Load regular cells
	sh_rho[s_k] = dev_rho[k];
	sh_u[s_k]   = dev_u[k];
	
	// Load halo cells
	if (threadIdx.x < RAD[0]) {
		sh_rho[ flatten( s_x -RAD[0],s_y,s_z,S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x-RAD[0],k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x -RAD[0],s_y,s_z,S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x-RAD[0],k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x+blockDim.x,s_y,s_z,S.x,S.y,S.z)] = 
			dev_rho[flatten(k_x+blockDim.x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x+blockDim.x,s_y,s_z,S.x,S.y,S.z)]   = 
			dev_u[flatten(k_x+blockDim.x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}
	
	if (threadIdx.y < RAD[0]) {
		sh_rho[ flatten( s_x,s_y-RAD[0],s_z,S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x,k_y-RAD[0],k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x ,s_y-RAD[0],s_z,S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x,k_y-RAD[0],k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x,s_y+blockDim.y,s_z,S.x,S.y,S.z)] 
				= dev_rho[flatten(k_x,k_y+blockDim.y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x,s_y+blockDim.y,s_z,S.x,S.y,S.z)]   = 
				dev_u[flatten(k_x,k_y+blockDim.y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}

	if (threadIdx.z < RAD[0]) {
		sh_rho[ flatten( s_x ,s_y,s_z-RAD[0],S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x,k_y,k_z-RAD[0],dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x,s_y,s_z-RAD[0],S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x,k_y,k_z-RAD[0],dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x,s_y,s_z+blockDim.z,S.x,S.y,S.z)] = 
			dev_rho[flatten(k_x,k_y,k_z+blockDim.z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x,s_y,s_z+blockDim.z,S.x,S.y,S.z)]   = 
			dev_u[flatten(k_x,k_y,k_z+blockDim.z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}

	__syncthreads();

	//__shared__ float3 stencil[NUS][2];
	float3 stencil[NUS][2];
	
	
	for (int nu = 0; nu < NUS; ++nu ) {
		stencil[nu][0].x = sh_rho[flatten(s_x-(nu+1),s_y,s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x-(nu+1),s_y,s_z,S.x,S.y,S.z)].x;
		stencil[nu][1].x = sh_rho[flatten(s_x+(nu+1),s_y,s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x+(nu+1),s_y,s_z,S.x,S.y,S.z)].x;
		stencil[nu][0].y = sh_rho[flatten(s_x,s_y-(nu+1),s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y-(nu+1),s_z,S.x,S.y,S.z)].y;
		stencil[nu][1].y = sh_rho[flatten(s_x,s_y+(nu+1),s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y+(nu+1),s_z,S.x,S.y,S.z)].y;
		stencil[nu][0].z = sh_rho[flatten(s_x,s_y,s_z-(nu+1),S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y,s_z-(nu+1),S.x,S.y,S.z)].z;
		stencil[nu][1].z = sh_rho[flatten(s_x,s_y,s_z+(nu+1),S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y,s_z+(nu+1),S.x,S.y,S.z)].z;
	}
	
	
	float div_value { dev_div2( stencil ) };
	
		
	return div_value;
}	
	
__device__ float sh_dev_div3( float* dev_rho, float3* dev_u ) {
	extern __shared__ float sh_rho[ ];
	extern __shared__ float3 sh_u[ ];

	// global indices
	const int k_x = threadIdx.x + blockIdx.x * blockDim.x; 
	const int k_y = threadIdx.y + blockIdx.y * blockDim.y; 
	const int k_z = threadIdx.z + blockIdx.z * blockDim.z; 
	
	// EY : 20160718 check this; I want nothing to be done, but I return 0.f	
	if (k_x >= dev_Ld[0] || k_y >= dev_Ld[1] || k_z >= dev_Ld[2] ) { return 0.f;  }

	const int k = flatten( k_x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2]);


	constexpr int NUS = 3;


	// local S
	const int3 S { static_cast<int>(blockDim.x + 2*RAD[0]) , 
					static_cast<int>(blockDim.y + 2*RAD[0]) , 
					static_cast<int>(blockDim.z + 2*RAD[0]) } ;

	// local s_i
	const int s_x = threadIdx.x + RAD[0];
	const int s_y = threadIdx.y + RAD[0];
	const int s_z = threadIdx.z + RAD[0];

	const int s_k = flatten( s_x,s_y,s_z, S.x, S.y, S.z );

	// Load regular cells
	sh_rho[s_k] = dev_rho[k];
	sh_u[s_k]   = dev_u[k];
	
	// Load halo cells
	if (threadIdx.x < RAD[0]) {
		sh_rho[ flatten( s_x -RAD[0],s_y,s_z,S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x-RAD[0],k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x -RAD[0],s_y,s_z,S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x-RAD[0],k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x+blockDim.x,s_y,s_z,S.x,S.y,S.z)] = 
			dev_rho[flatten(k_x+blockDim.x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x+blockDim.x,s_y,s_z,S.x,S.y,S.z)]   = 
			dev_u[flatten(k_x+blockDim.x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}
	
	if (threadIdx.y < RAD[0]) {
		sh_rho[ flatten( s_x,s_y-RAD[0],s_z,S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x,k_y-RAD[0],k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x ,s_y-RAD[0],s_z,S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x,k_y-RAD[0],k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x,s_y+blockDim.y,s_z,S.x,S.y,S.z)] 
				= dev_rho[flatten(k_x,k_y+blockDim.y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x,s_y+blockDim.y,s_z,S.x,S.y,S.z)]   = 
				dev_u[flatten(k_x,k_y+blockDim.y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}

	if (threadIdx.z < RAD[0]) {
		sh_rho[ flatten( s_x ,s_y,s_z-RAD[0],S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x,k_y,k_z-RAD[0],dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x,s_y,s_z-RAD[0],S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x,k_y,k_z-RAD[0],dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x,s_y,s_z+blockDim.z,S.x,S.y,S.z)] = 
			dev_rho[flatten(k_x,k_y,k_z+blockDim.z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x,s_y,s_z+blockDim.z,S.x,S.y,S.z)]   = 
			dev_u[flatten(k_x,k_y,k_z+blockDim.z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}

	__syncthreads();

//	__shared__ float3 stencil[NUS][2];
	float3 stencil[NUS][2];
	
	
	for (int nu = 0; nu < NUS; ++nu ) {
		stencil[nu][0].x = sh_rho[flatten(s_x-(nu+1),s_y,s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x-(nu+1),s_y,s_z,S.x,S.y,S.z)].x;
		stencil[nu][1].x = sh_rho[flatten(s_x+(nu+1),s_y,s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x+(nu+1),s_y,s_z,S.x,S.y,S.z)].x;
		stencil[nu][0].y = sh_rho[flatten(s_x,s_y-(nu+1),s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y-(nu+1),s_z,S.x,S.y,S.z)].y;
		stencil[nu][1].y = sh_rho[flatten(s_x,s_y+(nu+1),s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y+(nu+1),s_z,S.x,S.y,S.z)].y;
		stencil[nu][0].z = sh_rho[flatten(s_x,s_y,s_z-(nu+1),S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y,s_z-(nu+1),S.x,S.y,S.z)].z;
		stencil[nu][1].z = sh_rho[flatten(s_x,s_y,s_z+(nu+1),S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y,s_z+(nu+1),S.x,S.y,S.z)].z;
	}
	
	
	float div_value { dev_div3( stencil ) };
	
		
	return div_value;
}	

__device__ float sh_dev_div4( float* dev_rho, float3* dev_u ) {
	extern __shared__ float sh_rho[ ];
	extern __shared__ float3 sh_u[ ];

	// global indices
	const int k_x = threadIdx.x + blockIdx.x * blockDim.x; 
	const int k_y = threadIdx.y + blockIdx.y * blockDim.y; 
	const int k_z = threadIdx.z + blockIdx.z * blockDim.z; 
	
	// EY : 20160718 check this; I want nothing to be done, but I return 0.f	
	if (k_x >= dev_Ld[0] || k_y >= dev_Ld[1] || k_z >= dev_Ld[2] ) { return 0.f;  }

	const int k = flatten( k_x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2]);


	constexpr int NUS = 4;


	// local S
	const int3 S { static_cast<int>(blockDim.x + 2*RAD[0]) , 
					static_cast<int>(blockDim.y + 2*RAD[0]) , 
					static_cast<int>(blockDim.z + 2*RAD[0]) } ;

	// local s_i
	const int s_x = threadIdx.x + RAD[0];
	const int s_y = threadIdx.y + RAD[0];
	const int s_z = threadIdx.z + RAD[0];

	const int s_k = flatten( s_x,s_y,s_z, S.x, S.y, S.z );

	// Load regular cells
	sh_rho[s_k] = dev_rho[k];
	sh_u[s_k]   = dev_u[k];
	
	// Load halo cells
	if (threadIdx.x < RAD[0]) {
		sh_rho[ flatten( s_x -RAD[0],s_y,s_z,S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x-RAD[0],k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x -RAD[0],s_y,s_z,S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x-RAD[0],k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x+blockDim.x,s_y,s_z,S.x,S.y,S.z)] = 
			dev_rho[flatten(k_x+blockDim.x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x+blockDim.x,s_y,s_z,S.x,S.y,S.z)]   = 
			dev_u[flatten(k_x+blockDim.x,k_y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}
	
	if (threadIdx.y < RAD[0]) {
		sh_rho[ flatten( s_x,s_y-RAD[0],s_z,S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x,k_y-RAD[0],k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x ,s_y-RAD[0],s_z,S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x,k_y-RAD[0],k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x,s_y+blockDim.y,s_z,S.x,S.y,S.z)] 
				= dev_rho[flatten(k_x,k_y+blockDim.y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x,s_y+blockDim.y,s_z,S.x,S.y,S.z)]   = 
				dev_u[flatten(k_x,k_y+blockDim.y,k_z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}

	if (threadIdx.z < RAD[0]) {
		sh_rho[ flatten( s_x ,s_y,s_z-RAD[0],S.x,S.y,S.z)] = 
			dev_rho[ flatten(k_x,k_y,k_z-RAD[0],dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		sh_u[ flatten( s_x,s_y,s_z-RAD[0],S.x,S.y,S.z)] = 
			dev_u[ flatten(k_x,k_y,k_z-RAD[0],dev_Ld[0],dev_Ld[1],dev_Ld[2])] ;
		
		sh_rho[flatten(s_x,s_y,s_z+blockDim.z,S.x,S.y,S.z)] = 
			dev_rho[flatten(k_x,k_y,k_z+blockDim.z,dev_Ld[0],dev_Ld[1],dev_Ld[2])];
		sh_u[flatten(s_x,s_y,s_z+blockDim.z,S.x,S.y,S.z)]   = 
			dev_u[flatten(k_x,k_y,k_z+blockDim.z,dev_Ld[0],dev_Ld[1],dev_Ld[2])]  ;
	}

	__syncthreads();

//	__shared__ float3 stencil[NUS][2];
	float3 stencil[NUS][2];
		
	for (int nu = 0; nu < NUS; ++nu ) {
		stencil[nu][0].x = sh_rho[flatten(s_x-(nu+1),s_y,s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x-(nu+1),s_y,s_z,S.x,S.y,S.z)].x;
		stencil[nu][1].x = sh_rho[flatten(s_x+(nu+1),s_y,s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x+(nu+1),s_y,s_z,S.x,S.y,S.z)].x;
		stencil[nu][0].y = sh_rho[flatten(s_x,s_y-(nu+1),s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y-(nu+1),s_z,S.x,S.y,S.z)].y;
		stencil[nu][1].y = sh_rho[flatten(s_x,s_y+(nu+1),s_z,S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y+(nu+1),s_z,S.x,S.y,S.z)].y;
		stencil[nu][0].z = sh_rho[flatten(s_x,s_y,s_z-(nu+1),S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y,s_z-(nu+1),S.x,S.y,S.z)].z;
		stencil[nu][1].z = sh_rho[flatten(s_x,s_y,s_z+(nu+1),S.x,S.y,S.z)]*
							sh_u[flatten(s_x,s_y,s_z+(nu+1),S.x,S.y,S.z)].z;
	}
	
	
	float div_value { dev_div4( stencil ) };
	
		
	return div_value;
}	
	
	

}


<|start_filename|>convect1dupwind/commonlib/gpu_anim.h<|end_filename|>
/* cf. <NAME>, <NAME>. CUDA by Example: An Introduction to General-Purpose GPU Programming  
 * Chapter 8 Graphics Interoperability 
 * 8.3 GPU Ripple with Graphics Interoperability
 */
#ifndef __GPU_ANIM_H__
#define __GPU_ANIM_H__

#define GL_GLEXT_PROTOTYPES // needed for identifier glGenBuffer, glBindBuffer, glBufferData, glDeleteBuffers

#include <GL/glut.h> // GLuint
// #include <GL/glext.h>
// #include <GL/glx.h>
#include "cuda.h"
#include "cuda_gl_interop.h"
#include "errors.h"
#include <iostream>


struct GPUAnimBitmap {
	GLuint bufferObj;
	cudaGraphicsResource *resource;
	int  width, height;
	
	void *dataBlock;
	
	void (*fAnim)(uchar4*,void*,int);
	void (*animExit)(void*);
	void (*clickDrag)(void*,int,int,int,int);
	int  dragStartX, dragStartY;
	
	GPUAnimBitmap( int w, int h, void *d = NULL) {
		width     = w;
		height    = h;
		dataBlock = d;
		clickDrag = NULL;
	
		// first, find a CUDA device and set it to graphic interoperability
		cudaDeviceProp prop;
		int dev;
		memset( &prop, 0, sizeof( cudaDeviceProp ));
		prop.major = 2;
		prop.minor = 1;
		HANDLE_ERROR(
			cudaChooseDevice( &dev, &prop ));
		cudaGLSetGLDevice( dev );
	
		// trick GLUT into thinking we're passing an argument; hence soo and foo
		int soo = 1;
		char *foo = '\0';
		glutInit( &soo, &foo );
		glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
		glutInitWindowSize( width, height );
		glutCreateWindow( "bitmap" ); // to draw our results; "bitmap" name is arbitrary
	
		// create pixel buffer object in OpenGL, store in our global variable GLuint bufferObj
		glGenBuffers(1, &bufferObj);
		glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj );
		glBufferData( GL_PIXEL_UNPACK_BUFFER_ARB, width * height * 4, 
					  NULL, GL_DYNAMIC_DRAW_ARB );
		HANDLE_ERROR(
			cudaGraphicsGLRegisterBuffer( &resource, bufferObj, cudaGraphicsMapFlagsNone ) );
	}
	
	~GPUAnimBitmap() {
		free_resources();
	}
	
	void free_resources( void ) {
	// clean up OpenGL and CUDA
		HANDLE_ERROR(
			cudaGraphicsUnregisterResource( resource )) ;
		glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0 );
		glDeleteBuffers( 1, &bufferObj );
	//			exit(0) ;
	}
	
	long image_size( void ) const { return width * height * 4 ; }
	
	static GPUAnimBitmap** get_bitmap_ptr( void ) {
		static GPUAnimBitmap* gBitmap;
		return &gBitmap;
	}
	
	// static method used for GLUT callbacks
	// maps shared buffer and retrieves a GPU pointer for this buffer
	static void idle_func( void ) {
		static int ticks = 1;
		GPUAnimBitmap* bitmap = *(get_bitmap_ptr() );
		uchar4*        devPtr;
		size_t size;
		
		HANDLE_ERROR(
			cudaGraphicsMapResources( 1, &(bitmap->resource), NULL) );
		HANDLE_ERROR(
			cudaGraphicsResourceGetMappedPointer( (void**)&devPtr, &size, bitmap->resource) );
			
		// fAnim() will launch CUDA C kernel to fill buffer at devPtr with image data.
		bitmap->fAnim( devPtr, bitmap->dataBlock, ticks++);
		
		// unmap GPU pointer that'll release buffer for use by OpenGL driver in rendering
		// this rendering is triggered by glutPostRedisplay() call
		HANDLE_ERROR(
			cudaGraphicsUnmapResources( 1, &(bitmap->resource), NULL ));
		glutPostRedisplay();
	};

	void anim_and_exit( void (*f)(uchar4*,void*,int), void(*e)(void*) ) {
		GPUAnimBitmap** bitmap = get_bitmap_ptr();
		*bitmap = this;
		fAnim = f;
		animExit = e;
		
		glutKeyboardFunc( key_func );
		glutDisplayFunc( draw_func );
		if (clickDrag != NULL )
			glutMouseFunc( mouse_func );
		glutIdleFunc( idle_func);
		glutMainLoop();
	}
	
	
	static void draw_func(void) {
		GPUAnimBitmap* bitmap = *(get_bitmap_ptr());
		glClearColor( 0.0, 0.0, 0.0, 1.0 );
		glClear( GL_COLOR_BUFFER_BIT );
		glDrawPixels( bitmap->width, bitmap->height, 
					  GL_RGBA, GL_UNSIGNED_BYTE, 0 );
		glutSwapBuffers();
	}
	
	static void key_func( unsigned char key, int x, int y) {
		switch (key) {
			case 27:
				GPUAnimBitmap* bitmap = *(get_bitmap_ptr() );
				if (bitmap->animExit)
					bitmap->animExit( bitmap->dataBlock );
				bitmap->free_resources();
				exit(0);
		}
	}
	
	void click_drag( void (*f)(void*,int,int,int,int)) {
		clickDrag = f;
	}
	
	static void mouse_func( int button, int state,
							int mx, int my) {
		if (button == GLUT_LEFT_BUTTON) {
			GPUAnimBitmap* bitmap = *(get_bitmap_ptr() );
			if (state == GLUT_DOWN) {
				bitmap->dragStartX = mx;
				bitmap->dragStartY = my;
			} else if (state == GLUT_UP) {
				bitmap->clickDrag(  bitmap->dataBlock,
									bitmap->dragStartX,
									bitmap->dragStartY,
									mx, my );
			}
		}
	}
};

#endif // __GPU_ANIM_H__


<|start_filename|>NavSt2DIncompFiniteDiff/main_draft01.cu<|end_filename|>
/* main.cu
 * \file main.cu
 * Navier-Stokes equation solver in 2-dimensions, incompressible flow, by finite difference
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161206
 * 
 * Compilation tips if you're not using a make file
 * 
 * nvcc -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o  // or 
 * g++ -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o
 * 
 * nvcc -std=c++11 -c ./physlib/dev_R2grid.cu -o dev_R2grid.o
 * nvcc -std=c++11 -c ./commonlib/surfObj2d.cu -o surfObj2d.o
 * nvcc -std=c++11 main.cu R2grid.o dev_R2grid.o surfObj2d.o -o main.exe
 * 
 */
/*
 * cf. <NAME>, <NAME>.  
 * Accelerating reactive-flow simulations using graphics processing units.  
 * AIAA 2013-0371  American Institute of Aeronautics and Astronautics.  
 * http://dx.doi.org/10.5281/zenodo.44333
 * 
 * <NAME>, <NAME>, <NAME>. 
 * Numerical Simulation in Fluid Dynamics: A Practical Introduction (Monographs on Mathematical Modeling and Computation). 
 * SIAM: Society for Industrial and Applied Mathematics (December 1997). 
 * ISBN-13:978-0898713985 QA911.G718 1997
 * 
 * */ 
 
#include <iostream> 				// std::cout
#include <cmath>    				// std::sqrt, std::fmax 

#include "./physlib/R2grid.h"      	// Grid2d
#include "./physlib/dev_R2grid.h"  	// Dev_Grid2d
#include "./physlib/boundary.h"     // set_BConditions_host, set_BConditions, set_lidcavity_BConditions_host, set_lidcavity_BConditions
#include "./commonlib/checkerror.h" // checkCudaErrors

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/reduce.h>
#include <thrust/extrema.h>  // thrust::max_element (thrust::min_element)  


int main(int argc, char* argv[]) {
	// ################################################################
	// ####################### Initialization #########################
	// ################################################################
	
	// discretization (parameters) <==> graphical (parameters)
	const int L_X { 64 };  			// WIDTH   // I've tried values 32
	const int L_Y { 64 };  			// HEIGHT  // I've tried values 32

	// "real", physical parameters
	/** try domain size (non-dimensional) */
	constexpr const float l_X = 1.0;  	// length (in x-direction)
	constexpr const float l_Y = 1.0; 	// height (in y-direction)

	// physics (on device); Euclidean (spatial) space
	dim3 dev_L2 { static_cast<unsigned int>(L_X), 
				static_cast<unsigned int>(L_Y) };

	Dev_Grid2d dev_grid2d( dev_L2); 

	// physics (on host); Euclidean (spatial) space
	constexpr std::array<int,2> LdS { L_X, L_Y } ;
	constexpr std::array<float,2> ldS { l_X, l_Y };

	Grid2d grid2d{LdS, ldS};

	// dynamics (parameters)
	const dim3 M_i { 16, 16 }; 	// number of threads per block, i.e. Niemeyer's BLOCK_SIZE // I've tried values 4,4

	float t = 0.0 ;
	int cycle = 0;
	
	// iterations for SOR successive over relaxation
	int iter = 0;
	int itermax = 10000;  // I tried values such as 10000, 100

	/* READ the parameters of the problem                 */
	/* -------------------------------------------------- */ 

	/** Safety factor for time step modification; safety factor for time stepsize control */
	constexpr const float tau = 0.5; 

	/** SOR relaxation parameter; omg is Griebel's notation */
	constexpr const float omega = 1.7;  
	
	/** Discretization mixture parameter (gamma); gamma:upwind differencing factor is Griebel's notation */
	constexpr const float gamma = 0.9;

	/** Reynolds number */
	constexpr const float Re_num = 1000.0;

	// SOR iteration tolerance
	const float tol = 0.001;  // Griebel, et. al., and Niemeyer has this at 0.001
	
	// time range
	const float time_start = 0.0;
	const float time_end = 0.01;
	
	// initial time step size
	float deltat = 0.002; // I've tried values 0.002
	
	// set initial BCs on host CPU
	set_BConditions_host( grid2d );
	set_lidcavity_BConditions_host( grid2d );

	set_BConditions( dev_grid2d );
	set_lidcavity_BConditions( dev_grid2d );

	/* delt satisfying CFL conditions */
	/* ------------------------------ */
	float max_u = 1.0e-10;
	float max_v = 1.0e-10;

	thrust::device_vector<float>::iterator max_u_iter = 
		thrust::max_element( dev_grid2d.u.begin(), dev_grid2d.u.end() );
	max_u = std::fmax( *max_u_iter, max_u ) ;

	thrust::device_vector<float>::iterator max_v_iter = 
		thrust::max_element( dev_grid2d.v.begin(), dev_grid2d.v.end() );
	max_v = std::fmax( *max_v_iter, max_v ) ;
	

	////////////////////////////////////////	
	// block and grid dimensions
	// "default" blockSize is number of blocks on a grid along a dimension
	dim3 blockSize ( (grid2d.staggered_Ld[0] + M_i.x -1)/M_i.x, 
						(grid2d.staggered_Ld[1] + M_i.y - 1)/M_i.y) ;
	////////////////////////////////////////

	// residual variable
	// residualsquared thrust device vector
	thrust::device_vector<float> residualsq(grid2d.staggered_SIZE() );
	float* residualsq_Array = thrust::raw_pointer_cast( residualsq.data() );

	// pressure sum 
	/* Note that the pressure summation needed to normalize to the pressure magnitude for 
	 * relative tolerance is, in Griebel, et. al's implementation, the first part of the 
	 * POISSON routine, and used at the very end of POISSON, here in the GPU implementation
	 * it's separated */ 
	thrust::device_vector<float> pres_sum_vec(grid2d.staggered_SIZE());
	float* pres_sum_Arr = thrust::raw_pointer_cast( pres_sum_vec.data() );
	
	// sanity check
	std::cout << " residualsq.size() : " << residualsq.size() << std::endl;
	std::cout << " pres_sum_vec.size() : " << pres_sum_vec.size() << std::endl;
	
	

	// time-step size based on grid and Reynolds number
	float dt_Re = 0.5 * Re_num / ((1.0 / (grid2d.hd[0] * grid2d.hd[0])) + (1.0 / (grid2d.hd[1] * grid2d.hd[1])));
	
				/* t i m e    l o o p */
				/* ------------------ */
	// time iteration loop
	for (t=time_start,cycle=0; t < time_end; cycle++) {

		// calculate time step based on stability and CFL
		deltat = std::fmin( (grid2d.hd[0] / max_u), ( grid2d.hd[1]/ max_v) );
		deltat = tau * std::fmin( dt_Re, deltat);
	
		if ((t+deltat) >= time_end) {
			deltat = time_end - t; }
	

		t += deltat;

	}


	
	std::cout << " End of program " << std::endl;
	return 0;
} 



<|start_filename|>NavSt2DIncompFiniteDiff/main_draft00.cu<|end_filename|>
/* main.cu
 * \file main.cu
 * Navier-Stokes equation solver in 2-dimensions, incompressible flow, by finite difference
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161206
 * 
 * Compilation tips if you're not using a make file
 * 
 * nvcc -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o  // or 
 * g++ -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o
 * 
 * nvcc -std=c++11 -c ./physlib/dev_R2grid.cu -o dev_R2grid.o
 * nvcc -std=c++11 -c ./commonlib/surfObj2d.cu -o surfObj2d.o
 * nvcc -std=c++11 main.cu R2grid.o dev_R2grid.o surfObj2d.o -o main.exe
 * 
 */
/*
 * cf. <NAME>, <NAME>.  
 * Accelerating reactive-flow simulations using graphics processing units.  
 * AIAA 2013-0371  American Institute of Aeronautics and Astronautics.  
 * http://dx.doi.org/10.5281/zenodo.44333
 * 
 * <NAME>, <NAME>, <NAME>. 
 * Numerical Simulation in Fluid Dynamics: A Practical Introduction (Monographs on Mathematical Modeling and Computation). 
 * SIAM: Society for Industrial and Applied Mathematics (December 1997). 
 * ISBN-13:978-0898713985 QA911.G718 1997
 * 
 * */ 
 
#include <iostream> 				// std::cout
#include <cmath>    				// std::sqrt, std::fmax 

#include "./physlib/R2grid.h"      	// Grid2d
#include "./physlib/dev_R2grid.h"  	// Dev_Grid2d
#include "./physlib/boundary.h"     // set_BConditions_host, set_BConditions, set_lidcavity_BConditions_host, set_lidcavity_BConditions
#include "./commonlib/checkerror.h" // checkCudaErrors

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/reduce.h>
#include <thrust/extrema.h>  // thrust::max_element (thrust::min_element)  


int main(int argc, char* argv[]) {
	// ################################################################
	// ####################### Initialization #########################
	// ################################################################
	
	// discretization (parameters) <==> graphical (parameters)
	const int L_X { 64 };  			// WIDTH   // I've tried values 32
	const int L_Y { 64 };  			// HEIGHT  // I've tried values 32

	// "real", physical parameters
	/** try domain size (non-dimensional) */
	constexpr const float l_X = 1.0;  	// length (in x-direction)
	constexpr const float l_Y = 1.0; 	// height (in y-direction)

	// physics (on device); Euclidean (spatial) space
	dim3 dev_L2 { static_cast<unsigned int>(L_X), 
				static_cast<unsigned int>(L_Y) };

	Dev_Grid2d dev_grid2d( dev_L2); 

	// physics (on host); Euclidean (spatial) space
	constexpr std::array<int,2> LdS { L_X, L_Y } ;
	constexpr std::array<float,2> ldS { l_X, l_Y };

	Grid2d grid2d{LdS, ldS};

	// dynamics (parameters)
	const dim3 M_i { 16, 16 }; 	// number of threads per block, i.e. Niemeyer's BLOCK_SIZE // I've tried values 4,4

	float t = 0.0 ;
	int cycle = 0;
	
	// iterations for SOR successive over relaxation
	int iter = 0;
	int itermax = 10000;  // I tried values such as 10000, 100

	/* READ the parameters of the problem                 */
	/* -------------------------------------------------- */ 

	/** Safety factor for time step modification; safety factor for time stepsize control */
	constexpr const float tau = 0.5; 

	/** SOR relaxation parameter; omg is Griebel's notation */
	constexpr const float omega = 1.7;  
	
	/** Discretization mixture parameter (gamma); gamma:upwind differencing factor is Griebel's notation */
	constexpr const float gamma = 0.9;

	/** Reynolds number */
	constexpr const float Re_num = 1000.0;

	// SOR iteration tolerance
	const float tol = 0.001;  // Griebel, et. al., and Niemeyer has this at 0.001
	
	// time range
	const float time_start = 0.0;
	const float time_end = 0.01;
	
	// initial time step size
	float deltat = 0.002; // I've tried values 0.002
	
	// set initial BCs on host CPU
	set_BConditions_host( grid2d );
	set_lidcavity_BConditions_host( grid2d );

	set_BConditions( dev_grid2d );

	// sanity check
	thrust::device_vector<float>::iterator max_u0_iter = 
		thrust::max_element( dev_grid2d.u.begin(), dev_grid2d.u.end() );
	float max_u0 = std::fmax( *max_u0_iter, static_cast<float>(0.0) ) ;

	thrust::device_vector<float>::iterator max_v0_iter = 
		thrust::max_element( dev_grid2d.v.begin(), dev_grid2d.v.end() );
	float max_v0 = std::fmax( *max_v0_iter, static_cast<float>(0.0) ) ;
	
	std::cout << " max_u0 : " << max_u0 << " max_v0 : " << max_v0 << std::endl;
	
	set_lidcavity_BConditions( dev_grid2d );

	/* delt satisfying CFL conditions */
	/* ------------------------------ */

	float max_u = 1.0e-10;
	float max_v = 1.0e-10;
	// get max velocity for initial values (including BCs)
	// cf. read Farzad's answer in http://stackoverflow.com/questions/22278631/using-pragma-unroll-in-cuda
/*	#pragma unroll
	for (auto j=1; j <=(grid2d.Ld[1]+1); ++j) {
		#pragma unroll
		for (auto i=0; i<=(grid2d.Ld[1]+1); ++i) {
			max_u = std::fmax( max_u, std::abs( grid2d.u[ grid2d.staggered_flatten(i,j) ] ) );
		}
	}

	#pragma unroll
	for (auto j=0; j <=(grid2d.Ld[1]+1); ++j) {
		#pragma unroll
		for (auto i=1; i<=(grid2d.Ld[1]+1); ++i) {
			max_v = std::fmax( max_v, std::abs( grid2d.v[ grid2d.staggered_flatten(i,j) ] ) );
		}
	}
*/
	

	// sanity check
	thrust::device_vector<float>::iterator max_u_iter = 
		thrust::max_element( dev_grid2d.u.begin(), dev_grid2d.u.end() );
	max_u = std::fmax( *max_u_iter, max_u ) ;

	thrust::device_vector<float>::iterator max_v_iter = 
		thrust::max_element( dev_grid2d.v.begin(), dev_grid2d.v.end() );
	max_v = std::fmax( *max_v_iter, max_v ) ;
	
	std::cout << " This is max_u : " << max_u << std::endl;
	std::cout << " This is max_v : " << max_v << std::endl;



	
	std::cout << " End of program " << std::endl;
	return 0;
} 



<|start_filename|>convect2dfinitedifftex/physlib/dev_R2grid.h<|end_filename|>
/* dev_R2grid.h
 * R2 under discretization (discretize functor) to a thread block
 * <NAME>  <EMAIL>
 * 20160701
 */
#ifndef __DEV_R2GRID_H__
#define __DEV_R2GRID_H__

#include "../commonlib/errors.h"

extern __constant__ int dev_Ld[2]; // L^{d=3} = (L_x,L_y,L_z) \in \mathbb{N}^3

class dev_Grid2d
{
	public:
		dim3 Ld;
	
		float *dev_rho;
		float2 *dev_u;
		float2 *dev_p;

		float *dev_E;

		// constructor
		__host__ dev_Grid2d( dim3 );

//		__host__ ~dev_Grid3d();

		__host__ int NFLAT();
};

class dev_block3d
{
	public:
		unsigned int  N_is[3];

		__device__ dev_block3d(unsigned int N_x, unsigned int N_y, unsigned int N_z);

		__device__ int flatten(int i_x, int i_y, int i_z);
};

#endif // __DEV_R2GRID_H__

 


<|start_filename|>convect3dfinitedifftex/commonlib/bit_anim2d.cu<|end_filename|>
/* bit_anim2d.cu
 * 2-dim. GPU bit animation 
 * <NAME>  <EMAIL>
 * 20160722
 */
#include "bit_anim2d.h"
 
int iterationCount = 0 ;

// interactions

void keyboard_func( unsigned char key, int x, int y) {
	if (key==27) {
		
		exit(0) ;
	}
	glutPostRedisplay();
}	
	
void mouse_func( int button, int state,
							int x, int y) {
	glutPostRedisplay();
}

// make* functions make functions to pass into OpenGL (note OpenGL is inherently a C API)

void make_display_func(int width, int height) {
	glClearColor( 0.0, 0.0, 0.0, 1.0 );
	glClear( GL_COLOR_BUFFER_BIT );
	glDrawPixels( width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
	glutSwapBuffers();
	
} 




__global__ void float_to_color3d( uchar4* optr, const float* outSrc) {
	// map from threadIdx/BlockIdx to pixel position
	int k_x = threadIdx.x + blockIdx.x*blockDim.x ;
	int k_y = threadIdx.y + blockIdx.y*blockDim.y ;

	// choose at which z coordinate to make the slice in x-y plane
	int zcoordslice = blockDim.z*gridDim.z/2*1; 

	int offset = k_x + k_y*blockDim.x*gridDim.x ;
	int fulloffset = offset + zcoordslice*blockDim.x*gridDim.x*blockDim.y*gridDim.y ;
	float value = outSrc[fulloffset];
	
	// Be aware of the "hard-coded" (numerical) constants for 
	// maximum and minimum scalar values that'll be assigned white and black, respectively
	if (value < 0.0001 ) { value = 0; }
	else if (value > 1.0 ) { value = 1.; } 

	// convert to long rainbow RGB* 
	value = value/0.20;
	int valueint  = ((int) floorf( value )); // this is the integer part 
	int valuefrac = ((int) floorf(255*(value-valueint)) );
	
	switch( valueint )
	{
		case 0:	optr[offset].x = 255; optr[offset].y = valuefrac; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 1:	optr[offset].x = 255-valuefrac; optr[offset].y = 255; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 2:	optr[offset].x = 0; optr[offset].y = 255; optr[offset].z = valuefrac; 
		optr[offset].w = 255; 
		break;
		case 3:	optr[offset].x = 0; optr[offset].y = 255-valuefrac; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 4:	optr[offset].x = valuefrac; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 5:	optr[offset].x = 255; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
	}
}





<|start_filename|>lid-driven-cavity_gpu-gfx/physlib/uvp.h<|end_filename|>
/** uvp.h
 * \file uvp.h
 * computation of u, v, p for 2-dim. incompressible Navier-Stokes equation with finite difference
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161209
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/u_p.cu -o u_p.o
 * 
 */
#ifndef __UVP_H__
#define __UVP_H__

#include "../commonlib/checkerror.h"  // checkCudaErrors

__host__ __device__ int flatten( int, int, int );

/*------------------------------------------------------------------- */
/* Computation of tentative velocity field (F,G) -------------------- */
/*------------------------------------------------------------------- */

///////////////////////////////////////////////////////////////////////////////
__global__ void calculate_F ( const float* u, const float* v,
				  float* F,
				  const float mix_param, const float Re_num, float gx,
  				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x) ;
				  
__global__ void calculate_G ( const float* u, const float* v,
				  float* G, 
				  const float mix_param, const float Re_num, float gy,
  				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x) ;

__global__ void sum_pressure (const float* pres_red, const float* pres_black, 
					float* pres_sum, const int imax, const int jmax, const int M_x) ;
				  
/*------------------------------------------------------------------- */
/* SOR iteration for the Poisson equation for the pressure
/*------------------------------------------------------------------- */
///////////////////////////////////////////////////////////////////////////////
__global__ void red_kernel ( const float* F, 
				 const float* G, const float* pres_black,
				 float* pres_red, 
				const float omega, 
				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x		 ); 				  
				  
__global__ void black_kernel ( const float* F, 
				   const float* G, const float* pres_red, 
				   float* pres_black,
				const float omega, 
				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x) ;
			  

/*------------------------------------------------------------------- */
/* computation of residual */
/*------------------------------------------------------------------- */
__global__ void calc_residual ( const float* F, const float* G, 
					const float* pres_red, const float* pres_black,
					float* res_array,
				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x);



/*------------------------------------------------------------------- */
/* computation of new velocity values */
/*------------------------------------------------------------------- */ 

__global__ void calculate_u ( const float* F, 
				  const float* pres_red, const float* pres_black, 
				  float* u, float* max_u, 
  				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x);


__global__ void calculate_v ( const float* G, 
				  const float* pres_red, const float* pres_black, 
				  float* v, float* max_v,
  				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x);


#endif // __UVP_H__


<|start_filename|>Euler2d/commonlib/tex_anim2d.cu<|end_filename|>
/* tex_anim2d.cu
 * 2-dim. GPU texture animation 
 * <NAME>  <EMAIL>
 * 20160720
 */
#include "tex_anim2d.h"
  
int iterationCount = 0 ;


// interactions

void keyboard_func( unsigned char key, int x, int y) {

	if (key==27) {
//		std::exit(0) ;
		exit(0);
	}
	glutPostRedisplay();
}
	
void mouse_func( int button, int state, int x, int y ) {
	glutPostRedisplay();
}

void idle() {
	++iterationCount;
	glutPostRedisplay();
}

void printInstructions() {
	printf("2 dim. texture animation \n"

			"Exit                           : Esc\n"
	
	);
}

// make* functions make functions to pass into OpenGL (note OpenGL is inherently a C API

void make_draw_texture(int w, int h) {
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 
		GL_UNSIGNED_BYTE, NULL);
	glEnable(GL_TEXTURE_2D);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f); glVertex2f(0,0);
	glTexCoord2f(0.0f, 1.0f); glVertex2f(0,h);
	glTexCoord2f(1.0f, 1.0f); glVertex2f(w,h);
	glTexCoord2f(1.0f, 0.0f); glVertex2f(w,0);
	glEnd();
	glDisable(GL_TEXTURE_2D);
}	


<|start_filename|>convect1dupwind/convect1dupwind.cu<|end_filename|>
/*
 * convect1dupwind.cu
 * 1-dimensional convection with time-independent velocty vector field using
 * CUDA C/C++ on GPU implementing "Upwind" interpolation scheme	
 * <NAME>  <EMAIL>
 * 20160618
*/

#include "commonlib/gpu_anim.h"
#include "cuda.h"
#include "math.h" // CUDA C/C++ math.h

#define Nthreads 400
#define DELTAt 1./(10.)
#define RHO0 0.656
#define L_0 1.0 
#define DELTAx L_0/((float) Nthreads)
#define DIMY 400

__global__ void convect( float* mavg, float* u ) {
	int k_x = threadIdx.x + blockIdx.x * blockDim.x ;
	
	int left     = k_x - 1;
	int right    = k_x + 1;
	
	// boundary conditions
	if (k_x == 0) {
		left++;
	}
	else if (k_x == (Nthreads - 1)) {
		right--;
	}	
	float flux_right;
	if (u[k_x] > 0. ) {
		flux_right = mavg[k_x]*u[k_x]; }
	else {
		flux_right = mavg[right]*u[k_x]; }
	float flux_left;
	if (u[left] > 0.) {
		flux_left = mavg[left]*u[left]; }
	else {
		flux_left = mavg[k_x]*u[left]; }
	mavg[k_x] += (-1.)*(DELTAt/ DELTAx)*( flux_right - flux_left);

}

float gaussian( float x, float A, float k, float x_0) 
{
	return A*exp(-k*(x-x_0)*(x-x_0)); 
}

struct DataBlock {
	float 				*dev_mavg;
	float 				*dev_u;
	GPUAnimBitmap 		*bitmap;
// The following are for time-keeping
	cudaEvent_t 		start, stop; 
	float 				totalTime;
	float 				frames;
};


__global__ void float_to_1dimplot( uchar4* optr, const float* outSrc) {
	// map from threadIdx/BlockIdx to pixel position
	int x = threadIdx.x + blockIdx.x * blockDim.x ;
	
	int ivalue = ((int) (outSrc[x]*((float) DIMY) ));
	
	// remember optr is a pointer to the buffer that OpenGL and CUDA SHARES
	for (int j = 0 ; j < DIMY ; ++j ) {
		int offset = x + j *gridDim.x * blockDim.x ;
		if (j < ivalue ) {
			optr[offset].x = 0 ;
			optr[offset].y = 255 ;
			optr[offset].z = 0;
			optr[offset].w = 255;
		} else {
			optr[offset].x = 255 ;
			optr[offset].y = 0;
			optr[offset].z = 0;
			optr[offset].w = 255;
		}
	}
}


void anim_gpu(uchar4* outputBitmap, DataBlock *d, int ticks) {
	cudaEventRecord( d->start, 0 ) ;
	
	/* change the 1000 time steps per frame manually */
	for (int i =0; i< 1000; ++i) {
		convect<<<Nthreads/20,20>>>( d->dev_mavg, d->dev_u);
	}
		
	float_to_1dimplot<<<Nthreads/20,20>>>(outputBitmap,d->dev_mavg);
	
	// Recording time for rough benchmarking only	
	cudaEventRecord( d->stop, 0) ;
	cudaEventSynchronize( d->stop ) ;
	float elapsedTime;
	cudaEventElapsedTime( &elapsedTime, d->start, d->stop);
	
	d->totalTime += elapsedTime;
	++d->frames;
	printf( "Average Time per frame:  %3.1f ms\n", d->totalTime/d->frames );
// END of Recording time for rough benchmarking only, END
}

int main() {
	DataBlock data;
	GPUAnimBitmap bitmap( Nthreads, DIMY, &data);
	data.bitmap = &bitmap;
	data.totalTime = 0;
	data.frames = 0;
	// END of GPU animation setup END
	cudaEventCreate( &data.start );
	cudaEventCreate( &data.stop  );
	
	
	float mavg[Nthreads];
	float u[Nthreads];
	
	cudaMalloc((void**)&data.dev_mavg, Nthreads*sizeof(float));
	cudaMalloc((void**)&data.dev_u, Nthreads*sizeof(float));
	
	// fill in host memory for time-independent u 
	for(int j = 0; j<Nthreads; ++j) {
		u[j] = 1.0; // m/s
	}
	// fill in host memory for initial mavg, which I chose to be a gaussian here
	// for some reason nvcc doesn't like C++11 lambda features
	/* auto gaussian = [](float x, float A, float k, float x_0) { return A*exp(-k*(x-x_0)*(x-x_0)); }; 
	for (int j = 0; j <= Nthreads; ++j) {
		rho.push_back( gaussian( ((float) j)*DELTAx, RHO0, 1./sqrt(0.00001),0.25) );
	}
	* nvcc didn't like inline either
	* */
	for (int j = 0; j < Nthreads; ++j) {
		mavg[j] =  gaussian( ((float) j)*DELTAx, RHO0, 1./sqrt(0.0001),0.25); 
	}

	cudaMemcpy( data.dev_mavg, mavg, Nthreads*sizeof(float), cudaMemcpyHostToDevice);	
	cudaMemcpy( data.dev_u, u, Nthreads*sizeof(float), cudaMemcpyHostToDevice);
	
//	delete [] rho;
//	delete [] u;
	
	bitmap.anim_and_exit( (void (*)(uchar4* , void*,int))anim_gpu, NULL);
}


<|start_filename|>convect3dupwind/physlib/dev_R3grid.h<|end_filename|>
/* dev_R3grid.h
 * R3 under discretization (discretize functor) to a thread block
 * <NAME>  <EMAIL>
 * 20160701
 */
#ifndef __DEV_R3GRID_H__
#define __DEV_R3GRID_H__

class dev_Grid3d
{
	public:
		unsigned int  N_is[3];

		__device__ dev_Grid3d(unsigned int N_x, unsigned int N_y, unsigned int N_z);

		__device__ unsigned int flatten(unsigned int i_x, unsigned int i_y, unsigned int i_z);
};

#endif // __DEV_R3GRID_H__

 


<|start_filename|>Euler2d/physlib/Euler2d.cu<|end_filename|>
/* Euler2d.cu
 * 2-dim. Euler eq. (heat eq.) by finite difference with shared memory
 * <NAME>  <EMAIL>
 * 20160804
 */
#include "Euler2d.h"


void kernelLauncher(uchar4 *d_out, float *dev_rho,  
									float2 *dev_u, 
									dim3 Ld, dim3 M_in) {

	const dim3 gridSize(blocksNeeded(Ld.x,M_in.x), blocksNeeded(Ld.y, M_in.y) );
	
//	convect_fd<<<gridSize,M_in>>>(dev_rho, dev_u) ;	
	convect_fd_sh<<<gridSize,M_in>>>(dev_rho, dev_u) ;	

	float_to_char<<<gridSize,M_in>>>(d_out,dev_rho);
	
}


void kernelLauncher2(uchar4 *d_out, float *dev_rho,  
									float2 *dev_u, 
									dim3 Ld, dim3 M_in) {

	const dim3 gridSize(blocksNeeded(Ld.x,M_in.x), blocksNeeded(Ld.y, M_in.y) );
	
	convect_fd2<<<gridSize,M_in>>>(dev_rho, dev_u) ;	

	
	float_to_char<<<gridSize,M_in>>>(d_out,dev_rho);
	
}

void EulerLauncher(uchar4 *d_out, float *dev_rho, float2 *dev_p, 
									float2 *dev_u, 
									float *dev_E,
									dim3 Ld, dim3 M_in) {

	const dim3 gridSize(blocksNeeded(Ld.x,M_in.x), blocksNeeded(Ld.y, M_in.y) );
	
	Euler2dp1<<<gridSize,M_in>>>(dev_rho, dev_p, dev_u, dev_E) ;	

	
	float_to_char<<<gridSize,M_in>>>(d_out,dev_rho);
	
}

void EulerLauncher2(uchar4 *d_out, float *dev_rho, float2 *dev_p, 
									float2 *dev_u, 
									float *dev_E,
									dim3 Ld, dim3 M_in) {

	const dim3 gridSize(blocksNeeded(Ld.x,M_in.x), blocksNeeded(Ld.y, M_in.y) );
	
	Euler2dp2<<<gridSize,M_in>>>(dev_rho, dev_p, dev_u, dev_E) ;	

	
	float_to_char<<<gridSize,M_in>>>(d_out,dev_rho);
	
}



<|start_filename|>Euler2d/physlib/Euler2d.h<|end_filename|>
/* Euler2d.h
 * 2-dim. Euler eq. (heat eq.) by finite difference with shared memory
 * <NAME>  <EMAIL>
 * 20160804
 */
#ifndef __EULER2D_H__
#define __EULER2D_H__

#include "../commonlib/sharedmem.h" // __global__ void float_to_char
#include "convect.h"  // __global__void convectKernel



void kernelLauncher(uchar4 *d_out, 
	float *dev_rho, 
	float2 *dev_u,
	dim3 Ld, dim3 M_in) ;

void kernelLauncher2(uchar4 *d_out, 
	float *dev_rho, 
	float2 *dev_u,
	dim3 Ld, dim3 M_in) ;	


void EulerLauncher(uchar4 *d_out, 
	float *dev_rho, float2 *dev_p,
	float2 *dev_u, float *dev_E,
	dim3 Ld, dim3 M_in) ;	

void EulerLauncher2(uchar4 *d_out, 
	float *dev_rho, float2 *dev_p,
	float2 *dev_u, float *dev_E,
	dim3 Ld, dim3 M_in) ;	


#endif // __EULER2D_H__


<|start_filename|>NavSt2DIncompFiniteDiff/physlib/u_p.cu<|end_filename|>
/** u_p.cu
 * \file u_p.cu
 * \brief computation of u, p for 2-dim. incompressible Navier-Stokes equation with finite difference
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161209
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/u_p.cu -o u_p.o
 * 
 */

/*------------------------------------------------------------------- */
/* Computation of tentative velocity field (F,G) -------------------- */
/*------------------------------------------------------------------- */

__global__ void compute_F(const float deltat, 
	const float* u, const float* v, float* F,
	const int imax, const int jmax, const float deltax, const float deltay,
	const float gamma, const float Re) {
	
	const int i = threadIdx.x  + (blockDim.x*blockIdx.x) ; // be forewarned; Niemeyer has this "reversed" as the row as indexed differently as (blockIdx.x * blockDim.x)+threadIdx.x + 1
	const int j = threadIdx.y  + (blockDim.y*blockIdx.y) ; // be forewarned; Niemeyer has this "reversed" as the col as indexed differently as (blockIdx.y * blockDim.y)+threadIdx.y + 1
	if ((i > (imax+1)) || (j > (jmax+1))) { return; }

	if ((i>0)&&(i<=(imax-1))&&(j>0)&&(j<=jmax)) {
	// velocities u 
	float u_ij   = u[i + (imax+2)*j];
	float u_ip1j = u[i+1 + (imax+2)*j];
	float u_im1j = u[i-1 + (imax+2)*j];
	float u_ijp1 = u[i + (imax+2)*(j+1)];
	float u_ijm1 = u[i + (imax+2)*(j-1)];

	// velocities v 
	float v_ij     = v[i + (imax+2)*j];
	float v_ip1j   = v[i+1 + (imax+2)*j];
	float v_ijm1   = v[i + (imax+2)*(j-1)];
	float v_ip1jm1 = v[i+1 + (imax+2)*(j-1)];

	// finite differences
	float du2dx, duvdy;

	du2dx = ( ((u_ij + u_ip1j) * (u_ij + u_ip1j) - (u_im1j + u_ij) * (u_im1j + u_ij) ) + 
				gamma * ( fabs( u_ij + u_ip1j) * (u_ij - u_ip1j) - 
							fabs( u_im1j + u_ij) * (u_im1j - u_ij) ) )/(4.0*deltax) ; 
							
	duvdy = ( ((v_ij + v_ip1j)*(u_ij + u_ijp1) - (v_ijm1 + v_ip1jm1)*(u_ijm1 + u_ij) ) + 
				gamma * ( fabs( v_ij + v_ip1j ) * (u_ij - u_ijp1) - 
							fabs( v_ijm1 + v_ip1jm1 ) * ( u_ijm1 - u_ij ) ))/ (4.0 * deltay) ;
		
	// calculate the Laplacian, d^2udx^2 + d^2vdy^2, Laplacianu, i.e. Niemeyer's d2udx2, d2udy2
	float Laplacianu = (u_ip1j - 2.0*u_ij + u_im1j)/deltax/deltax + 
						(u_ijp1 - 2.0*u_ij + u_ijm1)/deltay/deltay ;
	
	float temp_F = u_ij + deltat * (Laplacianu/Re - du2dx - duvdy );
	F[i + (imax+2)*j] = temp_F;
	}

	/* F at external boundary  */
	/* ----------------------- */
	// eastern boundary or right boundary, F_ij = u_ij
	if (i == imax) {
		if ((j>=1)&&(j<=jmax)) {
			float u_imaxj = u[ imax + (imax+2)*j] ; 
			F[imax+(imax+2)*j] = u_imaxj ; } 
	}		
			
	// western boundary or left boundary
	if (i == 0) {
		if ((j>=1)&&(j<=jmax)) {
			float u_0j = u[ 0 + (imax+2)*j] ; 
			F[0 + (imax+2)*j] = u_0j ; }
	}	
} 	// end of compute_F

__global__ void compute_G(const float deltat, 
	const float* u, const float* v, float* G,
	const int imax, const int jmax, const float deltax, const float deltay,
	const float gamma, const float Re) {

	const int i = threadIdx.x  + (blockDim.x*blockIdx.x) ; // be forewarned; Niemeyer has this "reversed" as the row as indexed differently as (blockIdx.x * blockDim.x)+threadIdx.x + 1
	const int j = threadIdx.y  + (blockDim.y*blockIdx.y) ; // be forewarned; Niemeyer has this "reversed" as the col as indexed differently as (blockIdx.y * blockDim.y)+threadIdx.y + 1
	if ((i > (imax+1)) || (j > (jmax+1))) { return; }

	if ((i>0)&&(i<=imax)&&(j>0)&&(j<=(jmax-1)) ) {
	// velocities u 
	float u_ij   = u[i + (imax+2)*j];
	float u_im1j = u[i-1 + (imax+2)*j];
	float u_ijp1 = u[i + (imax+2)*(j+1)];
	float u_im1jp1 = u[i-1 + (imax+2)*(j+1)];

	// velocities v 
	float v_ij     = v[i + (imax+2)*j];
	float v_ip1j   = v[i+1 + (imax+2)*j];
	float v_im1j   = v[i-1 + (imax+2)*j];
	float v_ijp1 = v[i + (imax+2)*(j+1)];
	float v_ijm1   = v[i + (imax+2)*(j-1)];

	float duvdx = (( (u_ij + u_ijp1)*(v_ij + v_ip1j) - (u_im1j + u_im1jp1)*(v_im1j+v_ij)) 
					+ gamma * ( fabs(u_ij   + u_ijp1)   * (v_ij   - v_ip1j) - 
								fabs(u_im1j + u_im1jp1) * (v_im1j - v_ij) ))/(4.0*deltax);
	
	float dv2dy = (((v_ij + v_ijp1 )*( v_ij + v_ijp1 ) - ( v_ijm1 + v_ij )*( v_ijm1 + v_ij)) 
					+ gamma * ( fabs( v_ij   + v_ijp1) * (v_ij   - v_ijp1) - 
								fabs( v_ijm1 + v_ij  ) * ( v_ijm1 - v_ij) ))/(4.0*deltay);
		
	// calculate the Laplacian, d^2vdx^2 + d^2vdy^2, Laplacianu, i.e. Niemeyer's d2vdx2, d2vdy2
	float Laplacianv = (v_ip1j  -2.0*v_ij + v_im1j)/deltax/deltax + 
						(v_ijp1 -2.0*v_ij + v_ijm1)/deltay/deltay ;
	
	float temp_G  = v_ij + deltat * (Laplacianv/Re - dv2dy - duvdx );
	G[i + (imax+2)*j] = temp_G;
}

	/* G at external boundary  */
	/* ----------------------- */
	// northern boundary or top boundary
	if (j == jmax) {
		if ((i>=1)&&(i<=imax)) {
			float v_ijmax = v[ i + (imax+2)*jmax] ; 
			G[i + (imax+2)*jmax] = v_ijmax ; }
	}
			
	// southern boundary or bottom boundary
	if (j == 0) {
		if ((i>=1)&&(i<=imax)) {
			float v_i0 = v[ i + 0 ] ;
			G[i + 0 ] = v_i0; }
	}
} 	// end of compute_G

////////////////////////////////////////////////////////////////////////
// copy_press_int /brief copy interior pressure values
/*__host__ void copy_press_int( thrust::device_vector<float> p_all, 
	thrust::device_vector<float> & p_int,
	const int imax, const int jmax) {
	
	for (auto j = 0; j < (jmax+2); ++j) {
		for (auto i = 0; i < (imax+2); ++i) {
			if ((i>0)&&(i<(imax+1)) && (j>0) && (j<(jmax+1))) {
				const int k = (i-1) + imax * (j-1) ; 
				p_int[k] = p_all[ i + (imax+2)*j ] ; 
			}
		}
	}
}

void copy_press_int( const float* p_all, float* p_int,
	const int imax, const int jmax) {
	
	for (auto j = 0; j < (jmax+2); ++j) {
		for (auto i = 0; i < (imax+2); ++i) {
			if ((i>0)&&(i<(imax+1)) && (j>0) && (j<(jmax+1))) {
				const int k = (i-1) + imax * (j-1) ; 
				p_int[k] = p_all[ i + (imax+2)*j ] ; 
			}
		}
	}
}


__global__ void sum_pressure( cudaSurfaceObject_t pSurfObj, 
	const int imax, const int jmax, float* pres_sum) {

	const int k_x = threadIdx.x  + (blockDim.x*blockIdx.x) ; // be forewarned; Niemeyer has this "reversed" as the row as indexed differently as (blockIdx.x * blockDim.x)+threadIdx.x + 1
	const int k_y = threadIdx.y  + (blockDim.y*blockIdx.y) ; // be forewarned; Niemeyer has this "reversed" as the col as indexed differently as (blockIdx.y * blockDim.y)+threadIdx.y + 1
	const int k   = k_x + (imax+2)*k_y; // take note of the "striding" here, or i.e. choice of "stride" as imax+2 here

	if ((k_x > (imax+1)) || (k_y > (jmax+1))) { return; }

	float temp_val = 0.0; // temporary value
	float psq    = 0.0; // residual, squared

	if ((k_x >= 1)&&(k_x<=imax)) {
		if ((k_y >=1)&&(k_y<=jmax)) {
			surf2Dread(&temp_val, pSurfObj, k_x*4,    k_y);
			psq = temp_val * temp_val;			
			pres_sum[k] = psq; }
	}

	if ((k_x == 0) || (k_y == 0) || (k_x == (imax+1)) || (k_y == (jmax+1))  ) {
			pres_sum[k] = 0.0 ; }
} 
*/


/*------------------------------------------------------------------- */
/* Computation of the right hand side of the pressure equation ------ */
/* it's the "RHS" of the Poisson equation involving pressure p        */
/*------------------------------------------------------------------- */

__global__ void compute_RHS( const float* F, const float* G, 
	float* RHS, 
	const int imax, const int jmax, 
	const float deltat, const float deltax, const float deltay)  {

	// "striding" needed to "flatten" (i,j) indices 
	const int Nx = imax+2;
	
	const int i = threadIdx.x  + (blockDim.x*blockIdx.x) ; // be forewarned; Niemeyer has this "reversed" as the row as indexed differently as (blockIdx.x * blockDim.x)+threadIdx.x + 1
	const int j = threadIdx.y  + (blockDim.y*blockIdx.y) ; // be forewarned; Niemeyer has this "reversed" as the col as indexed differently as (blockIdx.y * blockDim.y)+threadIdx.y + 1
	if ((i > (imax+1)) || (j > (jmax+1))) { return; }

	if ((i >=1)&&(i<=imax)) { 
		if ((j >=1)&&(j<=jmax)) {
			float F_ij   = F[ i + Nx * j] ; 
			float F_im1j = F[ i-1 + Nx * j] ;
			float G_ij   = G[ i + Nx * j] ; 
			float G_ijm1 = G[ i + Nx * (j-1)] ;
			
			float temp_RHS_val = ((F_ij-F_im1j)/deltax + (G_ij-G_ijm1)/deltay)/deltat;
			RHS[ i + Nx * j ] = temp_RHS_val; 
		}
	}
}

/*------------------------------------------------------------------- */
/* SOR iteration for the Poisson equation for the pressure
/*------------------------------------------------------------------- */

__global__ void poisson( const float* p, const float* RHS, 
	float* p_temp, 
	const int imax, const int jmax,
	const float deltax, const float deltay, 
	const float omega) {
	
	// "striding" needed to "flatten" (i,j) indices
	const int Nx = imax+2;
	
	const int i = threadIdx.x  + (blockDim.x*blockIdx.x) ; // be forewarned; Niemeyer has this "reversed" as the row as indexed differently as (blockIdx.x * blockDim.x)+threadIdx.x + 1
	const int j = threadIdx.y  + (blockDim.y*blockIdx.y) ; // be forewarned; Niemeyer has this "reversed" as the col as indexed differently as (blockIdx.y * blockDim.y)+threadIdx.y + 1
	

	if ((i > (imax+1)) || (j > (jmax+1))) { return; }

	if ((i >= 1)&&(i <=imax)) {
		if ((j >=1)&&(  j <=jmax)) {
			float p_ij   = p[ i + Nx *j] ; 
			float p_ip1j = p[ i +1 + Nx *j] ;
			float p_im1j = p[ i -1 + Nx *j] ;
			float p_ijp1 = p[ i + Nx * (j+1) ] ; 
			float p_ijm1 = p[ i + Nx * (j-1) ] ;

			float RHS_ij = RHS[ i + Nx * j];
			
			float temp_val = (1.0-omega)*p_ij + 
				(omega/(2.0*(1./deltax/deltax+1./deltay/deltay))) * 
					( (p_ip1j + p_im1j)*(1./deltax/deltax) + 
						(p_ijp1 + p_ijm1)*(1./deltay/deltay) - 
							 RHS_ij ) ; // temp_val is RHS of poisson equation for pressure, in this case
			p_temp[ i+Nx*j] = temp_val ; }
	}
}


__global__ void poisson_redblack( float* p, const float* RHS, 
	const int imax, const int jmax,
	const float deltax, const float deltay, 
	const float omega) {
	
	// "striding" needed to "flatten" (i,j) indices
	const int Nx = imax+2;
	
	const int i = threadIdx.x  + (blockDim.x*blockIdx.x) ; // be forewarned; Niemeyer has this "reversed" as the row as indexed differently as (blockIdx.x * blockDim.x)+threadIdx.x + 1
	const int j = threadIdx.y  + (blockDim.y*blockIdx.y) ; // be forewarned; Niemeyer has this "reversed" as the col as indexed differently as (blockIdx.y * blockDim.y)+threadIdx.y + 1
	

	if ((i > (imax+1)) || (j > (jmax+1))) { return; }

	if ((i >= 1)&&(i <=imax)) {
		if ((j >=1)&&(  j <=jmax)) {
			if ( ((i+j) % 2) ==0 )  // red
				{ 
			float p_ij   = p[ i + Nx *j] ; 
			float p_ip1j = p[ i +1 + Nx *j] ;
			float p_im1j = p[ i -1 + Nx *j] ;
			float p_ijp1 = p[ i + Nx * (j+1) ] ; 
			float p_ijm1 = p[ i + Nx * (j-1) ] ;

			float RHS_ij = RHS[ i + Nx * j];
			
			float temp_val = (1.0-omega)*p_ij + 
				(omega/(2.0*(1./deltax/deltax+1./deltay/deltay))) * 
					( (p_ip1j + p_im1j)*(1./deltax/deltax) + 
						(p_ijp1 + p_ijm1)*(1./deltay/deltay) - 
							 RHS_ij ) ; // temp_val is RHS of poisson equation for pressure, in this case
			p[ i+Nx*j] = temp_val ; } }
	}
	__syncthreads();
	
	if ((i >= 1)&&(i <=imax)) {
		if ((j >=1)&&(  j <=jmax)) {
			if ( ((i+j) % 2) == 1 )  // black
				{ 
			float p_ij   = p[ i + Nx *j] ; 
			float p_ip1j = p[ i +1 + Nx *j] ;
			float p_im1j = p[ i -1 + Nx *j] ;
			float p_ijp1 = p[ i + Nx * (j+1) ] ; 
			float p_ijm1 = p[ i + Nx * (j-1) ] ;

			float RHS_ij = RHS[ i + Nx * j];
			
			float temp_val = (1.0-omega)*p_ij + 
				(omega/(2.0*(1./deltax/deltax+1./deltay/deltay))) * 
					( (p_ip1j + p_im1j)*(1./deltax/deltax) + 
						(p_ijp1 + p_ijm1)*(1./deltay/deltay) - 
							 RHS_ij ) ; // temp_val is RHS of poisson equation for pressure, in this case
			p[ i+Nx*j] = temp_val ; } }
	}	
}

/* ------------------------------------------------------------------ */
/* Computation of residual  */
/* ------------------------------------------------------------------ */
 
__global__ void compute_residual( const float* p, const float* RHS, 
	const int imax, const int jmax,
	const float deltax, const float deltay, 
	float* residualsq_Array) {

/* can't do this
	thrust::device_vector<float> & residualsq) { 	
	* cf. http://stackoverflow.com/questions/5510715/thrust-inside-user-written-kernels
	* */

	// "striding" needed to "flatten" (i,j) indices
	const int Nx = imax+2;
	
	const int i = threadIdx.x  + (blockDim.x*blockIdx.x) ; // be forewarned; Niemeyer has this "reversed" as the row as indexed differently as (blockIdx.x * blockDim.x)+threadIdx.x + 1
	const int j = threadIdx.y  + (blockDim.y*blockIdx.y) ; // be forewarned; Niemeyer has this "reversed" as the col as indexed differently as (blockIdx.y * blockDim.y)+threadIdx.y + 1
	

	if ((i > (imax+1)) || (j > (jmax+1))) { return; }

	if ((i >= 1)&&(i <=imax)) {
		if ((j >=1)&&(  j <=jmax)) {
			float p_ij   = p[ i + Nx *j] ; 
			float p_ip1j = p[ i +1 + Nx *j] ;
			float p_im1j = p[ i -1 + Nx *j] ;
			float p_ijp1 = p[ i + Nx * (j+1) ] ; 
			float p_ijm1 = p[ i + Nx * (j-1) ] ;

			float RHS_ij = RHS[ i + Nx * j ] ;

			// "temp_val" here is residual or res or "res2" for Griebel, et. al. and/or Niemeyer
			float temp_val = (((p_ip1j - p_ij)-(p_ij-p_im1j))/deltax/deltax + 
						((p_ijp1 - p_ij)-(p_ij-p_ijm1))/deltay/deltay) - RHS_ij;
			float ressq = temp_val * temp_val;			// residual, squared
			residualsq_Array[i + Nx * j] = ressq; }
	}

	if ((i == 0) || (j == 0) || (i == (imax+1)) || (j == (jmax+1))  ) {
			residualsq_Array[i + Nx *j] = 0.0 ; }
} 

/*------------------------------------------------------------------- */
/* computation of new velocity values */
/*------------------------------------------------------------------- */

__global__ void calculate_u( float* u, const float* p, const float* F, 
	const int imax, const int jmax, const float deltat, const float deltax ) {

	// "striding" needed to "flatten" (i,j) indices
	const int Nx = imax+2;
	
	const int i = threadIdx.x  + (blockDim.x*blockIdx.x) ; // be forewarned; Niemeyer has this "reversed" as the row as indexed differently as (blockIdx.x * blockDim.x)+threadIdx.x + 1
	const int j = threadIdx.y  + (blockDim.y*blockIdx.y) ; // be forewarned; Niemeyer has this "reversed" as the col as indexed differently as (blockIdx.y * blockDim.y)+threadIdx.y + 1

	if ((i > (imax+1)) || (j > (jmax+1))) { return; }

	float new_u = 0.0;
	if ((i >= 1)&&(i <=(imax-1))) {
		if ((j >=1)&&(  j <=jmax)) {
			float p_ij   = p[ i + Nx *j] ; 
			float p_ip1j = p[ i +1 + Nx *j] ;

			float F_ij = F[ i + Nx * j ] ;
			new_u = F_ij - (p_ip1j - p_ij)*deltat/deltax ; 
			u[ i + Nx *j] = new_u ; }
	}
}

__global__ void calculate_v( float* v, const float* p, const float* G, 
	const int imax, const int jmax, const float deltat, const float deltay ) {

	// "striding" needed to "flatten" (i,j) indices
	const int Nx = imax+2;
	
	const int i = threadIdx.x  + (blockDim.x*blockIdx.x) ; // be forewarned; Niemeyer has this "reversed" as the row as indexed differently as (blockIdx.x * blockDim.x)+threadIdx.x + 1
	const int j = threadIdx.y  + (blockDim.y*blockIdx.y) ; // be forewarned; Niemeyer has this "reversed" as the col as indexed differently as (blockIdx.y * blockDim.y)+threadIdx.y + 1

	if ((i > (imax+1)) || (j > (jmax+1))) { return; }

	float new_v = 0.0;
	if ((i >= 1)&&(i <=imax)) {
		if ((j >=1)&&(  j <=(jmax-1))) {
			float p_ij   = p[ i + Nx *j] ; 
			float p_ijp1 = p[ i  + Nx *(j+1)] ;

			float G_ij = G[ i + Nx * j ] ;
			new_v = G_ij - (p_ijp1 - p_ij)*deltat/deltay ; 
			v[ i + Nx *j] = new_v ; }
	}
}

/* --------------------------------------------------------- */
/* Routines to assist in the 								 */		
/* Computation of adaptive time stepsize satisfying  		 */
/* the CFL stability criteria								 */
/* and set the flag "write" if some data has to be written   */
/* into a file.												 */
/* --------------------------------------------------------- */

/*void calculate_max_uv( thrust::device_vector<float> & max_u_vec, thrust::device_vector<float> & max_v_vec, 
	const thrust::device_vector<float> u_vec, const thrust::device_vector<float> v_vec ) {
		
}
* */

	
	 




<|start_filename|>lid-driven-cavity_gpu-gfx/physlib/boundary.h<|end_filename|>
/** boundary.h
 * \file boundary.h
 * fix boundary conditions at the "boundary strip" cf. Griebel, Dornseifer, & Neunhoeffer (1997)
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161207
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/boundary.cu -o boundary.o
 * 
 */
#ifndef __BOUNDARY_H__
#define __BOUNDARY_H__

#include "../physlib/uvp.h"       // flatten




/* --------------------------------------------------------------- */
/* Setting the boundary conditions at the boundary strip.      	   */
// on the host CPU memory
/* --------------------------------------------------------------- */

void set_BCs_host (float* u, float* v, 
	const int imax, const int jmax) ;

/* --------------------------------------------------------------- */
/* Setting the boundary conditions at the boundary strip.      	   */
// on the device GPU memory
/* --------------------------------------------------------------- */

__global__
void set_BCs (float* u, float* v,
	const int imax, const int jmax) ;

////////////////////////////////////////////////////////////////////////
__global__ 
void set_horz_pres_BCs (float* pres_red, float* pres_black,
	const int imax, const int jmax) ;
	
////////////////////////////////////////////////////////////////////////
__global__
void set_vert_pres_BCs (float* pres_red, float* pres_black,
	const int imax, const int jmax) ;


#endif // __BOUNDARY_H__



<|start_filename|>convect3dfinitedifftex/commonlib/bit_anim2d.h<|end_filename|>
/* bit_anim2d.h
 * 2-dim. GPU bit animation 
 * <NAME>  <EMAIL>
 * 20160722
 */
#ifndef __BIT_ANIM2D_H__
#define __BIT_ANIM2D_H__

#define GL_GLEXT_PROTOTYPES // needed for identifier glGenBuffer, glBindBuffer, glBufferData, glDeleteBuffers

#include <GL/glut.h>

#include <cuda_runtime.h>
#include <cuda_gl_interop.h>

#include "errors.h"

#include <stdlib.h>
// #include <cstdlib> // std::exit

extern int iterationCount  ;

struct GPUAnim2dBit {
	GLuint pixbufferObj ; // OpenGL pixel buffer object

	cudaGraphicsResource *cuda_pixbufferObj_resource;
 
	int width, height;
 
	GPUAnim2dBit( int w, int h ) {
		width  = w;
		height = h;

		pixbufferObj = 0 ;
	}
/*
	~GPUAnim2dBit() {
		exitfunc();
	}
*/

	void initGLUT(int *argc, char **argv) {
		glutInit(argc, argv);
		glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
		glutInitWindowSize(width, height);
		glutCreateWindow("Mass Density. Vis.");

	}
	
	void initPixelBuffer() {
		glGenBuffers(1, &pixbufferObj );
		glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pixbufferObj);
		glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width*height*sizeof(GLubyte)*4, 0, 
			GL_DYNAMIC_DRAW_ARB);

		HANDLE_ERROR(
			cudaGraphicsGLRegisterBuffer( &cuda_pixbufferObj_resource, pixbufferObj, 
			cudaGraphicsMapFlagsNone) );
	}
	
	void exitfunc() {
		if (pixbufferObj) {
		HANDLE_ERROR( 
			cudaGraphicsUnregisterResource( cuda_pixbufferObj_resource) );

		glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0 ) ;

		glDeleteBuffers(1, &pixbufferObj);
	}
	}
};	

// interactions

void keyboard_func( unsigned char key, int x, int y) ; 
	
void mouse_func( int button, int state, int x, int y ) ;

// make* functions make functions to pass into OpenGL (note OpenGL is inherently a C API)

void make_display_func(int width, int height) ;



__global__ void float_to_color3d( uchar4* optr, const float* outSrc) ;


#endif // # __BIT_ANIM2D_H__


<|start_filename|>convect3dfinitedifftex/commonlib/gpu_anim.cu<|end_filename|>
/*
 * gpu_anim.cu
 * <NAME>  <EMAIL>
 * 20160716
 */
#include "gpu_anim.h"

__global__ void float_to_color3d( uchar4* optr, const float* outSrc) {
	// map from threadIdx/BlockIdx to pixel position
	int k_x = threadIdx.x + blockIdx.x*blockDim.x ;
	int k_y = threadIdx.y + blockIdx.y*blockDim.y ;

	// choose at which z coordinate to make the slice in x-y plane
	int zcoordslice = blockDim.z*gridDim.z/2*1; 

	int offset = k_x + k_y*blockDim.x*gridDim.x ;
	int fulloffset = offset + zcoordslice*blockDim.x*gridDim.x*blockDim.y*gridDim.y ;
	float value = outSrc[fulloffset];
	
	// Be aware of the "hard-coded" (numerical) constants for 
	// maximum and minimum scalar values that'll be assigned white and black, respectively
	if (value < 0.0001 ) { value = 0; }
	else if (value > 1.0 ) { value = 1.; } 

	// convert to long rainbow RGB* 
	value = value/0.20;
	int valueint  = ((int) floorf( value )); // this is the integer part 
	int valuefrac = ((int) floorf(255*(value-valueint)) );
	
	switch( valueint )
	{
		case 0:	optr[offset].x = 255; optr[offset].y = valuefrac; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 1:	optr[offset].x = 255-valuefrac; optr[offset].y = 255; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 2:	optr[offset].x = 0; optr[offset].y = 255; optr[offset].z = valuefrac; 
		optr[offset].w = 255; 
		break;
		case 3:	optr[offset].x = 0; optr[offset].y = 255-valuefrac; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 4:	optr[offset].x = valuefrac; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 5:	optr[offset].x = 255; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
	}
}


<|start_filename|>Euler2d/physlib/dev_phys_param.h<|end_filename|>
/* dev_phys_param.h
 * physical parameters on the device
 * <NAME>  <EMAIL>
 * 20160804
 */
#ifndef __DEV_PHYS_PARAM_H__
#define __DEV_PHYS_PARAM_H__

extern __constant__ float dev_Deltat[1]; // Deltat

extern __constant__ float dev_gas_params[3] ; // dev_gas_params[0] = heat capacity ratio, dev_gas_params[1] = C_V, dev_gas_params[2] = M

//__device__ float pressure( float energy, float rho, float2 u ) ;

__device__ float pressure( float energy, float rho, float usq) ;


#endif // __DEV_PHYS_PARAM_H__


<|start_filename|>NavSt2DIncompFiniteDiff/physlib/dev_R2grid.cu<|end_filename|>
/* dev_R2grid.cu
 * R3 under discretization (discretize functor) to a (staggered) grid
 * <NAME>  <EMAIL>
 * 2016115
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/dev_R2grid.cu -o dev_R2grid.o
 * 
 */
#include "dev_R2grid.h"

//__constant__ int dev_Ld[2];

// constructor
__host__ Dev_Grid2d::Dev_Grid2d( dim3 Ld_in) : Ld(Ld_in)
{
	staggered_Ld.x  = Ld.x+2;
	staggered_Ld.y  = Ld.y+2;

	thrust::device_vector<float> temp_p( this->staggered_SIZE(), 0.0 );
	p = temp_p;
	p_temp = temp_p;
	F = temp_p;
	G = temp_p;
	RHS= temp_p;
	
	u = temp_p;
	v = temp_p;


	p_arr = thrust::raw_pointer_cast( (this->p).data() );	
	p_temp_arr = thrust::raw_pointer_cast( (this->p_temp).data() );	
	F_arr = thrust::raw_pointer_cast( (this->F).data() );	
	G_arr = thrust::raw_pointer_cast( (this->G).data() );	
	RHS_arr = thrust::raw_pointer_cast( (this->RHS).data() );	

	u_arr = thrust::raw_pointer_cast( (this->u).data() );	
	v_arr = thrust::raw_pointer_cast( (this->v).data() );	

	
}

// destructor

__host__ Dev_Grid2d::~Dev_Grid2d() {

}


__host__ int Dev_Grid2d :: NFLAT() {
	return Ld.x*Ld.y;
}	

__host__ int Dev_Grid2d :: staggered_SIZE() {
	return (staggered_Ld.x)*(staggered_Ld.y);
}	

__host__ int Dev_Grid2d :: flatten(const int i_x, const int i_y ) {
	return i_x+i_y*Ld.x  ;
}

__host__ int Dev_Grid2d :: staggered_flatten(const int i_x, const int i_y ) {
	return i_x+i_y*(staggered_Ld.x)  ;
}



<|start_filename|>convect3dupwind/physlib/R3grid.cpp<|end_filename|>
/* R3grid.cpp
 * R3 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20160630
 */
#include "R3grid.h"


Grid3d :: Grid3d(const int N_x, const int N_y, const int N_z, 
				const float h_x, const float h_y, const float h_z)
	: N_is {N_x,N_y,N_z}, h_is {h_x,h_y,h_z} 	
{}	


	
float Grid3d :: l_i(int i) {
		return N_is[i]*h_is[i];
	}

int* Grid3d :: is_grid_pt(int* I) {
	if (I[0] >= N_is[0] || I[1] >= N_is[1] || I[2] >= N_is[2]) {
			return nullptr; }
		return I;
	}
	
void Grid3d :: gridpt_to_space(int* Index, float* Xi) {
	auto checkingrid = this->is_grid_pt(Index);
	if (checkingrid == nullptr) {
		return; }
		
	Xi[0] = Index[0]*h_is[0]; 
	Xi[1] = Index[1]*h_is[1]; 
	Xi[2] = Index[2]*h_is[2];
	}

int Grid3d :: NFLAT() {
	int N {1};
		for (auto N_i : N_is) {
			N *= N_i; }
		return N;
	}

int Grid3d :: flatten(const int i_x, const int i_y, const int i_z) {
	return i_x+i_y*N_is[0]+i_z*N_is[0]*N_is[1];	
}

//Grid3d::~Grid3d() {}



<|start_filename|>Euler2d/physlib/R2grid.cu<|end_filename|>
/* R3grid.cpp
 * R3 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20160630
 */
#include "R2grid.h"


Grid2d :: Grid2d(std::array<int,2> Ld_in, std::array<float,2> ld_in)
	: Ld(Ld_in), ld(ld_in)
{
	hd = { ld[0]/Ld[0], ld[1]/Ld[1]  };
	
	rho = new float[ this->NFLAT() ];
	u = new float2[ this->NFLAT() ];
	p = new float2[ this->NFLAT() ];
	E = new float[ this->NFLAT() ];
}

std::array<float,2> Grid2d :: gridpt_to_space(std::array<int,2> index) {
	std::array<float,2> Xi { index[0]*hd[0], index[1]*hd[1]  } ;
	return Xi;
}

int Grid2d :: NFLAT() {
	return Ld[0]*Ld[1] ;

}	

int Grid2d :: flatten(const int i_x, const int i_y ) {
	return i_x+i_y*Ld[0]  ;
}


Grid2d::~Grid2d() {
	delete[] rho;
	delete[] u;
	delete[] p;
	delete[] E;
}

float gaussian2d(float A, float c, std::array<float,2> x_0, std::array<float,2> x) {
	return A * expf( (-1.f)*
		( (x[0]-x_0[0])*(x[0]-x_0[0]) + (x[1]-x_0[1])*(x[1]-x_0[1])   ) /  
			(2.f * c*c) );
}



<|start_filename|>MacCor1d/physlib/dev_R1grid.cu<|end_filename|>
/* dev_R1grid.cu
 * R1 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20161026
 * */
#include "dev_R1grid.h"

__constant__ int dev_Ld[1];

//__constant__ float dev_Deltat[1];


__host__ dev_Grid1d::dev_Grid1d( dim3 Ld_in) : Ld(Ld_in)
{
	HANDLE_ERROR(
		cudaMalloc((void**)&this->dev_f, this->NFLAT()*sizeof(float) ));

	HANDLE_ERROR(
		cudaMalloc((void**)&this->dev_foverline, this->NFLAT()*sizeof(float) ));

	HANDLE_ERROR(
		cudaMalloc((void**)&this->dev_f_out, this->NFLAT()*sizeof(float) ));

}

__host__ __device__ int dev_Grid1d :: NFLAT() {
	return Ld.x ;
}



<|start_filename|>Euler2d/physlib/dev_phys_param.cu<|end_filename|>
/* dev_phys_param.cu
 * physical parameters on the device
 * <NAME>  <EMAIL>
 * 20160804
 */
#include "dev_phys_param.h" 
 
__constant__ float dev_Deltat[1]; // Deltat

__constant__ float dev_gas_params[3] ; // dev_gas_params[0] = heat capacity ratio

/*
__device__ float pressure( float energy, float rho, float2 u ) {
	float pressure_val {0.f};
	float usqr { u.x*u.x+u.y+u.y };
	pressure_val = (dev_gas_params[0] - 1.f)*(energy-0.5f*rho*usqr) ;
	return pressure_val;
}
* */

__device__ float pressure( float energy, float rho, float usq ) {
	float pressure_val {0.f};
	
	pressure_val = (dev_gas_params[0] - 1.f)*(energy-0.5f*rho*usq) ;
	return pressure_val;
}


<|start_filename|>lid-driven-cavity_gpu-gfx/commonlib/tex_anim2d.cu<|end_filename|>
/* tex_anim2d.cu
 * 2-dim. GPU texture animation 
 * <NAME>  <EMAIL>
 * 20160720
 */
#include "tex_anim2d.h"
  
int iterationCount = 0 ;


// interactions

void keyboard_func( unsigned char key, int x, int y) {

	if (key==27) {
//		std::exit(0) ;
		exit(0);
	}
	glutPostRedisplay();
}
	
void mouse_func( int button, int state, int x, int y ) {
	glutPostRedisplay();
}

void idle() {
	++iterationCount;
	glutPostRedisplay();
}

void printInstructions() {
	printf("2 dim. texture animation \n"

			"Exit                           : Esc\n"
	
	);
}

// make* functions make functions to pass into OpenGL (note OpenGL is inherently a C API
void make_draw_texture(int w, int h) {
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 
		GL_UNSIGNED_BYTE, NULL);
	glEnable(GL_TEXTURE_2D);

	glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f); glVertex2f(0,0);
	glTexCoord2f(0.0f, 1.0f); glVertex2f(0,h);
	glTexCoord2f(1.0f, 1.0f); glVertex2f(w,h);
	glTexCoord2f(1.0f, 0.0f); glVertex2f(w,0);  // glVertex2f(float(w),0);
	glEnd();
	
	glDisable(GL_TEXTURE_2D);
}	

/* NOTE: this version of float_to_char wants to access only the "internal"
 * cells, or the so-called fluid cells (of Griebel, et. al.), NOT the 
 * boundary cells.  Hence the indexing isn't 1-to-1 */

__global__ void float_to_char( uchar4* dev_out, const float* outSrc, const int L_x, const int L_y) {
	const int k_x = threadIdx.x + blockDim.x * blockIdx.x ;
	const int k_y = threadIdx.y + blockDim.y * blockIdx.y ;
	
	const int k = k_x + k_y * blockDim.x * gridDim.x;
	if ((k_x >= L_x) || (k_y >= L_y)) {
		return ; }
		
	/* staggered_k is the index on the "staggered grid" which INCLUDES
	 * boundary cells: [0,L_X+1] x [ 0,L_Y+1]	
	 * */
	const int staggered_k = (k_x+1) + (L_x + 2) * (k_y+1);
		
	dev_out[k].x = 0;
	dev_out[k].z = 0;
	dev_out[k].y = 0;
	dev_out[k].w = 255;
	
	float value = outSrc[staggered_k] ; 

	// convert to long rainbox RGB*
	// 1. convert to [0.0,1.0] scale from [minval,maxval] (set minval,maxval MANUALLY)
	// MANUALLY change minval, maxval
	const float minval = -0.4;
	const float maxval = 1.6;

	value = (value - minval) / ( maxval - minval) ; 
	if (value < minval ) { value = 0.0; }
	else if (value > maxval ) { value = 1.0; }
	
	// 2. convert to long rainbox RGB*
	value = value / 0.20;
	int valueint  = ((int) floorf( value )); // this is the integer part
	int valuefrac = ((int) floorf( 255*(value - valueint)) );
	
	switch( valueint )
	{
		case 0: dev_out[k].x = 255; dev_out[k].y = valuefrac; dev_out[k].z = 0;
		dev_out[k].w = 255;
		break;
		case 1: dev_out[k].x = 255- valuefrac; dev_out[k].y = 255; dev_out[k].z = 0;
		dev_out[k].w = 255;
		break;
		case 2: dev_out[k].x = 0; dev_out[k].y = 255; dev_out[k].z = valuefrac;
		dev_out[k].w = 255;
		break;
		case 3: dev_out[k].x = 0; dev_out[k].y = 255- valuefrac; dev_out[k].z = 255;
		dev_out[k].w = 255;
		break;
		case 4: dev_out[k].x = valuefrac; dev_out[k].y = 0; dev_out[k].z = 255;
		dev_out[k].w = 255;
		break;
		case 5: dev_out[k].x = 255; dev_out[k].y = 0; dev_out[k].z = 255;
		dev_out[k].w = 255;
		break;
	}
}


// from physical scalar values to color intensities on an OpenGL bitmap
__global__ void floatux_to_char( uchar4* dev_out, cudaSurfaceObject_t uSurf, 
									const int L_x, const int L_y) {
	const int k_x = threadIdx.x + blockDim.x * blockIdx.x ; 
	const int k_y = threadIdx.y + blockDim.y * blockIdx.y ; 
	
	const int k = k_x + k_y * blockDim.x *gridDim.x ; 
	if ((k_x >= L_x ) || (k_y >= L_y)) {
		return ; }
	
	dev_out[k].x = 0;
	dev_out[k].y = 0;
	dev_out[k].z = 0;
	dev_out[k].w = 255;
	 
	float2 tempu; 
	surf2Dread(&tempu, uSurf, k_x * 8, k_y );

	// clipping part
	const float scale = 2.f ;
	const float newval = tempu.x / scale; 
	 
	int n = 256 * newval ; 
	n = max( min( n, 255) , 0 ) ; 
	// END of clipping part
	 
	const unsigned char intensity = n ; 
	dev_out[k].x = intensity ;  // higher magnitude -> more red
	dev_out[k].z = 255 - intensity ; // lower magnitude -> more blue
}


<|start_filename|>MacCor1d/main.cu<|end_filename|>
/* main.cu
 * 1-dim. MacCormack method
 * <NAME>  <EMAIL>
 * 20161026
 */
#include <iostream>

#include <cmath>  // std::sin
#include <cstdio> // FILE fopen
#include <vector> // std::vector

#include "./physlib/dev_R1grid.h"
#include "./physlib/R1grid.h"

#include "./commonlib/errors.h"
#include "./commonlib/kernelLaunch.h"

// device sanity checks
__global__ void sanity_checks_constants() {
	// dev_sigmaconst is the so-called Courant number, i.e. CFL (Courant Friedrichs-Lewy) number,
	// on the device GPU
	printf(" dev_sigmaconst : %2.8f \n", dev_sigmaconst[0] ) ; 
}

// host error checks
// error_check_1d : error check 1-dimensional
float error_check_1d(float *f, float *f_ref, const int L) {
	float error_val { 0.f }; 
	for (auto i = 0; i < L; ++i) {
		error_val += (f[i]-f_ref[i])*(f[i]-f_ref[i]) ; 
	}
	return error_val;
}

void traveling_sine( std::vector<float>& f, Grid1d grid1d_in, float t_now ) {
	const float PI_CONST { std::acos(-1.f) };

	std::array<int,1> ix_in { 0 }; // i index variable for initial values
	std::array<float,1> x_init{  0.f  }; // x variable for initial values
	for (auto i = 0; i < grid1d_in.NFLAT(); ++i) {
		ix_in[0] = i;
		x_init = grid1d_in.gridpt_to_space( ix_in ) ;
		if ((x_init[0] >= t_now) && ( x_init[0] <= (t_now + 1.f) )) {
			f[i] = std::sin( 2.f * PI_CONST * (x_init[0] - t_now ) ) ;
		}
		else {
			f[i] = 0.f;
		}
	}
}
		

int main(int argc, char** argv) {
	// math (constants)
	const float PI_CONST { std::acos(-1.f) };

	// computation constants
	constexpr const float Deltat {  0.001f };

	// Calculate the total number of iterations, related to time interval T
	constexpr const float timeT { 4.f };
	const int iterations { static_cast<int>(timeT/ Deltat ) } ; 
	// sanity check
	std::cout << " iterations to do : " << iterations << std::endl;

	constexpr const int WIDTH  { 500 };

	dim3 L_x(WIDTH);
	dim3 M_x(2);
	
	// physics
	//  on the host, set up the spatial manifold, Euclidean R1

	constexpr std::array<int,1> LdS { WIDTH  };
	constexpr std::array<float,1> ldS { 5.f };
	
	Grid1d grid1d( LdS, ldS);
	
	// sanity check
	std::cout << " This is hd[0], i.e. Delta x : " << grid1d.hd[0] << std::endl;
	
	//  on device, set up the spatial manifold, Euclidean R1
	dim3 dev_L1 { static_cast<unsigned int>(WIDTH) };
	dev_Grid1d dev_grid1d( dev_L1 );
	
	// initial conditions (on the host)
	std::array<int,1> ix_in { 0 }; // i index variable for initial values
	std::array<float,1> x_init{  0.f  }; // x variable for initial values
	for (int i=0; i<(grid1d.Ld[0]); ++i) {
		ix_in[0] = i;
		x_init = grid1d.gridpt_to_space( ix_in ) ;
		if ((x_init[0] >= 0.f) && ( x_init[0] <= 1.f )) {
			grid1d.f[i] = std::sin( 2.f * PI_CONST * x_init[0] ) ;
		}
		else {
			grid1d.f[i] = 0.f;
		}
	}
	
	// copy initial conditions (to the device)
	HANDLE_ERROR(
		cudaMemcpy( dev_grid1d.dev_f, grid1d.f, grid1d.NFLAT() * sizeof(float),
			cudaMemcpyHostToDevice)
	);

	// computational constants
	// Courant number, or CFL (Courant-Friedrichs-Lewy) number, denoted sigma
	float sigmaconst[1] = { Deltat/grid1d.hd[0] };
	// sanity check
	std::cout << " This is Delta t    : " << Deltat        << std::endl;
	std::cout << " This is sigmaconst : " << sigmaconst[0] << std::endl;
	std::cout << " sigmaconst denotes the so-called Courant number, \
					i.e. CFL (Courant-Friedrichs-Lewy) number " << std::endl;
	HANDLE_ERROR(
		cudaMemcpyToSymbol(
			dev_sigmaconst, sigmaconst, sizeof(float)*1, 0, cudaMemcpyHostToDevice)
	);
	// on device, sanity check
	sanity_checks_constants<<<1,1>>>();
	
	for (auto i = 0; i<iterations; ++i) {
//	for (auto i = 0; i<3000; ++i) {
		kernelLauncher( dev_grid1d.dev_f, dev_grid1d.dev_foverline, dev_grid1d.dev_f_out,
			L_x, M_x);
	}

	// copy to the host the results from the device
	HANDLE_ERROR(
		cudaMemcpy( grid1d.f , dev_grid1d.dev_f, grid1d.NFLAT() * sizeof(float),
			cudaMemcpyDeviceToHost)
	);

	std::vector<float> f_ref ;
//	traveling_sine( f_ref, grid1d, timeT ) ;

	FILE *outfile = fopen("results.csv", "w");
	for (int i = 1; i < grid1d.NFLAT(); ++i) {
		ix_in[0] = i;
		x_init = grid1d.gridpt_to_space( ix_in ); 
//		fprintf(outfile, "%d,%f,%f,%f\n", i, x_init[0], grid1d.f[i], f_ref[i] );
		fprintf(outfile, "%d,%f,%f\n", i, x_init[0], grid1d.f[i]  );
	}
	fclose(outfile);
	
	
	// 
	

	HANDLE_ERROR(
		cudaFree( dev_grid1d.dev_f )
	);
	
	HANDLE_ERROR(
		cudaFree( dev_grid1d.dev_foverline )
	);

	HANDLE_ERROR(
		cudaFree( dev_grid1d.dev_f_out )
	);

	
	
}


<|start_filename|>NavSt2DIncompFiniteDiff/main_draft03.cu<|end_filename|>
/* main.cu
 * \file main.cu
 * Navier-Stokes equation solver in 2-dimensions, incompressible flow, by finite difference
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161206
 * 
 * Compilation tips if you're not using a make file
 * 
 * nvcc -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o  // or 
 * g++ -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o
 * 
 * nvcc -std=c++11 -c ./physlib/dev_R2grid.cu -o dev_R2grid.o
 * nvcc -std=c++11 main.cu R2grid.o dev_R2grid.o o main.exe
 * 
 */
/*
 * cf. <NAME>, <NAME>.  
 * Accelerating reactive-flow simulations using graphics processing units.  
 * AIAA 2013-0371  American Institute of Aeronautics and Astronautics.  
 * http://dx.doi.org/10.5281/zenodo.44333
 * 
 * <NAME>, <NAME>, <NAME>. 
 * Numerical Simulation in Fluid Dynamics: A Practical Introduction (Monographs on Mathematical Modeling and Computation). 
 * SIAM: Society for Industrial and Applied Mathematics (December 1997). 
 * ISBN-13:978-0898713985 QA911.G718 1997
 * 
 * */ 

#include <iomanip>					// std::setprecision
#include <iostream> 				// std::cout
#include <cmath>    				// std::sqrt, std::fmax 

#include "./physlib/R2grid.h"      	// Grid2d
#include "./physlib/dev_R2grid.h"  	// Dev_Grid2d
#include "./physlib/u_p.h"          // compute_F, compute_G, compute_RHS, etc.
#include "./physlib/boundary.h"     // set_BConditions_host, set_BConditions, set_lidcavity_BConditions_host, set_lidcavity_BConditions
#include "./commonlib/checkerror.h" // checkCudaErrors

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/reduce.h>
#include <thrust/extrema.h>  // thrust::max_element (thrust::min_element)  
#include <thrust/copy.h>  // thrust::copy
#include <thrust/execution_policy.h> // thrust::device

// File I/O includes
#include <fstream> 		// std::ofstream

#include <array> 		// std::array

int main(int argc, char* argv[]) {
	// ################################################################
	// ####################### Initialization #########################
	// ################################################################
	
	// discretization (parameters) <==> graphical (parameters)
	const int L_X { 512 };  			// WIDTH   // I've tried values 32.  128, 32, 0.5 works; 256, 32, 0.25 works (even though 256, 64 doesn't); 512, 64, doesn't work, neither does 512,32; 512, 16 works
	const int L_Y { 512 };  			// HEIGHT  // I've tried values 32,  128, 32, 0.5 works

	// "real", physical parameters
	/** try domain size (non-dimensional) */
	constexpr const float l_X = 1.0;  	// length (in x-direction)
	constexpr const float l_Y = 1.0; 	// height (in y-direction)

	// physics (on device); Euclidean (spatial) space
	dim3 dev_L2 { static_cast<unsigned int>(L_X), 
				static_cast<unsigned int>(L_Y) };

	Dev_Grid2d dev_grid2d( dev_L2); 

	// physics (on host); Euclidean (spatial) space
	constexpr std::array<int,2> LdS { L_X, L_Y } ;
	constexpr std::array<float,2> ldS { l_X, l_Y };

	Grid2d grid2d{LdS, ldS};

	// dynamics (parameters)
	const dim3 M_i { 32, 32 }; 	// number of threads per block, i.e. Niemeyer's BLOCK_SIZE // I've tried values 4,4

	float t = 0.0 ;
	int cycle = 0;
	
	// iterations for SOR successive over relaxation
	int iter = 0;
	int itermax = 10000;  // I tried values such as 10000, Griebel, et. al. = 100

	/* READ the parameters of the problem                 */
	/* -------------------------------------------------- */ 

	/** Safety factor for time step modification; safety factor for time stepsize control */
	constexpr const float tau = 0.5; 

	/** SOR relaxation parameter; omg is Griebel's notation */
	constexpr const float omega = 1.7;  
	
	/** Discretization mixture parameter (gamma); gamma:upwind differencing factor is Griebel's notation */
	constexpr const float gamma = 0.9;

	/** Reynolds number */
	constexpr const float Re_num = 1000.0;

	// SOR iteration tolerance
	const float tol = 0.001;  // Griebel, et. al., and Niemeyer has this at 0.001
	
	// time range
	const float time_start = 0.0;
	const float time_end = 1.4000;  // L_X=L_Y=128, M_i=32, t_f=0.5 works
	
	// initial time step size
	float deltat = 0.02; // I've tried values 0.002
	
	// set initial BCs on host CPU
	set_BConditions_host( grid2d );
	set_lidcavity_BConditions_host( grid2d );

	set_BConditions( dev_grid2d );
	set_lidcavity_BConditions( dev_grid2d );

	/* delt satisfying CFL conditions */
	/* ------------------------------ */
	float max_u = 1.0e-10;
	float max_v = 1.0e-10;

	// variables to store maximum velocities
	thrust::device_vector<float> max_u_vec(grid2d.NFLAT());
	thrust::device_vector<float> max_v_vec(grid2d.NFLAT());

	// get max velocity for initial values (including BCs)
	#pragma unroll
	for (auto j = 1; j < grid2d.staggered_Ld[1]; ++j) {
		#pragma unroll
		for (auto i = 0; i < grid2d.staggered_Ld[0]; ++i) {
			max_u = std::fmax( max_u, 
				fabs( dev_grid2d.u[ i + grid2d.staggered_Ld[0] * j] )  ) ;
		}
	}	
	#pragma unroll
	for (auto j = 0; j < grid2d.staggered_Ld[1]; ++j) {
		#pragma unroll
		for (auto i = 1; i < grid2d.staggered_Ld[0]; ++i) {
			max_v = std::fmax( max_v, 
				fabs( dev_grid2d.v[ i + grid2d.staggered_Ld[0] * j] )  ) ;
		}
	}	
	

// This is why you can't do (dev_grid2d->u).end()
// cf. http://stackoverflow.com/questions/13104138/error-expression-must-have-a-pointer-type-when-using-the-this-keyword
/*	thrust::device_vector<float>::iterator max_u_iter = 
		thrust::max_element( dev_grid2d.u.begin(), dev_grid2d.u.end() );
	max_u = std::fmax( *max_u_iter, max_u ) ;

	thrust::device_vector<float>::iterator max_v_iter = 
		thrust::max_element( dev_grid2d.v.begin(), dev_grid2d.v.end() );
	max_v = std::fmax( *max_v_iter, max_v ) ;
*/	

	////////////////////////////////////////	
	// block and grid dimensions
	// "default" gridSize is number of blocks on a grid along a dimension
	dim3 gridSize ( (grid2d.staggered_Ld[0] + M_i.x -1)/M_i.x, 
						(grid2d.staggered_Ld[1] + M_i.y - 1)/M_i.y) ;
	
	// pressure kernel, alternative way to launch threads in blocks, so called sPencil
/*	dim3 block_press( M_i.x, 1 ) ; 
	dim3 grid_press( ( grid2d.staggered_Ld[0] + block_press.x - 1)/block_press.x , grid2d.staggered_Ld[1] ) ;
	* */
	////////////////////////////////////////

	// residual variable
	// residualsquared thrust device vector
	thrust::device_vector<float> residualsq(grid2d.staggered_SIZE() );
	float* residualsq_Array = thrust::raw_pointer_cast( residualsq.data() );

	
	// pressure sum 
	/* Note that the pressure summation needed to normalize to the pressure magnitude for 
	 * relative tolerance is, in Griebel, et. al's implementation, the first part of the 
	 * POISSON routine, and used at the very end of POISSON, here in the GPU implementation
	 * it's separated */ 
	thrust::device_vector<float> pres_sum_vec(grid2d.NFLAT());
	float* pres_sum_Arr = thrust::raw_pointer_cast( pres_sum_vec.data() );
	

	// time-step size based on grid and Reynolds number
	float dt_Re = 0.5 * Re_num / ((1.0 / (grid2d.hd[0] * grid2d.hd[0])) + (1.0 / (grid2d.hd[1] * grid2d.hd[1])));
	
	// ################################################################
	// #######################               ##########################
	// #######################   MAIN LOOP   ##########################
	// #######################               ##########################
	// ################################################################
	
				/* t i m e    l o o p */
				/* ------------------ */
	// time iteration loop
	for (t=time_start,cycle=0; t < time_end; cycle++) {

		// calculate time step based on stability and CFL
		deltat = std::fmin( (grid2d.hd[0] / max_u), ( grid2d.hd[1]/ max_v) );
		deltat = tau * std::fmin( dt_Re, deltat);

		if ((t+deltat) >= time_end) {
			deltat = time_end - t; }
	
	
		/* Compute tentative velocity field (F,G) */
		// i.e. calculate F and G
		/* -------------------------------------- */			
		compute_F<<<gridSize,M_i>>>( deltat, 
			dev_grid2d.u_arr, dev_grid2d.v_arr, dev_grid2d.F_arr,
			grid2d.Ld[0], grid2d.Ld[1], grid2d.hd[0], grid2d.hd[1],
			gamma, Re_num); 

		compute_G<<<gridSize,M_i>>>( deltat, 
			dev_grid2d.u_arr, dev_grid2d.v_arr, dev_grid2d.G_arr,
			grid2d.Ld[0], grid2d.Ld[1], grid2d.hd[0], grid2d.hd[1],
			gamma, Re_num); 

	

	// get L2 norm of initial pressure
	for (auto j = 0; j < dev_grid2d.staggered_Ld.y; ++j) {
		for (auto i = 0; i < dev_grid2d.staggered_Ld.x; ++i) {
			if ((i>0)&&(i<(dev_grid2d.Ld.x+1)) && (j>0) && (j<(dev_grid2d.Ld.y+1))) {
				int k = (i-1) + dev_grid2d.Ld.x * (j-1) ; 
				pres_sum_vec[k] = dev_grid2d.p[ dev_grid2d.staggered_flatten(i,j) ] ; 
			}
		}
	}
	float p0_norm = 0.0;
	p0_norm = thrust::reduce( pres_sum_vec.begin(), pres_sum_vec.end(), 0, thrust::plus<float>() );
	
	p0_norm =sqrt(p0_norm / (static_cast<float>( grid2d.NFLAT() ) ));
	
	if (p0_norm < 0.0001) {
		p0_norm = 1.0;
	}
	
	// ensure all kernels are finished
	cudaDeviceSynchronize();
	
	/* Compute right hand side for pressure equation */
	/* --------------------------------------------- */
	compute_RHS<<<gridSize,M_i>>>( dev_grid2d.F_arr, dev_grid2d.G_arr,
		dev_grid2d.RHS_arr, 
		dev_grid2d.Ld.x, dev_grid2d.Ld.y, 
		deltat, grid2d.hd[0], grid2d.hd[1] );
	
	float norm_L2; // residual; res for Griebel, et. al., norm_L2 for Niemeyer
	
	/* Solve the pressure equation by successive over relaxation */
	/* ---------------------------------------------------------- */
	// calculate new pressure
	for (iter = 1; iter <= itermax; iter++) {
		// set pressure boundary conditions
		set_horiz_press_BCs( dev_grid2d ) ;
		set_vert_press_BCs( dev_grid2d ) ;
	
		// ensure kernel finished
		cudaDeviceSynchronize();
	
		// operations needed to do poisson; poisson and thrust::swap
/*
		poisson<<<gridSize, M_i>>>( dev_grid2d.p_arr, dev_grid2d.RHS_arr, 
			dev_grid2d.p_temp_arr, 
			grid2d.Ld[0], grid2d.Ld[1], grid2d.hd[0], grid2d.hd[1], omega) ; 

		thrust::copy( thrust::device, dev_grid2d.p_temp.begin(), dev_grid2d.p_temp.end(), dev_grid2d.p.begin() );
			// dev_grid2d.p is no a copy of dev_grid2d.p_temp
*/
		// END of operations needed to do poisson; poisson and thrust::swap


		
		poisson_redblack<<<gridSize, M_i>>>( dev_grid2d.p_arr, dev_grid2d.RHS_arr, 
			grid2d.Ld[0], grid2d.Ld[1], grid2d.hd[0], grid2d.hd[1], omega) ; 


		// calculate residual values
		compute_residual<<<gridSize, M_i>>>( dev_grid2d.p_arr, dev_grid2d.RHS_arr, 
			grid2d.Ld[0], grid2d.Ld[1], grid2d.hd[0], grid2d.hd[1], 
			residualsq_Array) ; 

		
		norm_L2 = thrust::reduce( residualsq.begin(), residualsq.end(), 0, thrust::plus<float>() );
		
		// calculate residual
		norm_L2 = sqrt( norm_L2/ ( static_cast<float>( grid2d.NFLAT() )) ) / p0_norm;


		// if tolerance has been reached, end SOR iterations
		if (norm_L2 < tol) {
			break;
		}				
	} // END for loop, to solve the pressure equation by SOR

	std::cout << "Time = " << t + deltat << ", delta t = " << deltat << ", iter = " 
		<< iter << 	", res (or norm_L2) = " << std::setprecision(9) << norm_L2 << 
		", max_u : " << max_u << ", max_v : " << max_v << ", p0_norm : " << p0_norm << 
		", cycle = " << cycle << std::endl; 

		/* Compute the new velocity field */
		// i.e. calculate new velocities
		/* ------------------------------ */

		calculate_u<<<gridSize,M_i>>>( dev_grid2d.u_arr, dev_grid2d.p_arr,
			dev_grid2d.F_arr, grid2d.Ld[0], grid2d.Ld[1], deltat, grid2d.hd[0] );

		calculate_v<<<gridSize,M_i>>>( dev_grid2d.v_arr, dev_grid2d.p_arr,
			dev_grid2d.G_arr, grid2d.Ld[0], grid2d.Ld[1], deltat, grid2d.hd[1] );


		// get maximum u- and v- velocities
		max_v = 1.0e-10;
		max_u = 1.0e-10;
	
		for (auto j = 0 ; j < grid2d.Ld[1] ; ++j) { 
			for (auto i = 0; i < grid2d.Ld[0]; ++i) {
				max_u_vec[i + grid2d.Ld[0]*j] = dev_grid2d.u[ (i+1) + grid2d.staggered_Ld[0] * (j+1) ] ;  
				max_v_vec[i + grid2d.Ld[0]*j] = dev_grid2d.v[ (i+1) + grid2d.staggered_Ld[0] * (j+1) ] ;
			}
		}

		thrust::device_vector<float>::iterator max_u_iter = 
			thrust::max_element( max_u_vec.begin(), max_u_vec.end() );
		max_u = std::fmax( *max_u_iter, max_u);

		thrust::device_vector<float>::iterator max_v_iter = 
			thrust::max_element( max_v_vec.begin(), max_v_vec.end() );
		max_v = std::fmax( *max_v_iter, max_v);



		// set velocity boundary conditions
		/* Set boundary conditions */
		/* ----------------------- */
		set_BConditions( dev_grid2d ) ;
		
		/* Set special boundary conditions */
		/* Overwrite preset default values */
		/* ------------------------------- */
		set_lidcavity_BConditions( dev_grid2d  );

		cudaDeviceSynchronize();

		// increase time
		t += deltat;

	} // END end for loop, time iteration loop 

	// sanity check
	std::cout << " Right after time iteration loop, final p : " << std::endl;
	std::cout << "\n dev_grid2d.p : " << std::endl; 
//		for (auto j = (grid2d.staggered_Ld[1]-1); j >= 0; --j) {
//			for (auto i = 0; i < grid2d.staggered_Ld[0]; ++i) {
		for (auto j = (grid2d.staggered_Ld[1]-1)/2; j >= 0; --j) {
			for (auto i = 0; i < grid2d.staggered_Ld[0]/2; ++i) {
				std::cout << std::setprecision(3) << dev_grid2d.p[i+(grid2d.staggered_Ld[0])*j] << " " ; }
			std::cout << std::endl ; }
	// END of sanity check

	// ################################################################
	// ########################## File I/O ############################
	// ################################################################

	std::ofstream ofile; // no file mode is set
	ofile.open("velocity_gpu.dat"); // mode implicitly out and trunc

	ofile << "#x\ty\tu\tv\n" ;
	
	std::array<int,2> ix_ind;
	std::array<float,2> x_ind;
	
	for (auto j = 0; j <= grid2d.Ld[1]; j++) {
		for (auto i = 0; i <= grid2d.Ld[0]; i++) {
			float u_ij = dev_grid2d.u[ i + grid2d.staggered_Ld[0] * j ] ; 
			float v_ij = dev_grid2d.v[ i + grid2d.staggered_Ld[0] * j ] ; 
			
			ix_ind[0] = i; 
			ix_ind[1] = j; 
			x_ind = grid2d.gridpt_to_space( ix_ind ) ;
			
			ofile << x_ind[0] << "\t" << x_ind[1] << "\t" << u_ij << "\t" << v_ij << std::endl;
		}
	}
	ofile.close();

	
	std::cout << " End of program " << std::endl;
	return 0;
} 



<|start_filename|>convect3dfinitedifftex/physlib/convect.h<|end_filename|>
/* convect.h
 * 3-dim. convection by finite difference with shared memory
 * <NAME>  <EMAIL>
 * 20160720
 */
#ifndef __CONVECT_H__
#define __CONVECT_H__

#include "../commonlib/finitediff.h"
#include "../commonlib/sharedmem.h"

#include "../physlib/dev_R3grid.h"

extern __constant__ float dev_Deltat[1] ; // Deltat

// convect_fd_naive_sh - convection with finite difference and naive shared memory scheme
__global__ void convect_fd_naive_sh( float* dev_rho, float3* dev_u ) ;

__global__ void convect_sh( float* dev_rho, float3* dev_u);

#endif // __CONVECT_H__


<|start_filename|>convect3dupwind/convect3dupwind.cu<|end_filename|>
/*
 * convect3dupwind_shared.cu
 * 3-dimensional convection with time-independent velocty vector field using
 * CUDA C/C++ implementing "Upwind" interpolation
 * <NAME>  <EMAIL>
 * 20160704
*/

#include "./commonlib/gpu_anim.h"
#include "./commonlib/errors.h"
#include "./commonlib/gpu_bitmap.h"

#include "./physlib/R3grid.h"
#include "./physlib/dev_R3grid.h"

#include "math.h" // CUDA C/C++ math.h

#define N_x 1920 // total number of blocks in the grid in x-direction
#define N_y 1920 // total number of blocks in the grid in y-direction
#define N_z 32 // total number of blocks in the grid in z-direction

#define M_x 16 // number of threads per block in x-direction
#define M_y 16 // number of threads per block in y-direction
#define M_z 4 // number of threads per block in z-direction

#define DELTAt 1./(100000.)
#define RHO0 0.956 // 0.656
#define L_0X 1.0
#define L_0Y 1.0
#define L_0Z 1.0
#define DELTAx L_0X/((float) N_x)
#define DELTAy L_0Y/((float) N_y)
#define DELTAz L_0Z/((float) N_z)


__global__ void convect( float *rho, float *ux, float *uy, float *uz) {
	// Experimental 
	dev_Grid3d blockgrid3d {blockDim.x*gridDim.x, blockDim.y*gridDim.y, blockDim.z*gridDim.z};

	// map from threadIdx/blockIdx to x grid position
	int k_x = threadIdx.x + blockIdx.x * blockDim.x;
	int k_y = threadIdx.y + blockIdx.y * blockDim.y;
	int k_z = threadIdx.z + blockIdx.z * blockDim.z;
	int offset = k_x + k_y*blockDim.x*gridDim.x + k_z*blockDim.x*gridDim.x*blockDim.y*gridDim.y;

	int left     = offset - 1;
	int right    = offset + 1;
	int down     = offset + N_x;  // on a bitmap, up down is "backwards"
	int up       = offset - N_x;
	int top      = offset + N_x*N_y;
	int bottom   = offset - N_x*N_y;

	if (k_x == 0) {
		left++;
	}
	if (k_x==(N_x-1)) {
		right--; }
	if (k_y == 0) { up += N_x; }
	if (k_y == (N_y - 1 )) { down -= N_x ; }
	if (k_z == 0) { bottom += N_x*N_y; }
	if (k_z == (N_z - 1) ) { top -= N_x*N_y ; }

	float flux_right;
	if (ux[offset]>0.) { flux_right = DELTAy*DELTAz*rho[offset]*ux[offset] ; }
	else { flux_right = DELTAy*DELTAz*rho[right]*ux[offset] ; }
	float flux_left;
	if (ux[left] > 0.) { flux_left = (-1.)*DELTAy*DELTAz*rho[left]*ux[left]; }
	else { flux_left = (-1.)*DELTAy*DELTAz*rho[offset]*ux[left] ; }
	
	float flux_up;
	if (uy[up] > 0.) { flux_up = (-1.)*DELTAx*DELTAz*rho[up]*uy[up] ; }
	else { flux_up = (-1.)*DELTAx*DELTAz*rho[offset]*uy[up] ; }
	
	float flux_down;
	if (uy[offset] >0.) { flux_down = DELTAx*DELTAz*rho[offset]*uy[offset]; }
	else { flux_down = DELTAx*DELTAz*rho[down]*uy[offset]; }
		
	float flux_top;
	if (uz[offset]>0.) { flux_top = DELTAx*DELTAy*rho[offset]*uz[offset] ; }
	else { flux_top = DELTAx*DELTAy*rho[top]*uz[offset]; }
	float flux_bottom;
	if (uz[bottom]>0. ) { flux_bottom = (-1.)*DELTAx*DELTAy*rho[bottom]*uz[bottom] ; }
	else { flux_bottom = (-1.)*DELTAx*DELTAy*rho[offset]*uz[bottom] ; }
		
	rho[offset] += (-1.)*(DELTAt/(DELTAx*DELTAy*DELTAz))*( 
					flux_right+flux_left+flux_up+flux_down +flux_top+flux_bottom);
}
	
float gaussian3d( float x, float y, float z, float A, float k, float x_0, float y_0, float z_0) 
{
	return A*exp(-k*((x-x_0)*(x-x_0)+(y-y_0)*(y-y_0) +(z-z_0)*(z-z_0))); 
}


// globals needed by the update routine
struct DataBlock {
	float         *dev_rho;
	float         *dev_ux;
	float         *dev_uy;
	float         *dev_uz;
	GPUAnimBitmap *bitmap;
	cudaEvent_t   start, stop;
	float         totalTime;
	float         frames;
};

__global__ void profile2d( uchar4* optr , const float* outSrc) {
	// map from threadIdx/BlockIdx to pixel position
	int k_x = threadIdx.x + blockIdx.x*blockDim.x ;
	int k_y = threadIdx.y + blockIdx.y*blockDim.y ;

	// choose at which z coordinate to make the slice in x-y plane
	int zcoordslice = blockDim.z*gridDim.z/2*1; 
	int offset = k_x + k_y*blockDim.x*gridDim.x ;
	int fulloffset = offset + zcoordslice*blockDim.x*gridDim.x*blockDim.y*gridDim.y ;
	float value = outSrc[fulloffset];
	
	if (value < 0.0001 ) { value = 0; }
	else if (value > 1.0 ) { value = 1.; } 

	// convert to long rainbow RGB* 
	value = value/0.20;
	int valueint  = ((int) floorf( value )); // this is the integer part 
	int valuefrac = ((int) floorf(255*(value-valueint)) );
	
	switch( valueint )
	{
		case 0:	optr[offset].x = 255; optr[offset].y = valuefrac; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 1:	optr[offset].x = 255-valuefrac; optr[offset].y = 255; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 2:	optr[offset].x = 0; optr[offset].y = 255; optr[offset].z = valuefrac; 
		optr[offset].w = 255; 
		break;
		case 3:	optr[offset].x = 0; optr[offset].y = 255-valuefrac; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 4:	optr[offset].x = valuefrac; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 5:	optr[offset].x = 255; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
	}
}

__global__ void float_to_color3d( uchar4* optr, const float* outSrc) {
	// map from threadIdx/BlockIdx to pixel position
	int k_x = threadIdx.x + blockIdx.x*blockDim.x ;
	int k_y = threadIdx.y + blockIdx.y*blockDim.y ;

	// choose at which z coordinate to make the slice in x-y plane
	int zcoordslice = blockDim.z*gridDim.z/2*1; 

	int offset = k_x + k_y*blockDim.x*gridDim.x ;
	int fulloffset = offset + zcoordslice*blockDim.x*gridDim.x*blockDim.y*gridDim.y ;
	float value = outSrc[fulloffset];
	
	// Be aware of the "hard-coded" (numerical) constants for 
	// maximum and minimum scalar values that'll be assigned white and black, respectively
	if (value < 0.0001 ) { value = 0; }
	else if (value > 1.0 ) { value = 1.; } 

	// convert to long rainbow RGB* 
	value = value/0.20;
	int valueint  = ((int) floorf( value )); // this is the integer part 
	int valuefrac = ((int) floorf(255*(value-valueint)) );
	
	switch( valueint )
	{
		case 0:	optr[offset].x = 255; optr[offset].y = valuefrac; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 1:	optr[offset].x = 255-valuefrac; optr[offset].y = 255; optr[offset].z = 0; 
		optr[offset].w = 255; 
		break;
		case 2:	optr[offset].x = 0; optr[offset].y = 255; optr[offset].z = valuefrac; 
		optr[offset].w = 255; 
		break;
		case 3:	optr[offset].x = 0; optr[offset].y = 255-valuefrac; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 4:	optr[offset].x = valuefrac; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
		case 5:	optr[offset].x = 255; optr[offset].y = 0; optr[offset].z = 255; 
		optr[offset].w = 255; 
		break;
	}
}

void anim_gpu(uchar4* outputBitmap, DataBlock *d, int ticks) {
	cudaEventRecord( d-> start,0 );
	
	dim3 grids((N_x+M_x-1)/M_x,(N_y+M_x-1)/M_y,(N_z+M_z-1)/M_z);
	dim3 threads(M_x,M_y,M_z);
//	/* change the 1000 time steps per frame manually 
	for (int i = 0; i < 2; ++i ) {
		convect<<<grids,threads>>>( d->dev_rho, d->dev_ux, d->dev_uy, d->dev_uz);
	}
	
	float_to_color3d<<<grids,threads>>>( outputBitmap, d->dev_rho);
	
	// Recording time for rough benchmarking, only
	cudaEventRecord( d-> stop, 0);
	cudaEventSynchronize(d-> stop);
	float elapsedTime;
	cudaEventElapsedTime( &elapsedTime, d->start, d->stop);
	
	d->totalTime += elapsedTime;
	++d->frames;
	printf("Average Time per frame:  %3.1f ms\n",d->totalTime/d->frames );
	// END of Recording time for rough benchmarking, only, END
}

int main( void ) {
	// sanity check
	Grid3d grid3dsanity { N_x,N_y,N_z };
	std::cout << " These are the default h_i values : " << grid3dsanity.h_is[0] << " " 
		<< grid3dsanity.h_is[1] << " " << grid3dsanity.h_is[2] << std::endl;

	Grid3d grid3d { N_x,N_y,N_z, DELTAx, DELTAy, DELTAz };
	
	DataBlock data;

	GPUAnimBitmap bitmap( grid3d.N_is[0], grid3d.N_is[1], &data );

	data.bitmap = &bitmap;
	data.totalTime = 0;
	data.frames = 0;
	// END of GPU animation setup END

	cudaEventCreate( &data.start );
	cudaEventCreate( &data.stop  );
	
	float* rho = new float[grid3d.NFLAT()];
	float* ux  = new float[grid3d.NFLAT()];  
	float* uy  = new float[grid3d.NFLAT()];  
	float* uz  = new float[grid3d.NFLAT()];  


	HANDLE_ERROR( 
		cudaMalloc((void**)&data.dev_rho,grid3d.NFLAT()*sizeof(float))
		);
	HANDLE_ERROR(
		cudaMalloc((void**)&data.dev_ux,grid3d.NFLAT()*sizeof(float))
			);
	HANDLE_ERROR(
		cudaMalloc((void**)&data.dev_uy,grid3d.NFLAT()*sizeof(float))
		);
	HANDLE_ERROR(
		cudaMalloc((void**)&data.dev_uz,grid3d.NFLAT()*sizeof(float))
		);

	// initial conditions

	for (int k=0; k<(grid3d.N_is[2]); ++k) {
		for (int j=0; j<(grid3d.N_is[1]); ++j) {
			for (int i=0;i<(grid3d.N_is[0]); ++i) {
				ux[ grid3d.flatten(i,j,k)] = 20.0; // meters/second

				uy[ grid3d.flatten(i,j,k) ] = 20.0; // meters/second
				uz[ grid3d.flatten(i,j,k) ] = 16.0 ;
			}
		}
	}

	for (int k=0; k<(grid3d.N_is[2]); ++k) {
		for (int j=0; j<(grid3d.N_is[1]); ++j) {
			for (int i=0; i<(grid3d.N_is[0]); ++i) {
				rho[ grid3d.flatten(i,j,k) ] = 
					gaussian3d( ((float) i)*grid3d.h_is[0],
								((float) j)*grid3d.h_is[1], ((float) k)*grid3d.h_is[2],
									RHO0, 1./sqrt(0.0001),0.25,0.25, 0.5);
			}
		}
	}
	
	HANDLE_ERROR(
		cudaMemcpy( data.dev_rho, rho, grid3d.NFLAT()*sizeof(float), cudaMemcpyHostToDevice)
		);
	HANDLE_ERROR(
		cudaMemcpy( data.dev_ux, ux, grid3d.NFLAT()*sizeof(float), cudaMemcpyHostToDevice)
		);
	HANDLE_ERROR(
		cudaMemcpy( data.dev_uy, uy, grid3d.NFLAT()*sizeof(float), cudaMemcpyHostToDevice)
		);
	HANDLE_ERROR(
		cudaMemcpy( data.dev_uz, uz, grid3d.NFLAT()*sizeof(float), cudaMemcpyHostToDevice)
		);
	
	delete[] rho;
	delete[] ux;
	delete[] uy;
	delete[] uz;
	
	bitmap.anim_and_exit((void (*)(uchar4*,void*,int))anim_gpu, NULL);
}
	


<|start_filename|>convect3dupwind/physlib/R3grid.h<|end_filename|>
/* R3grid.h
 * R3 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20160701
 */
#ifndef __R3GRID_H__
#define __R3GRID_H__

class Grid3d
{
	public : 
		const int   N_is[3];
		const float h_is[3];
		
		Grid3d(const int N_x = 2, const int N_y = 2, const int N_z = 2, 
				const float h_x = 0.1f, const float h_y = 0.1f, const float h_z = 0.1f);

		
		float l_i(int i) ;
		int* is_grid_pt(int* I) ;
		void gridpt_to_space(int* Index, float* Xi) ;
		
		int NFLAT();
		
		int flatten(const int i_x, const int i_y, const int i_z) ;
	
//		~Grid3d();	
};

#endif // __R3GRID_H__


<|start_filename|>MacCor1d/physlib/R1grid.h<|end_filename|>
/* R1grid.h
 * R1 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20161026
 * */
#ifndef __R1GRID_H__
#define __R1GRID_H__

#include <array> // std::array

class Grid1d
{
	public :
		std::array<int,1> Ld;
		std::array<float,1> ld;
		std::array<float,1> hd;

		// Put in the desired physical objects that live on top of manifold here.
		// this has to be a pointer to a float or "old-school" float array 
		// in order to be cuda copied back to the host
		float* f; // represents dynamic scalar quantity, u in Cebeci, Shao, Kafyeke, Laurendeau
		
		Grid1d(std::array<int,1> Ld_in, std::array<float,1> ld_in);
		
		std::array<float,1> gridpt_to_space(std::array<int,1> );
		
		int NFLAT();
		
		// destroy the physical quantities that sit on the R1 manifold
		~Grid1d();
};

#endif // __R1GRID_H__


<|start_filename|>NavSt2DIncompFiniteDiff/physlib/boundary.h<|end_filename|>
/* boundary.h
 * fix boundary conditions at the "boundary strip" cf. Griebel, Dornseifer, & Neunhoeffer (1997)
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161207
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/boundary.cu -o boundary.o
 * 
 */
#ifndef __BOUNDARY_H__
#define __BOUNDARY_H__

#include "../physlib/R2grid.h"       // Grid2d
#include "../physlib/dev_R2grid.h"       // Dev_Grid2d

/* --------------------------------------------------------------- */
/* Setting the boundary conditions at the boundary strip.      	   */
// on the host CPU memory
/* --------------------------------------------------------------- */
__host__ void set_BConditions_host( Grid2d & grid2d) ; 

__host__ void set_lidcavity_BConditions_host( Grid2d & ) ; 

/* --------------------------------------------------------------- */
/* Setting the boundary conditions at the boundary strip.      	   */
// on the device GPU memory
/* --------------------------------------------------------------- */

void set_BConditions( Dev_Grid2d & dev_grid2d ) ;

__host__ void set_lidcavity_BConditions( Dev_Grid2d & );

////////////////////////////////////////////////////////////////////////

__host__ void set_horiz_press_BCs( Dev_Grid2d & ) ;

////////////////////////////////////////////////////////////////////////

__host__ void set_vert_press_BCs( Dev_Grid2d & ) ;



#endif // __BOUNDARY_H__


<|start_filename|>convect2dfinitedifftex/main.cu<|end_filename|>
/*
 * main.cu
 * 3-dimensional convection with time-independent velocty vector field using
 * CUDA C/C++ implementing finite difference
 * <NAME>  <EMAIL>
 * 20160723
*/
#include <functional>

#include "./commonlib/tex_anim2d.h"
#include "./commonlib/errors.h"
#include "./commonlib/finitediff.h"

#include "./physlib/convect.h"
#include "./physlib/R2grid.h"
#include "./physlib/dev_R2grid.h"

#include "math.h" // CUDA C/C++ math.h

#define GL_GLEXT_PROTOTYPES // needed for identifier glGenBuffer, glBindBuffer, glBufferData, glDeleteBuffers

#include <GL/glut.h>

#include <cuda_runtime.h>

#include <cuda_gl_interop.h>


const float Deltat[1] { 0.00001f } ; 

// physics
const int W { 680 } ;
const int H { 680 } ;

dim3 dev_L2 { static_cast<unsigned int>(W), 
				static_cast<unsigned int>(H)
				 };
				
dev_Grid2d dev_grid2d( dev_L2 );		


// graphics + physics

const dim3 M_i { 2, 2  };

const int iters_per_render { 5 } ;


GPUAnim2dTex animtexmap( W, H );
GPUAnim2dTex* texptr = &animtexmap;


// struct DataBlock for recording, benchmarking events, iterations
struct DataBlock {
	cudaEvent_t  start, stop;
	float        totalTime;
	float        frames; 
};

DataBlock databenchmarks ; 



void make_render(int iters_per_render ) {
	uchar4* dev_out=0; 
	
	HANDLE_ERROR(
		cudaGraphicsMapResources(1, &(texptr->cuda_pixbufferObj_resource), 0 ) );
	
	HANDLE_ERROR(
		cudaGraphicsResourceGetMappedPointer((void **)&dev_out, NULL, 
			texptr->cuda_pixbufferObj_resource ) 
	);
	
	dim3 grids( (dev_L2.x+M_i.x-1)/M_i.x,(dev_L2.y+M_i.y-1)/M_i.y ) ;

	
	cudaEventRecord( databenchmarks.start, 0 );
	
	for (int i = 0 ; i < iters_per_render; ++i ) {
		convect_fd_naive_sh<<<grids,M_i>>>(
			dev_grid2d.dev_rho, dev_grid2d.dev_u ); 

//		convect_sh<<<grids,M_i, smSz>>>( dev_grid3d.dev_rho, dev_grid3d.dev_u ) ;

//		float_to_color3d<<<grids,M_i>>>(dev_out, dev_grid3d.dev_rho ) ;


//		float_to_char<<<grids,M_i>>>(dev_out, dev_grid3d.dev_rho ) ;

	}
	//float_to_color3d<<<grids,M_i>>>(dev_out, dev_grid3d.dev_rho ) ;

	float_to_char<<<grids,M_i>>>(dev_out, dev_grid2d.dev_rho ) ;


	// Recording time for rough benchmarking, only
	cudaEventRecord( databenchmarks.stop, 0 );
	cudaEventSynchronize( databenchmarks.stop );

	float elapsedTime;
	cudaEventElapsedTime( &elapsedTime, databenchmarks.start, databenchmarks.stop );

	databenchmarks.totalTime += elapsedTime;
	++databenchmarks.frames;

//	printf("Iteration complete : ticks %d \n ", ticks );
	printf("Average Time per frame: %3.1f ms \n", databenchmarks.totalTime/databenchmarks.frames );
	// END of Recording time for rough benchmarking, only, END


	HANDLE_ERROR(
		cudaGraphicsUnmapResources( 1, &texptr->cuda_pixbufferObj_resource, 0 ));


	char title[128];
	sprintf(title, "mass density Visualizer - Iterations=%4d, ", iterationCount );
	
	glutSetWindowTitle(title);
}; 

std::function<void()> render = std::bind( make_render, iters_per_render ) ;



std::function<void()> draw_texture = std::bind( make_draw_texture, W,H) ;

void display() {
	render();
	draw_texture()   ;


	glutSwapBuffers();
}




int main(int argc, char** argv) {
	// physics
	constexpr float rho_0 { 0.956 };
	constexpr std::array<int,2> LdS { W, H} ; 
	constexpr std::array<float,2> ldS { 1.f, 1.f };

	HANDLE_ERROR(
		cudaMemcpyToSymbol( dev_Deltat, Deltat, sizeof(float)*1,0,cudaMemcpyHostToDevice) );

	const int Ld_to_const[2] { LdS[0], LdS[1]  };
	
	HANDLE_ERROR(
		cudaMemcpyToSymbol( dev_Ld, Ld_to_const, sizeof(int)*2,0,cudaMemcpyHostToDevice) );



	Grid2d grid2d( LdS, ldS);

	const float hds[2] { grid2d.hd[0], grid2d.hd[1] };

	set2DerivativeParameters(hds );

	// data benchmarking, cuda timing of events
	databenchmarks.totalTime = 0;
	databenchmarks.frames = 0 ;

	cudaEventCreate( &databenchmarks.start );
	cudaEventCreate( &databenchmarks.stop );
	


	// graphics setup
	
	texptr->initGLUT(&argc,argv) ;
	 
	glutKeyboardFunc( keyboard_func );
	glutMouseFunc( mouse_func );
	glutIdleFunc( idle );
	glutDisplayFunc( display) ;
	texptr->initPixelBuffer();
		

	// initial conditions

	for (int j=0; j<(grid2d.Ld[1]); ++j) {
		for (int i=0;i<(grid2d.Ld[0]); ++i) {
			grid2d.u[ grid2d.flatten(i,j) ].x = 25.0;  // meters/second
			grid2d.u[ grid2d.flatten(i,j) ].y = 25.0;  // meters/second
		}
	}

	std::array<int,2> ix_in { 0, 0  };
	std::array<float,2> b_0 { 0.25f*grid2d.ld[0], 0.25f*grid2d.ld[1]   };
	
	for (int j=0; j<(grid2d.Ld[1]); ++j) {
		for (int i=0; i<(grid2d.Ld[0]); ++i) {
			ix_in[0] = i;
			ix_in[1] = j;
			grid2d.rho[ grid2d.flatten(i,j) ] = 
					gaussian2d( rho_0, 0.05, b_0,grid2d.gridpt_to_space(ix_in));

		}
	}
	


	HANDLE_ERROR(
		cudaMemcpy( dev_grid2d.dev_rho, grid2d.rho, grid2d.NFLAT()*sizeof(float), cudaMemcpyHostToDevice)
		);

	HANDLE_ERROR(
		cudaMemcpy( dev_grid2d.dev_u, grid2d.u, grid2d.NFLAT()*sizeof(float2), cudaMemcpyHostToDevice)
		);


	glutMainLoop();

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_rho )  );

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_u ) );
		
	texptr->exitfunc(); 
}
	


<|start_filename|>NavSt2DIncompFiniteDiff/physlib/R2grid.h<|end_filename|>
/* R2grid.h
 * R2 under discretization (discretize functor) to a (staggered) grid
 * <NAME>  <EMAIL>
 * 20161113
 */
#ifndef __R2GRID_H__
#define __R2GRID_H__

#include <array> // std::array
#include <vector> // std::vector
#include <cstdlib> // std::exit
#include <cmath> // expf, acos

#include <thrust/host_vector.h>  // thrust::host_vector.h


class Grid2d
{
	public : 
		std::array<int,2> Ld;		// Ld[0],Ld[1] = L_x, L_y or i.e. imax,jmax 
		std::array<float,2> ld;  // xlength, ylength or xLength, yLength (i.e. Domain size (non-dimensional))
		std::array<float,2> hd;  // delx, dely or dx, dy
		std::array<int,2> staggered_Ld; // Ld[0]+2,Ld[1]+2 = L_x+2,L_y+2, or i.e. imax+2,jmax+2 

		// You need to compile using nvcc compiler and possibly -x cu flag, to treat C++ code as CUDA code
		// vector for velocity
//		std::vector<float2> u2 ;	  // of size staggered_SIZE, or i.e. (L_x+2)*(L_y+2)==(imax+2)*(jmax+2)

		thrust::host_vector<float> u;
		thrust::host_vector<float> v;

		// since size isn't known statically at compile-time, but until runtime, using std::vector
		// vector for pressure
		thrust::host_vector<float> p ;	 // of size staggered_SIZE, or i.e. (L_x+2)*(L_y+2)==(imax+2)*(jmax+2)
		thrust::host_vector<float> F, G ; // of size staggered_SIZE, or i.e. (L_x+2)*(L_y+2)==(imax+2)*(jmax+2)
		thrust::host_vector<float> RHS; // of size staggered_SIZE, or i.e. (L_x+2)*(L_y+2)==(imax+2)*(jmax+2)
		
		// Constructor
		/* --------------------------------------------------------- */
		/* Sets the initial values for velocity u, p                 */
		/* --------------------------------------------------------- */
		Grid2d(std::array<int,2> Ld_in, std::array<float,2> ld_in);
		Grid2d(std::array<int,2> Ld_in, std::array<float,2> ld_in, 
				float UI, float VI);
		
		std::array<float,2> gridpt_to_space(std::array<int,2> );
		
		int NFLAT();

		// int Grid2d :: staggered_SIZE() - returns the staggered grid size
		/* this would correspond to Griebel's notation of 
		 * (imax+1)*(jmax+1)
		 */
		int staggered_SIZE();
		
		int flatten(const int i_x, const int i_y ) ;

		int staggered_flatten(const int i_x, const int i_y ) ;

	
		~Grid2d();	
};


#endif // __R2GRID_H__


<|start_filename|>MacCor1d/commonlib/kernelLaunch.cu<|end_filename|>
/* kernelLaunch.cu
 * 1-dim. MacCormack method with global memory
 * <NAME>  <EMAIL>
 * 20161028
 */
#include "kernelLaunch.h"

void kernelLauncher(float *f, float *foverline, float *f_out, dim3 Ld, dim3 M_in) {
	const dim3 gridSize( blocksNeeded( Ld.x, M_in.x) );
	
	MacCor_global_predict<<<gridSize,M_in>>>(f, foverline, Ld.x ) ;

	MacCor_global_correctupdate<<<gridSize,M_in>>>(f,foverline,f_out,Ld.x);

	swap<<<gridSize,M_in>>>( f, f_out, Ld.x ) ;

	BoundaryCondcheck_end<<<gridSize,M_in>>>(f, Ld.x) ;

}

int blocksNeeded( int N_i, int M_i) { return (N_i + M_i - 1)/M_i ; }


<|start_filename|>Euler2d/commonlib/sharedmem.cu<|end_filename|>
/* sharedmem.cu
 * shared shared memory routines
 * <NAME>  <EMAIL>
 * 20160804
 */
#include "sharedmem.h"

int blocksNeeded( int N_i, int M_i) { return (N_i+M_i-1)/M_i; }

__device__ unsigned char clip(const float val) { 
	// Set limits, range
	const float scale = 0.999f ;
	const float newval = val/scale;
	
	int n = 256 * newval ;
	if (n==256) { n=256; }
	
	return n > 255 ? 255 : (n < 0 ? 0 : n);
}

__device__ int idxClip( int idx, int idxMax) {
	return idx > (idxMax - 1) ? (idxMax - 1): (idx < 0 ? 0 : idx);
}

__device__ int flatten(int col, int row, int width, int height) {
	return idxClip(col, width) + idxClip(row,height)*width ;
}
/*
__device__ float pressure( float energy, float rho, float2 u ) {
	float pressure_val {0.f};
	float usqr { u.x*u.x+u.y+u.y };
	pressure_val = (dev_gas_params[0] - 1.f)*(energy-0.5f*rho*usqr)
	return pressure_val;
}
* */

__global__ void float_to_char( uchar4* dev_out, const float* outSrc) {
	const int k_x = threadIdx.x + blockDim.x * blockIdx.x;
	const int k_y = threadIdx.y + blockDim.y * blockIdx.y;
	
	const int k   = k_x + k_y * blockDim.x*gridDim.x ; 

	dev_out[k].x = 0;
	dev_out[k].z = 0;
	dev_out[k].y = 0;
	dev_out[k].w = 255;

	float value = outSrc[k] ;

	const unsigned char intensity = clip( value ) ;
	dev_out[k].x = intensity ;       // higher temp -> more red
	dev_out[k].z = 255 - intensity ; // lower temp -> more blue
	
}


<|start_filename|>convect3dfinitedifftex/physlib/dev_R3grid.cu<|end_filename|>
/* dev_R3grid.cu
 * R3 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20160630
 */
#include "dev_R3grid.h"

__constant__ int dev_Ld[3];

__host__ dev_Grid3d::dev_Grid3d( dim3 Ld_in) : Ld(Ld_in)
{
	HANDLE_ERROR(
		cudaMalloc((void**)&this->dev_rho, this->NFLAT()*sizeof(float) ) );
	HANDLE_ERROR(
		cudaMalloc((void**)&this->dev_E, this->NFLAT()*sizeof(float) ) );
	HANDLE_ERROR(
		cudaMalloc((void**)&this->dev_u, this->NFLAT()*sizeof(float3) ) );
	
}

/*
__host__ dev_Grid3d::~dev_Grid3d() {
	HANDLE_ERROR( 
		cudaFree( this->dev_rho ) );
	HANDLE_ERROR(
		cudaFree( this->dev_E ) );
	HANDLE_ERROR(
		cudaFree( this->dev_u ) );
	
}
* */

__host__ int dev_Grid3d :: NFLAT() {
	return Ld.x*Ld.y*Ld.z;
}	



__device__ dev_block3d :: dev_block3d(unsigned int N_x, unsigned int N_y, unsigned int N_z ) :
	N_is {N_x,N_y,N_z} 
{}


__device__ int dev_block3d :: flatten(
							int i_x, int i_y, int i_z) {
	return i_x+i_y*N_is[0]+i_z*N_is[0]*N_is[1];

}	
	


<|start_filename|>MacCor1d/physlib/dev_R1grid.h<|end_filename|>
/* dev_R1grid.h
 * R1 under discretization (discretize) functor to a thread block
 * <NAME>  <EMAIL>
 * 20161026
 * */

#ifndef __DEV_R1GRID_H__
#define __DEV_R1GRID_H__

#include "../commonlib/errors.h"

extern __constant__ int dev_Ld[1]; // L^{d=1} = L_x \in \mathbb{N}

extern __constant__ float dev_Deltat[1]; // \Delta t, on the device


class dev_Grid1d
{
	public:
		dim3 Ld;
		
		// this has to be a pointer to a float or "old-school" float array 
		// in order to be cuda copied back to the host
		float *dev_f;

		float *dev_foverline;
		float *dev_f_out;
		
		// constructor
		__host__ dev_Grid1d( dim3 );
		
		__host__ __device__ int NFLAT();
};


#endif // __DEV_R1GRID_H__


<|start_filename|>convect2dfinitedifftex/commonlib/finitediff.h<|end_filename|>
/* finitediff.h
 * finite difference methods on a grid
 * <NAME>  <EMAIL>
 * 20160710
 */
#ifndef __FINITEDIFF_H__
#define __FINITEDIFF_H__ 

#include "errors.h"

// I fixed the size of dev_c to be 4 because I don't anticipate that we'd need more accuracy 
extern __constant__ float2 dev_cnus[4]; // i = x,y,z; j = 1,2,3,4

void set1DerivativeParameters(const float hd_i[3] );

void set2DerivativeParameters(const float hd_i[3] );

void set3DerivativeParameters(const float hd_i[3] );

void set4DerivativeParameters(const float hd_i[3] );


__device__ float dev_dirder1(float stencil[1][2], float c_nus[4]);

__device__ float dev_dirder2(float stencil[2][2], float c_nus[4]);

__device__ float dev_dirder3(float stencil[3][2], float c_nus[4]);

__device__ float dev_dirder4(float stencil[4][2], float c_nus[4]);

// DIVERGENCE (DIV) in 1, 2, 3, 4 stencils, central difference

__device__ float dev_div1( float2 stencil[1][2]  ) ;

__device__ float dev_div2( float2 stencil[2][2]  ) ; 

__device__ float dev_div3( float2 stencil[3][2]  ) ;

__device__ float dev_div4( float2 stencil[4][2]  ) ;


#endif // __FINITEDIFF_H__


<|start_filename|>Euler2d/Makefile<|end_filename|>
LDFLAGS += -L/usr/local/cuda/samples/common/lib/linux/x86_64
LDFLAGS += -lglut -lGL -lGLU

NVCC = /usr/local/cuda/bin/nvcc
NVCC_FLAGS = -g -G -Xcompiler "-Wall -Wno-deprecated-declarations"
INC = -I/usr/local/cuda/samples/common/inc

gfxobjects  = tex_anim2d.o
mathobjects = finitediff.o sharedmem.o
physobjects = dev_phys_param.o dev_R2grid.o R2grid.o convect.o Euler2d.o

all: main.exe

main.exe: main.o $(gfxobjects) $(mathobjects) $(physobjects)
	$(NVCC) -std=c++11 $^ -o $@ $(LDFLAGS)
		
main.o: main.cu 
	$(NVCC) -std=c++11 $(NVCC_FLAGS) $(INC) -dc $< -o $@

# graphics (gfx)
tex_anim2d.o: ./commonlib/tex_anim2d.cu 
		$(NVCC) -std=c++11 $(NVCC_FLAGS) $(LDFLAGS) -dc $< -o $@

# math
sharedmem.o: ./commonlib/sharedmem.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@
	
finitediff.o: ./commonlib/finitediff.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@
	


# physics
dev_phys_param.o: ./physlib/dev_phys_param.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@

dev_R2grid.o: ./physlib/dev_R2grid.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@

R2grid.o: ./physlib/R2grid.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@

convect.o: ./physlib/convect.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@
	
Euler2d.o: ./physlib/Euler2d.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@

		
clean:
		rm -f *.o *.exe


<|start_filename|>convect2dfinitedifftex/physlib/convect.h<|end_filename|>
/* convect.h
 * 3-dim. convection by finite difference with shared memory
 * <NAME>  <EMAIL>
 * 20160720
 */
#ifndef __CONVECT_H__
#define __CONVECT_H__

#include "../commonlib/finitediff.h"

#include "../physlib/dev_R2grid.h"

extern __constant__ float dev_Deltat[1] ; // Deltat

// convect_fd_naive_sh - convection with finite difference and naive shared memory scheme
__global__ void convect_fd_naive_sh( float* dev_rho, float2* dev_u ) ;


#endif // __CONVECT_H__


<|start_filename|>MacCor1d/Makefile<|end_filename|>
#  <NAME>  <EMAIL>
#  20161029
# 
LDFLAGS += -L/usr/local/cuda/samples/common/lib/linux/x86_64

NVCC = /usr/local/cuda/bin/nvcc
NVCC_FLAGS = -g -G -Xcompiler "-Wall -Wno-deprecated-declarations"
INC = -I/usr/local/cuda/samples/common/inc

physobjects = dev_R1grid.o R1grid.o 
compobjects = MacCor1d.o kernelLaunch.o

all: main.exe

main.exe: main.o $(physobjects) $(compobjects)
	$(NVCC) -std=c++11 $^ -o $@ $(LDFLAGS)
	
main.o: main.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) $(LDFLAGS) -dc $< -o $@
	
# physics

dev_R1grid.o: ./physlib/dev_R1grid.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@

R1grid.o: ./physlib/R1grid.cpp
	$(NVCC) -std=c++11 -x cu $(NVCC_FLAGS) -dc $< -o $@
	
# computational

MacCor1d.o: ./commonlib/MacCor1d.cu
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@

kernelLaunch.o: ./commonlib/kernelLaunch.cu 
	$(NVCC) -std=c++11 $(NVCC_FLAGS) -dc $< -o $@
	
	
clean:
	rm -f *.o *.exe


<|start_filename|>convect2dfinitedifftex/physlib/convect.cu<|end_filename|>
/* convect.cu
 * 3-dim. convection by finite difference with shared memory
 * <NAME>  <EMAIL>
 * 20160720
 */
#include "convect.h"

__constant__ float dev_Deltat[1] ;

// convect_fd_naive_sh - convection with finite difference and naive shared memory scheme
__global__ void convect_fd_naive_sh( float* dev_rho, float2* dev_u ) {

	const int NU = 2;
	
	// map from threadIdx/blockIdx to x grid position
	int k_x = threadIdx.x + blockIdx.x * blockDim.x;
	int k_y = threadIdx.y + blockIdx.y * blockDim.y;
	
	int k = k_x + k_y*blockDim.x*gridDim.x  ;

	__shared__ int2 stencilindicesplus[NU] ;
	__shared__ int2 stencilindicesminus[NU] ;

	for (int nu = 0; nu < NU; ++nu ) {
		stencilindicesplus[  nu ].x = k + (nu + 1) ; 
		stencilindicesminus[ nu ].x = k - (nu + 1) ; 
		stencilindicesplus[  nu ].y = k + (nu + 1)*dev_Ld[0] ; 
		stencilindicesminus[ nu ].y = k - (nu + 1)*dev_Ld[0] ; 
	}

	int XI = 0;

	// check boundary conditions
	for (int nu = 0; nu < NU; ++nu) {
		if (k_x == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesminus[ NU - 1 - xi ].x += XI- xi ;  
			}
		}
	
		if (k_y == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi) { 
				stencilindicesminus[ NU - 1 - xi ].y += (XI - xi)*dev_Ld[0] ;
			}
		}
		
	
		if (k_x == (dev_Ld[0] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].x -= XI-xi ;
			}
		}
		
		if (k_y == (dev_Ld[1] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].y -= (XI-xi)*dev_Ld[0] ;
			}
		}
		
		
	}

	__syncthreads();
	
	__shared__ float2 stencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		stencil[nu][0].x = dev_rho[stencilindicesminus[nu].x]*dev_u[stencilindicesminus[nu].x].x  ;
		stencil[nu][1].x = dev_rho[stencilindicesplus[nu].x]*dev_u[stencilindicesplus[nu].x].x  ;
		stencil[nu][0].y = dev_rho[stencilindicesminus[nu].y]*dev_u[stencilindicesminus[nu].y].y  ;
		stencil[nu][1].y = dev_rho[stencilindicesplus[nu].y]*dev_u[stencilindicesplus[nu].y].y  ;
	}	
	
	float div_value { dev_div2( stencil ) } ;
	
	__syncthreads();
	
	dev_rho[k] +=  dev_Deltat[0] * (-1.f) * div_value ;		
			
//	__syncthreads();		
			
}








<|start_filename|>lid-driven-cavity_gpu-gfx/physlib/dev_R2grid.cu<|end_filename|>
/* dev_R2grid.cu
 * R3 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 20160728
 */
#include "dev_R2grid.h"


__host__ Dev_Grid2d::Dev_Grid2d( dim3 Ld_in) : Ld(Ld_in)
{
	checkCudaErrors(
		cudaMalloc((void**)&this->u, this->staggered_NFLAT()*sizeof(float) ) );

	checkCudaErrors(
		cudaMalloc((void**)&this->v, this->staggered_NFLAT()*sizeof(float) ) );

	checkCudaErrors(
		cudaMalloc((void**)&this->F, this->staggered_NFLAT()*sizeof(float) ) );

	checkCudaErrors(
		cudaMalloc((void**)&this->G, this->staggered_NFLAT()*sizeof(float) ) );

	int size_pres = ((Ld.x / 2 ) + 2 ) * (Ld.y + 2);

	checkCudaErrors(
		cudaMalloc((void**)&this->pres_red, size_pres*sizeof(float) ) );

	checkCudaErrors(
		cudaMalloc((void**)&this->pres_black, size_pres*sizeof(float) ) );

}

// destructor
/*
__host__ dev_Grid3d::~dev_Grid3d() {
	HANDLE_ERROR( 
		cudaFree( this->dev_rho ) );
	HANDLE_ERROR(
		cudaFree( this->dev_E ) );
	HANDLE_ERROR(
		cudaFree( this->dev_u ) );
	
}
* */

__host__ int Dev_Grid2d :: NFLAT() {
	return Ld.x*Ld.y;
}	

__host__ int Dev_Grid2d :: staggered_NFLAT() {
	return (Ld.x+2)*(Ld.y+2);
}	


	


<|start_filename|>heat3d/commonlib/tex_anim2d.cu<|end_filename|>
/* tex_anim2d.cu
 * 2-dim. GPU texture animation 
 * <NAME>  <EMAIL>
 * 20160720
 */
#include "tex_anim2d.h"
  
int iterationCount = 0 ;

// int x, y location of pipe center; float rad; radius of "pipe", int chamfer; float t_s, t_a, t_g
//BC bc = {W / 2, H / 2, W / 15.f, 150, 212.f, 70.f, 0.f}; // Boundary conds
BC bc = {W / 2, H / 2, W / 15.f, 150, 212.f, 10.f, 150.f}; // Boundary conds

// interactions

void keyboard_func( unsigned char key, int x, int y) {
	if (key == 'S') bc.t_s += DT;
	if (key == 's') bc.t_s -= DT;
	if (key == 'A') bc.t_a += DT;
	if (key == 'a') bc.t_a -= DT;
	if (key == 'G') bc.t_g += DT;
	if (key == 'g') bc.t_g -= DT;
	if (key == 'R') bc.rad += DT;
	if (key == 'r') bc.rad = MAX(0.f, bc.rad - DT);
	if (key == 'C') ++bc.chamfer;
	if (key == 'c') --bc.chamfer;

	if (key==27) {
		std::exit(0) ;
	}
	glutPostRedisplay();
}
	
void mouse_func( int button, int state, int x, int y ) {
	bc.x = x, bc.y = y;
	glutPostRedisplay();
}

void idle() {
	++iterationCount;
	glutPostRedisplay();
}

void printInstructions() {
	printf("3 dim. texture animation \n"
			"Relocate source with mouse click\n"
		   "Change source temperature (-/+): s/S\n"
		   "Change air temperature    (-/+): a/A\n"
		   "Change ground temperature (-/+): g/G\n"
		   "Change pipe radius        (-/+): r/R\n"
		   "Change chamfer            (-/+): c/C\n"

			"Exit                           : Esc\n"
	
	);
}

// make* functions make functions to pass into OpenGL (note OpenGL is inherently a C API

void make_draw_texture(int w, int h) {
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 
		GL_UNSIGNED_BYTE, NULL);
	glEnable(GL_TEXTURE_2D);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f); glVertex2f(0,0);
	glTexCoord2f(0.0f, 1.0f); glVertex2f(0,h);
	glTexCoord2f(1.0f, 1.0f); glVertex2f(w,h);
	glTexCoord2f(1.0f, 0.0f); glVertex2f(w,0);
	glEnd();
	glDisable(GL_TEXTURE_2D);
}	


<|start_filename|>SuddenExpansion/physlib/dev_R2grid.cu<|end_filename|>
/* dev_R2grid.cu
 * R3 under discretization (discretize functor) to a grid
 * <NAME>  <EMAIL>
 * 2016115
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/dev_R2grid.cu -o dev_R2grid.o
 * 
 */
#include "dev_R2grid.h"

//__constant__ int dev_Ld[2];

// constructor
__host__ dev_Grid2d::dev_Grid2d( dim3 Ld_in) : Ld(Ld_in)
{
	checkCudaErrors(
		cudaMalloc((void**)&this->dev_f, this->NFLAT()*sizeof(float)) );

	checkCudaErrors(
		cudaMalloc((void**)&this->dev_f_out, this->NFLAT()*sizeof(float)) );

	checkCudaErrors(
		cudaMalloc((void**)&this->dev_u, this->NFLAT()*sizeof(float2)) );

	checkCudaErrors(
		cudaMalloc((void**)&this->dev_u_out, this->NFLAT()*sizeof(float2)) );


	(this->channelDesc_f) = cudaCreateChannelDesc( 32, 0, 0, 0, 
													cudaChannelFormatKindFloat);

	// 8 bits * 4 bytes in float (sizeof(float)) = 32
/*	(this->channelDesc_f2) = cudaCreateChannelDesc( 32, 32, 0, 0, 
								cudaChannelFormatKindFloat);*/ // This gave a Segmentation Fault 
	(this->channelDesc_f2) = cudaCreateChannelDesc<float2>();
	

	checkCudaErrors(
		cudaMallocArray(&(this->cuArr_f), &(this->channelDesc_f), (this->Ld).x, (this->Ld).y, 
						cudaArraySurfaceLoadStore) ); 

	checkCudaErrors(
		cudaMallocArray(&(this->cuArr_f_out), &(this->channelDesc_f), (this->Ld).x, (this->Ld).y,
						cudaArraySurfaceLoadStore) ); 

	checkCudaErrors(
		cudaMallocArray(&(this->cuArr_u), &(this->channelDesc_f2), (this->Ld).x, (this->Ld).y,
						cudaArraySurfaceLoadStore) ); 

	checkCudaErrors(
		cudaMallocArray(&(this->cuArr_u_out), &(this->channelDesc_f2), (this->Ld).x, (this->Ld).y,
						cudaArraySurfaceLoadStore) ); 

}

// destructor

__host__ dev_Grid2d::~dev_Grid2d() {

	checkCudaErrors(
		cudaFree( this->dev_f ) );

	checkCudaErrors(
		cudaFree( this->dev_f_out ) );


	checkCudaErrors(
		cudaFree( this->dev_u ) );

	checkCudaErrors(
		cudaFree( this->dev_u_out ) );


	checkCudaErrors(
		cudaFreeArray( this->cuArr_f ));
		
	checkCudaErrors(
		cudaFreeArray( this->cuArr_f_out ));


	checkCudaErrors(
		cudaFreeArray( this->cuArr_u )); 

	checkCudaErrors(
		cudaFreeArray( this->cuArr_u_out )); 

}


__host__ int dev_Grid2d :: NFLAT() {
	return Ld.x*Ld.y;
}	

__global__ void d_BoundaryConditions( float2 hds, 
										cudaSurfaceObject_t uSurf , 
										const int L_x, const int L_y,
										const float h_val) {
	const int k_x = threadIdx.x + blockIdx.x * blockDim.x ;
	const int k_y = threadIdx.y + blockIdx.y * blockDim.y ;
	if ((k_x >= L_x) || (k_y >= L_y)) { 
		return ; }

	// real values on Euclidean space
	float2 xreal ; 
	float2 lreal ;
	xreal.x = hds.x * k_x; 
	xreal.y = hds.y * k_y; 
	lreal.x = hds.x * L_x; 
	lreal.y = hds.y * L_y; 
	
	// stencil values, or halo cells
	float2 tempu, b, bb;

	// wall boundary condition, y=0
	if (k_y == 0) {
		// no slip condition
		tempu.x = 0.f;
		tempu.y = 0.f;
		surf2Dwrite( tempu, uSurf, k_x * 8 , 0) ; }

	// symmetry plane boundary condition, y=H
	else if (k_y == (L_y - 1)) {
		surf2Dread(&b, uSurf, k_x * 8, L_y - 2) ;  
		surf2Dread(&bb, uSurf, k_x * 8, L_y - 3) ;  
		tempu.x = (4.f/3.f) * b.x - (1.f/3.f) * bb.x ;
		tempu.y = 0.f ;
		surf2Dwrite( tempu, uSurf, k_x * 8, L_y-1) ; }
	
	// inlet condition at x=0
	else if (k_x == 0) {
		tempu.y = 0.f ;
		
		if ( xreal.y <= (lreal.y -h_val )) {
			tempu.x = 0.f ; }
		else if (( xreal.y > (lreal.y -h_val)) && (xreal.y <= lreal.y)) {
			float tempux {0.f };
			tempux = 1.5f*( 2.f *(xreal.y-lreal.y+h_val)/h_val  
							-(xreal.y-lreal.y+h_val)*(xreal.y-lreal.y+h_val)/(h_val*h_val)) ; 
			tempu.x = tempux;
		}
		surf2Dwrite( tempu, uSurf, 0 , k_y ) ; }
			
}	
	





<|start_filename|>Euler2d/physlib/convect.cu<|end_filename|>
/* convect.cu
 * 2-dim. Euler eq. (heat eq.) by finite difference with shared memory
 * <NAME>  <EMAIL>
 * 20160804
 */
#include "convect.h"

/*
__device__ float pressure( float energy, float rho, float2 u ) {
	float pressureval { (dev_gas_params[0] - 1.f ) * ( energy - 0.5f * rho * (u.x*u.x+u.y*u.y) ) } ;
	return pressureval ; 
}*/

__global__ void convect_fd( float* dev_rho, float2* dev_u ) {
	const int NU = 1;
	
	// map from threadIdx/blockIdx to x grid position
	int k_x = threadIdx.x + blockIdx.x * blockDim.x;
	int k_y = threadIdx.y + blockIdx.y * blockDim.y;
	
	int k = k_x + k_y*blockDim.x*gridDim.x ;
	
	int2 stencilindicesplus[NU] ;
	int2 stencilindicesminus[NU] ;

	for (int nu = 0; nu < NU; ++nu ) {
		stencilindicesplus[  nu ].x = k + (nu + 1) ; 
		stencilindicesminus[ nu ].x = k - (nu + 1) ; 
		stencilindicesplus[  nu ].y = k + (nu + 1)*dev_Ld[0] ; 
		stencilindicesminus[ nu ].y = k - (nu + 1)*dev_Ld[0] ; 
	}

	int XI = 0;

	// check boundary conditions
	for (int nu = 0; nu < NU; ++nu) {
		if (k_x == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesminus[ NU - 1 - xi ].x += XI- xi ;  
			}
		}
	
		if (k_y == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi) { 
				stencilindicesminus[ NU - 1 - xi ].y += (XI - xi)*dev_Ld[0] ;
			}
		}
		
		if (k_x == (dev_Ld[0] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].x -= XI-xi ;
			}
		}
		
		if (k_y == (dev_Ld[1] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].y -= (XI-xi)*dev_Ld[0] ;
			}
		}
	}

	__syncthreads();
	
	__shared__ float2 stencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		stencil[nu][0].x = dev_rho[stencilindicesminus[nu].x]*dev_u[stencilindicesminus[nu].x].x  ;
		stencil[nu][1].x = dev_rho[stencilindicesplus[nu].x]*dev_u[stencilindicesplus[nu].x].x  ;
		stencil[nu][0].y = dev_rho[stencilindicesminus[nu].y]*dev_u[stencilindicesminus[nu].y].y  ;
		stencil[nu][1].y = dev_rho[stencilindicesplus[nu].y]*dev_u[stencilindicesplus[nu].y].y  ;
	}	
	
	float div_value { dev_div1( stencil ) } ;

	__syncthreads();
	
	dev_rho[k] +=  dev_Deltat[0] * (-1.f) * div_value ;		
			
//	__syncthreads();		
			
}


__global__ void convect_fd2( float* dev_rho, float2* dev_u ) {
	const int NU = 2;
	
	// map from threadIdx/blockIdx to x grid position
	int k_x = threadIdx.x + blockIdx.x * blockDim.x;
	int k_y = threadIdx.y + blockIdx.y * blockDim.y;
	
	int k = k_x + k_y*blockDim.x*gridDim.x ;
	
	int2 stencilindicesplus[NU] ;
	int2 stencilindicesminus[NU] ;

	for (int nu = 0; nu < NU; ++nu ) {
		stencilindicesplus[  nu ].x = k + (nu + 1) ; 
		stencilindicesminus[ nu ].x = k - (nu + 1) ; 
		stencilindicesplus[  nu ].y = k + (nu + 1)*dev_Ld[0] ; 
		stencilindicesminus[ nu ].y = k - (nu + 1)*dev_Ld[0] ; 
	}

	int XI = 0;

	// check boundary conditions
	for (int nu = 0; nu < NU; ++nu) {
		if (k_x == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesminus[ NU - 1 - xi ].x += XI- xi ;  
			}
		}
	
		if (k_y == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi) { 
				stencilindicesminus[ NU - 1 - xi ].y += (XI - xi)*dev_Ld[0] ;
			}
		}
		
		if (k_x == (dev_Ld[0] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].x -= XI-xi ;
			}
		}
		
		if (k_y == (dev_Ld[1] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].y -= (XI-xi)*dev_Ld[0] ;
			}
		}
	}

	__syncthreads();
	
	__shared__ float2 stencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		stencil[nu][0].x = dev_rho[stencilindicesminus[nu].x]*dev_u[stencilindicesminus[nu].x].x  ;
		stencil[nu][1].x = dev_rho[stencilindicesplus[nu].x]*dev_u[stencilindicesplus[nu].x].x  ;
		stencil[nu][0].y = dev_rho[stencilindicesminus[nu].y]*dev_u[stencilindicesminus[nu].y].y  ;
		stencil[nu][1].y = dev_rho[stencilindicesplus[nu].y]*dev_u[stencilindicesplus[nu].y].y  ;
	}	
	
	float div_value { dev_div2( stencil ) } ;
	
	__syncthreads();
	
	dev_rho[k] +=  dev_Deltat[0] * (-1.f) * div_value ;		
			
//	__syncthreads();		
			
}

__global__ void convect_fd_sh( float* dev_rho, float2* dev_u ) {
	const int NU = 1;
	
	// map from threadIdx/blockIdx to x grid position
	int k_x = threadIdx.x + blockIdx.x * blockDim.x;
	int k_y = threadIdx.y + blockIdx.y * blockDim.y;
	
	int k = k_x + k_y*blockDim.x*gridDim.x ;
	
	int2 stencilindicesplus[NU] ;
	int2 stencilindicesminus[NU] ;

	for (int nu = 0; nu < NU; ++nu ) {
		stencilindicesplus[  nu ].x = k + (nu + 1) ; 
		stencilindicesminus[ nu ].x = k - (nu + 1) ; 
		stencilindicesplus[  nu ].y = k + (nu + 1)*dev_Ld[0] ; 
		stencilindicesminus[ nu ].y = k - (nu + 1)*dev_Ld[0] ; 
	}

	int XI = 0;

	// check boundary conditions
	for (int nu = 0; nu < NU; ++nu) {
		if (k_x == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesminus[ NU - 1 - xi ].x += XI- xi ;  
			}
		}
	
		if (k_y == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi) { 
				stencilindicesminus[ NU - 1 - xi ].y += (XI - xi)*dev_Ld[0] ;
			}
		}
		
		if (k_x == (dev_Ld[0] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].x -= XI-xi ;
			}
		}
		
		if (k_y == (dev_Ld[1] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].y -= (XI-xi)*dev_Ld[0] ;
			}
		}
	}

	__syncthreads();

	__shared__ float2 sh_rho[NU][2] ; 
	__shared__ float2 sh_u[NU][2]  ;

	for (int nu = 0 ; nu < NU; ++nu ) {
		sh_rho[nu][0].x = dev_rho[stencilindicesminus[nu].x] ; 
		sh_u[nu][0].x = dev_u[stencilindicesminus[nu].x].x ;
		sh_rho[nu][1].x = dev_rho[stencilindicesplus[nu].x] ; 
		sh_u[nu][1].x = dev_u[stencilindicesplus[nu].x].x ;
		sh_rho[nu][0].y = dev_rho[stencilindicesminus[nu].y] ; 
		sh_u[nu][0].y = dev_u[stencilindicesminus[nu].y].y ; 
		sh_rho[nu][1].y = dev_rho[stencilindicesplus[nu].y] ; 
		sh_u[nu][1].y = dev_u[stencilindicesplus[nu].y].y ;
	}
	
	__shared__ float2 rhoustencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		rhoustencil[nu][0].x = sh_rho[nu][0].x * sh_u[nu][0].x ; 
//		dev_rho[stencilindicesminus[nu].x]*dev_u[stencilindicesminus[nu].x].x  ;
		rhoustencil[nu][1].x = sh_rho[nu][1].x * sh_u[nu][1].x ; 
//		dev_rho[stencilindicesplus[nu].x]*dev_u[stencilindicesplus[nu].x].x  ;
		rhoustencil[nu][0].y = sh_rho[nu][0].y * sh_u[nu][0].y ; 
		//dev_rho[stencilindicesminus[nu].y]*dev_u[stencilindicesminus[nu].y].y  ;
		rhoustencil[nu][1].y = sh_rho[nu][1].y * sh_u[nu][1].y ; 
		//dev_rho[stencilindicesplus[nu].y]*dev_u[stencilindicesplus[nu].y].y  ;
	}	
	
	float div_value { dev_div1( rhoustencil ) } ;

	__syncthreads();
	
	dev_rho[k] +=  dev_Deltat[0] * (-1.f) * div_value ;		
			
//	__syncthreads();		
			
}


__global__ void Euler2dp1( float* dev_rho, float2* dev_p, float2* dev_u, float* dev_E ) {
	const int NU = 1;
	
	// map from threadIdx/blockIdx to x grid position
	int k_x = threadIdx.x + blockIdx.x * blockDim.x;
	int k_y = threadIdx.y + blockIdx.y * blockDim.y;
	
	int k = k_x + k_y*blockDim.x*gridDim.x ;
	
	int2 stencilindicesplus[NU] ;
	int2 stencilindicesminus[NU] ;

	for (int nu = 0; nu < NU; ++nu ) {
		stencilindicesplus[  nu ].x = k + (nu + 1) ; 
		stencilindicesminus[ nu ].x = k - (nu + 1) ; 
		stencilindicesplus[  nu ].y = k + (nu + 1)*dev_Ld[0] ; 
		stencilindicesminus[ nu ].y = k - (nu + 1)*dev_Ld[0] ; 
	}

	int XI = 0;

	// check boundary conditions
	for (int nu = 0; nu < NU; ++nu) {
		if (k_x == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesminus[ NU - 1 - xi ].x += XI- xi ;  
			}
		}
	
		if (k_y == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi) { 
				stencilindicesminus[ NU - 1 - xi ].y += (XI - xi)*dev_Ld[0] ;
			}
		}
		
		if (k_x == (dev_Ld[0] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].x -= XI-xi ;
			}
		}
		
		if (k_y == (dev_Ld[1] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].y -= (XI-xi)*dev_Ld[0] ;
			}
		}
	}

	__syncthreads();
	
	__shared__ float2 sh_rho[NU][2] ; 
	__shared__ float2 sh_u[NU][2]  ;
	__shared__ float2 sh_usq[NU][2] ; // u^2
	__shared__ float2 sh_E[NU][2] ; 
	__shared__ float2 sh_px[NU][2] ; 
	__shared__ float2 sh_py[NU][2] ; 
	

	for (int nu = 0 ; nu < NU; ++nu ) {
		sh_rho[nu][0].x = dev_rho[stencilindicesminus[nu].x] ; 
		sh_u[nu][0].x = dev_u[stencilindicesminus[nu].x].x ;
		sh_usq[nu][0].x = dev_u[stencilindicesminus[nu].x].x * dev_u[stencilindicesminus[nu].x].x + 
					dev_u[stencilindicesminus[nu].x].y * dev_u[stencilindicesminus[nu].x].y ;
		sh_E[nu][0].x = dev_E[stencilindicesminus[nu].x] ;
		sh_px[nu][0].x = dev_p[stencilindicesminus[nu].x].x ;
		sh_py[nu][0].x = dev_p[stencilindicesminus[nu].x].y ;


		sh_rho[nu][1].x = dev_rho[stencilindicesplus[nu].x] ; 
		sh_u[nu][1].x = dev_u[stencilindicesplus[nu].x].x ;
		sh_usq[nu][1].x = dev_u[stencilindicesplus[nu].x].x * dev_u[stencilindicesplus[nu].x].x + 
					dev_u[stencilindicesplus[nu].x].y * dev_u[stencilindicesplus[nu].x].y ;
		sh_E[nu][1].x = dev_E[stencilindicesplus[nu].x] ;
		sh_px[nu][1].x = dev_p[stencilindicesplus[nu].x].x ;
		sh_py[nu][1].x = dev_p[stencilindicesplus[nu].x].y ;


		sh_rho[nu][0].y = dev_rho[stencilindicesminus[nu].y] ; 
		sh_u[nu][0].y = dev_u[stencilindicesminus[nu].y].y ; 
		sh_usq[nu][0].y = dev_u[stencilindicesminus[nu].y].x * dev_u[stencilindicesminus[nu].y].x + 
				dev_u[stencilindicesminus[nu].y].y * dev_u[stencilindicesminus[nu].y].y ; 
		sh_E[nu][0].y = dev_E[stencilindicesminus[nu].y] ;
		sh_px[nu][0].y = dev_p[stencilindicesminus[nu].y].x ;
		sh_py[nu][0].y = dev_p[stencilindicesminus[nu].y].y ;


		sh_rho[nu][1].y = dev_rho[stencilindicesplus[nu].y] ; 
		sh_u[nu][1].y = dev_u[stencilindicesplus[nu].y].y ;
		sh_usq[nu][1].y = dev_u[stencilindicesplus[nu].y].x * dev_u[stencilindicesplus[nu].y].x + 
				dev_u[stencilindicesplus[nu].y].y * dev_u[stencilindicesplus[nu].y].y ;
		sh_E[nu][1].y = dev_E[stencilindicesplus[nu].y] ;
		sh_px[nu][1].y = dev_p[stencilindicesplus[nu].y].x ;
		sh_py[nu][1].y = dev_p[stencilindicesplus[nu].y].y ;

	}

	
	__shared__ float2 rhoustencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		rhoustencil[nu][0].x = sh_rho[nu][0].x * sh_u[nu][0].x ; 
		rhoustencil[nu][1].x = sh_rho[nu][1].x * sh_u[nu][1].x ; 
		rhoustencil[nu][0].y = sh_rho[nu][0].y * sh_u[nu][0].y ; 
		rhoustencil[nu][1].y = sh_rho[nu][1].y * sh_u[nu][1].y ; 
	}	
	
	float div_value { dev_div1( rhoustencil ) } ;

	__shared__ float2 Estencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		Estencil[nu][0].x = dev_gas_params[0] * sh_E[nu][0].x * sh_u[nu][0].x ; 
		Estencil[nu][1].x = dev_gas_params[0] * sh_E[nu][1].x * sh_u[nu][1].x ; 
		Estencil[nu][0].y = dev_gas_params[0] * sh_E[nu][0].y * sh_u[nu][0].y ; 
		Estencil[nu][1].y = dev_gas_params[0] * sh_E[nu][1].y * sh_u[nu][1].y ; 
	}	
	
	float div_Eval { dev_div1( Estencil ) } ; 

	__shared__ float2 KEstencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		KEstencil[nu][0].x = 0.5f*(dev_gas_params[0]-1.f) * 
						sh_rho[nu][0].x * sh_usq[nu][0].x * sh_u[nu][0].x ; 
		KEstencil[nu][1].x = 0.5f*(dev_gas_params[0]-1.f) * 
						sh_rho[nu][1].x * sh_usq[nu][1].x * sh_u[nu][1].x ; 
		KEstencil[nu][0].y = 0.5f*(dev_gas_params[0]-1.f) * 
						sh_rho[nu][0].y * sh_usq[nu][0].y * sh_u[nu][0].y ; 
		KEstencil[nu][1].y = 0.5f*(dev_gas_params[0]-1.f) * 
						sh_rho[nu][1].y * sh_usq[nu][1].y * sh_u[nu][1].y ; 
	}	
	
	float div_KEval { dev_div1( KEstencil ) } ; 

	__shared__ float2 pxstencil[NU][2] ; 

	for (int nu = 0 ; nu < NU; ++nu ) {
		pxstencil[nu][0].x = sh_px[nu][0].x * sh_u[nu][0].x ; 
		pxstencil[nu][1].x = sh_px[nu][1].x * sh_u[nu][1].x ; 
		pxstencil[nu][0].y = sh_px[nu][0].y * sh_u[nu][0].y ; 
		pxstencil[nu][1].y = sh_px[nu][1].y * sh_u[nu][1].y ; 
	}
	
	float div_pxval { dev_div1( pxstencil ) } ; 

	__shared__ float2 pystencil[NU][2] ; 

	for (int nu = 0 ; nu < NU; ++nu ) {
		pystencil[nu][0].x = sh_py[nu][0].x * sh_u[nu][0].x ; 
		pystencil[nu][1].x = sh_py[nu][1].x * sh_u[nu][1].x ; 
		pystencil[nu][0].y = sh_py[nu][0].y * sh_u[nu][0].y ; 
		pystencil[nu][1].y = sh_py[nu][1].y * sh_u[nu][1].y ; 
	}

	float div_pyval { dev_div1( pystencil ) };

	__shared__ float2 pressurestencil[NU][2] ; 

	for (int nu = 0 ; nu < NU; ++nu ) {
		pressurestencil[nu][0].x = pressure( sh_E[nu][0].x, sh_rho[nu][0].x, sh_usq[nu][0].x ) ; 
		pressurestencil[nu][1].x = pressure( sh_E[nu][1].x, sh_rho[nu][1].x, sh_usq[nu][1].x )  ; 
		pressurestencil[nu][0].y = pressure( sh_E[nu][0].y, sh_rho[nu][0].y, sh_usq[nu][0].y )  ; 
		pressurestencil[nu][1].y = pressure( sh_E[nu][1].y, sh_rho[nu][1].y, sh_usq[nu][1].y )  ; 
	}

	float2 grad_pressureval = dev_grad1( pressurestencil ) ;
	
	__syncthreads() ;
	
	dev_rho[k] +=  dev_Deltat[0] * (-1.f) * div_value ;		
	dev_E[k] += dev_Deltat[0] * ( (-1.f) * div_Eval + div_KEval ) ; 		
	dev_p[k].x += dev_Deltat[0] * (-1.f) * ( div_pxval + grad_pressureval.x ) ; 
	dev_p[k].y += dev_Deltat[0] * (-1.f) * ( div_pyval + grad_pressureval.y ) ; 

	__syncthreads();

	if (dev_rho[k] != 0.f ) {
		float2 temp_u { dev_p[k].x / dev_rho[k] , dev_p[k].y / dev_rho[k] } ;
	
		if ( (isfinite( temp_u.x )) && (isfinite( temp_u.y) ) ) {
			dev_u[k] = temp_u  ;
		}
		else {
			;
		}
	}
	else
	{
		;
	}

			
//	__syncthreads();		
			
}

__global__ void Euler2dp2( float* dev_rho, float2* dev_p, float2* dev_u, float* dev_E ) {
	const int NU = 2;
	
	// map from threadIdx/blockIdx to x grid position
	int k_x = threadIdx.x + blockIdx.x * blockDim.x;
	int k_y = threadIdx.y + blockIdx.y * blockDim.y;
	
	int k = k_x + k_y*blockDim.x*gridDim.x ;
	
	int2 stencilindicesplus[NU] ;
	int2 stencilindicesminus[NU] ;

	for (int nu = 0; nu < NU; ++nu ) {
		stencilindicesplus[  nu ].x = k + (nu + 1) ; 
		stencilindicesminus[ nu ].x = k - (nu + 1) ; 
		stencilindicesplus[  nu ].y = k + (nu + 1)*dev_Ld[0] ; 
		stencilindicesminus[ nu ].y = k - (nu + 1)*dev_Ld[0] ; 
	}

	int XI = 0;

	// check boundary conditions
	for (int nu = 0; nu < NU; ++nu) {
		if (k_x == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesminus[ NU - 1 - xi ].x += XI- xi ;  
			}
		}
	
		if (k_y == nu ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi) { 
				stencilindicesminus[ NU - 1 - xi ].y += (XI - xi)*dev_Ld[0] ;
			}
		}
		
		if (k_x == (dev_Ld[0] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].x -= XI-xi ;
			}
		}
		
		if (k_y == (dev_Ld[1] - (nu + 1) ) ) {
			XI = NU - nu ;
			for (int xi = 0; xi < XI; ++xi ) {
				stencilindicesplus[ NU - 1 - xi].y -= (XI-xi)*dev_Ld[0] ;
			}
		}
	}

	__syncthreads();
	
	__shared__ float2 sh_rho[NU][2] ; 
	__shared__ float2 sh_u[NU][2]  ;
	__shared__ float2 sh_usq[NU][2] ; // u^2
	__shared__ float2 sh_E[NU][2] ; 
	__shared__ float2 sh_px[NU][2] ; 
	__shared__ float2 sh_py[NU][2] ; 
	

	for (int nu = 0 ; nu < NU; ++nu ) {
		sh_rho[nu][0].x = dev_rho[stencilindicesminus[nu].x] ; 
		sh_u[nu][0].x = dev_u[stencilindicesminus[nu].x].x ;
		sh_usq[nu][0].x = dev_u[stencilindicesminus[nu].x].x * dev_u[stencilindicesminus[nu].x].x + 
					dev_u[stencilindicesminus[nu].x].y * dev_u[stencilindicesminus[nu].x].y ;
		sh_E[nu][0].x = dev_E[stencilindicesminus[nu].x] ;
		sh_px[nu][0].x = dev_p[stencilindicesminus[nu].x].x ;
		sh_py[nu][0].x = dev_p[stencilindicesminus[nu].x].y ;


		sh_rho[nu][1].x = dev_rho[stencilindicesplus[nu].x] ; 
		sh_u[nu][1].x = dev_u[stencilindicesplus[nu].x].x ;
		sh_usq[nu][1].x = dev_u[stencilindicesplus[nu].x].x * dev_u[stencilindicesplus[nu].x].x + 
					dev_u[stencilindicesplus[nu].x].y * dev_u[stencilindicesplus[nu].x].y ;
		sh_E[nu][1].x = dev_E[stencilindicesplus[nu].x] ;
		sh_px[nu][1].x = dev_p[stencilindicesplus[nu].x].x ;
		sh_py[nu][1].x = dev_p[stencilindicesplus[nu].x].y ;


		sh_rho[nu][0].y = dev_rho[stencilindicesminus[nu].y] ; 
		sh_u[nu][0].y = dev_u[stencilindicesminus[nu].y].y ; 
		sh_usq[nu][0].y = dev_u[stencilindicesminus[nu].y].x * dev_u[stencilindicesminus[nu].y].x + 
				dev_u[stencilindicesminus[nu].y].y * dev_u[stencilindicesminus[nu].y].y ; 
		sh_E[nu][0].y = dev_E[stencilindicesminus[nu].y] ;
		sh_px[nu][0].y = dev_p[stencilindicesminus[nu].y].x ;
		sh_py[nu][0].y = dev_p[stencilindicesminus[nu].y].y ;


		sh_rho[nu][1].y = dev_rho[stencilindicesplus[nu].y] ; 
		sh_u[nu][1].y = dev_u[stencilindicesplus[nu].y].y ;
		sh_usq[nu][1].y = dev_u[stencilindicesplus[nu].y].x * dev_u[stencilindicesplus[nu].y].x + 
				dev_u[stencilindicesplus[nu].y].y * dev_u[stencilindicesplus[nu].y].y ;
		sh_E[nu][1].y = dev_E[stencilindicesplus[nu].y] ;
		sh_px[nu][1].y = dev_p[stencilindicesplus[nu].y].x ;
		sh_py[nu][1].y = dev_p[stencilindicesplus[nu].y].y ;

	}

	
	__shared__ float2 rhoustencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		rhoustencil[nu][0].x = sh_rho[nu][0].x * sh_u[nu][0].x ; 
		rhoustencil[nu][1].x = sh_rho[nu][1].x * sh_u[nu][1].x ; 
		rhoustencil[nu][0].y = sh_rho[nu][0].y * sh_u[nu][0].y ; 
		rhoustencil[nu][1].y = sh_rho[nu][1].y * sh_u[nu][1].y ; 
	}	
	
	float div_value { dev_div2( rhoustencil ) } ;

	__shared__ float2 Estencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		Estencil[nu][0].x = dev_gas_params[0] * sh_E[nu][0].x * sh_u[nu][0].x ; 
		Estencil[nu][1].x = dev_gas_params[0] * sh_E[nu][1].x * sh_u[nu][1].x ; 
		Estencil[nu][0].y = dev_gas_params[0] * sh_E[nu][0].y * sh_u[nu][0].y ; 
		Estencil[nu][1].y = dev_gas_params[0] * sh_E[nu][1].y * sh_u[nu][1].y ; 
	}	
	
	float div_Eval { dev_div2( Estencil ) } ; 

	__shared__ float2 KEstencil[NU][2] ; 
	
	for (int nu = 0 ; nu < NU; ++nu ) {
		KEstencil[nu][0].x = 0.5f*(dev_gas_params[0]-1.f) * 
						sh_rho[nu][0].x * sh_usq[nu][0].x * sh_u[nu][0].x ; 
		KEstencil[nu][1].x = 0.5f*(dev_gas_params[0]-1.f) * 
						sh_rho[nu][1].x * sh_usq[nu][1].x * sh_u[nu][1].x ; 
		KEstencil[nu][0].y = 0.5f*(dev_gas_params[0]-1.f) * 
						sh_rho[nu][0].y * sh_usq[nu][0].y * sh_u[nu][0].y ; 
		KEstencil[nu][1].y = 0.5f*(dev_gas_params[0]-1.f) * 
						sh_rho[nu][1].y * sh_usq[nu][1].y * sh_u[nu][1].y ; 
	}	
	
	float div_KEval { dev_div2( KEstencil ) } ; 

	__shared__ float2 pxstencil[NU][2] ; 

	for (int nu = 0 ; nu < NU; ++nu ) {
		pxstencil[nu][0].x = sh_px[nu][0].x * sh_u[nu][0].x ; 
		pxstencil[nu][1].x = sh_px[nu][1].x * sh_u[nu][1].x ; 
		pxstencil[nu][0].y = sh_px[nu][0].y * sh_u[nu][0].y ; 
		pxstencil[nu][1].y = sh_px[nu][1].y * sh_u[nu][1].y ; 
	}
	
	float div_pxval { dev_div2( pxstencil ) } ; 

	__shared__ float2 pystencil[NU][2] ; 

	for (int nu = 0 ; nu < NU; ++nu ) {
		pystencil[nu][0].x = sh_py[nu][0].x * sh_u[nu][0].x ; 
		pystencil[nu][1].x = sh_py[nu][1].x * sh_u[nu][1].x ; 
		pystencil[nu][0].y = sh_py[nu][0].y * sh_u[nu][0].y ; 
		pystencil[nu][1].y = sh_py[nu][1].y * sh_u[nu][1].y ; 
	}

	float div_pyval { dev_div2( pystencil ) };

	__shared__ float2 pressurestencil[NU][2] ; 

	for (int nu = 0 ; nu < NU; ++nu ) {
		pressurestencil[nu][0].x = pressure( sh_E[nu][0].x, sh_rho[nu][0].x, sh_usq[nu][0].x ) ; 
		pressurestencil[nu][1].x = pressure( sh_E[nu][1].x, sh_rho[nu][1].x, sh_usq[nu][1].x )  ; 
		pressurestencil[nu][0].y = pressure( sh_E[nu][0].y, sh_rho[nu][0].y, sh_usq[nu][0].y )  ; 
		pressurestencil[nu][1].y = pressure( sh_E[nu][1].y, sh_rho[nu][1].y, sh_usq[nu][1].y )  ; 
	}

	float2 grad_pressureval = dev_grad2( pressurestencil ) ;
	
	__syncthreads() ;
	
	dev_rho[k] +=  dev_Deltat[0] * (-1.f) * div_value ;		
	dev_E[k] += dev_Deltat[0] * ( (-1.f) * div_Eval + div_KEval ) ; 		
	dev_p[k].x += dev_Deltat[0] * (-1.f) * ( div_pxval + grad_pressureval.x ) ; 
	dev_p[k].y += dev_Deltat[0] * (-1.f) * ( div_pyval + grad_pressureval.y ) ; 

	__syncthreads();

	if (dev_rho[k] != 0.f ) {
		float2 temp_u { dev_p[k].x / dev_rho[k] , dev_p[k].y / dev_rho[k] } ;
	
		if ( (isfinite( temp_u.x )) && (isfinite( temp_u.y) ) ) {
			dev_u[k] = temp_u  ;
		}
		else {
			;
		}
	}
	else
	{
		;
	}
	__syncthreads();
}






<|start_filename|>Euler2d/main.cu<|end_filename|>
/* main.cpp
 * 2-dim. Euler Eq. by finite difference with shared memory
 * <NAME>  <EMAIL>
 * 20160802
 */
#include <functional>

#include <stdio.h>
#include <stdlib.h>
#include <iostream>


#include "./physlib/dev_R2grid.h"
#include "./physlib/R2grid.h"
#include "./physlib/dev_phys_param.h"
#include "./physlib/Euler2d.h"
#include "./physlib/convect.h"

#include "./commonlib/sharedmem.h"
#include "./commonlib/errors.h"
#include "./commonlib/tex_anim2d.h"
#include "./commonlib/finitediff.h"

#include "math.h" // CUDA C/C++ math.h

#define GL_GLEXT_PROTOTYPES // needed for identifier glGenBuffer, glBindBuffer, glBufferData, glDeleteBuffers

#include <GL/glut.h>

#include <cuda_runtime.h>
#include <cuda_gl_interop.h> // or #include "cuda_gl_interop.h"

const float Deltat[1] { 0.0000015f };

// physics
const int WIDTH  { 640 } ;
const int HEIGHT { 640 } ;

dim3 dev_L2 { static_cast<unsigned int>(WIDTH), 
				static_cast<unsigned int>(HEIGHT) };

dev_Grid2d dev_grid2d( dev_L2 );		

// graphics + physics

const dim3 M_i { 2 , 2  };

const int iters_per_render { 10 };

GPUAnim2dTex bitmap( WIDTH, HEIGHT );
GPUAnim2dTex* testGPUAnim2dTex = &bitmap; 


void make_render(dim3 Ld_in, int iters_per_render_in, GPUAnim2dTex* texmap  ) {
	uchar4 *d_out = 0;
	cudaGraphicsMapResources(1, &texmap->cuda_pixbufferObj_resource, 0);
	cudaGraphicsResourceGetMappedPointer((void **)&d_out, NULL,
		texmap->cuda_pixbufferObj_resource);

	for (int i = 0; i < iters_per_render_in; ++i) {
//		kernelLauncher(d_out, dev_grid2d.dev_rho, dev_grid2d.dev_u, Ld_in, M_i );
//		kernelLauncher2(d_out, dev_grid2d.dev_rho, dev_grid2d.dev_u, Ld_in, M_i );
		EulerLauncher2(d_out, dev_grid2d.dev_rho, 
				dev_grid2d.dev_p, dev_grid2d.dev_u, dev_grid2d.dev_E, Ld_in, M_i) ;

				cudaDeviceSynchronize();
	}

	cudaGraphicsUnmapResources(1, &texmap->cuda_pixbufferObj_resource, 0);
	
	char title[128];
	sprintf(title, "Mass density Visualizer - Iterations=%4d, ", 
				   iterationCount );
	glutSetWindowTitle(title);

	cudaDeviceSynchronize();
}	



std::function<void()> render = std::bind( make_render, dev_L2, iters_per_render, testGPUAnim2dTex);	

std::function<void()> draw_texture = std::bind( make_draw_texture, WIDTH, HEIGHT) ;

void display() {
	render();
	draw_texture();
	glutSwapBuffers();
}



int main(int argc, char** argv) {
	// physics
	constexpr std::array<int,2> LdS {WIDTH, HEIGHT };
	constexpr std::array<float,2> ldS {1.f, 1.f };
	
	HANDLE_ERROR(
		cudaMemcpyToSymbol( dev_Deltat, Deltat, sizeof(float)*1,0,cudaMemcpyHostToDevice) );

	const float gas_params[3] { 
								 1.4f,
								 1.f, 1.f } ; // \gamma  
										// heat capacity for constant volume, per volume
										// M


	HANDLE_ERROR(
		cudaMemcpyToSymbol( dev_gas_params, gas_params, sizeof(float)*3,0,cudaMemcpyHostToDevice) );
	
	const int Ld_to_const[2] { LdS[0], LdS[1] } ;
	
	HANDLE_ERROR(
		cudaMemcpyToSymbol( dev_Ld, Ld_to_const, sizeof(int)*2,0,cudaMemcpyHostToDevice) );
	
	Grid2d grid2d( LdS, ldS);
	
	const float hds[2] { grid2d.hd[0], grid2d.hd[1] } ;
	
	// sanity check
	std::cout << " hds : .x : " << hds[0] << " .y : " << hds[1] << std::endl;
	
	//	set1DerivativeParameters(hds);
	set2DerivativeParameters(hds);
//	set3DerivativeParameters(hds);
//	set4DerivativeParameters(hds);
	
	// initial conditions	
	constexpr float rho_0 { 0.956 };
	
	constexpr float tau_0 { 0.001f };
	
	for (int j=0; j<(grid2d.Ld[1]); ++j) {
		for (int i=0;i<(grid2d.Ld[0]); ++i) {
			grid2d.u[ grid2d.flatten(i,j) ].x = 25.0;  // meters/second
			grid2d.u[ grid2d.flatten(i,j) ].y = 25.0;  // meters/second

		}
	}

	std::array<int,2> ix_in { 0, 0 };
	std::array<float,2> b_0 { 0.25f*grid2d.ld[0], 0.25f*grid2d.ld[1]  };

	for (int j=0; j<(grid2d.Ld[1]); ++j) {
		for (int i=0; i<(grid2d.Ld[0]); ++i) {
			ix_in[0] = i;
			ix_in[1] = j;
			grid2d.rho[ grid2d.flatten(i,j) ] = 
				gaussian2d( rho_0, 0.025, b_0,grid2d.gridpt_to_space(ix_in));

		}
	}

	for (int j=0; j<(grid2d.Ld[1]); ++j) {
		for (int i=0; i<(grid2d.Ld[0]); ++i) {
			grid2d.p[grid2d.flatten(i,j)].x = grid2d.rho[grid2d.flatten(i,j)]*
										grid2d.u[grid2d.flatten(i,j)].x ;
			grid2d.p[grid2d.flatten(i,j)].y = grid2d.rho[grid2d.flatten(i,j)]*
										grid2d.u[grid2d.flatten(i,j)].y ;
		}
	}

	int k { 0 } ;
	for (int j=0; j<(grid2d.Ld[1]); ++j) {
		for (int i=0; i<(grid2d.Ld[0]); ++i) {
			k = grid2d.flatten(i,j);
			grid2d.E[k] = grid2d.rho[k]*
				(tau_0*gas_params[1]/gas_params[2] + 
					0.5f*(grid2d.u[k].x*grid2d.u[k].x+grid2d.u[k].y*grid2d.u[k].y) );
		}
	}
	
	
	HANDLE_ERROR( 
		cudaMemcpy( dev_grid2d.dev_rho , grid2d.rho, grid2d.NFLAT()*sizeof(float), 
			cudaMemcpyHostToDevice)
	);

	HANDLE_ERROR( 
		cudaMemcpy( dev_grid2d.dev_u , grid2d.u, grid2d.NFLAT()*sizeof(float2), 
			cudaMemcpyHostToDevice)
	);
	
	HANDLE_ERROR( 
		cudaMemcpy( dev_grid2d.dev_p , grid2d.p, grid2d.NFLAT()*sizeof(float2), 
			cudaMemcpyHostToDevice)
	);

	HANDLE_ERROR( 
		cudaMemcpy( dev_grid2d.dev_E , grid2d.E, grid2d.NFLAT()*sizeof(float), 
			cudaMemcpyHostToDevice)
	);
	
	printInstructions();


	testGPUAnim2dTex->initGLUT(&argc, argv);

	glutKeyboardFunc(keyboard_func);
	glutMouseFunc(mouse_func);
	glutIdleFunc(idle);

	glutDisplayFunc(display);

	testGPUAnim2dTex->initPixelBuffer();

	glutMainLoop();

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_rho ) );

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_rho_out ) );

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_u ) );

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_u_out ) );

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_p ) );

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_p_out ) );

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_E ) );

	HANDLE_ERROR(
		cudaFree( dev_grid2d.dev_E_out ) );

	//	HANDLE_ERROR(
	//	     cudaDeviceSynchronize()
	//	     );
	
	return 0;
} 

	


<|start_filename|>lid-driven-cavity_gpu-gfx/main_gfx_draft.cu<|end_filename|>
/** main.cu
 * \file main.cu
 * Navier-Stokes equation solver in 2-dimensions, incompressible flow, by finite difference
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161206
 * 
 * Compilation tips if you're not using a make file
 * 
 * nvcc -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o  // or 
 * g++ -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o
 * 
 * nvcc -std=c++11 -c ./physlib/dev_R2grid.cu -o dev_R2grid.o
 * nvcc -std=c++11 main.cu R2grid.o dev_R2grid.o o main.exe
 * 
 */
/*
 * cf. <NAME>, <NAME>.  
 * Accelerating reactive-flow simulations using graphics processing units.  
 * AIAA 2013-0371  American Institute of Aeronautics and Astronautics.  
 * http://dx.doi.org/10.5281/zenodo.44333
 * 
 * <NAME>, <NAME>, <NAME>. 
 * Numerical Simulation in Fluid Dynamics: A Practical Introduction (Monographs on Mathematical Modeling and Computation). 
 * SIAM: Society for Industrial and Applied Mathematics (December 1997). 
 * ISBN-13:978-0898713985 QA911.G718 1997
 * 
 * */ 

#include <iomanip>					// std::setprecision
#include <iostream> 				// std::cout
#include <cmath>    				// std::sqrt, std::fmax , std::fmin

#include "./physlib/R2grid.h"      	// Grid2d
#include "./physlib/dev_R2grid.h"  	// Dev_Grid2d
#include "./physlib/uvp.h"          // compute_F, compute_G, etc.
#include "./physlib/boundary.h"     // set_BCs_host, set_BCs
#include "./commonlib/checkerror.h" // checkCudaErrors

#include "./commonlib/tex_anim2d.h" // GPUAnim2dTex

#define GL_GLEXT_PROTOTYPES // needed for identifier glGenBuffer, glBindBuffer, glBufferData, glDeleteBuffers

#include <GL/glut.h>

#include <cuda_runtime.h>
#include <cuda_gl_interop.h> // or #include "cuda_gl_interop.h"

#include <array>  				// std::array
#include <vector>				// std::vector
#include <functional>

// ################################################################
// ####################### Initialization #########################
// ######################## of global-scope variables and objects #
// ################################################################

// ################################################################
// ####################### Initialization #########################
// ################################################################

// discretization (parameters) <==> graphical (parameters)
const int L_X { 256 };  			// WIDTH   // I've tried values 32.  128, 32, 0.5 works; 256, 32, 0.25 works (even though 256, 64 doesn't); 512, 64, doesn't work, neither does 512,32; 512, 16 works
const int L_Y { 256 };  			// HEIGHT  // I've tried values 32,  128, 32, 0.5 works

// "real", physical parameters
/** try domain size (non-dimensional) */
constexpr const float l_X = 1.0;  	// length (in x-direction)
constexpr const float l_Y = 1.0; 	// height (in y-direction)

// physics (on device); Euclidean (spatial) space
dim3 dev_L2 { static_cast<unsigned int>(L_X), 
				static_cast<unsigned int>(L_Y) };

Dev_Grid2d dev_grid2d( dev_L2); 

// physics (on host); Euclidean (spatial) space
constexpr std::array<int,2> LdS { L_X, L_Y } ;
constexpr std::array<float,2> ldS { l_X, l_Y };

//Grid2d grid2d{LdS, ldS};
Grid2d grid2d(LdS, ldS);

// dynamics (parameters)
const dim3 M_i { 64, 64 }; 	// number of threads per block, i.e. Niemeyer's BLOCK_SIZE // I've tried values 4,4

float t = 0.0 ;
int cycle = 0;
	
// iterations for SOR successive over relaxation
int iter = 0;
int itermax = 1000000;  // I tried values such as 10000, Griebel, et. al. = 100

/* READ the parameters of the problem                 */
/* -------------------------------------------------- */ 

/** Safety factor for time step modification; safety factor for time stepsize control */
constexpr const float tau = 0.5; 

/** SOR relaxation parameter; omg is Griebel's notation */
constexpr const float omega = 1.7;  
	
/** Discretization mixture parameter (gamma); gamma:upwind differencing factor is Griebel's notation */
constexpr const float gamma_mix_param = 0.9;

/** Reynolds number */
constexpr const float Re_num = 1000.0;

// SOR iteration tolerance
const float tol = 0.001;  // Griebel, et. al., and Niemeyer has this at 0.001
	
// time range
const float time_start = 0.0;
//const float time_end = 0.25;  // L_X=L_Y=128, M_i=32, t_f=0.5 works
	
// initial time step size
float deltat = 0.02; // I've tried values 0.002

////////////////////////////////////////	
// block and grid dimensions

// boundary conditions kernel
dim3 block_bcs (M_i.x, 1);
dim3 grid_bcs (grid2d.Ld[0] / M_i.x, 1);

// pressure kernel
dim3 block_pr (M_i.y, 1);
dim3 grid_pr (grid2d.Ld[1] / (2 * M_i.y), grid2d.Ld[0]);

// block and grid dimensions for F
dim3 block_F (M_i.y, 1);
dim3 grid_F (grid2d.Ld[1] / M_i.y, grid2d.Ld[0]);

// block and grid dimensions for G
dim3 block_G (M_i.y, 1);
dim3 grid_G (grid2d.Ld[1] / M_i.y, grid2d.Ld[0]);
	
// horizontal pressure boundary conditions
dim3 block_hpbc (M_i.x, 1);
dim3 grid_hpbc (grid2d.Ld[0] / (2 * M_i.x), 1);

// vertical pressure boundary conditions
dim3 block_vpbc (M_i.y, 1);
dim3 grid_vpbc (grid2d.Ld[1] / (2 * M_i.y), 1);

// "internal" cells only, so-called fluid cells from Griebel, et. al.
dim3 inter_gridSize ( (grid2d.Ld[0] + M_i.x-1)/M_i.x , 
						(grid2d.Ld[1]+M_i.y-1)/M_i.y ) ;
////////////////////////////////////////

// residual variable
//constexpr const int size_res = grid_pr.x * grid_pr.y;  doesn't work in std::array, expression must have a constant value
constexpr const int size_res = L_Y/2 * L_X;
std::array<float, size_res> res_array;

/* delt satisfying CFL conditions */
/* ------------------------------ */
float max_u = 1.0e-10;
float max_v = 1.0e-10;

// variables to store maximum velocities
constexpr const int size_max = L_Y/2 * L_X ;
std::array<float, size_max> max_u_array;
std::array<float, size_max> max_v_array;

// pressure sum
std::array<float, size_res> pres_sum_array;

////////////////////////////////////////
// allocate and transfer device memory
float* pres_sum_d;
float* res_d;

float* max_u_d;
float* max_v_d;


// time-step size based on grid and Reynolds number
float dt_Re = 0.5 * Re_num / ((1.0 / (grid2d.hd[0] * grid2d.hd[0])) + (1.0 / (grid2d.hd[1] * grid2d.hd[1])));


/* ----------------------------------------------------------------- */
// graphics
/* ----------------------------------------------------------------- */
const int iters_per_render { 100 };

GPUAnim2dTex bitmap( L_X, L_Y );
GPUAnim2dTex* testGPUAnim2dTex = &bitmap;

void make_render(dim3 Ld_in, int iters_per_render_in, GPUAnim2dTex* texmap ) {
	uchar4 *d_out = 0;
	cudaGraphicsMapResources(1, &texmap->cuda_pixbufferObj_resource, 0);
	cudaGraphicsResourceGetMappedPointer((void **)&d_out, NULL,
		texmap->cuda_pixbufferObj_resource);

	for (int i = 0; i < iters_per_render_in; ++i) {
	// ################################################################
	// #######################               ##########################
	// #######################   MAIN LOOP   ##########################
	// #######################               ##########################
	// ################################################################
	
				/* t i m e    l o o p */
				/* ------------------ */
				/* time loop step     */
		
	// calculate time step based on stability and CFL
		deltat = std::fmin((grid2d.hd[0] / max_u), (grid2d.hd[1] / max_v));
		deltat = tau * std::fmin(dt_Re, deltat);

		// calculate F and G		
		calculate_F <<<grid_F, block_F>>> ( dev_grid2d.u, dev_grid2d.v, dev_grid2d.F, 
			gamma_mix_param, Re_num, 0.0,
			deltat, grid2d.hd[0], grid2d.hd[1], grid2d.Ld[0], grid2d.Ld[1], M_i.x);
		calculate_G <<<grid_G, block_G>>> (dev_grid2d.u, dev_grid2d.v, dev_grid2d.G, 
			gamma_mix_param, Re_num, 0.0,
			deltat, grid2d.hd[0], grid2d.hd[1], grid2d.Ld[0], grid2d.Ld[1], M_i.x);


		// get L2 norm of initial pressure
		sum_pressure <<<grid_pr, block_pr>>> (dev_grid2d.pres_red, dev_grid2d.pres_black, pres_sum_d, 
				grid2d.Ld[0], grid2d.Ld[1], M_i.x);
		cudaMemcpy (pres_sum_array.data(), pres_sum_d, size_res * sizeof(float), cudaMemcpyDeviceToHost);

		float p0_norm = 0.0;
		#pragma unroll
		for (int i = 0; i < size_res; ++i) {
			p0_norm += pres_sum_array[i];
		}
		
		p0_norm = sqrt(p0_norm / ((float)(grid2d.NFLAT())));
		if (p0_norm < 0.0001) {
		   p0_norm = 1.0;
		}

		// ensure all kernels are finished
		cudaDeviceSynchronize();

		float norm_L2;
		
		// calculate new pressure
		// red-black Gauss-Seidel with SOR iteration loop
		for (iter = 1; iter <= itermax; ++iter) {

			// set pressure boundary conditions
			set_horz_pres_BCs <<<grid_hpbc, block_hpbc>>> (dev_grid2d.pres_red, dev_grid2d.pres_black,
				grid2d.Ld[0], grid2d.Ld[1] );
			set_vert_pres_BCs <<<grid_vpbc, block_hpbc>>> (dev_grid2d.pres_red, dev_grid2d.pres_black,
				grid2d.Ld[0], grid2d.Ld[1] );

			// ensure kernel finished
			cudaDeviceSynchronize();

			// update red cells
			red_kernel <<<grid_pr, block_pr>>> (dev_grid2d.F, dev_grid2d.G, 
				dev_grid2d.pres_black, dev_grid2d.pres_red, 
				omega,
				deltat, grid2d.hd[0], grid2d.hd[1], grid2d.Ld[0], grid2d.Ld[1], M_i.x);

			// ensure red kernel finished
			cudaDeviceSynchronize();
			
			// update black cells
			black_kernel <<<grid_pr, block_pr>>> (dev_grid2d.F, dev_grid2d.G, 
				dev_grid2d.pres_red, dev_grid2d.pres_black, 
				omega,
				deltat, grid2d.hd[0], grid2d.hd[1], grid2d.Ld[0], grid2d.Ld[1], M_i.x);

			// ensure red kernel finished
			cudaDeviceSynchronize();
			
			// calculate residual values
			calc_residual <<<grid_pr, block_pr>>> (dev_grid2d.F, dev_grid2d.G, 
				dev_grid2d.pres_red, dev_grid2d.pres_black, res_d,
				deltat, grid2d.hd[0], grid2d.hd[1], grid2d.Ld[0], grid2d.Ld[1], M_i.x);

			// transfer residual value(s) back to CPU
			cudaMemcpy (res_array.data(), res_d, size_res * sizeof(float), cudaMemcpyDeviceToHost);

			norm_L2 = 0.0;
			#pragma unroll
			for (int i = 0; i < size_res; ++i) {
				norm_L2 += res_array[i];
			}
			
			// calculate residual
			norm_L2 = sqrt(norm_L2 / ((float)( grid2d.NFLAT() ))) / p0_norm;
			
			// if tolerance has been reached, end SOR iterations
			if (norm_L2 < tol) {
				break;
			}	
		} // end for

		std::cout << "Time = " << t+deltat << ", deltat = " << deltat << ", iter = " <<
			iter << ", res (i.e. norm_L2) = " << norm_L2 << std::endl;
		
		// calculate new velocities and transfer maximums back

		calculate_u <<<grid_pr, block_pr>>> ( dev_grid2d.F, dev_grid2d.pres_red, dev_grid2d.pres_black, 
			dev_grid2d.u, max_u_d,
			deltat, grid2d.hd[0], grid2d.hd[1], grid2d.Ld[0], grid2d.Ld[1], M_i.x);
		cudaMemcpy (max_u_array.data(), max_u_d, size_max * sizeof(float), cudaMemcpyDeviceToHost);

		calculate_v <<<grid_pr, block_pr>>> (dev_grid2d.G, dev_grid2d.pres_red, dev_grid2d.pres_black, 
			dev_grid2d.v, max_v_d,
			deltat, grid2d.hd[0], grid2d.hd[1], grid2d.Ld[0], grid2d.Ld[1], M_i.x);
		cudaMemcpy (max_v_array.data(), max_v_d, size_max * sizeof(float), cudaMemcpyDeviceToHost);
	
		// get maximum u- and v- velocities
		max_v = 1.0e-10;
		max_u = 1.0e-10;

		#pragma unroll
		for (int i = 0; i < size_max; ++i) {
			float test_u = max_u_array[i];
			max_u = std::fmax(max_u, test_u);

			float test_v = max_v_array[i];
			max_v = std::fmax(max_v, test_v);
		}

		// set velocity boundary conditions
		set_BCs <<<grid_bcs, block_bcs>>> (dev_grid2d.u, dev_grid2d.v, grid2d.Ld[0], grid2d.Ld[1]);

		cudaDeviceSynchronize();


		// increase time
		t += deltat;

		float_to_char<<<inter_gridSize, M_i>>>( d_out, dev_grid2d.u, 
			grid2d.Ld[0], grid2d.Ld[1] );


	} // for loop, iters per render, END


	
	cudaGraphicsUnmapResources(1, &texmap->cuda_pixbufferObj_resource, 0 );
	
	cudaDeviceSynchronize();
	
} // END make render

std::function<void()> render = std::bind( make_render, dev_L2, iters_per_render, testGPUAnim2dTex);

std::function<void()> draw_texture = std::bind( make_draw_texture, L_X, L_Y);

void display() {
	render() ;
	draw_texture();
	glutSwapBuffers();
}



int main( int argc, char *argv[] ) {
	// set initial BCs
	set_BCs_host (grid2d.u , grid2d.v, grid2d.Ld[0], grid2d.Ld[1]);

	// get max velocity for initial values (including BCs)
	#pragma unroll
	for (int col = 0; col < grid2d.Ld[0] + 2; ++col) {
		#pragma unroll
		for (int row = 1; row < grid2d.Ld[1] + 2; ++row) {
			max_u = fmax(max_u, fabs( grid2d.u[flatten(col, row, grid2d.Ld[1]+2)] ));
		}
	}

	#pragma unroll
	for (int col = 1; col < grid2d.Ld[0] + 2; ++col) {
		#pragma unroll
		for (int row = 0; row < grid2d.Ld[1] + 2; ++row) {
			max_v = fmax(max_v, fabs( grid2d.v[ flatten(col, row, grid2d.Ld[1] + 2) ] ));
		}
	}

	
	cudaMalloc ((void**) &pres_sum_d, size_res * sizeof(float));
	cudaMalloc ((void**) &res_d, size_res * sizeof(float));
	cudaMalloc ((void**) &max_u_d, size_max * sizeof(float));
	cudaMalloc ((void**) &max_v_d, size_max * sizeof(float));
	
	// copy to device memory
	cudaMemcpy (dev_grid2d.u, grid2d.u, grid2d.staggered_NFLAT() * sizeof(float), cudaMemcpyHostToDevice);
	cudaMemcpy (dev_grid2d.F, grid2d.F, grid2d.staggered_NFLAT() * sizeof(float), cudaMemcpyHostToDevice);
	cudaMemcpy (dev_grid2d.v, grid2d.v, grid2d.staggered_NFLAT() * sizeof(float), cudaMemcpyHostToDevice);
	cudaMemcpy (dev_grid2d.G, grid2d.G, grid2d.staggered_NFLAT() * sizeof(float), cudaMemcpyHostToDevice);
	cudaMemcpy (dev_grid2d.pres_red, grid2d.pres_red, (grid2d.Ld[0]/2+2)*(grid2d.Ld[1]+2) * sizeof(float), cudaMemcpyHostToDevice);
	cudaMemcpy (dev_grid2d.pres_black, grid2d.pres_black, (grid2d.Ld[0]/2+2 )*(grid2d.Ld[1]+2)* sizeof(float), cudaMemcpyHostToDevice);
	////////////////////////////////////////

	float t = time_start;
	
	
	// graphics run
	testGPUAnim2dTex->initGLUT(&argc, argv);

	glutKeyboardFunc(keyboard_func);
	glutMouseFunc(mouse_func);
	glutIdleFunc(idle);

	glutDisplayFunc(display);

	testGPUAnim2dTex->initPixelBuffer();

	glutMainLoop();
	
	
	
	
	
	// free device memory
	checkCudaErrors( cudaFree( dev_grid2d.u )); 
	checkCudaErrors( cudaFree( dev_grid2d.v )); 
	checkCudaErrors( cudaFree( dev_grid2d.F )); 
	checkCudaErrors( cudaFree( dev_grid2d.G )); 
	
	checkCudaErrors( cudaFree( dev_grid2d.pres_red )); 
	checkCudaErrors( cudaFree( dev_grid2d.pres_black )); 

	checkCudaErrors( cudaFree( max_u_d )); 
	checkCudaErrors( cudaFree( max_v_d )); 
	checkCudaErrors( cudaFree( pres_sum_d )); 
	checkCudaErrors( cudaFree( res_d )); 

	cudaDeviceReset();
	return 0;
} // END of main


<|start_filename|>lid-driven-cavity_gpu-gfx/physlib/uvp.cu<|end_filename|>
/** uvp.cu
 * \file uvp.cu
 * \brief computation of u, v, p for 2-dim. incompressible Navier-Stokes equation with finite difference
 * \author <NAME>  
 * \email <EMAIL>
 * \date 20161209
 * 
 * compilation tip: (compile separately)
 * nvcc -std=c++11 -c ./physlib/u_p.cu -o u_p.o
 * 
 */
#include "uvp.h"

__host__ __device__ int flatten( int i, int j, int stride) {
	return i * stride + j ;
}

/*------------------------------------------------------------------- */
/* Computation of tentative velocity field (F,G) -------------------- */
/*------------------------------------------------------------------- */

__global__ 
void calculate_F ( const float* u, const float* v,
				  float* F, 
					const float mix_param, const float Re_num, float gx,
  				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x)
{	
	int row = (blockIdx.x * blockDim.x) + threadIdx.x + 1;
	int col = (blockIdx.y * blockDim.y) + threadIdx.y + 1;
	
	if (col == imax) {
		// right boundary, F_ij = u_ij
		// also do left boundary
		F[ 0 * ( jmax + 2 ) + row ]    = u[ 0 * ( jmax + 2 ) + row ] ;
		F[ imax * ( jmax + 2 ) + row ] = u[ imax * ( jmax + 2 ) + row ] ;
	} else {
		
		// u velocities
		float u_ij   = u[ col * ( jmax + 2 ) + row ] ; 
		float u_ip1j = u[ (col+1) * ( jmax + 2 ) + row ] ; 
		float u_ijp1 = u[ col * ( jmax + 2 ) + row + 1 ] ; 
		float u_im1j = u[ (col - 1 ) * ( jmax + 2 ) + row ] ; 
		float u_ijm1 = u[ col * ( jmax + 2 ) + row - 1 ] ; 

		// v velocities
		float v_ij   = v[ col * ( jmax + 2 ) + row ] ; 
		float v_ip1j = v[ (col + 1) * ( jmax + 2 ) + row ] ; 
		float v_ijm1 = v[ col * ( jmax + 2 ) + row -1 ] ; 
		float v_ip1jm1 = v[ (col + 1 ) * ( jmax + 2 ) + row - 1] ; 


		// finite differences
		float du2dx, duvdy, d2udx2, d2udy2;

		du2dx = (((u_ij + u_ip1j) * (u_ij + u_ip1j) - (u_im1j + u_ij) * (u_im1j + u_ij))
				+ mix_param * (fabs(u_ij + u_ip1j) * (u_ij - u_ip1j)
				- fabs(u_im1j + u_ij) * (u_im1j - u_ij))) / (4.0 * dx);
		duvdy = ((v_ij + v_ip1j) * (u_ij + u_ijp1) - (v_ijm1 + v_ip1jm1) * (u_ijm1 + u_ij)
				+ mix_param * (fabs(v_ij + v_ip1j) * (u_ij - u_ijp1)
				- fabs(v_ijm1 + v_ip1jm1) * (u_ijm1 - u_ij))) / (4.0 * dy);
		d2udx2 = (u_ip1j - (2.0 * u_ij) + u_im1j) / (dx * dx);
		d2udy2 = (u_ijp1 - (2.0 * u_ij) + u_ijm1) / (dy * dy);

		F[ col * ( jmax + 2 ) + row ] = 
			u_ij + dt * (((d2udx2 + d2udy2) / Re_num) - du2dx - duvdy + gx);
		
	} // end if
		
} // end calculate_F

///////////////////////////////////////////////////////////////////////////////

__global__ 
void calculate_G ( const float* u, const float* v,
				  float* G, 
					const float mix_param, const float Re_num, float gy,
  				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x)

{
	int row = (blockIdx.x * blockDim.x) + threadIdx.x + 1;
	int col = (blockIdx.y * blockDim.y) + threadIdx.y + 1;
	
	if (row == jmax) {
		// top and bottom boundaries
		G[ col * ( jmax + 2 ) + 0 ]    = v[ col * ( jmax + 2 ) + 0 ] ;
		G[ col * ( jmax + 2 ) + jmax ] = v[ col * ( jmax + 2 ) + jmax ] ;
	} else {
		
		// u velocities
		float u_ij   = u[ col * ( jmax + 2 ) + row ] ; 
		float u_ijp1 = u[ col  * ( jmax + 2 ) + row + 1 ] ; 
		float u_im1j = u[ (col-1) * ( jmax + 2 ) + row  ] ; 
		float u_im1jp1 = u[ (col - 1 ) * ( jmax + 2 ) + row + 1] ; 

		// v velocities
		float v_ij   = v[ col * ( jmax + 2 ) + row ] ; 
		float v_ijp1 = v[ col * ( jmax + 2 ) + row +1 ] ; 
		float v_ip1j = v[ (col+1) * ( jmax + 2 ) + row  ] ; 
		float v_ijm1 = v[ col  * ( jmax + 2 ) + row -1 ] ; 
		float v_im1j = v[ (col - 1) * ( jmax + 2 ) + row  ] ; 

		
		// finite differences
		float dv2dy, duvdx, d2vdx2, d2vdy2;

		dv2dy = ((v_ij + v_ijp1) * (v_ij + v_ijp1) - (v_ijm1 + v_ij) * (v_ijm1 + v_ij)
				+ mix_param * (fabs(v_ij + v_ijp1) * (v_ij - v_ijp1)
				- fabs(v_ijm1 + v_ij) * (v_ijm1 - v_ij))) / (4.0 * dy);
		duvdx = ((u_ij + u_ijp1) * (v_ij + v_ip1j) - (u_im1j + u_im1jp1) * (v_im1j + v_ij)
				+ mix_param * (fabs(u_ij + u_ijp1) * (v_ij - v_ip1j) 
				- fabs(u_im1j + u_im1jp1) * (v_im1j - v_ij))) / (4.0 * dx);
		d2vdx2 = (v_ip1j - (2.0 * v_ij) + v_im1j) / (dx * dx);
		d2vdy2 = (v_ijp1 - (2.0 * v_ij) + v_ijm1) / (dy * dy);


		G[ col * ( jmax + 2 ) + row ] = 
			v_ij + dt * (((d2vdx2 + d2vdy2) / Re_num) - dv2dy - duvdx + gy);
			
	} // end if
		
} // end calculate_G

///////////////////////////////////////////////////////////////////////////////

// M_x is the number of threads in a block along the x-dimension
__global__ 
void sum_pressure (const float* pres_red, const float* pres_black, 
					float* pres_sum, 
					const int imax, const int jmax, const int M_x) 
{
	int row = (blockIdx.x * blockDim.x) + threadIdx.x + 1;
	int col = (blockIdx.y * blockDim.y) + threadIdx.y + 1;

	// shared memory for block's sum
	extern __shared__ float sum_cache[];
			
	int NUM_2 = jmax >> 1;

	float pres_r = pres_red[ col * ( NUM_2 + 2 ) + row ] ;
	float pres_b = pres_black[ col * ( NUM_2 + 2 ) + row ] ;

	// add squared pressure
	sum_cache[threadIdx.x] = (pres_r * pres_r) + (pres_b * pres_b);

	// synchronize threads in block to ensure all thread values stored
	__syncthreads();

	// add up values for block
	int i = M_x >> 1;
	while (i != 0) {
		if (threadIdx.x < i) {
			sum_cache[threadIdx.x] += sum_cache[threadIdx.x + i];
		}
		__syncthreads();
		i >>= 1;
	}

	// store block's summed values
	if (threadIdx.x == 0) {
		pres_sum[blockIdx.y + (gridDim.y * blockIdx.x)] = sum_cache[0];
	}

} // end sum_pressure

/*------------------------------------------------------------------- */
/* SOR iteration for the Poisson equation for the pressure
/*------------------------------------------------------------------- */
///////////////////////////////////////////////////////////////////////////////

/** Function to update pressure for red cells
 * 
 * \param[in]		dt			time-step size
 * \param[in]		F			array of discretized x-momentum eqn terms
 * \param[in]		G			array of discretized y-momentum eqn terms
 * \param[in]		pres_black	pressure values of black cells
 * \param[inout]	pres_red	pressure values of red cells
 */
__global__
void red_kernel ( const float* F, 
				 const float* G, const float* pres_black,
				 float* pres_red,
				const float omega, 
				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x)

{
	int row = (blockIdx.x * blockDim.x) + threadIdx.x + 1;
	int col = (blockIdx.y * blockDim.y) + threadIdx.y + 1;
	
	int NUM_2 = jmax >> 1;			
	
	float p_ij = 	pres_red[ col * ( NUM_2 + 2 ) + row ] ;
		
	float p_im1j = 	pres_black[ (col - 1) * ( NUM_2 + 2 ) + row ] ;
	float p_ip1j = 	pres_black[ (col + 1) * ( NUM_2 + 2 ) + row ] ;
	float p_ijm1 = 	pres_black[ col * ( NUM_2 + 2 ) + row - (col & 1 ) ] ;
	float p_ijp1 = 	pres_black[ col * ( NUM_2 + 2 ) + row + ((col + 1) & 1 ) ] ;
	
	// right-hand side
	float rhs = ((
	(
	F[ col * ( jmax + 2 ) + (2 * row) - (col & 1)  ]
	 - F[ (col - 1) * ( jmax + 2 ) + (2 * row) - (col & 1)  ] 
	 ) / dx)
			  + (
	(
	G[ col * ( jmax + 2 ) + (2 * row) - (col & 1)  ]
    - G[ col * ( jmax + 2 ) + (2 * row) - (col & 1) - 1 ]
	   ) / dy)) / dt;

	
	pres_red[ col * ( NUM_2 + 2 ) + row ] = p_ij * (1.0 - omega) + omega * 
		(((p_ip1j + p_im1j) / (dx * dx)) + ((p_ijp1 + p_ijm1) / (dy * dy)) - 
		rhs) / ((2.0 / (dx * dx)) + (2.0 / (dy * dy)));
	
} // end red_kernel

///////////////////////////////////////////////////////////////////////////////

/** Function to update pressure for black cells
 * 
 * \param[in]		dt			time-step size
 * \param[in]		F			array of discretized x-momentum eqn terms
 * \param[in]		G			array of discretized y-momentum eqn terms
 * \param[in]		pres_red	pressure values of red cells
 * \param[inout]	pres_black	pressure values of black cells
 */
__global__ 
void black_kernel ( const float* F, 
				   const float* G, const float* pres_red, 
				   float* pres_black,
				   const float omega,
				   const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x) 
{
	int row = (blockIdx.x * blockDim.x) + threadIdx.x + 1;
	int col = (blockIdx.y * blockDim.y) + threadIdx.y + 1;
	
	int NUM_2 = jmax >> 1;
	
	
	float p_ij = 	pres_black[ col * ( NUM_2 + 2 ) + row ] ;
		
	float p_im1j = 	pres_red[ (col - 1) * ( NUM_2 + 2 ) + row ] ;
	float p_ip1j = 	pres_red[ (col + 1) * ( NUM_2 + 2 ) + row ] ;
	float p_ijm1 = 	pres_red[ col * ( NUM_2 + 2 ) + row - ((col + 1) & 1 ) ] ;
	float p_ijp1 = 	pres_red[ col * ( NUM_2 + 2 ) + row + (col & 1 ) ] ;
	
	// right-hand side
	float rhs = ((
	(
	F[ col * ( jmax + 2 ) + (2 * row) - ((col + 1) & 1)  ]
	 - F[ (col - 1) * ( jmax + 2 ) + (2 * row) - ((col + 1) & 1)  ] 
	 ) / dx)
			  + (
	(
	G[ col * ( jmax + 2 ) + (2 * row) - ((col + 1) & 1)  ]
    - G[ col * ( jmax + 2 ) + (2 * row) - ((col+1) & 1) - 1 ]
	   ) / dy)) / dt;

	pres_black[ col * ( NUM_2 + 2 ) + row ] 
		 = p_ij * (1.0 - omega) + omega * 
		(((p_ip1j + p_im1j) / (dx * dx)) + ((p_ijp1 + p_ijm1) / (dy * dy)) - 
		rhs) / ((2.0 / (dx * dx)) + (2.0 / (dy * dy)));
		
} // end black_kernel

/*------------------------------------------------------------------- */
/* computation of residual */
/*------------------------------------------------------------------- */
///////////////////////////////////////////////////////////////////////////////

__global__
void calc_residual ( const float* F, const float* G, 
					const float* pres_red, const float* pres_black,
					float* res_array,
				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x)

{
	int row = (blockIdx.x * blockDim.x) + threadIdx.x + 1;
	int col = (blockIdx.y * blockDim.y) + threadIdx.y + 1;
	
	int NUM_2 = jmax >> 1;

	float p_ij, p_im1j, p_ip1j, p_ijm1, p_ijp1, rhs, res, res2;

	// red point
	p_ij = pres_red[flatten(col, row, (NUM_2+2))];
	
	p_im1j = pres_black[flatten(col-1,row,NUM_2+2)] ; 
	p_ip1j = pres_black[flatten(col+1,row,NUM_2+2)] ; 
	p_ijm1 = pres_black[flatten(col,row - (col & 1),NUM_2+2)] ; 
	p_ijp1 = pres_black[flatten(col,row+((col + 1) & 1),NUM_2+2)] ;

	rhs = (((
		F[ flatten(col, (2*row)-(col & 1),jmax + 2)] - 
		F[ flatten(col-1, (2*row)- (col & 1) , jmax + 2)] )
//		F(col, (2 * row) - (col & 1)) - F(col - 1, (2 * row) - (col & 1))) 
	/ dx)
		+  ((
		G[flatten(col, (2 * row) - (col & 1), jmax + 2)] - 
		G[flatten(col, (2 * row) - (col & 1)-1, jmax + 2)] )
//		G(col, (2 * row) - (col & 1)) - G(col, (2 * row) - (col & 1) - 1)) 
		/ dy)) / dt;

	// calculate residual
	res = ((p_ip1j - (2.0 * p_ij) + p_im1j) / (dx * dx))
		+ ((p_ijp1 - (2.0 * p_ij) + p_ijm1) / (dy * dy)) - rhs;

	// black point
	p_ij = pres_black[flatten(col, row, NUM_2 + 2)];

	p_im1j = pres_red[flatten(col - 1, row, NUM_2 + 2)];
	p_ip1j = pres_red[flatten(col + 1, row, NUM_2 + 2)];
	p_ijm1 = pres_red[flatten(col, row - ((col + 1) & 1) , NUM_2 + 2)];
	p_ijp1 = pres_red[flatten(col, row + (col & 1) , NUM_2 + 2)];
	
	// right-hand side
	rhs = ((
		(
		F[flatten(col, (2 * row) - ((col + 1) & 1),jmax +2)] - 
		F[flatten(col - 1, (2 * row) - ((col + 1) & 1), jmax + 2) ] 
		) / dx)
		+  (
		(
		G[ flatten(col, (2 * row) - ((col + 1) & 1), jmax + 2) ] - 
		G[ flatten( col, (2 * row) - ((col + 1) & 1) - 1, jmax + 2) ]
		) / dy
		)) / dt;

	// calculate residual
	res2 = ((p_ip1j - (2.0 * p_ij) + p_im1j) / (dx * dx))
		 + ((p_ijp1 - (2.0 * p_ij) + p_ijm1) / (dy * dy)) - rhs;

	// shared memory for block's sum
	extern __shared__ float sum_cache[];

	sum_cache[threadIdx.x] = (res * res) + (res2 * res2);

	// synchronize threads in block to ensure all residuals stored
	__syncthreads();

	// add up squared residuals for block
	int i = M_x >> 1;
	while (i != 0) {
		if (threadIdx.x < i) {
			sum_cache[threadIdx.x] += sum_cache[threadIdx.x + i];
		}
		__syncthreads();
		i >>= 1;
	}

	// store block's summed residuals
	if (threadIdx.x == 0) {
		res_array[blockIdx.y + (gridDim.y * blockIdx.x)] = sum_cache[0];
	}
} 


/*------------------------------------------------------------------- */
/* computation of new velocity values */
/*------------------------------------------------------------------- */
///////////////////////////////////////////////////////////////////////////////

__global__ 
void calculate_u ( const float* F, 
				  const float* pres_red, const float* pres_black, 
				  float* u, float* max_u, 
  				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x)

{
	int row = (blockIdx.x * blockDim.x) + threadIdx.x + 1;
	int col = (blockIdx.y * blockDim.y) + threadIdx.y + 1;
	
	// allocate shared memory to store max velocities
	extern __shared__ float max_cache[];
	max_cache[threadIdx.x] = 0.0;
	
	int NUM_2 = jmax >> 1;
	float new_u = 0.0;

	if (col != jmax) {

		float p_ij, p_ip1j, new_u2;

		// red point
		p_ij = pres_red[ flatten(col, row, NUM_2 + 2)];
		p_ip1j = pres_black[ flatten(col + 1, row, NUM_2 + 2) ];

		new_u = F[ flatten(col, (2 * row) - (col & 1), jmax + 2)] - (dt * (p_ip1j - p_ij) / dx);
		u[ flatten(col, (2 * row) - (col & 1), jmax + 2)] = new_u;

		// black point
		p_ij = pres_black[ flatten(col, row, NUM_2 + 2)];
		p_ip1j = pres_red[ flatten(col + 1, row, NUM_2 + 2) ];

		new_u2 = F[ flatten(col, (2 * row) - ((col + 1) & 1), jmax + 2) ] - (dt * (p_ip1j - p_ij) / dx);
		u[ flatten(col, (2 * row) - ((col + 1) & 1), jmax + 2) ] = new_u2;

		// check for max of these two
		new_u = fmax(fabs(new_u), fabs(new_u2));

		if ((2 * row) == jmax) {
			// also test for max velocity at vertical boundary
			new_u = fmax(new_u, fabs( u[ flatten(col, jmax + 1, jmax + 2) ] ));
		}
	} else {
		// check for maximum velocity in boundary cells also
		new_u = fmax(fabs( u[ flatten(imax, (2 * row), jmax + 2) ] ), 
			fabs( u[ flatten(0, (2 * row), jmax + 2)] ));
		new_u = fmax(fabs( u[flatten(imax, (2 * row) - 1, jmax + 2) ]), new_u);
		new_u = fmax(fabs( u[flatten(0, (2 * row) - 1, jmax + 2) ] ), new_u);

		new_u = fmax(fabs( u[flatten(imax + 1, (2 * row), jmax + 2)] ), new_u);
		new_u = fmax(fabs( u[ flatten(imax + 1, (2 * row) - 1, jmax + 2)] ), new_u);

	} // end if

	// store maximum u for block from each thread
	max_cache[threadIdx.x] = new_u;

	// synchronize threads in block to ensure all velocities stored
	__syncthreads();

	// calculate maximum for block
	int i = M_x >> 1;
	while (i != 0) {
		if (threadIdx.x < i) {
			max_cache[threadIdx.x] = fmax(max_cache[threadIdx.x], max_cache[threadIdx.x + i]);
		}
		__syncthreads();
		i >>= 1;
	}

	// store block's maximum
	if (threadIdx.x == 0) {
		max_u[blockIdx.y + (gridDim.y * blockIdx.x)] = max_cache[0];
	}

	
} // end calculate_u

///////////////////////////////////////////////////////////////////////////////

__global__ 
void calculate_v ( const float* G, 
				  const float* pres_red, const float* pres_black, 
				  float* v, float* max_v,
				  const float dt, const float dx, const float dy,
				  const int imax, const int jmax, const int M_x)
{
	int row = (blockIdx.x * blockDim.x) + threadIdx.x + 1;
	int col = (blockIdx.y * blockDim.y) + threadIdx.y + 1;
	
	// allocate shared memory to store maximum velocities
	extern __shared__ float max_cache[];
	max_cache[threadIdx.x] = 0.0;

	int NUM_2 = jmax >> 1;
	float new_v = 0.0;
	
	if (row != NUM_2) {
		float p_ij, p_ijp1, new_v2;

		// red pressure point
		p_ij = pres_red[ flatten(col, row, NUM_2 + 2)];
		p_ijp1 = pres_black[flatten(col, row + ((col + 1) & 1), NUM_2 + 2)];
	
		new_v = G[ flatten(col, (2 * row) - (col & 1), jmax + 2)] - (dt * (p_ijp1 - p_ij) / dy);
		v[ flatten(col, (2 * row) - (col & 1), jmax + 2)] = new_v;


		// black pressure point
		p_ij = pres_black[ flatten(col, row, NUM_2 + 2)];
		p_ijp1 = pres_red[ flatten(col, row + (col & 1), NUM_2 + 2)];
		
		new_v2 = G[ flatten(col, (2 * row) - ((col + 1) & 1), jmax + 2)] - (dt * (p_ijp1 - p_ij) / dy);
		v[ flatten(col, (2 * row) - ((col + 1) & 1) , jmax + 2)] = new_v2;


		// check for max of these two
		new_v = fmax(fabs(new_v), fabs(new_v2));

		if (col == imax) {
			// also test for max velocity at vertical boundary
			new_v = fmax(new_v, fabs( v[ flatten(imax + 1, (2 * row), jmax + 2) ] ));
		}

	} else {

		if ((col & 1) == 1) {
			// black point is on boundary, only calculate red point below it
			float p_ij = pres_red[ flatten(col, row, NUM_2 +2) ];
			float p_ijp1 = pres_black[ flatten(col, row + ((col + 1) & 1), NUM_2 + 2)];
		
			new_v = G[ flatten(col, (2 * row) - (col & 1), jmax + 2) ] - (dt * (p_ijp1 - p_ij) / dy);
			v[ flatten(col, (2 * row) - (col & 1), jmax + 2 ) ] = new_v;

		} else {
			// red point is on boundary, only calculate black point below it
			float p_ij = pres_black[ flatten(col, row, NUM_2 + 2)];
			float p_ijp1 = pres_red[ flatten(col, row + (col & 1), NUM_2 + 2)];
		
			new_v = G[ flatten(col, (2 * row) - ((col + 1) & 1), jmax + 2) ] - (dt * (p_ijp1 - p_ij) / dy);
			v[ flatten(col, (2 * row) - ((col + 1) & 1), jmax + 2) ] = new_v;
		}

		// get maximum v velocity
		new_v = fabs(new_v);

		// check for maximum velocity in boundary cells also
		new_v = fmax(fabs( v[flatten(col, jmax, jmax + 2)] ), new_v);
		new_v = fmax(fabs( v[flatten(col, 0, jmax + 2)] ), new_v);

		new_v = fmax(fabs( v[flatten(col, jmax + 1, jmax + 2) ] ), new_v);

	} // end if
		
	// store absolute value of velocity
	max_cache[threadIdx.x] = new_v;
	
	// synchronize threads in block to ensure all velocities stored
	__syncthreads();

	// calculate maximum for block
	int i = M_x >> 1;
	while (i != 0) {
		if (threadIdx.x < i) {
			max_cache[threadIdx.x] = fmax(max_cache[threadIdx.x], max_cache[threadIdx.x + i]);
		}
		__syncthreads();
		i >>= 1;
	}

	// store block's summed residuals
	if (threadIdx.x == 0) {
		max_v[blockIdx.y + (gridDim.y * blockIdx.x)] = max_cache[0];
	}
	
} // end calculate_v

///////////////////////////////////////////////////////////////////////////////



 


<|start_filename|>convect3dfinitedifftex/physlib/dev_R3grid.h<|end_filename|>
/* dev_R3grid.h
 * R3 under discretization (discretize functor) to a thread block
 * <NAME>  <EMAIL>
 * 20160701
 */
#ifndef __DEV_R3GRID_H__
#define __DEV_R3GRID_H__

#include "../commonlib/errors.h"

extern __constant__ int dev_Ld[3]; // L^{d=3} = (L_x,L_y,L_z) \in \mathbb{N}^3

class dev_Grid3d
{
	public:
		dim3 Ld;
	
		float *dev_rho;
		float3 *dev_u;
		float *dev_E;

		// constructor
		__host__ dev_Grid3d( dim3 );

//		__host__ ~dev_Grid3d();

		__host__ int NFLAT();
};

class dev_block3d
{
	public:
		unsigned int  N_is[3];

		__device__ dev_block3d(unsigned int N_x, unsigned int N_y, unsigned int N_z);

		__device__ int flatten(int i_x, int i_y, int i_z);
};

#endif // __DEV_R3GRID_H__

 


<|start_filename|>MacCor1d/physlib/dev_phys_param.h<|end_filename|>
/* dev_phys_param.h
 * physical parameters on the device
 * <NAME>  <EMAIL>
 * 20161027
 * */
#ifndef __DEV_PHYS_PARAM_H__
#define __DEV_PHYS_PARAM_H__

extern __constant__ float dev_Deltat[1]; // Delta t

#endif // __DEV_PHYS_PARAM_H__


<|start_filename|>convect2dfinitedifftex/commonlib/sharedmem.h<|end_filename|>
/* sharedmem.h
 * shared memory to a 1-dim. grid
 * <NAME>  <EMAIL>
 * 20160710
 */
#ifndef __SHAREDMEM_H__
#define __SHAREDMEM_H__

#include "finitediff.h"

#include "../physlib/dev_R3grid.h"

namespace sharedmem {

extern __constant__ int RAD[1] ;  // radius of the stencil; helps to deal with "boundary conditions" at (thread) block's ends



__device__ int idxClip( int idx, int idxMax) ;
		
__device__ int flatten(int k_x, int k_y, int k_z, int L_x, int L_y, int L_z) ;

__device__ void sh_dev_div1( float* dev_rho, float3* dev_u, float &result  ) ;

__device__ float sh_dev_div2( float* dev_rho, float3* dev_u  ) ;

__device__ float sh_dev_div3( float* dev_rho, float3* dev_u  ) ;

__device__ float sh_dev_div4( float* dev_rho, float3* dev_u  ) ;


}

#endif // __SHAREDMEM_H__

		

		
		


<|start_filename|>convect3dfinitedifftex/commonlib/finitediff.h<|end_filename|>
/* finitediff.h
 * finite difference methods on a grid
 * <NAME>  <EMAIL>
 * 20160710
 */
#ifndef __FINITEDIFF_H__
#define __FINITEDIFF_H__ 

#include "errors.h"

// I fixed the size of dev_c to be 4 because I don't anticipate that we'd need more accuracy 
extern __constant__ float3 dev_cnus[4]; // i = x,y,z; j = 1,2,3,4

void set1DerivativeParameters(const float hd_i[3] );

void set2DerivativeParameters(const float hd_i[3] );

void set3DerivativeParameters(const float hd_i[3] );

void set4DerivativeParameters(const float hd_i[3] );


__device__ float dev_dirder1(float stencil[1][2], float c_nus[4]);

__device__ float dev_dirder2(float stencil[2][2], float c_nus[4]);

__device__ float dev_dirder3(float stencil[3][2], float c_nus[4]);

__device__ float dev_dirder4(float stencil[4][2], float c_nus[4]);

// DIVERGENCE (DIV) in 1, 2, 3, 4 stencils, central difference

__device__ float dev_div1( float3 stencil[1][2]  ) ;

__device__ float dev_div2( float3 stencil[2][2]  ) ; 

__device__ float dev_div3( float3 stencil[3][2]  ) ;

__device__ float dev_div4( float3 stencil[4][2]  ) ;


#endif // __FINITEDIFF_H__


<|start_filename|>SuddenExpansion/main.cu<|end_filename|>
/* main.cu
 * Sudden Expansion, in 2-dimensions
 * <NAME>  <EMAIL>
 * 20161120
 * 
 * Compilation tips if you're not using a make file
 * 
 * nvcc -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o  // or 
 * g++ -std=c++11 -c ./physlib/R2grid.cpp -o R2grid.o
 * 
 * nvcc -std=c++11 -c ./physlib/dev_R2grid.cu -o dev_R2grid.o
 * nvcc -std=c++11 -c ./commonlib/surfObj2d.cu -o surfObj2d.o
 * nvcc -std=c++11 main.cu R2grid.o dev_R2grid.o surfObj2d.o -o main.exe
 * 
 */
#include <functional>

#include <iostream> // std::cout
#include <fstream>  // std::ofstream
#include <cmath>    // std::sqrt

#include "./physlib/R2grid.h" // Grid2d
#include "./physlib/dev_R2grid.h" // dev_Grid2d
#include "./commonlib/surfObj2d.h" // SurfObj2d
#include "./commonlib/checkerror.h" // checkCudaErrors
#include "./commonlib/tex_anim2d.h" // GPUAnim2dTex, iterationCount, keyboard_func, mouse_func, idle, display

// discretization (parameters) <=> graphical (parameters)
const int L_X  { 640 } ;  // WIDTH
const int L_Y  { 640 } ;  // HEIGHT

// "real", physical parameters
constexpr const float l_X = 10.f; // length (in x-direction)
constexpr const float l_Y = 2.f ; // height (in y-direction)
constexpr const float h_val { l_Y * 0.75f } ; // inlet radius

// physics (on device); Euclidean (spatial) space
dim3 dev_L2 { static_cast<unsigned int>(L_X), 
				static_cast<unsigned int>(L_Y) };

dev_Grid2d dev_grid2d( dev_L2 );

// Create surface object to "bind" to corresponding cudaArray
SurfObj2d surf_rho( dev_grid2d.cuArr_f) ;  
SurfObj2d surf_rho_out( dev_grid2d.cuArr_f_out) ;  
SurfObj2d surf_u( dev_grid2d.cuArr_u) ;  
SurfObj2d surf_u_out( dev_grid2d.cuArr_u_out) ;  



// physics (on host); Euclidean (spatial) space
constexpr std::array<int,2> LdS { L_X, L_Y } ; 
constexpr std::array<float,2> ldS { l_X, l_Y };
	
Grid2d grid2d{ LdS, ldS };

const float2 hds { grid2d.hd[0], grid2d.hd[1] }; 

// dynamics (parameters)
const dim3 M_i { 4, 4 };

// graphics + dynamics (parameters)
const int iters_per_render { 10 } ;
// graphics
GPUAnim2dTex bitmap( L_X, L_Y );
GPUAnim2dTex* eleGPUAnim2dTex = &bitmap; 

void make_render(dim3 Ld_in, int iters_per_render_in, GPUAnim2dTex* texmap ) {
	uchar4 *d_out = 0;
	cudaGraphicsMapResources(1, &texmap->cuda_pixbufferObj_resource, 0) ;
	cudaGraphicsResourceGetMappedPointer((void **)&d_out, NULL,
		texmap->cuda_pixbufferObj_resource);
		
	const dim3 N_i {  (Ld_in.x + M_i.x - 1)/M_i.x, (Ld_in.y + M_i.y - 1)/M_i.y  } ;
		
	for (int i =0; i < iters_per_render_in; ++i) {
		d_BoundaryConditions<<<N_i, M_i>>>( hds, surf_u.surfObj, Ld_in.x, Ld_in.y, h_val ) ;
		
		floatux_to_char<<<N_i,M_i>>>( d_out, surf_u.surfObj, Ld_in.x, Ld_in.y ) ;
		cudaDeviceSynchronize() ;
	}
	
	cudaGraphicsUnmapResources(1, &texmap->cuda_pixbufferObj_resource,0);
	
	char title[128];
	sprintf( title, "velocity (in x-direction) Visualizer - Iterations=%4d, ",
		iterationCount );
	glutSetWindowTitle(title);
	
	cudaDeviceSynchronize() ;
	
}

std::function<void()> render = std::bind( make_render, dev_L2, iters_per_render, eleGPUAnim2dTex) ;

std::function<void()> draw_texture = std::bind( make_draw_texture, L_X, L_Y );

void display() {
	render() ;
	draw_texture() ;
	glutSwapBuffers();
}


int main(int argc, char* argv[]) {

	// initial condition 
	std::array<int,2> ix_in {0,0};
	std::array<float,2> x_in {0.f, 0.f };
	float radius_pos { 0.f } ; 
	float tempux { 0.f } ;
	float tempuy { 0.f } ;
	
	for (auto j = 0; j < grid2d.Ld[1] ; ++j) { 
		for (auto i = 0; i < grid2d.Ld[0]; ++i ) {
			ix_in[0] = i;
			ix_in[1] = j;
			x_in = grid2d.gridpt_to_space( ix_in ) ; 
			grid2d.f[ grid2d.flatten(i,j) ] = 0.0f ;  // kg/m^3 
			grid2d.u[ grid2d.flatten(i,j) ].x = 0.1f ; 
			grid2d.u[ grid2d.flatten(i,j) ].y = 0.f ;
			radius_pos = (x_in[0]-l_X/2.f)*(x_in[0]-l_X/2.f)+(x_in[1]-l_Y/2.f)*(x_in[1]-l_Y/2.f) ; 
			radius_pos = std::sqrt( radius_pos ) ;
			if (radius_pos < l_Y/5.f ) {
				tempux = (l_Y/5.f - radius_pos)*(-1.f*( x_in[1]-l_Y/2.f ) ) ; 
				tempuy = (l_Y/5.f - radius_pos)*( x_in[0]-l_X/2.f ) ;
				grid2d.u[ grid2d.flatten(i,j)].x = tempux ; 
				grid2d.u[ grid2d.flatten(i,j)].y = tempuy ; 
				
			}
			if (x_in[0] == 0 ) {
				grid2d.f[ grid2d.flatten(i,j) ] = 1.f ;  // kg/m^3
			}	
		}
	}

	checkCudaErrors(
		cudaMemcpyToArray( dev_grid2d.cuArr_f,0,0,
			(grid2d.f).data(), sizeof(float)*grid2d.NFLAT(), cudaMemcpyHostToDevice) );

	checkCudaErrors(
		cudaMemcpyToArray( dev_grid2d.cuArr_u,0,0,
			(grid2d.u).data(), sizeof(float2)*grid2d.NFLAT(), cudaMemcpyHostToDevice) );





	eleGPUAnim2dTex->initGLUT(&argc, argv) ;
	
	glutKeyboardFunc(keyboard_func);
	glutMouseFunc(mouse_func);
	glutIdleFunc(idle);

	glutDisplayFunc(display); 
	
	eleGPUAnim2dTex->initPixelBuffer();
	
	glutMainLoop();


	return 0;
	
}


<|start_filename|>NavSt2DIncompFiniteDiff/physlib/R2grid.cpp<|end_filename|>
/* R2grid.cpp
 * R2 under discretization (discretize functor) to a (staggered) grid
 * <NAME>  <EMAIL>
 * 20161113
 */
#include "R2grid.h"

// Constructor
/* ---------------------------------------------------------------- */
/* Sets the initial values for velocity u, p                        */
/* ---------------------------------------------------------------- */
Grid2d :: Grid2d(std::array<int,2> Ld_in, std::array<float,2> ld_in)
	: Ld(Ld_in), ld(ld_in)
{
	hd = { ld[0]/static_cast<float>(Ld[0]), ld[1]/static_cast<float>(Ld[1])  };
	staggered_Ld = { Ld[0]+2, Ld[1]+2 };
	
	thrust::host_vector<float> temp_p( this->staggered_SIZE(), 0.0 );
	p = temp_p;
	F = temp_p;
	G = temp_p;
	RHS=temp_p;

	u = temp_p;
	v = temp_p;

/*	std::vector<float2> temp_u( this->staggered_SIZE() );
	u = temp_u;*/
}

Grid2d :: Grid2d(std::array<int,2> Ld_in, std::array<float,2> ld_in, 
					float UI, float VI)
	: Ld(Ld_in), ld(ld_in)
{
	hd = { ld[0]/static_cast<float>(Ld[0]), ld[1]/static_cast<float>(Ld[1])  };
	staggered_Ld = { Ld[0]+2, Ld[1]+2 };
	
	thrust::host_vector<float> temp_p( this->staggered_SIZE(),0.0 );
	p = temp_p;
	F = temp_p;
	G = temp_p;
	RHS=temp_p;

	thrust::host_vector<float> temp_u( this->staggered_SIZE(),UI );
	thrust::host_vector<float> temp_v( this->staggered_SIZE(),VI );
	u = temp_u;
	v = temp_v;
	
//	float2 uI { UI, VI };
//	std::vector<float2> temp_u( this->staggered_SIZE(), uI );
//	u = temp_u;
}


std::array<float,2> Grid2d :: gridpt_to_space(std::array<int,2> index) {
	std::array<float,2> Xi { index[0]*hd[0], index[1]*hd[1]  } ;
	return Xi;
}

int Grid2d :: NFLAT() {
	return Ld[0]*Ld[1] ;

}
	
// int Grid2d :: staggered_SIZE() - returns the staggered grid size
/* this would correspond to Griebel's notation of 
 * (imax+1)*(jmax+1)
 */
int Grid2d :: staggered_SIZE() {
	return (staggered_Ld[0] )*(staggered_Ld[1]);
}

int Grid2d :: flatten(const int i_x, const int i_y ) {
	return i_x+i_y*Ld[0]  ;
}

int Grid2d :: staggered_flatten(const int i_x, const int i_y ) {
	return i_x+i_y*(staggered_Ld[0])  ;
}


Grid2d::~Grid2d() {
	std::exit(0);
}


