#ifdef METAL
#if !defined(METALCOMPUTE) && !defined(MLX)
#define N1 p_CONSTANT_BUFFER_UINT[CInd_N1]
#define N2 p_CONSTANT_BUFFER_UINT[CInd_N2]
#define N3 p_CONSTANT_BUFFER_UINT[CInd_N3]
#define Limit_I_low_PML p_CONSTANT_BUFFER_UINT[CInd_Limit_I_low_PML]
#define Limit_J_low_PML p_CONSTANT_BUFFER_UINT[CInd_Limit_J_low_PML]
#define Limit_K_low_PML p_CONSTANT_BUFFER_UINT[CInd_Limit_K_low_PML]
#define Limit_I_up_PML p_CONSTANT_BUFFER_UINT[CInd_Limit_I_up_PML]
#define Limit_J_up_PML p_CONSTANT_BUFFER_UINT[CInd_Limit_J_up_PML]
#define Limit_K_up_PML p_CONSTANT_BUFFER_UINT[CInd_Limit_K_up_PML]
#define SizeCorrI p_CONSTANT_BUFFER_UINT[CInd_SizeCorrI]
#define SizeCorrJ p_CONSTANT_BUFFER_UINT[CInd_SizeCorrJ]
#define SizeCorrK p_CONSTANT_BUFFER_UINT[CInd_SizeCorrK]
#define PML_Thickness p_CONSTANT_BUFFER_UINT[CInd_PML_Thickness]
#define NumberSources p_CONSTANT_BUFFER_UINT[CInd_NumberSources]
#define LengthSource p_CONSTANT_BUFFER_UINT[CInd_LengthSource]
#define NumberSensors p_CONSTANT_BUFFER_UINT[CInd_NumberSensors]
#define TimeSteps p_CONSTANT_BUFFER_UINT[CInd_TimeSteps]

#define SizePML p_CONSTANT_BUFFER_UINT[CInd_SizePML]
#define SizePMLxp1 p_CONSTANT_BUFFER_UINT[CInd_SizePMLxp1]
#define SizePMLyp1 p_CONSTANT_BUFFER_UINT[CInd_SizePMLyp1]
#define SizePMLzp1 p_CONSTANT_BUFFER_UINT[CInd_SizePMLzp1]
#define SizePMLxp1yp1zp1 p_CONSTANT_BUFFER_UINT[CInd_SizePMLxp1yp1zp1]
#define ZoneCount p_CONSTANT_BUFFER_UINT[CInd_ZoneCount]

#define SelRMSorPeak p_CONSTANT_BUFFER_UINT[CInd_SelRMSorPeak]
#define SelMapsRMSPeak p_CONSTANT_BUFFER_UINT[CInd_SelMapsRMSPeak]
#define IndexRMSPeak_Vx p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Vx]
#define IndexRMSPeak_Vy p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Vy]
#define IndexRMSPeak_Vz p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Vz]
#define IndexRMSPeak_Sigmaxx p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Sigmaxx]
#define IndexRMSPeak_Sigmayy p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Sigmayy]
#define IndexRMSPeak_Sigmazz p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Sigmazz]
#define IndexRMSPeak_Sigmaxy p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Sigmaxy]
#define IndexRMSPeak_Sigmaxz p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Sigmaxz]
#define IndexRMSPeak_Sigmayz p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Sigmayz]
#define IndexRMSPeak_Pressure p_CONSTANT_BUFFER_UINT[CInd_IndexRMSPeak_Pressure]
#define NumberSelRMSPeakMaps p_CONSTANT_BUFFER_UINT[CInd_NumberSelRMSPeakMaps]

#define SelMapsSensors p_CONSTANT_BUFFER_UINT[CInd_SelMapsSensors]
#define IndexSensor_Vx p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Vx]
#define IndexSensor_Vy p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Vy]
#define IndexSensor_Vz p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Vz]
#define IndexSensor_Sigmaxx p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Sigmaxx]
#define IndexSensor_Sigmayy p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Sigmayy]
#define IndexSensor_Sigmazz p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Sigmazz]
#define IndexSensor_Sigmaxy p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Sigmaxy]
#define IndexSensor_Sigmaxz p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Sigmaxz]
#define IndexSensor_Sigmayz p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Sigmayz]
#define IndexSensor_Pressure p_CONSTANT_BUFFER_UINT[CInd_IndexSensor_Pressure]
#define NumberSelSensorMaps p_CONSTANT_BUFFER_UINT[CInd_NumberSelSensorMaps]
#define SensorSubSampling p_CONSTANT_BUFFER_UINT[CInd_SensorSubSampling]
#define SensorStart p_CONSTANT_BUFFER_UINT[CInd_SensorStart]
#define nStep p_CONSTANT_BUFFER_UINT[CInd_nStep]
#define CurrSnap p_CONSTANT_BUFFER_UINT[CInd_CurrSnap]
#define TypeSource p_CONSTANT_BUFFER_UINT[CInd_TypeSource]
#define SelK p_CONSTANT_BUFFER_UINT[CInd_SelK]

#define DT p_CONSTANT_BUFFER_MEX[CInd_DT]
#define InvDXDTplus_pr (p_CONSTANT_BUFFER_MEX + CInd_InvDXDTplus)
#define DXDTminus_pr (p_CONSTANT_BUFFER_MEX + CInd_DXDTminus)
#define InvDXDTplushp_pr (p_CONSTANT_BUFFER_MEX + CInd_InvDXDTplushp)
#define DXDTminushp_pr (p_CONSTANT_BUFFER_MEX + CInd_DXDTminushp)
#else
#define nStep p_CONSTANT_BUFFER_UINT[CInd_nStep]
#define TypeSource p_CONSTANT_BUFFER_UINT[CInd_TypeSource]
#endif

#define __def_MEX_VAR_0(__NameVar)  (&p_MEX_BUFFER_0[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_1(__NameVar)  (&p_MEX_BUFFER_1[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_2(__NameVar)  (&p_MEX_BUFFER_2[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_3(__NameVar)  (&p_MEX_BUFFER_3[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_4(__NameVar)  (&p_MEX_BUFFER_4[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_5(__NameVar)  (&p_MEX_BUFFER_5[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_6(__NameVar)  (&p_MEX_BUFFER_6[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_7(__NameVar)  (&p_MEX_BUFFER_7[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_8(__NameVar)  (&p_MEX_BUFFER_8[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_9(__NameVar)  (&p_MEX_BUFFER_9[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_10(__NameVar)  (&p_MEX_BUFFER_10[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 
#define __def_MEX_VAR_11(__NameVar)  (&p_MEX_BUFFER_11[ ((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar *2])) | (((unsigned long) (p_INDEX_MEX[CInd_ ##__NameVar*2+1]))<<32) ]) 

#define __def_UINT_VAR(__NameVar)  (&p_UINT_BUFFER[ ((unsigned long) (p_INDEX_UINT[CInd_ ##__NameVar*2])) | (((unsigned long) (p_INDEX_UINT[CInd_ ##__NameVar*2+1]))<<32) ])

// #define __def_MEX_VAR(__NameVar)  (&p_MEX_BUFFER[ p_INDEX_MEX[CInd_ ##__NameVar ]]) 
// #define __def_UINT_VAR(__NameVar)  (&p_UINT_BUFFER[ p_INDEX_UINT[CInd_ ##__NameVar]])


#define k_V_x_x_pr  __def_MEX_VAR_0(V_x_x)
#define k_V_y_x_pr  __def_MEX_VAR_0(V_y_x)
#define k_V_z_x_pr  __def_MEX_VAR_0(V_z_x)
#define k_V_x_y_pr  __def_MEX_VAR_0(V_x_y)
#define k_V_y_y_pr  __def_MEX_VAR_0(V_y_y)
#define k_V_z_y_pr  __def_MEX_VAR_0(V_z_y)
#define k_V_x_z_pr  __def_MEX_VAR_0(V_x_z)
#define k_V_y_z_pr  __def_MEX_VAR_0(V_y_z)
#define k_V_z_z_pr  __def_MEX_VAR_0(V_z_z)

#define k_Vx_pr  __def_MEX_VAR_1(Vx)
#define k_Vy_pr  __def_MEX_VAR_1(Vy)
#define k_Vz_pr  __def_MEX_VAR_1(Vz)

#define k_Rxx_pr  __def_MEX_VAR_2(Rxx)
#define k_Ryy_pr  __def_MEX_VAR_2(Ryy)
#define k_Rzz_pr  __def_MEX_VAR_2(Rzz)

#define k_Rxy_pr  __def_MEX_VAR_3(Rxy)
#define k_Rxz_pr  __def_MEX_VAR_3(Rxz)
#define k_Ryz_pr  __def_MEX_VAR_3(Ryz)

#define k_Sigma_x_xx_pr  __def_MEX_VAR_4(Sigma_x_xx)
#define k_Sigma_y_xx_pr  __def_MEX_VAR_4(Sigma_y_xx)
#define k_Sigma_z_xx_pr  __def_MEX_VAR_4(Sigma_z_xx)
#define k_Sigma_x_yy_pr  __def_MEX_VAR_4(Sigma_x_yy)
#define k_Sigma_y_yy_pr  __def_MEX_VAR_4(Sigma_y_yy)
#define k_Sigma_z_yy_pr  __def_MEX_VAR_4(Sigma_z_yy)
#define k_Sigma_x_zz_pr  __def_MEX_VAR_4(Sigma_x_zz)
#define k_Sigma_y_zz_pr  __def_MEX_VAR_4(Sigma_y_zz)

#define k_Sigma_z_zz_pr  __def_MEX_VAR_5(Sigma_z_zz)
#define k_Sigma_x_xy_pr  __def_MEX_VAR_5(Sigma_x_xy)
#define k_Sigma_y_xy_pr  __def_MEX_VAR_5(Sigma_y_xy)
#define k_Sigma_x_xz_pr  __def_MEX_VAR_5(Sigma_x_xz)
#define k_Sigma_z_xz_pr  __def_MEX_VAR_5(Sigma_z_xz)
#define k_Sigma_y_yz_pr  __def_MEX_VAR_5(Sigma_y_yz)
#define k_Sigma_z_yz_pr  __def_MEX_VAR_5(Sigma_z_yz)

#define k_Sigma_xy_pr  __def_MEX_VAR_6(Sigma_xy)
#define k_Sigma_xz_pr  __def_MEX_VAR_6(Sigma_xz)
#define k_Sigma_yz_pr  __def_MEX_VAR_6(Sigma_yz)

#define k_Sigma_xx_pr  __def_MEX_VAR_7(Sigma_xx)
#define k_Sigma_yy_pr  __def_MEX_VAR_7(Sigma_yy)
#define k_Sigma_zz_pr  __def_MEX_VAR_7(Sigma_zz)

#define k_SourceFunctions_pr __def_MEX_VAR_8(SourceFunctions)

#define k_LambdaMiuMatOverH_pr  __def_MEX_VAR_9(LambdaMiuMatOverH)
#define k_LambdaMatOverH_pr     __def_MEX_VAR_9(LambdaMatOverH)
#define k_MiuMatOverH_pr        __def_MEX_VAR_9(MiuMatOverH)
#define k_TauLong_pr            __def_MEX_VAR_9(TauLong)
#define k_OneOverTauSigma_pr    __def_MEX_VAR_9(OneOverTauSigma)
#define k_TauShear_pr           __def_MEX_VAR_9(TauShear)
#define k_InvRhoMatH_pr         __def_MEX_VAR_9(InvRhoMatH)
#define k_Ox_pr  __def_MEX_VAR_9(Ox)
#define k_Oy_pr  __def_MEX_VAR_9(Oy)
#define k_Oz_pr  __def_MEX_VAR_9(Oz)
#define k_Pressure_pr  __def_MEX_VAR_9(Pressure)

#define k_SqrAcc_pr  __def_MEX_VAR_10(SqrAcc)

#define k_SensorOutput_pr  __def_MEX_VAR_11(SensorOutput)

#define k_IndexSensorMap_pr  __def_UINT_VAR(IndexSensorMap)
#define k_SourceMap_pr		 __def_UINT_VAR(SourceMap)
#define k_MaterialMap_pr	 __def_UINT_VAR(MaterialMap)

#ifdef METALCOMPUTE
#define CGID uint
#else
#define CGID uint3
#endif
#if !defined(METALCOMPUTE) && !defined(MLX)
#define METAL_PARAMS\
	const device unsigned int *p_CONSTANT_BUFFER_UINT [[ buffer(0) ]],\
	const device mexType * p_CONSTANT_BUFFER_MEX [[ buffer(1) ]],\
	const device unsigned int *p_INDEX_MEX [[ buffer(2) ]],\
	const device unsigned int *p_INDEX_UINT [[ buffer(3) ]],\
	const device unsigned int *p_UINT_BUFFER [[ buffer(4) ]],\
	device mexType * p_MEX_BUFFER_0 [[ buffer(5) ]],\
	device mexType * p_MEX_BUFFER_1 [[ buffer(6) ]],\
	device mexType * p_MEX_BUFFER_2 [[ buffer(7) ]],\
	device mexType * p_MEX_BUFFER_3 [[ buffer(8) ]],\
	device mexType * p_MEX_BUFFER_4 [[ buffer(9) ]],\
	device mexType * p_MEX_BUFFER_5 [[ buffer(10) ]],\
	device mexType * p_MEX_BUFFER_6 [[ buffer(11) ]],\
	device mexType * p_MEX_BUFFER_7 [[ buffer(12) ]],\
	device mexType * p_MEX_BUFFER_8 [[ buffer(13) ]],\
	device mexType * p_MEX_BUFFER_9 [[ buffer(14) ]],\
	device mexType * p_MEX_BUFFER_10 [[ buffer(15) ]],\
	device mexType * p_MEX_BUFFER_11 [[ buffer(16) ]],\
	CGID gid[[thread_position_in_grid]])\
{
#else
#define METAL_PARAMS\
	const device unsigned int *p_CONSTANT_BUFFER_UINT [[ buffer(0) ]],\
	const device unsigned int *p_INDEX_MEX [[ buffer(1) ]],\
	const device unsigned int *p_INDEX_UINT [[ buffer(2) ]],\
	const device unsigned int *p_UINT_BUFFER [[ buffer(3) ]],\
	device mexType * p_MEX_BUFFER_0 [[ buffer(4) ]],\
	device mexType * p_MEX_BUFFER_1 [[ buffer(5) ]],\
	device mexType * p_MEX_BUFFER_2 [[ buffer(6) ]],\
	device mexType * p_MEX_BUFFER_3 [[ buffer(7) ]],\
	device mexType * p_MEX_BUFFER_4 [[ buffer(8) ]],\
	device mexType * p_MEX_BUFFER_5 [[ buffer(9) ]],\
	device mexType * p_MEX_BUFFER_6 [[ buffer(10) ]],\
	device mexType * p_MEX_BUFFER_7 [[ buffer(11) ]],\
	device mexType * p_MEX_BUFFER_8 [[ buffer(12) ]],\
	device mexType * p_MEX_BUFFER_9 [[ buffer(13) ]],\
	device mexType * p_MEX_BUFFER_10 [[ buffer(14) ]],\
	device mexType * p_MEX_BUFFER_11 [[ buffer(15) ]],\
	CGID gid[[thread_position_in_grid]])\
{
#endif
#endif
/// PMLS

#if ((defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)) 
//MLX_BLOCK_PML_1_STRESS_START
#define _ST_PML
#if ((defined(MLX)) && defined(MLX_PML_1_STRESS)) || !defined(MLX)
#define _PML_KERNEL_I_BOTTOM
#ifdef CUDA
extern "C" __global__ void PML_1_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_1_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_1_StressKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else
	#define nN1 (PML_Thickness)
	#define nN2 (N2)
	#define nN3 (N3)
    _PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
//MLX does not need input variable declarations
#if defined(MLX)
	#define nN1 (PML_Thickness)
	#define nN2 (N2)
	#define nN3 (N3)
    _PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
	
#if defined(_ST_PML)
	mexType Diff;
	mexType Diff2;
	mexType Diff3;
#endif

#if defined(_ST_MAIN)
	mexType Dx;
	mexType Dy;
	mexType Dz;
#endif


	mexType value;

	mexType m1;
	mexType m2;
	mexType m3;
	mexType m4;

	mexType RigidityXY=0.0;
	mexType RigidityXZ=0.0;
	mexType RigidityYZ=0.0;
	mexType TauShearXY=0.0;
	mexType TauShearXZ=0.0;
	mexType TauShearYZ=0.0;

#if defined(_ST_MAIN)
	mexType LambdaMiu;
	mexType LambdaMiuComp;
	mexType dFirstPart;
	mexType dFirstPartForR;
	mexType accum_xx=0.0;
	mexType accum_yy=0.0;
	mexType accum_zz=0.0;
	mexType accum_p=0.0;
	_PT source;
	_PT bAttenuating=1;
	mexType Miu;
	mexType MiuComp;
	mexType OneOverTauSigma;
	mexType NextR;
	mexType accum_xy=0.0;
	mexType accum_xz=0.0;
	mexType accum_yz=0.0;
#endif


#ifdef USE_2ND_ORDER_EDGES
    interface_t interfaceZ=inside, interfaceY=inside, interfaceX=inside;
#endif

_PT index2;
_PT index;
_PT  MaterialID;

_PT CurZone;

for ( CurZone=0;CurZone<ZoneCount;CurZone++)
  {
	  index=Ind_MaterialMap(i,j,k);
      MaterialID=ELD(MaterialMap,index);

	  	m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j+1,k));
   		value=m1*m2*m3*m4;
  		RigidityXY =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
      
	    #if  defined(_ST_MAIN) 
  		TauShearXY = value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j+1,k)))
  							 : ELD(TauShear,MaterialID);

	   #endif
	    m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k+1));

  		value=m1*m2*m3*m4;
  		RigidityXZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
	   #if defined(_ST_MAIN)
  		TauShearXZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k+1)))
  							 : ELD(TauShear,MaterialID);

		#endif
		m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k+1));

        value=m1*m2*m3*m4;

  		RigidityYZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
		
		#if  defined(_ST_MAIN)
  		TauShearYZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k+1)))
  							 : ELD(TauShear,MaterialID);
		#endif

  	
  	if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 ||  IsOnPML_K(k)==1)//We are in the PML borders
  	 {
		#if defined(_ST_PML)
  		if (i<N1-1 && j <N2-1 && k < N3-1)
  		{

  			Diff= i>1 && i <N1-1 ? CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k)) -
  			                       CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k))
  			      : i>0 && i <N1 ? (EL(Vx,i,j,k)-EL(Vx,i-1,j,k))  :0;

			Diff2= j>1 && j < N2-1 ? CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
  									CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k))
  			        : j>0 && j < N2 ? EL(Vy,i,j,k)-EL(Vy,i,j-1,k):0;

			Diff3= k>1 && k < N3-1 ? CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1)) -
  									CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2))
  			                       :k>0 && k < N3 ? EL(Vz,i,j,k)-EL(Vz,i,j,k-1) : 0;
  			
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_x_xx,index2) =InvDXDT_I*(
  											ELD(Sigma_x_xx,index2)*DXDT_I+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff);
			index2=Ind_Sigma_y_xx(i,j,k);
  			ELD(Sigma_y_xx,index2) =InvDXDT_J*(
  											ELD(Sigma_y_xx,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_xx(i,j,k);
  			ELD(Sigma_z_xx,index2) =InvDXDT_K*(
  											ELD(Sigma_z_xx,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_xx,index)= ELD(Sigma_x_xx,index2) + ELD(Sigma_y_xx,index2)+ ELD(Sigma_z_xx,index2);

			index2=Ind_Sigma_x_yy(i,j,k);
  			ELD(Sigma_x_yy,index2) =InvDXDT_I*(
  											ELD(Sigma_x_yy,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);

			index2=Ind_Sigma_y_yy(i,j,k);
  			ELD(Sigma_y_yy,index2) =InvDXDT_J*(
  											ELD(Sigma_y_yy,index2)*DXDT_J+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_yy(i,j,k);
  			ELD(Sigma_z_yy,index2) =InvDXDT_K*(
  											ELD(Sigma_z_yy,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_yy,index)= ELD(Sigma_x_yy,index2) + ELD(Sigma_y_yy,index2)+ ELD(Sigma_z_yy,index2);


  			index2=Ind_Sigma_x_zz(i,j,k);
  			ELD(Sigma_x_zz,index2) =InvDXDT_I*(
  											ELD(Sigma_x_zz,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);




  			index2=Ind_Sigma_y_zz(i,j,k);
  			ELD(Sigma_y_zz,index2) =InvDXDT_J*(
  											ELD(Sigma_y_zz,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);



  			index2=Ind_Sigma_z_zz(i,j,k);
  			ELD(Sigma_z_zz,index2) =InvDXDT_K*(
  											ELD(Sigma_z_zz,index2)*DXDT_K+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_zz,index)= ELD(Sigma_x_zz,index2) + ELD(Sigma_y_zz,index2)+ ELD(Sigma_z_zz,index2);

  			index2=Ind_Sigma_x_xy(i,j,k);

  			Diff= i >0 && i<N1-2 ? CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k)) -
  			                   CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k))
  			                    :i<N1-1 ? EL(Vy,i+1,j,k)-EL(Vy,i,j,k):0;

  			ELD(Sigma_x_xy,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xy,index2)*DXDThp_I+
  											RigidityXY*
  											Diff);
			index2=Ind_Sigma_y_xy(i,j,k);

  			Diff=j > 0 && j<N2-2 ? CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k) )-
  			                       CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k) )
  			                       :j<N2-1 ? EL(Vx,i,j+1,k)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_y_xy,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_xy,index2)*DXDThp_J+
  											RigidityXY*
  											Diff);
			index=Ind_Sigma_xy(i,j,k);

			ELD(Sigma_xy,index)= ELD(Sigma_x_xy,Ind_Sigma_x_xy(i,j,k)) + ELD(Sigma_y_xy,index2);

  			index2=Ind_Sigma_x_xz(i,j,k);

  			Diff= i>0 && i<N1-2 ? CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k)) -
  								  CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k))
  								  :i<N1-1 ? EL(Vz,i+1,j,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_x_xz,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xz,index2)*DXDThp_I+
  											RigidityXZ*
  											Diff);



  			index2=Ind_Sigma_z_xz(i,j,k);


  			Diff=k >0 && k < N3-2 ? CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k)) -
  			                        CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1)):
                                      k < N3-1 ? EL(Vx,i,j,k+1)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_z_xz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_xz,index2)*DXDThp_K+
  											RigidityXZ*
  											Diff);
			index=Ind_Sigma_xz(i,j,k);

  		    ELD(Sigma_xz,index)= ELD(Sigma_x_xz,Ind_Sigma_x_xz(i,j,k)) + ELD(Sigma_z_xz,index2);

  			index2=Ind_Sigma_y_yz(i,j,k);

  			Diff=j>0 && j<N2-2 ? CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k)) -
  							     CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k))
  							     :j<N2-1 ? EL(Vz,i,j+1,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_y_yz,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_yz,index2)*DXDThp_J+
  											RigidityYZ*
  											Diff);

  			

  			index2=Ind_Sigma_z_yz(i,j,k);

  			Diff=k>0 && k < N3-2 ? CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
  			                       CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1))
  			                       :k < N3-1 ? EL(Vy,i,j,k+1)-EL(Vy,i,j,k):0;
  			ELD(Sigma_z_yz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_yz,index2)*DXDThp_K+
  											RigidityYZ*
  											Diff);

			index=Ind_Sigma_yz(i,j,k);
	
			ELD(Sigma_yz,index)= ELD(Sigma_y_yz,Ind_Sigma_y_yz(i,j,k)) + ELD(Sigma_z_yz,index2);

		  }	 
		#endif  
	 }
	else
	{
#if defined(_ST_MAIN)
  		//We are in the center, no need to check any limits, the use of the PML simplify this
  		index=Ind_Sigma_xx(i,j,k);

		if (REQUIRES_2ND_ORDER_M(X))
			Dx=EL(Vx,i,j,k)-EL(Vx,i-1,j,k);
		else
			Dx=CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k))-
				CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k));

		if REQUIRES_2ND_ORDER_M(Y)
			Dy=EL(Vy,i,j,k)-EL(Vy,i,j-1,k);
		else
			Dy=CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
				CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k));

		if REQUIRES_2ND_ORDER_M(Z)
			Dz=EL(Vz,i,j,k)-EL(Vz,i,j,k-1);
		else
			Dz=CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1))-
              CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2));

		
		//We will use the particle displacement to estimate the acoustic pressure, and using the conservation of mass formula
		//We can use the stress kernel as V matrices are not being modified in this kernel,
		// and the spatial derivatives are the same ones required for pressure calculation
        // partial(p)/partial(t) = \rho c^2 div(V)
        //it is important to mention that the Python function will need still to multiply the result for the maps of (speed of sound)^2 and density, 
		// and divide by the spatial step.
		EL(Pressure,i,j,k)+=DT*(Dx+Dy+Dz);
        accum_p+=EL(Pressure,i,j,k);


  		LambdaMiu=ELD(LambdaMiuMatOverH,MaterialID)*(1.0+ELD(TauLong,MaterialID));
  		Miu=2.0*ELD(MiuMatOverH,MaterialID)*(1.0+ELD(TauShear,MaterialID));
  		OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
		dFirstPart=LambdaMiu*(Dx+Dy+Dz);
		
		if (ELD(TauLong,MaterialID)!=0.0 || ELD(TauShear,MaterialID)!=0.0) // We avoid unnecessary calculations if there is no attenuation
		{
			
			LambdaMiuComp=DT*ELD(LambdaMiuMatOverH,MaterialID)*(ELD(TauLong,MaterialID)*OneOverTauSigma);
			dFirstPartForR=LambdaMiuComp*(Dx+Dy+Dz);
			MiuComp=DT*2.0*ELD(MiuMatOverH,MaterialID)*(ELD(TauShear,MaterialID)*OneOverTauSigma);
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxx,index) - dFirstPartForR + MiuComp*(Dy+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);

			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz) + 0.5*(ELD(Rxx,index) + NextR));
			ELD(Rxx,index)=NextR;
		}
		else
		{
			bAttenuating=0;
			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz));
		}
  		
	    accum_xx+=ELD(Sigma_xx,index);

		if (bAttenuating==1)
		{
  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryy,index) - dFirstPartForR + MiuComp*(Dx+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);
				
  			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz) + 0.5*(ELD(Ryy,index) + NextR));
			ELD(Ryy,index)=NextR;
		}
		else
			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz));
      	
		accum_yy+=ELD(Sigma_yy,index);

  		if (bAttenuating==1)
		{
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rzz,index) - dFirstPartForR +MiuComp*(Dx+Dy))
				/(1+DT*0.5*OneOverTauSigma);
  			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy) + 0.5*(ELD(Rzz,index) + NextR));
			ELD(Rzz,index)=NextR;
		}
		else
			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy));

      	accum_zz+=ELD(Sigma_zz,index);


  		index=Ind_Sigma_xy(i,j,k);

		if (RigidityXY!=0.0)
  		{
			  OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
              if (REQUIRES_2ND_ORDER_P(X))
                  Dx=EL(Vy,i+1,j,k)-EL(Vy,i,j,k);
              else
                  Dx=CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k))-
                     CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k));


              if (REQUIRES_2ND_ORDER_P(Y))
                  Dx+=EL(Vx,i,j+1,k)-EL(Vx,i,j,k);
              else
                  Dx+=CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k))-
                      CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k));

  			Miu=RigidityXY*(1.0+TauShearXY);

			if (TauShearXY!=0.0)
			{
				MiuComp=RigidityXY*(TauShearXY*OneOverTauSigma);
				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxy,index) - DT*MiuComp*Dx)
  		          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xy,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxy,index) +NextR));
				ELD(Rxy,index)=NextR;
			}
			else
				ELD(Sigma_xy,index)+= DT*(Miu*Dx );
        	
			accum_xy+=ELD(Sigma_xy,index);

  		}
        // else
        //     ELD(Rxy,index)=0.0;

		if (RigidityXZ!=0.0)
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(X))
				Dx=EL(Vz,i+1,j,k)-EL(Vz,i,j,k);
			else
				Dx=CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dx+=EL(Vx,i,j,k+1)-EL(Vx,i,j,k);
			else
				Dx+=CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k))-
					CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1));

	  		Miu=RigidityXZ*(1.0+TauShearXZ);

			if (TauShearXZ!=0.0)
			{
  				MiuComp=RigidityXZ*(TauShearXZ*OneOverTauSigma);
	  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxz,index) - DT*MiuComp*Dx)
  			          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xz,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxz,index) +NextR));
				ELD(Rxz,index)=NextR;
			}
			else
				ELD(Sigma_xz,index)+= DT*(Miu*Dx );
        	accum_xz+=ELD(Sigma_xz,index);
  			
  		}
        // else
        //     ELD(Rxz,index)=0.0;
 
  		if (RigidityYZ!=0.0 )
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(Y))
				Dy=EL(Vz,i,j+1,k)-EL(Vz,i,j,k);
			else
				Dy=CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dy+=EL(Vy,i,j,k+1)-EL(Vy,i,j,k);
			else
				Dy+=CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
					CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1));

  			Miu=RigidityYZ*(1.0+TauShearYZ);
			
			if (TauShearYZ!=0)
			{
				MiuComp=RigidityYZ*(TauShearYZ*OneOverTauSigma);

				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryz,index) - DT*MiuComp*Dy)
					/(1+DT*0.5*OneOverTauSigma);

				ELD(Sigma_yz,index)+= DT*(Miu*Dy + 0.5*(ELD(Ryz,index) +NextR));
				ELD(Ryz,index)=NextR;
			}
			else 
				ELD(Sigma_yz,index)+= DT*(Miu*Dy );
        	accum_yz+=ELD(Sigma_yz,index);

  		}
        //   else
        //       ELD(Ryz,index)=0.0;

		if ((nStep < LengthSource) && TypeSource>=2) //Source is stress
  		{
  			index=IndN1N2N3(i,j,k,0);
  			source=ELD(SourceMap,index);
  			if (source>0)
  			{
  			  source--; //need to use C index
  			  value=ELD(SourceFunctions,nStep*NumberSources+source)*ELD(Ox,index); // We use Ox as mechanism to provide weighted arrays
				index=Ind_Sigma_xx(i,j,k);
                if ((TypeSource-2)==0)
                {
                    ELD(Sigma_xx,index)+=value;
                    ELD(Sigma_yy,index)+=value;
                    ELD(Sigma_zz,index)+=value;
                }
                else
                {
                   ELD(Sigma_xx,index)=value;
                   ELD(Sigma_yy,index)=value;
                   ELD(Sigma_zz,index)=value;
                }

  			}
  		}
	#endif
	}
  }
  #if defined(_ST_MAIN) 
  if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
  {
	
    accum_xx/=ZoneCount;
    accum_yy/=ZoneCount;
    accum_zz/=ZoneCount;
	accum_xy/=ZoneCount;
	accum_xz/=ZoneCount;
	accum_yz/=ZoneCount;
	
    CurZone=0;
    index=IndN1N2N3(i,j,k,0);
    index2=N1*N2*N3;


    if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
    {
		if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)+=accum_xx*accum_xx;
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)+=accum_yy*accum_yy;
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)+=accum_zz*accum_zz;
		if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)+=accum_p*accum_p;
		if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)+=accum_xy*accum_xy;
		if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)+=accum_xz*accum_xz;
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)+=accum_yz*accum_yz;
		
		
    }
    if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
        index+=index2*NumberSelRMSPeakMaps;
    if (SelRMSorPeak & SEL_PEAK)
    {
		
        if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)=accum_xx>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx) ? accum_xx: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx);
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)=accum_yy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy) ? accum_yy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy);
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)=accum_zz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz) ? accum_zz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz);
        if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)=accum_p > ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure) ? accum_p :ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure);
	    if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)=accum_xy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy) ? accum_xy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy);
        if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)=accum_xz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz) ? accum_xz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz);
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)=accum_yz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz) ? accum_yz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz);
		
		
    }
}
 #endif


#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_I_BOTTOM
#endif
#undef _ST_PML
//MLX_BLOCK_PML_1_STRESS_END
//MLX_BLOCK_PML_2_STRESS_START
#define _ST_PML
#if ((defined(MLX)) && defined(MLX_PML_2_STRESS)) || !defined(MLX)
#define _PML_KERNEL_I_TOP
#ifdef CUDA
extern "C" __global__ void PML_2_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_2_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_2_StressKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
	_PT i = (_PT) gid.x;
	_PT j = (_PT) gid.y;
	_PT k = (_PT) gid.z;
	#else
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (PML_Thickness)
	#define nN2 (N2)
	#define nN3 (N3)
    _PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
//MLX does not need input variable declarations
#if defined(MLX)
#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (PML_Thickness)
	#define nN2 (N2)
	#define nN3 (N3)
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
	
#if defined(_ST_PML)
	mexType Diff;
	mexType Diff2;
	mexType Diff3;
#endif

#if defined(_ST_MAIN)
	mexType Dx;
	mexType Dy;
	mexType Dz;
#endif


	mexType value;

	mexType m1;
	mexType m2;
	mexType m3;
	mexType m4;

	mexType RigidityXY=0.0;
	mexType RigidityXZ=0.0;
	mexType RigidityYZ=0.0;
	mexType TauShearXY=0.0;
	mexType TauShearXZ=0.0;
	mexType TauShearYZ=0.0;

#if defined(_ST_MAIN)
	mexType LambdaMiu;
	mexType LambdaMiuComp;
	mexType dFirstPart;
	mexType dFirstPartForR;
	mexType accum_xx=0.0;
	mexType accum_yy=0.0;
	mexType accum_zz=0.0;
	mexType accum_p=0.0;
	_PT source;
	_PT bAttenuating=1;
	mexType Miu;
	mexType MiuComp;
	mexType OneOverTauSigma;
	mexType NextR;
	mexType accum_xy=0.0;
	mexType accum_xz=0.0;
	mexType accum_yz=0.0;
#endif


#ifdef USE_2ND_ORDER_EDGES
    interface_t interfaceZ=inside, interfaceY=inside, interfaceX=inside;
#endif

_PT index2;
_PT index;
_PT  MaterialID;

_PT CurZone;

for ( CurZone=0;CurZone<ZoneCount;CurZone++)
  {
	  index=Ind_MaterialMap(i,j,k);
      MaterialID=ELD(MaterialMap,index);

	  	m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j+1,k));
   		value=m1*m2*m3*m4;
  		RigidityXY =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
      
	    #if  defined(_ST_MAIN) 
  		TauShearXY = value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j+1,k)))
  							 : ELD(TauShear,MaterialID);

	   #endif
	    m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k+1));

  		value=m1*m2*m3*m4;
  		RigidityXZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
	   #if defined(_ST_MAIN)
  		TauShearXZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k+1)))
  							 : ELD(TauShear,MaterialID);

		#endif
		m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k+1));

        value=m1*m2*m3*m4;

  		RigidityYZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
		
		#if  defined(_ST_MAIN)
  		TauShearYZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k+1)))
  							 : ELD(TauShear,MaterialID);
		#endif

  	
  	if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 ||  IsOnPML_K(k)==1)//We are in the PML borders
  	 {
		#if defined(_ST_PML)
  		if (i<N1-1 && j <N2-1 && k < N3-1)
  		{

  			Diff= i>1 && i <N1-1 ? CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k)) -
  			                       CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k))
  			      : i>0 && i <N1 ? (EL(Vx,i,j,k)-EL(Vx,i-1,j,k))  :0;

			Diff2= j>1 && j < N2-1 ? CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
  									CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k))
  			        : j>0 && j < N2 ? EL(Vy,i,j,k)-EL(Vy,i,j-1,k):0;

			Diff3= k>1 && k < N3-1 ? CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1)) -
  									CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2))
  			                       :k>0 && k < N3 ? EL(Vz,i,j,k)-EL(Vz,i,j,k-1) : 0;
  			
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_x_xx,index2) =InvDXDT_I*(
  											ELD(Sigma_x_xx,index2)*DXDT_I+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff);
			index2=Ind_Sigma_y_xx(i,j,k);
  			ELD(Sigma_y_xx,index2) =InvDXDT_J*(
  											ELD(Sigma_y_xx,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_xx(i,j,k);
  			ELD(Sigma_z_xx,index2) =InvDXDT_K*(
  											ELD(Sigma_z_xx,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_xx,index)= ELD(Sigma_x_xx,index2) + ELD(Sigma_y_xx,index2)+ ELD(Sigma_z_xx,index2);

			index2=Ind_Sigma_x_yy(i,j,k);
  			ELD(Sigma_x_yy,index2) =InvDXDT_I*(
  											ELD(Sigma_x_yy,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);

			index2=Ind_Sigma_y_yy(i,j,k);
  			ELD(Sigma_y_yy,index2) =InvDXDT_J*(
  											ELD(Sigma_y_yy,index2)*DXDT_J+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_yy(i,j,k);
  			ELD(Sigma_z_yy,index2) =InvDXDT_K*(
  											ELD(Sigma_z_yy,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_yy,index)= ELD(Sigma_x_yy,index2) + ELD(Sigma_y_yy,index2)+ ELD(Sigma_z_yy,index2);


  			index2=Ind_Sigma_x_zz(i,j,k);
  			ELD(Sigma_x_zz,index2) =InvDXDT_I*(
  											ELD(Sigma_x_zz,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);




  			index2=Ind_Sigma_y_zz(i,j,k);
  			ELD(Sigma_y_zz,index2) =InvDXDT_J*(
  											ELD(Sigma_y_zz,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);



  			index2=Ind_Sigma_z_zz(i,j,k);
  			ELD(Sigma_z_zz,index2) =InvDXDT_K*(
  											ELD(Sigma_z_zz,index2)*DXDT_K+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_zz,index)= ELD(Sigma_x_zz,index2) + ELD(Sigma_y_zz,index2)+ ELD(Sigma_z_zz,index2);

  			index2=Ind_Sigma_x_xy(i,j,k);

  			Diff= i >0 && i<N1-2 ? CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k)) -
  			                   CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k))
  			                    :i<N1-1 ? EL(Vy,i+1,j,k)-EL(Vy,i,j,k):0;

  			ELD(Sigma_x_xy,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xy,index2)*DXDThp_I+
  											RigidityXY*
  											Diff);
			index2=Ind_Sigma_y_xy(i,j,k);

  			Diff=j > 0 && j<N2-2 ? CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k) )-
  			                       CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k) )
  			                       :j<N2-1 ? EL(Vx,i,j+1,k)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_y_xy,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_xy,index2)*DXDThp_J+
  											RigidityXY*
  											Diff);
			index=Ind_Sigma_xy(i,j,k);

			ELD(Sigma_xy,index)= ELD(Sigma_x_xy,Ind_Sigma_x_xy(i,j,k)) + ELD(Sigma_y_xy,index2);

  			index2=Ind_Sigma_x_xz(i,j,k);

  			Diff= i>0 && i<N1-2 ? CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k)) -
  								  CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k))
  								  :i<N1-1 ? EL(Vz,i+1,j,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_x_xz,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xz,index2)*DXDThp_I+
  											RigidityXZ*
  											Diff);



  			index2=Ind_Sigma_z_xz(i,j,k);


  			Diff=k >0 && k < N3-2 ? CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k)) -
  			                        CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1)):
                                      k < N3-1 ? EL(Vx,i,j,k+1)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_z_xz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_xz,index2)*DXDThp_K+
  											RigidityXZ*
  											Diff);
			index=Ind_Sigma_xz(i,j,k);

  		    ELD(Sigma_xz,index)= ELD(Sigma_x_xz,Ind_Sigma_x_xz(i,j,k)) + ELD(Sigma_z_xz,index2);

  			index2=Ind_Sigma_y_yz(i,j,k);

  			Diff=j>0 && j<N2-2 ? CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k)) -
  							     CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k))
  							     :j<N2-1 ? EL(Vz,i,j+1,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_y_yz,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_yz,index2)*DXDThp_J+
  											RigidityYZ*
  											Diff);

  			

  			index2=Ind_Sigma_z_yz(i,j,k);

  			Diff=k>0 && k < N3-2 ? CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
  			                       CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1))
  			                       :k < N3-1 ? EL(Vy,i,j,k+1)-EL(Vy,i,j,k):0;
  			ELD(Sigma_z_yz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_yz,index2)*DXDThp_K+
  											RigidityYZ*
  											Diff);

			index=Ind_Sigma_yz(i,j,k);
	
			ELD(Sigma_yz,index)= ELD(Sigma_y_yz,Ind_Sigma_y_yz(i,j,k)) + ELD(Sigma_z_yz,index2);

		  }	 
		#endif  
	 }
	else
	{
#if defined(_ST_MAIN)
  		//We are in the center, no need to check any limits, the use of the PML simplify this
  		index=Ind_Sigma_xx(i,j,k);

		if (REQUIRES_2ND_ORDER_M(X))
			Dx=EL(Vx,i,j,k)-EL(Vx,i-1,j,k);
		else
			Dx=CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k))-
				CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k));

		if REQUIRES_2ND_ORDER_M(Y)
			Dy=EL(Vy,i,j,k)-EL(Vy,i,j-1,k);
		else
			Dy=CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
				CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k));

		if REQUIRES_2ND_ORDER_M(Z)
			Dz=EL(Vz,i,j,k)-EL(Vz,i,j,k-1);
		else
			Dz=CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1))-
              CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2));

		
		//We will use the particle displacement to estimate the acoustic pressure, and using the conservation of mass formula
		//We can use the stress kernel as V matrices are not being modified in this kernel,
		// and the spatial derivatives are the same ones required for pressure calculation
        // partial(p)/partial(t) = \rho c^2 div(V)
        //it is important to mention that the Python function will need still to multiply the result for the maps of (speed of sound)^2 and density, 
		// and divide by the spatial step.
		EL(Pressure,i,j,k)+=DT*(Dx+Dy+Dz);
        accum_p+=EL(Pressure,i,j,k);


  		LambdaMiu=ELD(LambdaMiuMatOverH,MaterialID)*(1.0+ELD(TauLong,MaterialID));
  		Miu=2.0*ELD(MiuMatOverH,MaterialID)*(1.0+ELD(TauShear,MaterialID));
  		OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
		dFirstPart=LambdaMiu*(Dx+Dy+Dz);
		
		if (ELD(TauLong,MaterialID)!=0.0 || ELD(TauShear,MaterialID)!=0.0) // We avoid unnecessary calculations if there is no attenuation
		{
			
			LambdaMiuComp=DT*ELD(LambdaMiuMatOverH,MaterialID)*(ELD(TauLong,MaterialID)*OneOverTauSigma);
			dFirstPartForR=LambdaMiuComp*(Dx+Dy+Dz);
			MiuComp=DT*2.0*ELD(MiuMatOverH,MaterialID)*(ELD(TauShear,MaterialID)*OneOverTauSigma);
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxx,index) - dFirstPartForR + MiuComp*(Dy+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);

			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz) + 0.5*(ELD(Rxx,index) + NextR));
			ELD(Rxx,index)=NextR;
		}
		else
		{
			bAttenuating=0;
			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz));
		}
  		
	    accum_xx+=ELD(Sigma_xx,index);

		if (bAttenuating==1)
		{
  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryy,index) - dFirstPartForR + MiuComp*(Dx+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);
				
  			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz) + 0.5*(ELD(Ryy,index) + NextR));
			ELD(Ryy,index)=NextR;
		}
		else
			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz));
      	
		accum_yy+=ELD(Sigma_yy,index);

  		if (bAttenuating==1)
		{
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rzz,index) - dFirstPartForR +MiuComp*(Dx+Dy))
				/(1+DT*0.5*OneOverTauSigma);
  			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy) + 0.5*(ELD(Rzz,index) + NextR));
			ELD(Rzz,index)=NextR;
		}
		else
			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy));

      	accum_zz+=ELD(Sigma_zz,index);


  		index=Ind_Sigma_xy(i,j,k);

		if (RigidityXY!=0.0)
  		{
			  OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
              if (REQUIRES_2ND_ORDER_P(X))
                  Dx=EL(Vy,i+1,j,k)-EL(Vy,i,j,k);
              else
                  Dx=CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k))-
                     CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k));


              if (REQUIRES_2ND_ORDER_P(Y))
                  Dx+=EL(Vx,i,j+1,k)-EL(Vx,i,j,k);
              else
                  Dx+=CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k))-
                      CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k));

  			Miu=RigidityXY*(1.0+TauShearXY);

			if (TauShearXY!=0.0)
			{
				MiuComp=RigidityXY*(TauShearXY*OneOverTauSigma);
				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxy,index) - DT*MiuComp*Dx)
  		          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xy,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxy,index) +NextR));
				ELD(Rxy,index)=NextR;
			}
			else
				ELD(Sigma_xy,index)+= DT*(Miu*Dx );
        	
			accum_xy+=ELD(Sigma_xy,index);

  		}
        // else
        //     ELD(Rxy,index)=0.0;

		if (RigidityXZ!=0.0)
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(X))
				Dx=EL(Vz,i+1,j,k)-EL(Vz,i,j,k);
			else
				Dx=CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dx+=EL(Vx,i,j,k+1)-EL(Vx,i,j,k);
			else
				Dx+=CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k))-
					CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1));

	  		Miu=RigidityXZ*(1.0+TauShearXZ);

			if (TauShearXZ!=0.0)
			{
  				MiuComp=RigidityXZ*(TauShearXZ*OneOverTauSigma);
	  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxz,index) - DT*MiuComp*Dx)
  			          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xz,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxz,index) +NextR));
				ELD(Rxz,index)=NextR;
			}
			else
				ELD(Sigma_xz,index)+= DT*(Miu*Dx );
        	accum_xz+=ELD(Sigma_xz,index);
  			
  		}
        // else
        //     ELD(Rxz,index)=0.0;
 
  		if (RigidityYZ!=0.0 )
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(Y))
				Dy=EL(Vz,i,j+1,k)-EL(Vz,i,j,k);
			else
				Dy=CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dy+=EL(Vy,i,j,k+1)-EL(Vy,i,j,k);
			else
				Dy+=CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
					CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1));

  			Miu=RigidityYZ*(1.0+TauShearYZ);
			
			if (TauShearYZ!=0)
			{
				MiuComp=RigidityYZ*(TauShearYZ*OneOverTauSigma);

				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryz,index) - DT*MiuComp*Dy)
					/(1+DT*0.5*OneOverTauSigma);

				ELD(Sigma_yz,index)+= DT*(Miu*Dy + 0.5*(ELD(Ryz,index) +NextR));
				ELD(Ryz,index)=NextR;
			}
			else 
				ELD(Sigma_yz,index)+= DT*(Miu*Dy );
        	accum_yz+=ELD(Sigma_yz,index);

  		}
        //   else
        //       ELD(Ryz,index)=0.0;

		if ((nStep < LengthSource) && TypeSource>=2) //Source is stress
  		{
  			index=IndN1N2N3(i,j,k,0);
  			source=ELD(SourceMap,index);
  			if (source>0)
  			{
  			  source--; //need to use C index
  			  value=ELD(SourceFunctions,nStep*NumberSources+source)*ELD(Ox,index); // We use Ox as mechanism to provide weighted arrays
				index=Ind_Sigma_xx(i,j,k);
                if ((TypeSource-2)==0)
                {
                    ELD(Sigma_xx,index)+=value;
                    ELD(Sigma_yy,index)+=value;
                    ELD(Sigma_zz,index)+=value;
                }
                else
                {
                   ELD(Sigma_xx,index)=value;
                   ELD(Sigma_yy,index)=value;
                   ELD(Sigma_zz,index)=value;
                }

  			}
  		}
	#endif
	}
  }
  #if defined(_ST_MAIN) 
  if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
  {
	
    accum_xx/=ZoneCount;
    accum_yy/=ZoneCount;
    accum_zz/=ZoneCount;
	accum_xy/=ZoneCount;
	accum_xz/=ZoneCount;
	accum_yz/=ZoneCount;
	
    CurZone=0;
    index=IndN1N2N3(i,j,k,0);
    index2=N1*N2*N3;


    if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
    {
		if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)+=accum_xx*accum_xx;
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)+=accum_yy*accum_yy;
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)+=accum_zz*accum_zz;
		if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)+=accum_p*accum_p;
		if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)+=accum_xy*accum_xy;
		if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)+=accum_xz*accum_xz;
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)+=accum_yz*accum_yz;
		
		
    }
    if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
        index+=index2*NumberSelRMSPeakMaps;
    if (SelRMSorPeak & SEL_PEAK)
    {
		
        if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)=accum_xx>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx) ? accum_xx: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx);
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)=accum_yy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy) ? accum_yy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy);
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)=accum_zz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz) ? accum_zz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz);
        if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)=accum_p > ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure) ? accum_p :ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure);
	    if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)=accum_xy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy) ? accum_xy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy);
        if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)=accum_xz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz) ? accum_xz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz);
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)=accum_yz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz) ? accum_yz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz);
		
		
    }
}
 #endif


#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_I_TOP
#endif
#undef _ST_PML
//MLX_BLOCK_PML_2_STRESS_END
//MLX_BLOCK_PML_3_STRESS_START
#define _ST_PML
#if ((defined(MLX)) && defined(MLX_PML_3_STRESS)) || !defined(MLX)
#define _PML_KERNEL_J_BOTTOM
#ifdef CUDA
extern "C" __global__ void PML_3_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_3_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_3_StressKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
	_PT i = (_PT) gid.x;
	_PT j = (_PT) gid.y;
	_PT k = (_PT) gid.z;
	#else
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (PML_Thickness)
	#define nN3 (N3)
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (PML_Thickness)
	#define nN3 (N3)
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
	
#if defined(_ST_PML)
	mexType Diff;
	mexType Diff2;
	mexType Diff3;
#endif

#if defined(_ST_MAIN)
	mexType Dx;
	mexType Dy;
	mexType Dz;
#endif


	mexType value;

	mexType m1;
	mexType m2;
	mexType m3;
	mexType m4;

	mexType RigidityXY=0.0;
	mexType RigidityXZ=0.0;
	mexType RigidityYZ=0.0;
	mexType TauShearXY=0.0;
	mexType TauShearXZ=0.0;
	mexType TauShearYZ=0.0;

#if defined(_ST_MAIN)
	mexType LambdaMiu;
	mexType LambdaMiuComp;
	mexType dFirstPart;
	mexType dFirstPartForR;
	mexType accum_xx=0.0;
	mexType accum_yy=0.0;
	mexType accum_zz=0.0;
	mexType accum_p=0.0;
	_PT source;
	_PT bAttenuating=1;
	mexType Miu;
	mexType MiuComp;
	mexType OneOverTauSigma;
	mexType NextR;
	mexType accum_xy=0.0;
	mexType accum_xz=0.0;
	mexType accum_yz=0.0;
#endif


#ifdef USE_2ND_ORDER_EDGES
    interface_t interfaceZ=inside, interfaceY=inside, interfaceX=inside;
#endif

_PT index2;
_PT index;
_PT  MaterialID;

_PT CurZone;

for ( CurZone=0;CurZone<ZoneCount;CurZone++)
  {
	  index=Ind_MaterialMap(i,j,k);
      MaterialID=ELD(MaterialMap,index);

	  	m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j+1,k));
   		value=m1*m2*m3*m4;
  		RigidityXY =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
      
	    #if  defined(_ST_MAIN) 
  		TauShearXY = value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j+1,k)))
  							 : ELD(TauShear,MaterialID);

	   #endif
	    m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k+1));

  		value=m1*m2*m3*m4;
  		RigidityXZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
	   #if defined(_ST_MAIN)
  		TauShearXZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k+1)))
  							 : ELD(TauShear,MaterialID);

		#endif
		m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k+1));

        value=m1*m2*m3*m4;

  		RigidityYZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
		
		#if  defined(_ST_MAIN)
  		TauShearYZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k+1)))
  							 : ELD(TauShear,MaterialID);
		#endif

  	
  	if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 ||  IsOnPML_K(k)==1)//We are in the PML borders
  	 {
		#if defined(_ST_PML)
  		if (i<N1-1 && j <N2-1 && k < N3-1)
  		{

  			Diff= i>1 && i <N1-1 ? CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k)) -
  			                       CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k))
  			      : i>0 && i <N1 ? (EL(Vx,i,j,k)-EL(Vx,i-1,j,k))  :0;

			Diff2= j>1 && j < N2-1 ? CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
  									CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k))
  			        : j>0 && j < N2 ? EL(Vy,i,j,k)-EL(Vy,i,j-1,k):0;

			Diff3= k>1 && k < N3-1 ? CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1)) -
  									CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2))
  			                       :k>0 && k < N3 ? EL(Vz,i,j,k)-EL(Vz,i,j,k-1) : 0;
  			
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_x_xx,index2) =InvDXDT_I*(
  											ELD(Sigma_x_xx,index2)*DXDT_I+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff);
			index2=Ind_Sigma_y_xx(i,j,k);
  			ELD(Sigma_y_xx,index2) =InvDXDT_J*(
  											ELD(Sigma_y_xx,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_xx(i,j,k);
  			ELD(Sigma_z_xx,index2) =InvDXDT_K*(
  											ELD(Sigma_z_xx,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_xx,index)= ELD(Sigma_x_xx,index2) + ELD(Sigma_y_xx,index2)+ ELD(Sigma_z_xx,index2);

			index2=Ind_Sigma_x_yy(i,j,k);
  			ELD(Sigma_x_yy,index2) =InvDXDT_I*(
  											ELD(Sigma_x_yy,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);

			index2=Ind_Sigma_y_yy(i,j,k);
  			ELD(Sigma_y_yy,index2) =InvDXDT_J*(
  											ELD(Sigma_y_yy,index2)*DXDT_J+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_yy(i,j,k);
  			ELD(Sigma_z_yy,index2) =InvDXDT_K*(
  											ELD(Sigma_z_yy,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_yy,index)= ELD(Sigma_x_yy,index2) + ELD(Sigma_y_yy,index2)+ ELD(Sigma_z_yy,index2);


  			index2=Ind_Sigma_x_zz(i,j,k);
  			ELD(Sigma_x_zz,index2) =InvDXDT_I*(
  											ELD(Sigma_x_zz,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);




  			index2=Ind_Sigma_y_zz(i,j,k);
  			ELD(Sigma_y_zz,index2) =InvDXDT_J*(
  											ELD(Sigma_y_zz,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);



  			index2=Ind_Sigma_z_zz(i,j,k);
  			ELD(Sigma_z_zz,index2) =InvDXDT_K*(
  											ELD(Sigma_z_zz,index2)*DXDT_K+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_zz,index)= ELD(Sigma_x_zz,index2) + ELD(Sigma_y_zz,index2)+ ELD(Sigma_z_zz,index2);

  			index2=Ind_Sigma_x_xy(i,j,k);

  			Diff= i >0 && i<N1-2 ? CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k)) -
  			                   CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k))
  			                    :i<N1-1 ? EL(Vy,i+1,j,k)-EL(Vy,i,j,k):0;

  			ELD(Sigma_x_xy,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xy,index2)*DXDThp_I+
  											RigidityXY*
  											Diff);
			index2=Ind_Sigma_y_xy(i,j,k);

  			Diff=j > 0 && j<N2-2 ? CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k) )-
  			                       CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k) )
  			                       :j<N2-1 ? EL(Vx,i,j+1,k)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_y_xy,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_xy,index2)*DXDThp_J+
  											RigidityXY*
  											Diff);
			index=Ind_Sigma_xy(i,j,k);

			ELD(Sigma_xy,index)= ELD(Sigma_x_xy,Ind_Sigma_x_xy(i,j,k)) + ELD(Sigma_y_xy,index2);

  			index2=Ind_Sigma_x_xz(i,j,k);

  			Diff= i>0 && i<N1-2 ? CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k)) -
  								  CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k))
  								  :i<N1-1 ? EL(Vz,i+1,j,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_x_xz,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xz,index2)*DXDThp_I+
  											RigidityXZ*
  											Diff);



  			index2=Ind_Sigma_z_xz(i,j,k);


  			Diff=k >0 && k < N3-2 ? CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k)) -
  			                        CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1)):
                                      k < N3-1 ? EL(Vx,i,j,k+1)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_z_xz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_xz,index2)*DXDThp_K+
  											RigidityXZ*
  											Diff);
			index=Ind_Sigma_xz(i,j,k);

  		    ELD(Sigma_xz,index)= ELD(Sigma_x_xz,Ind_Sigma_x_xz(i,j,k)) + ELD(Sigma_z_xz,index2);

  			index2=Ind_Sigma_y_yz(i,j,k);

  			Diff=j>0 && j<N2-2 ? CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k)) -
  							     CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k))
  							     :j<N2-1 ? EL(Vz,i,j+1,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_y_yz,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_yz,index2)*DXDThp_J+
  											RigidityYZ*
  											Diff);

  			

  			index2=Ind_Sigma_z_yz(i,j,k);

  			Diff=k>0 && k < N3-2 ? CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
  			                       CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1))
  			                       :k < N3-1 ? EL(Vy,i,j,k+1)-EL(Vy,i,j,k):0;
  			ELD(Sigma_z_yz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_yz,index2)*DXDThp_K+
  											RigidityYZ*
  											Diff);

			index=Ind_Sigma_yz(i,j,k);
	
			ELD(Sigma_yz,index)= ELD(Sigma_y_yz,Ind_Sigma_y_yz(i,j,k)) + ELD(Sigma_z_yz,index2);

		  }	 
		#endif  
	 }
	else
	{
#if defined(_ST_MAIN)
  		//We are in the center, no need to check any limits, the use of the PML simplify this
  		index=Ind_Sigma_xx(i,j,k);

		if (REQUIRES_2ND_ORDER_M(X))
			Dx=EL(Vx,i,j,k)-EL(Vx,i-1,j,k);
		else
			Dx=CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k))-
				CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k));

		if REQUIRES_2ND_ORDER_M(Y)
			Dy=EL(Vy,i,j,k)-EL(Vy,i,j-1,k);
		else
			Dy=CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
				CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k));

		if REQUIRES_2ND_ORDER_M(Z)
			Dz=EL(Vz,i,j,k)-EL(Vz,i,j,k-1);
		else
			Dz=CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1))-
              CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2));

		
		//We will use the particle displacement to estimate the acoustic pressure, and using the conservation of mass formula
		//We can use the stress kernel as V matrices are not being modified in this kernel,
		// and the spatial derivatives are the same ones required for pressure calculation
        // partial(p)/partial(t) = \rho c^2 div(V)
        //it is important to mention that the Python function will need still to multiply the result for the maps of (speed of sound)^2 and density, 
		// and divide by the spatial step.
		EL(Pressure,i,j,k)+=DT*(Dx+Dy+Dz);
        accum_p+=EL(Pressure,i,j,k);


  		LambdaMiu=ELD(LambdaMiuMatOverH,MaterialID)*(1.0+ELD(TauLong,MaterialID));
  		Miu=2.0*ELD(MiuMatOverH,MaterialID)*(1.0+ELD(TauShear,MaterialID));
  		OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
		dFirstPart=LambdaMiu*(Dx+Dy+Dz);
		
		if (ELD(TauLong,MaterialID)!=0.0 || ELD(TauShear,MaterialID)!=0.0) // We avoid unnecessary calculations if there is no attenuation
		{
			
			LambdaMiuComp=DT*ELD(LambdaMiuMatOverH,MaterialID)*(ELD(TauLong,MaterialID)*OneOverTauSigma);
			dFirstPartForR=LambdaMiuComp*(Dx+Dy+Dz);
			MiuComp=DT*2.0*ELD(MiuMatOverH,MaterialID)*(ELD(TauShear,MaterialID)*OneOverTauSigma);
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxx,index) - dFirstPartForR + MiuComp*(Dy+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);

			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz) + 0.5*(ELD(Rxx,index) + NextR));
			ELD(Rxx,index)=NextR;
		}
		else
		{
			bAttenuating=0;
			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz));
		}
  		
	    accum_xx+=ELD(Sigma_xx,index);

		if (bAttenuating==1)
		{
  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryy,index) - dFirstPartForR + MiuComp*(Dx+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);
				
  			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz) + 0.5*(ELD(Ryy,index) + NextR));
			ELD(Ryy,index)=NextR;
		}
		else
			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz));
      	
		accum_yy+=ELD(Sigma_yy,index);

  		if (bAttenuating==1)
		{
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rzz,index) - dFirstPartForR +MiuComp*(Dx+Dy))
				/(1+DT*0.5*OneOverTauSigma);
  			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy) + 0.5*(ELD(Rzz,index) + NextR));
			ELD(Rzz,index)=NextR;
		}
		else
			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy));

      	accum_zz+=ELD(Sigma_zz,index);


  		index=Ind_Sigma_xy(i,j,k);

		if (RigidityXY!=0.0)
  		{
			  OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
              if (REQUIRES_2ND_ORDER_P(X))
                  Dx=EL(Vy,i+1,j,k)-EL(Vy,i,j,k);
              else
                  Dx=CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k))-
                     CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k));


              if (REQUIRES_2ND_ORDER_P(Y))
                  Dx+=EL(Vx,i,j+1,k)-EL(Vx,i,j,k);
              else
                  Dx+=CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k))-
                      CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k));

  			Miu=RigidityXY*(1.0+TauShearXY);

			if (TauShearXY!=0.0)
			{
				MiuComp=RigidityXY*(TauShearXY*OneOverTauSigma);
				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxy,index) - DT*MiuComp*Dx)
  		          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xy,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxy,index) +NextR));
				ELD(Rxy,index)=NextR;
			}
			else
				ELD(Sigma_xy,index)+= DT*(Miu*Dx );
        	
			accum_xy+=ELD(Sigma_xy,index);

  		}
        // else
        //     ELD(Rxy,index)=0.0;

		if (RigidityXZ!=0.0)
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(X))
				Dx=EL(Vz,i+1,j,k)-EL(Vz,i,j,k);
			else
				Dx=CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dx+=EL(Vx,i,j,k+1)-EL(Vx,i,j,k);
			else
				Dx+=CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k))-
					CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1));

	  		Miu=RigidityXZ*(1.0+TauShearXZ);

			if (TauShearXZ!=0.0)
			{
  				MiuComp=RigidityXZ*(TauShearXZ*OneOverTauSigma);
	  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxz,index) - DT*MiuComp*Dx)
  			          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xz,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxz,index) +NextR));
				ELD(Rxz,index)=NextR;
			}
			else
				ELD(Sigma_xz,index)+= DT*(Miu*Dx );
        	accum_xz+=ELD(Sigma_xz,index);
  			
  		}
        // else
        //     ELD(Rxz,index)=0.0;
 
  		if (RigidityYZ!=0.0 )
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(Y))
				Dy=EL(Vz,i,j+1,k)-EL(Vz,i,j,k);
			else
				Dy=CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dy+=EL(Vy,i,j,k+1)-EL(Vy,i,j,k);
			else
				Dy+=CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
					CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1));

  			Miu=RigidityYZ*(1.0+TauShearYZ);
			
			if (TauShearYZ!=0)
			{
				MiuComp=RigidityYZ*(TauShearYZ*OneOverTauSigma);

				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryz,index) - DT*MiuComp*Dy)
					/(1+DT*0.5*OneOverTauSigma);

				ELD(Sigma_yz,index)+= DT*(Miu*Dy + 0.5*(ELD(Ryz,index) +NextR));
				ELD(Ryz,index)=NextR;
			}
			else 
				ELD(Sigma_yz,index)+= DT*(Miu*Dy );
        	accum_yz+=ELD(Sigma_yz,index);

  		}
        //   else
        //       ELD(Ryz,index)=0.0;

		if ((nStep < LengthSource) && TypeSource>=2) //Source is stress
  		{
  			index=IndN1N2N3(i,j,k,0);
  			source=ELD(SourceMap,index);
  			if (source>0)
  			{
  			  source--; //need to use C index
  			  value=ELD(SourceFunctions,nStep*NumberSources+source)*ELD(Ox,index); // We use Ox as mechanism to provide weighted arrays
				index=Ind_Sigma_xx(i,j,k);
                if ((TypeSource-2)==0)
                {
                    ELD(Sigma_xx,index)+=value;
                    ELD(Sigma_yy,index)+=value;
                    ELD(Sigma_zz,index)+=value;
                }
                else
                {
                   ELD(Sigma_xx,index)=value;
                   ELD(Sigma_yy,index)=value;
                   ELD(Sigma_zz,index)=value;
                }

  			}
  		}
	#endif
	}
  }
  #if defined(_ST_MAIN) 
  if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
  {
	
    accum_xx/=ZoneCount;
    accum_yy/=ZoneCount;
    accum_zz/=ZoneCount;
	accum_xy/=ZoneCount;
	accum_xz/=ZoneCount;
	accum_yz/=ZoneCount;
	
    CurZone=0;
    index=IndN1N2N3(i,j,k,0);
    index2=N1*N2*N3;


    if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
    {
		if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)+=accum_xx*accum_xx;
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)+=accum_yy*accum_yy;
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)+=accum_zz*accum_zz;
		if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)+=accum_p*accum_p;
		if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)+=accum_xy*accum_xy;
		if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)+=accum_xz*accum_xz;
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)+=accum_yz*accum_yz;
		
		
    }
    if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
        index+=index2*NumberSelRMSPeakMaps;
    if (SelRMSorPeak & SEL_PEAK)
    {
		
        if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)=accum_xx>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx) ? accum_xx: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx);
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)=accum_yy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy) ? accum_yy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy);
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)=accum_zz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz) ? accum_zz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz);
        if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)=accum_p > ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure) ? accum_p :ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure);
	    if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)=accum_xy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy) ? accum_xy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy);
        if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)=accum_xz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz) ? accum_xz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz);
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)=accum_yz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz) ? accum_yz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz);
		
		
    }
}
 #endif


#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_J_BOTTOM
#endif
#undef _ST_PML
//MLX_BLOCK_PML_3_STRESS_END
//MLX_BLOCK_PML_4_STRESS_START
#define _ST_PML
#if ((defined(MLX)) && defined(MLX_PML_4_STRESS)) || !defined(MLX)
#define _PML_KERNEL_J_TOP
#ifdef CUDA
extern "C" __global__ void PML_4_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_4_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_4_StressKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (PML_Thickness)
	#define nN3 (N3)
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (PML_Thickness)
	#define nN3 (N3)
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
	
#if defined(_ST_PML)
	mexType Diff;
	mexType Diff2;
	mexType Diff3;
#endif

#if defined(_ST_MAIN)
	mexType Dx;
	mexType Dy;
	mexType Dz;
#endif


	mexType value;

	mexType m1;
	mexType m2;
	mexType m3;
	mexType m4;

	mexType RigidityXY=0.0;
	mexType RigidityXZ=0.0;
	mexType RigidityYZ=0.0;
	mexType TauShearXY=0.0;
	mexType TauShearXZ=0.0;
	mexType TauShearYZ=0.0;

#if defined(_ST_MAIN)
	mexType LambdaMiu;
	mexType LambdaMiuComp;
	mexType dFirstPart;
	mexType dFirstPartForR;
	mexType accum_xx=0.0;
	mexType accum_yy=0.0;
	mexType accum_zz=0.0;
	mexType accum_p=0.0;
	_PT source;
	_PT bAttenuating=1;
	mexType Miu;
	mexType MiuComp;
	mexType OneOverTauSigma;
	mexType NextR;
	mexType accum_xy=0.0;
	mexType accum_xz=0.0;
	mexType accum_yz=0.0;
#endif


#ifdef USE_2ND_ORDER_EDGES
    interface_t interfaceZ=inside, interfaceY=inside, interfaceX=inside;
#endif

_PT index2;
_PT index;
_PT  MaterialID;

_PT CurZone;

for ( CurZone=0;CurZone<ZoneCount;CurZone++)
  {
	  index=Ind_MaterialMap(i,j,k);
      MaterialID=ELD(MaterialMap,index);

	  	m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j+1,k));
   		value=m1*m2*m3*m4;
  		RigidityXY =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
      
	    #if  defined(_ST_MAIN) 
  		TauShearXY = value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j+1,k)))
  							 : ELD(TauShear,MaterialID);

	   #endif
	    m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k+1));

  		value=m1*m2*m3*m4;
  		RigidityXZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
	   #if defined(_ST_MAIN)
  		TauShearXZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k+1)))
  							 : ELD(TauShear,MaterialID);

		#endif
		m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k+1));

        value=m1*m2*m3*m4;

  		RigidityYZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
		
		#if  defined(_ST_MAIN)
  		TauShearYZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k+1)))
  							 : ELD(TauShear,MaterialID);
		#endif

  	
  	if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 ||  IsOnPML_K(k)==1)//We are in the PML borders
  	 {
		#if defined(_ST_PML)
  		if (i<N1-1 && j <N2-1 && k < N3-1)
  		{

  			Diff= i>1 && i <N1-1 ? CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k)) -
  			                       CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k))
  			      : i>0 && i <N1 ? (EL(Vx,i,j,k)-EL(Vx,i-1,j,k))  :0;

			Diff2= j>1 && j < N2-1 ? CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
  									CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k))
  			        : j>0 && j < N2 ? EL(Vy,i,j,k)-EL(Vy,i,j-1,k):0;

			Diff3= k>1 && k < N3-1 ? CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1)) -
  									CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2))
  			                       :k>0 && k < N3 ? EL(Vz,i,j,k)-EL(Vz,i,j,k-1) : 0;
  			
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_x_xx,index2) =InvDXDT_I*(
  											ELD(Sigma_x_xx,index2)*DXDT_I+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff);
			index2=Ind_Sigma_y_xx(i,j,k);
  			ELD(Sigma_y_xx,index2) =InvDXDT_J*(
  											ELD(Sigma_y_xx,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_xx(i,j,k);
  			ELD(Sigma_z_xx,index2) =InvDXDT_K*(
  											ELD(Sigma_z_xx,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_xx,index)= ELD(Sigma_x_xx,index2) + ELD(Sigma_y_xx,index2)+ ELD(Sigma_z_xx,index2);

			index2=Ind_Sigma_x_yy(i,j,k);
  			ELD(Sigma_x_yy,index2) =InvDXDT_I*(
  											ELD(Sigma_x_yy,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);

			index2=Ind_Sigma_y_yy(i,j,k);
  			ELD(Sigma_y_yy,index2) =InvDXDT_J*(
  											ELD(Sigma_y_yy,index2)*DXDT_J+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_yy(i,j,k);
  			ELD(Sigma_z_yy,index2) =InvDXDT_K*(
  											ELD(Sigma_z_yy,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_yy,index)= ELD(Sigma_x_yy,index2) + ELD(Sigma_y_yy,index2)+ ELD(Sigma_z_yy,index2);


  			index2=Ind_Sigma_x_zz(i,j,k);
  			ELD(Sigma_x_zz,index2) =InvDXDT_I*(
  											ELD(Sigma_x_zz,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);




  			index2=Ind_Sigma_y_zz(i,j,k);
  			ELD(Sigma_y_zz,index2) =InvDXDT_J*(
  											ELD(Sigma_y_zz,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);



  			index2=Ind_Sigma_z_zz(i,j,k);
  			ELD(Sigma_z_zz,index2) =InvDXDT_K*(
  											ELD(Sigma_z_zz,index2)*DXDT_K+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_zz,index)= ELD(Sigma_x_zz,index2) + ELD(Sigma_y_zz,index2)+ ELD(Sigma_z_zz,index2);

  			index2=Ind_Sigma_x_xy(i,j,k);

  			Diff= i >0 && i<N1-2 ? CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k)) -
  			                   CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k))
  			                    :i<N1-1 ? EL(Vy,i+1,j,k)-EL(Vy,i,j,k):0;

  			ELD(Sigma_x_xy,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xy,index2)*DXDThp_I+
  											RigidityXY*
  											Diff);
			index2=Ind_Sigma_y_xy(i,j,k);

  			Diff=j > 0 && j<N2-2 ? CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k) )-
  			                       CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k) )
  			                       :j<N2-1 ? EL(Vx,i,j+1,k)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_y_xy,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_xy,index2)*DXDThp_J+
  											RigidityXY*
  											Diff);
			index=Ind_Sigma_xy(i,j,k);

			ELD(Sigma_xy,index)= ELD(Sigma_x_xy,Ind_Sigma_x_xy(i,j,k)) + ELD(Sigma_y_xy,index2);

  			index2=Ind_Sigma_x_xz(i,j,k);

  			Diff= i>0 && i<N1-2 ? CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k)) -
  								  CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k))
  								  :i<N1-1 ? EL(Vz,i+1,j,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_x_xz,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xz,index2)*DXDThp_I+
  											RigidityXZ*
  											Diff);



  			index2=Ind_Sigma_z_xz(i,j,k);


  			Diff=k >0 && k < N3-2 ? CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k)) -
  			                        CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1)):
                                      k < N3-1 ? EL(Vx,i,j,k+1)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_z_xz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_xz,index2)*DXDThp_K+
  											RigidityXZ*
  											Diff);
			index=Ind_Sigma_xz(i,j,k);

  		    ELD(Sigma_xz,index)= ELD(Sigma_x_xz,Ind_Sigma_x_xz(i,j,k)) + ELD(Sigma_z_xz,index2);

  			index2=Ind_Sigma_y_yz(i,j,k);

  			Diff=j>0 && j<N2-2 ? CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k)) -
  							     CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k))
  							     :j<N2-1 ? EL(Vz,i,j+1,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_y_yz,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_yz,index2)*DXDThp_J+
  											RigidityYZ*
  											Diff);

  			

  			index2=Ind_Sigma_z_yz(i,j,k);

  			Diff=k>0 && k < N3-2 ? CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
  			                       CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1))
  			                       :k < N3-1 ? EL(Vy,i,j,k+1)-EL(Vy,i,j,k):0;
  			ELD(Sigma_z_yz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_yz,index2)*DXDThp_K+
  											RigidityYZ*
  											Diff);

			index=Ind_Sigma_yz(i,j,k);
	
			ELD(Sigma_yz,index)= ELD(Sigma_y_yz,Ind_Sigma_y_yz(i,j,k)) + ELD(Sigma_z_yz,index2);

		  }	 
		#endif  
	 }
	else
	{
#if defined(_ST_MAIN)
  		//We are in the center, no need to check any limits, the use of the PML simplify this
  		index=Ind_Sigma_xx(i,j,k);

		if (REQUIRES_2ND_ORDER_M(X))
			Dx=EL(Vx,i,j,k)-EL(Vx,i-1,j,k);
		else
			Dx=CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k))-
				CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k));

		if REQUIRES_2ND_ORDER_M(Y)
			Dy=EL(Vy,i,j,k)-EL(Vy,i,j-1,k);
		else
			Dy=CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
				CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k));

		if REQUIRES_2ND_ORDER_M(Z)
			Dz=EL(Vz,i,j,k)-EL(Vz,i,j,k-1);
		else
			Dz=CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1))-
              CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2));

		
		//We will use the particle displacement to estimate the acoustic pressure, and using the conservation of mass formula
		//We can use the stress kernel as V matrices are not being modified in this kernel,
		// and the spatial derivatives are the same ones required for pressure calculation
        // partial(p)/partial(t) = \rho c^2 div(V)
        //it is important to mention that the Python function will need still to multiply the result for the maps of (speed of sound)^2 and density, 
		// and divide by the spatial step.
		EL(Pressure,i,j,k)+=DT*(Dx+Dy+Dz);
        accum_p+=EL(Pressure,i,j,k);


  		LambdaMiu=ELD(LambdaMiuMatOverH,MaterialID)*(1.0+ELD(TauLong,MaterialID));
  		Miu=2.0*ELD(MiuMatOverH,MaterialID)*(1.0+ELD(TauShear,MaterialID));
  		OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
		dFirstPart=LambdaMiu*(Dx+Dy+Dz);
		
		if (ELD(TauLong,MaterialID)!=0.0 || ELD(TauShear,MaterialID)!=0.0) // We avoid unnecessary calculations if there is no attenuation
		{
			
			LambdaMiuComp=DT*ELD(LambdaMiuMatOverH,MaterialID)*(ELD(TauLong,MaterialID)*OneOverTauSigma);
			dFirstPartForR=LambdaMiuComp*(Dx+Dy+Dz);
			MiuComp=DT*2.0*ELD(MiuMatOverH,MaterialID)*(ELD(TauShear,MaterialID)*OneOverTauSigma);
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxx,index) - dFirstPartForR + MiuComp*(Dy+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);

			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz) + 0.5*(ELD(Rxx,index) + NextR));
			ELD(Rxx,index)=NextR;
		}
		else
		{
			bAttenuating=0;
			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz));
		}
  		
	    accum_xx+=ELD(Sigma_xx,index);

		if (bAttenuating==1)
		{
  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryy,index) - dFirstPartForR + MiuComp*(Dx+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);
				
  			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz) + 0.5*(ELD(Ryy,index) + NextR));
			ELD(Ryy,index)=NextR;
		}
		else
			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz));
      	
		accum_yy+=ELD(Sigma_yy,index);

  		if (bAttenuating==1)
		{
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rzz,index) - dFirstPartForR +MiuComp*(Dx+Dy))
				/(1+DT*0.5*OneOverTauSigma);
  			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy) + 0.5*(ELD(Rzz,index) + NextR));
			ELD(Rzz,index)=NextR;
		}
		else
			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy));

      	accum_zz+=ELD(Sigma_zz,index);


  		index=Ind_Sigma_xy(i,j,k);

		if (RigidityXY!=0.0)
  		{
			  OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
              if (REQUIRES_2ND_ORDER_P(X))
                  Dx=EL(Vy,i+1,j,k)-EL(Vy,i,j,k);
              else
                  Dx=CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k))-
                     CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k));


              if (REQUIRES_2ND_ORDER_P(Y))
                  Dx+=EL(Vx,i,j+1,k)-EL(Vx,i,j,k);
              else
                  Dx+=CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k))-
                      CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k));

  			Miu=RigidityXY*(1.0+TauShearXY);

			if (TauShearXY!=0.0)
			{
				MiuComp=RigidityXY*(TauShearXY*OneOverTauSigma);
				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxy,index) - DT*MiuComp*Dx)
  		          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xy,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxy,index) +NextR));
				ELD(Rxy,index)=NextR;
			}
			else
				ELD(Sigma_xy,index)+= DT*(Miu*Dx );
        	
			accum_xy+=ELD(Sigma_xy,index);

  		}
        // else
        //     ELD(Rxy,index)=0.0;

		if (RigidityXZ!=0.0)
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(X))
				Dx=EL(Vz,i+1,j,k)-EL(Vz,i,j,k);
			else
				Dx=CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dx+=EL(Vx,i,j,k+1)-EL(Vx,i,j,k);
			else
				Dx+=CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k))-
					CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1));

	  		Miu=RigidityXZ*(1.0+TauShearXZ);

			if (TauShearXZ!=0.0)
			{
  				MiuComp=RigidityXZ*(TauShearXZ*OneOverTauSigma);
	  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxz,index) - DT*MiuComp*Dx)
  			          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xz,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxz,index) +NextR));
				ELD(Rxz,index)=NextR;
			}
			else
				ELD(Sigma_xz,index)+= DT*(Miu*Dx );
        	accum_xz+=ELD(Sigma_xz,index);
  			
  		}
        // else
        //     ELD(Rxz,index)=0.0;
 
  		if (RigidityYZ!=0.0 )
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(Y))
				Dy=EL(Vz,i,j+1,k)-EL(Vz,i,j,k);
			else
				Dy=CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dy+=EL(Vy,i,j,k+1)-EL(Vy,i,j,k);
			else
				Dy+=CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
					CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1));

  			Miu=RigidityYZ*(1.0+TauShearYZ);
			
			if (TauShearYZ!=0)
			{
				MiuComp=RigidityYZ*(TauShearYZ*OneOverTauSigma);

				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryz,index) - DT*MiuComp*Dy)
					/(1+DT*0.5*OneOverTauSigma);

				ELD(Sigma_yz,index)+= DT*(Miu*Dy + 0.5*(ELD(Ryz,index) +NextR));
				ELD(Ryz,index)=NextR;
			}
			else 
				ELD(Sigma_yz,index)+= DT*(Miu*Dy );
        	accum_yz+=ELD(Sigma_yz,index);

  		}
        //   else
        //       ELD(Ryz,index)=0.0;

		if ((nStep < LengthSource) && TypeSource>=2) //Source is stress
  		{
  			index=IndN1N2N3(i,j,k,0);
  			source=ELD(SourceMap,index);
  			if (source>0)
  			{
  			  source--; //need to use C index
  			  value=ELD(SourceFunctions,nStep*NumberSources+source)*ELD(Ox,index); // We use Ox as mechanism to provide weighted arrays
				index=Ind_Sigma_xx(i,j,k);
                if ((TypeSource-2)==0)
                {
                    ELD(Sigma_xx,index)+=value;
                    ELD(Sigma_yy,index)+=value;
                    ELD(Sigma_zz,index)+=value;
                }
                else
                {
                   ELD(Sigma_xx,index)=value;
                   ELD(Sigma_yy,index)=value;
                   ELD(Sigma_zz,index)=value;
                }

  			}
  		}
	#endif
	}
  }
  #if defined(_ST_MAIN) 
  if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
  {
	
    accum_xx/=ZoneCount;
    accum_yy/=ZoneCount;
    accum_zz/=ZoneCount;
	accum_xy/=ZoneCount;
	accum_xz/=ZoneCount;
	accum_yz/=ZoneCount;
	
    CurZone=0;
    index=IndN1N2N3(i,j,k,0);
    index2=N1*N2*N3;


    if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
    {
		if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)+=accum_xx*accum_xx;
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)+=accum_yy*accum_yy;
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)+=accum_zz*accum_zz;
		if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)+=accum_p*accum_p;
		if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)+=accum_xy*accum_xy;
		if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)+=accum_xz*accum_xz;
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)+=accum_yz*accum_yz;
		
		
    }
    if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
        index+=index2*NumberSelRMSPeakMaps;
    if (SelRMSorPeak & SEL_PEAK)
    {
		
        if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)=accum_xx>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx) ? accum_xx: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx);
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)=accum_yy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy) ? accum_yy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy);
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)=accum_zz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz) ? accum_zz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz);
        if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)=accum_p > ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure) ? accum_p :ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure);
	    if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)=accum_xy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy) ? accum_xy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy);
        if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)=accum_xz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz) ? accum_xz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz);
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)=accum_yz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz) ? accum_yz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz);
		
		
    }
}
 #endif


#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_J_TOP
#endif
#undef _ST_PML
//MLX_BLOCK_PML_4_STRESS_END
//MLX_BLOCK_PML_5_STRESS_START
#define _ST_PML
#if ((defined(MLX)) && defined(MLX_PML_5_STRESS)) || !defined(MLX)
#define _PML_KERNEL_K_BOTTOM
#ifdef CUDA
extern "C" __global__ void PML_5_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_5_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_5_StressKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else	
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (PML_Thickness)
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (PML_Thickness)
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
	
#if defined(_ST_PML)
	mexType Diff;
	mexType Diff2;
	mexType Diff3;
#endif

#if defined(_ST_MAIN)
	mexType Dx;
	mexType Dy;
	mexType Dz;
#endif


	mexType value;

	mexType m1;
	mexType m2;
	mexType m3;
	mexType m4;

	mexType RigidityXY=0.0;
	mexType RigidityXZ=0.0;
	mexType RigidityYZ=0.0;
	mexType TauShearXY=0.0;
	mexType TauShearXZ=0.0;
	mexType TauShearYZ=0.0;

#if defined(_ST_MAIN)
	mexType LambdaMiu;
	mexType LambdaMiuComp;
	mexType dFirstPart;
	mexType dFirstPartForR;
	mexType accum_xx=0.0;
	mexType accum_yy=0.0;
	mexType accum_zz=0.0;
	mexType accum_p=0.0;
	_PT source;
	_PT bAttenuating=1;
	mexType Miu;
	mexType MiuComp;
	mexType OneOverTauSigma;
	mexType NextR;
	mexType accum_xy=0.0;
	mexType accum_xz=0.0;
	mexType accum_yz=0.0;
#endif


#ifdef USE_2ND_ORDER_EDGES
    interface_t interfaceZ=inside, interfaceY=inside, interfaceX=inside;
#endif

_PT index2;
_PT index;
_PT  MaterialID;

_PT CurZone;

for ( CurZone=0;CurZone<ZoneCount;CurZone++)
  {
	  index=Ind_MaterialMap(i,j,k);
      MaterialID=ELD(MaterialMap,index);

	  	m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j+1,k));
   		value=m1*m2*m3*m4;
  		RigidityXY =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
      
	    #if  defined(_ST_MAIN) 
  		TauShearXY = value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j+1,k)))
  							 : ELD(TauShear,MaterialID);

	   #endif
	    m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k+1));

  		value=m1*m2*m3*m4;
  		RigidityXZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
	   #if defined(_ST_MAIN)
  		TauShearXZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k+1)))
  							 : ELD(TauShear,MaterialID);

		#endif
		m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k+1));

        value=m1*m2*m3*m4;

  		RigidityYZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
		
		#if  defined(_ST_MAIN)
  		TauShearYZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k+1)))
  							 : ELD(TauShear,MaterialID);
		#endif

  	
  	if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 ||  IsOnPML_K(k)==1)//We are in the PML borders
  	 {
		#if defined(_ST_PML)
  		if (i<N1-1 && j <N2-1 && k < N3-1)
  		{

  			Diff= i>1 && i <N1-1 ? CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k)) -
  			                       CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k))
  			      : i>0 && i <N1 ? (EL(Vx,i,j,k)-EL(Vx,i-1,j,k))  :0;

			Diff2= j>1 && j < N2-1 ? CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
  									CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k))
  			        : j>0 && j < N2 ? EL(Vy,i,j,k)-EL(Vy,i,j-1,k):0;

			Diff3= k>1 && k < N3-1 ? CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1)) -
  									CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2))
  			                       :k>0 && k < N3 ? EL(Vz,i,j,k)-EL(Vz,i,j,k-1) : 0;
  			
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_x_xx,index2) =InvDXDT_I*(
  											ELD(Sigma_x_xx,index2)*DXDT_I+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff);
			index2=Ind_Sigma_y_xx(i,j,k);
  			ELD(Sigma_y_xx,index2) =InvDXDT_J*(
  											ELD(Sigma_y_xx,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_xx(i,j,k);
  			ELD(Sigma_z_xx,index2) =InvDXDT_K*(
  											ELD(Sigma_z_xx,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_xx,index)= ELD(Sigma_x_xx,index2) + ELD(Sigma_y_xx,index2)+ ELD(Sigma_z_xx,index2);

			index2=Ind_Sigma_x_yy(i,j,k);
  			ELD(Sigma_x_yy,index2) =InvDXDT_I*(
  											ELD(Sigma_x_yy,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);

			index2=Ind_Sigma_y_yy(i,j,k);
  			ELD(Sigma_y_yy,index2) =InvDXDT_J*(
  											ELD(Sigma_y_yy,index2)*DXDT_J+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_yy(i,j,k);
  			ELD(Sigma_z_yy,index2) =InvDXDT_K*(
  											ELD(Sigma_z_yy,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_yy,index)= ELD(Sigma_x_yy,index2) + ELD(Sigma_y_yy,index2)+ ELD(Sigma_z_yy,index2);


  			index2=Ind_Sigma_x_zz(i,j,k);
  			ELD(Sigma_x_zz,index2) =InvDXDT_I*(
  											ELD(Sigma_x_zz,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);




  			index2=Ind_Sigma_y_zz(i,j,k);
  			ELD(Sigma_y_zz,index2) =InvDXDT_J*(
  											ELD(Sigma_y_zz,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);



  			index2=Ind_Sigma_z_zz(i,j,k);
  			ELD(Sigma_z_zz,index2) =InvDXDT_K*(
  											ELD(Sigma_z_zz,index2)*DXDT_K+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_zz,index)= ELD(Sigma_x_zz,index2) + ELD(Sigma_y_zz,index2)+ ELD(Sigma_z_zz,index2);

  			index2=Ind_Sigma_x_xy(i,j,k);

  			Diff= i >0 && i<N1-2 ? CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k)) -
  			                   CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k))
  			                    :i<N1-1 ? EL(Vy,i+1,j,k)-EL(Vy,i,j,k):0;

  			ELD(Sigma_x_xy,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xy,index2)*DXDThp_I+
  											RigidityXY*
  											Diff);
			index2=Ind_Sigma_y_xy(i,j,k);

  			Diff=j > 0 && j<N2-2 ? CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k) )-
  			                       CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k) )
  			                       :j<N2-1 ? EL(Vx,i,j+1,k)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_y_xy,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_xy,index2)*DXDThp_J+
  											RigidityXY*
  											Diff);
			index=Ind_Sigma_xy(i,j,k);

			ELD(Sigma_xy,index)= ELD(Sigma_x_xy,Ind_Sigma_x_xy(i,j,k)) + ELD(Sigma_y_xy,index2);

  			index2=Ind_Sigma_x_xz(i,j,k);

  			Diff= i>0 && i<N1-2 ? CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k)) -
  								  CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k))
  								  :i<N1-1 ? EL(Vz,i+1,j,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_x_xz,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xz,index2)*DXDThp_I+
  											RigidityXZ*
  											Diff);



  			index2=Ind_Sigma_z_xz(i,j,k);


  			Diff=k >0 && k < N3-2 ? CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k)) -
  			                        CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1)):
                                      k < N3-1 ? EL(Vx,i,j,k+1)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_z_xz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_xz,index2)*DXDThp_K+
  											RigidityXZ*
  											Diff);
			index=Ind_Sigma_xz(i,j,k);

  		    ELD(Sigma_xz,index)= ELD(Sigma_x_xz,Ind_Sigma_x_xz(i,j,k)) + ELD(Sigma_z_xz,index2);

  			index2=Ind_Sigma_y_yz(i,j,k);

  			Diff=j>0 && j<N2-2 ? CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k)) -
  							     CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k))
  							     :j<N2-1 ? EL(Vz,i,j+1,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_y_yz,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_yz,index2)*DXDThp_J+
  											RigidityYZ*
  											Diff);

  			

  			index2=Ind_Sigma_z_yz(i,j,k);

  			Diff=k>0 && k < N3-2 ? CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
  			                       CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1))
  			                       :k < N3-1 ? EL(Vy,i,j,k+1)-EL(Vy,i,j,k):0;
  			ELD(Sigma_z_yz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_yz,index2)*DXDThp_K+
  											RigidityYZ*
  											Diff);

			index=Ind_Sigma_yz(i,j,k);
	
			ELD(Sigma_yz,index)= ELD(Sigma_y_yz,Ind_Sigma_y_yz(i,j,k)) + ELD(Sigma_z_yz,index2);

		  }	 
		#endif  
	 }
	else
	{
#if defined(_ST_MAIN)
  		//We are in the center, no need to check any limits, the use of the PML simplify this
  		index=Ind_Sigma_xx(i,j,k);

		if (REQUIRES_2ND_ORDER_M(X))
			Dx=EL(Vx,i,j,k)-EL(Vx,i-1,j,k);
		else
			Dx=CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k))-
				CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k));

		if REQUIRES_2ND_ORDER_M(Y)
			Dy=EL(Vy,i,j,k)-EL(Vy,i,j-1,k);
		else
			Dy=CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
				CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k));

		if REQUIRES_2ND_ORDER_M(Z)
			Dz=EL(Vz,i,j,k)-EL(Vz,i,j,k-1);
		else
			Dz=CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1))-
              CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2));

		
		//We will use the particle displacement to estimate the acoustic pressure, and using the conservation of mass formula
		//We can use the stress kernel as V matrices are not being modified in this kernel,
		// and the spatial derivatives are the same ones required for pressure calculation
        // partial(p)/partial(t) = \rho c^2 div(V)
        //it is important to mention that the Python function will need still to multiply the result for the maps of (speed of sound)^2 and density, 
		// and divide by the spatial step.
		EL(Pressure,i,j,k)+=DT*(Dx+Dy+Dz);
        accum_p+=EL(Pressure,i,j,k);


  		LambdaMiu=ELD(LambdaMiuMatOverH,MaterialID)*(1.0+ELD(TauLong,MaterialID));
  		Miu=2.0*ELD(MiuMatOverH,MaterialID)*(1.0+ELD(TauShear,MaterialID));
  		OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
		dFirstPart=LambdaMiu*(Dx+Dy+Dz);
		
		if (ELD(TauLong,MaterialID)!=0.0 || ELD(TauShear,MaterialID)!=0.0) // We avoid unnecessary calculations if there is no attenuation
		{
			
			LambdaMiuComp=DT*ELD(LambdaMiuMatOverH,MaterialID)*(ELD(TauLong,MaterialID)*OneOverTauSigma);
			dFirstPartForR=LambdaMiuComp*(Dx+Dy+Dz);
			MiuComp=DT*2.0*ELD(MiuMatOverH,MaterialID)*(ELD(TauShear,MaterialID)*OneOverTauSigma);
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxx,index) - dFirstPartForR + MiuComp*(Dy+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);

			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz) + 0.5*(ELD(Rxx,index) + NextR));
			ELD(Rxx,index)=NextR;
		}
		else
		{
			bAttenuating=0;
			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz));
		}
  		
	    accum_xx+=ELD(Sigma_xx,index);

		if (bAttenuating==1)
		{
  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryy,index) - dFirstPartForR + MiuComp*(Dx+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);
				
  			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz) + 0.5*(ELD(Ryy,index) + NextR));
			ELD(Ryy,index)=NextR;
		}
		else
			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz));
      	
		accum_yy+=ELD(Sigma_yy,index);

  		if (bAttenuating==1)
		{
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rzz,index) - dFirstPartForR +MiuComp*(Dx+Dy))
				/(1+DT*0.5*OneOverTauSigma);
  			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy) + 0.5*(ELD(Rzz,index) + NextR));
			ELD(Rzz,index)=NextR;
		}
		else
			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy));

      	accum_zz+=ELD(Sigma_zz,index);


  		index=Ind_Sigma_xy(i,j,k);

		if (RigidityXY!=0.0)
  		{
			  OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
              if (REQUIRES_2ND_ORDER_P(X))
                  Dx=EL(Vy,i+1,j,k)-EL(Vy,i,j,k);
              else
                  Dx=CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k))-
                     CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k));


              if (REQUIRES_2ND_ORDER_P(Y))
                  Dx+=EL(Vx,i,j+1,k)-EL(Vx,i,j,k);
              else
                  Dx+=CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k))-
                      CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k));

  			Miu=RigidityXY*(1.0+TauShearXY);

			if (TauShearXY!=0.0)
			{
				MiuComp=RigidityXY*(TauShearXY*OneOverTauSigma);
				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxy,index) - DT*MiuComp*Dx)
  		          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xy,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxy,index) +NextR));
				ELD(Rxy,index)=NextR;
			}
			else
				ELD(Sigma_xy,index)+= DT*(Miu*Dx );
        	
			accum_xy+=ELD(Sigma_xy,index);

  		}
        // else
        //     ELD(Rxy,index)=0.0;

		if (RigidityXZ!=0.0)
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(X))
				Dx=EL(Vz,i+1,j,k)-EL(Vz,i,j,k);
			else
				Dx=CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dx+=EL(Vx,i,j,k+1)-EL(Vx,i,j,k);
			else
				Dx+=CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k))-
					CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1));

	  		Miu=RigidityXZ*(1.0+TauShearXZ);

			if (TauShearXZ!=0.0)
			{
  				MiuComp=RigidityXZ*(TauShearXZ*OneOverTauSigma);
	  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxz,index) - DT*MiuComp*Dx)
  			          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xz,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxz,index) +NextR));
				ELD(Rxz,index)=NextR;
			}
			else
				ELD(Sigma_xz,index)+= DT*(Miu*Dx );
        	accum_xz+=ELD(Sigma_xz,index);
  			
  		}
        // else
        //     ELD(Rxz,index)=0.0;
 
  		if (RigidityYZ!=0.0 )
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(Y))
				Dy=EL(Vz,i,j+1,k)-EL(Vz,i,j,k);
			else
				Dy=CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dy+=EL(Vy,i,j,k+1)-EL(Vy,i,j,k);
			else
				Dy+=CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
					CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1));

  			Miu=RigidityYZ*(1.0+TauShearYZ);
			
			if (TauShearYZ!=0)
			{
				MiuComp=RigidityYZ*(TauShearYZ*OneOverTauSigma);

				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryz,index) - DT*MiuComp*Dy)
					/(1+DT*0.5*OneOverTauSigma);

				ELD(Sigma_yz,index)+= DT*(Miu*Dy + 0.5*(ELD(Ryz,index) +NextR));
				ELD(Ryz,index)=NextR;
			}
			else 
				ELD(Sigma_yz,index)+= DT*(Miu*Dy );
        	accum_yz+=ELD(Sigma_yz,index);

  		}
        //   else
        //       ELD(Ryz,index)=0.0;

		if ((nStep < LengthSource) && TypeSource>=2) //Source is stress
  		{
  			index=IndN1N2N3(i,j,k,0);
  			source=ELD(SourceMap,index);
  			if (source>0)
  			{
  			  source--; //need to use C index
  			  value=ELD(SourceFunctions,nStep*NumberSources+source)*ELD(Ox,index); // We use Ox as mechanism to provide weighted arrays
				index=Ind_Sigma_xx(i,j,k);
                if ((TypeSource-2)==0)
                {
                    ELD(Sigma_xx,index)+=value;
                    ELD(Sigma_yy,index)+=value;
                    ELD(Sigma_zz,index)+=value;
                }
                else
                {
                   ELD(Sigma_xx,index)=value;
                   ELD(Sigma_yy,index)=value;
                   ELD(Sigma_zz,index)=value;
                }

  			}
  		}
	#endif
	}
  }
  #if defined(_ST_MAIN) 
  if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
  {
	
    accum_xx/=ZoneCount;
    accum_yy/=ZoneCount;
    accum_zz/=ZoneCount;
	accum_xy/=ZoneCount;
	accum_xz/=ZoneCount;
	accum_yz/=ZoneCount;
	
    CurZone=0;
    index=IndN1N2N3(i,j,k,0);
    index2=N1*N2*N3;


    if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
    {
		if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)+=accum_xx*accum_xx;
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)+=accum_yy*accum_yy;
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)+=accum_zz*accum_zz;
		if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)+=accum_p*accum_p;
		if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)+=accum_xy*accum_xy;
		if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)+=accum_xz*accum_xz;
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)+=accum_yz*accum_yz;
		
		
    }
    if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
        index+=index2*NumberSelRMSPeakMaps;
    if (SelRMSorPeak & SEL_PEAK)
    {
		
        if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)=accum_xx>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx) ? accum_xx: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx);
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)=accum_yy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy) ? accum_yy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy);
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)=accum_zz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz) ? accum_zz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz);
        if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)=accum_p > ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure) ? accum_p :ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure);
	    if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)=accum_xy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy) ? accum_xy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy);
        if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)=accum_xz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz) ? accum_xz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz);
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)=accum_yz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz) ? accum_yz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz);
		
		
    }
}
 #endif


#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_K_BOTTOM
#endif
#undef _ST_PML
//MLX_BLOCK_PML_5_STRESS_END
//MLX_BLOCK_PML_6_STRESS_START
#define _ST_PML
#if ((defined(MLX)) && defined(MLX_PML_6_STRESS)) || !defined(MLX)
#define _PML_KERNEL_K_TOP
#ifdef CUDA
extern "C" __global__ void PML_6_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_6_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_6_StressKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (PML_Thickness)
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (PML_Thickness)
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
	
#if defined(_ST_PML)
	mexType Diff;
	mexType Diff2;
	mexType Diff3;
#endif

#if defined(_ST_MAIN)
	mexType Dx;
	mexType Dy;
	mexType Dz;
#endif


	mexType value;

	mexType m1;
	mexType m2;
	mexType m3;
	mexType m4;

	mexType RigidityXY=0.0;
	mexType RigidityXZ=0.0;
	mexType RigidityYZ=0.0;
	mexType TauShearXY=0.0;
	mexType TauShearXZ=0.0;
	mexType TauShearYZ=0.0;

#if defined(_ST_MAIN)
	mexType LambdaMiu;
	mexType LambdaMiuComp;
	mexType dFirstPart;
	mexType dFirstPartForR;
	mexType accum_xx=0.0;
	mexType accum_yy=0.0;
	mexType accum_zz=0.0;
	mexType accum_p=0.0;
	_PT source;
	_PT bAttenuating=1;
	mexType Miu;
	mexType MiuComp;
	mexType OneOverTauSigma;
	mexType NextR;
	mexType accum_xy=0.0;
	mexType accum_xz=0.0;
	mexType accum_yz=0.0;
#endif


#ifdef USE_2ND_ORDER_EDGES
    interface_t interfaceZ=inside, interfaceY=inside, interfaceX=inside;
#endif

_PT index2;
_PT index;
_PT  MaterialID;

_PT CurZone;

for ( CurZone=0;CurZone<ZoneCount;CurZone++)
  {
	  index=Ind_MaterialMap(i,j,k);
      MaterialID=ELD(MaterialMap,index);

	  	m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j+1,k));
   		value=m1*m2*m3*m4;
  		RigidityXY =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
      
	    #if  defined(_ST_MAIN) 
  		TauShearXY = value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j+1,k)))
  							 : ELD(TauShear,MaterialID);

	   #endif
	    m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k+1));

  		value=m1*m2*m3*m4;
  		RigidityXZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
	   #if defined(_ST_MAIN)
  		TauShearXZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k+1)))
  							 : ELD(TauShear,MaterialID);

		#endif
		m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k+1));

        value=m1*m2*m3*m4;

  		RigidityYZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
		
		#if  defined(_ST_MAIN)
  		TauShearYZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k+1)))
  							 : ELD(TauShear,MaterialID);
		#endif

  	
  	if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 ||  IsOnPML_K(k)==1)//We are in the PML borders
  	 {
		#if defined(_ST_PML)
  		if (i<N1-1 && j <N2-1 && k < N3-1)
  		{

  			Diff= i>1 && i <N1-1 ? CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k)) -
  			                       CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k))
  			      : i>0 && i <N1 ? (EL(Vx,i,j,k)-EL(Vx,i-1,j,k))  :0;

			Diff2= j>1 && j < N2-1 ? CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
  									CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k))
  			        : j>0 && j < N2 ? EL(Vy,i,j,k)-EL(Vy,i,j-1,k):0;

			Diff3= k>1 && k < N3-1 ? CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1)) -
  									CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2))
  			                       :k>0 && k < N3 ? EL(Vz,i,j,k)-EL(Vz,i,j,k-1) : 0;
  			
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_x_xx,index2) =InvDXDT_I*(
  											ELD(Sigma_x_xx,index2)*DXDT_I+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff);
			index2=Ind_Sigma_y_xx(i,j,k);
  			ELD(Sigma_y_xx,index2) =InvDXDT_J*(
  											ELD(Sigma_y_xx,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_xx(i,j,k);
  			ELD(Sigma_z_xx,index2) =InvDXDT_K*(
  											ELD(Sigma_z_xx,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_xx,index)= ELD(Sigma_x_xx,index2) + ELD(Sigma_y_xx,index2)+ ELD(Sigma_z_xx,index2);

			index2=Ind_Sigma_x_yy(i,j,k);
  			ELD(Sigma_x_yy,index2) =InvDXDT_I*(
  											ELD(Sigma_x_yy,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);

			index2=Ind_Sigma_y_yy(i,j,k);
  			ELD(Sigma_y_yy,index2) =InvDXDT_J*(
  											ELD(Sigma_y_yy,index2)*DXDT_J+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_yy(i,j,k);
  			ELD(Sigma_z_yy,index2) =InvDXDT_K*(
  											ELD(Sigma_z_yy,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_yy,index)= ELD(Sigma_x_yy,index2) + ELD(Sigma_y_yy,index2)+ ELD(Sigma_z_yy,index2);


  			index2=Ind_Sigma_x_zz(i,j,k);
  			ELD(Sigma_x_zz,index2) =InvDXDT_I*(
  											ELD(Sigma_x_zz,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);




  			index2=Ind_Sigma_y_zz(i,j,k);
  			ELD(Sigma_y_zz,index2) =InvDXDT_J*(
  											ELD(Sigma_y_zz,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);



  			index2=Ind_Sigma_z_zz(i,j,k);
  			ELD(Sigma_z_zz,index2) =InvDXDT_K*(
  											ELD(Sigma_z_zz,index2)*DXDT_K+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_zz,index)= ELD(Sigma_x_zz,index2) + ELD(Sigma_y_zz,index2)+ ELD(Sigma_z_zz,index2);

  			index2=Ind_Sigma_x_xy(i,j,k);

  			Diff= i >0 && i<N1-2 ? CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k)) -
  			                   CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k))
  			                    :i<N1-1 ? EL(Vy,i+1,j,k)-EL(Vy,i,j,k):0;

  			ELD(Sigma_x_xy,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xy,index2)*DXDThp_I+
  											RigidityXY*
  											Diff);
			index2=Ind_Sigma_y_xy(i,j,k);

  			Diff=j > 0 && j<N2-2 ? CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k) )-
  			                       CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k) )
  			                       :j<N2-1 ? EL(Vx,i,j+1,k)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_y_xy,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_xy,index2)*DXDThp_J+
  											RigidityXY*
  											Diff);
			index=Ind_Sigma_xy(i,j,k);

			ELD(Sigma_xy,index)= ELD(Sigma_x_xy,Ind_Sigma_x_xy(i,j,k)) + ELD(Sigma_y_xy,index2);

  			index2=Ind_Sigma_x_xz(i,j,k);

  			Diff= i>0 && i<N1-2 ? CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k)) -
  								  CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k))
  								  :i<N1-1 ? EL(Vz,i+1,j,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_x_xz,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xz,index2)*DXDThp_I+
  											RigidityXZ*
  											Diff);



  			index2=Ind_Sigma_z_xz(i,j,k);


  			Diff=k >0 && k < N3-2 ? CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k)) -
  			                        CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1)):
                                      k < N3-1 ? EL(Vx,i,j,k+1)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_z_xz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_xz,index2)*DXDThp_K+
  											RigidityXZ*
  											Diff);
			index=Ind_Sigma_xz(i,j,k);

  		    ELD(Sigma_xz,index)= ELD(Sigma_x_xz,Ind_Sigma_x_xz(i,j,k)) + ELD(Sigma_z_xz,index2);

  			index2=Ind_Sigma_y_yz(i,j,k);

  			Diff=j>0 && j<N2-2 ? CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k)) -
  							     CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k))
  							     :j<N2-1 ? EL(Vz,i,j+1,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_y_yz,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_yz,index2)*DXDThp_J+
  											RigidityYZ*
  											Diff);

  			

  			index2=Ind_Sigma_z_yz(i,j,k);

  			Diff=k>0 && k < N3-2 ? CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
  			                       CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1))
  			                       :k < N3-1 ? EL(Vy,i,j,k+1)-EL(Vy,i,j,k):0;
  			ELD(Sigma_z_yz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_yz,index2)*DXDThp_K+
  											RigidityYZ*
  											Diff);

			index=Ind_Sigma_yz(i,j,k);
	
			ELD(Sigma_yz,index)= ELD(Sigma_y_yz,Ind_Sigma_y_yz(i,j,k)) + ELD(Sigma_z_yz,index2);

		  }	 
		#endif  
	 }
	else
	{
#if defined(_ST_MAIN)
  		//We are in the center, no need to check any limits, the use of the PML simplify this
  		index=Ind_Sigma_xx(i,j,k);

		if (REQUIRES_2ND_ORDER_M(X))
			Dx=EL(Vx,i,j,k)-EL(Vx,i-1,j,k);
		else
			Dx=CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k))-
				CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k));

		if REQUIRES_2ND_ORDER_M(Y)
			Dy=EL(Vy,i,j,k)-EL(Vy,i,j-1,k);
		else
			Dy=CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
				CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k));

		if REQUIRES_2ND_ORDER_M(Z)
			Dz=EL(Vz,i,j,k)-EL(Vz,i,j,k-1);
		else
			Dz=CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1))-
              CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2));

		
		//We will use the particle displacement to estimate the acoustic pressure, and using the conservation of mass formula
		//We can use the stress kernel as V matrices are not being modified in this kernel,
		// and the spatial derivatives are the same ones required for pressure calculation
        // partial(p)/partial(t) = \rho c^2 div(V)
        //it is important to mention that the Python function will need still to multiply the result for the maps of (speed of sound)^2 and density, 
		// and divide by the spatial step.
		EL(Pressure,i,j,k)+=DT*(Dx+Dy+Dz);
        accum_p+=EL(Pressure,i,j,k);


  		LambdaMiu=ELD(LambdaMiuMatOverH,MaterialID)*(1.0+ELD(TauLong,MaterialID));
  		Miu=2.0*ELD(MiuMatOverH,MaterialID)*(1.0+ELD(TauShear,MaterialID));
  		OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
		dFirstPart=LambdaMiu*(Dx+Dy+Dz);
		
		if (ELD(TauLong,MaterialID)!=0.0 || ELD(TauShear,MaterialID)!=0.0) // We avoid unnecessary calculations if there is no attenuation
		{
			
			LambdaMiuComp=DT*ELD(LambdaMiuMatOverH,MaterialID)*(ELD(TauLong,MaterialID)*OneOverTauSigma);
			dFirstPartForR=LambdaMiuComp*(Dx+Dy+Dz);
			MiuComp=DT*2.0*ELD(MiuMatOverH,MaterialID)*(ELD(TauShear,MaterialID)*OneOverTauSigma);
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxx,index) - dFirstPartForR + MiuComp*(Dy+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);

			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz) + 0.5*(ELD(Rxx,index) + NextR));
			ELD(Rxx,index)=NextR;
		}
		else
		{
			bAttenuating=0;
			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz));
		}
  		
	    accum_xx+=ELD(Sigma_xx,index);

		if (bAttenuating==1)
		{
  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryy,index) - dFirstPartForR + MiuComp*(Dx+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);
				
  			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz) + 0.5*(ELD(Ryy,index) + NextR));
			ELD(Ryy,index)=NextR;
		}
		else
			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz));
      	
		accum_yy+=ELD(Sigma_yy,index);

  		if (bAttenuating==1)
		{
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rzz,index) - dFirstPartForR +MiuComp*(Dx+Dy))
				/(1+DT*0.5*OneOverTauSigma);
  			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy) + 0.5*(ELD(Rzz,index) + NextR));
			ELD(Rzz,index)=NextR;
		}
		else
			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy));

      	accum_zz+=ELD(Sigma_zz,index);


  		index=Ind_Sigma_xy(i,j,k);

		if (RigidityXY!=0.0)
  		{
			  OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
              if (REQUIRES_2ND_ORDER_P(X))
                  Dx=EL(Vy,i+1,j,k)-EL(Vy,i,j,k);
              else
                  Dx=CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k))-
                     CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k));


              if (REQUIRES_2ND_ORDER_P(Y))
                  Dx+=EL(Vx,i,j+1,k)-EL(Vx,i,j,k);
              else
                  Dx+=CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k))-
                      CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k));

  			Miu=RigidityXY*(1.0+TauShearXY);

			if (TauShearXY!=0.0)
			{
				MiuComp=RigidityXY*(TauShearXY*OneOverTauSigma);
				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxy,index) - DT*MiuComp*Dx)
  		          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xy,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxy,index) +NextR));
				ELD(Rxy,index)=NextR;
			}
			else
				ELD(Sigma_xy,index)+= DT*(Miu*Dx );
        	
			accum_xy+=ELD(Sigma_xy,index);

  		}
        // else
        //     ELD(Rxy,index)=0.0;

		if (RigidityXZ!=0.0)
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(X))
				Dx=EL(Vz,i+1,j,k)-EL(Vz,i,j,k);
			else
				Dx=CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dx+=EL(Vx,i,j,k+1)-EL(Vx,i,j,k);
			else
				Dx+=CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k))-
					CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1));

	  		Miu=RigidityXZ*(1.0+TauShearXZ);

			if (TauShearXZ!=0.0)
			{
  				MiuComp=RigidityXZ*(TauShearXZ*OneOverTauSigma);
	  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxz,index) - DT*MiuComp*Dx)
  			          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xz,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxz,index) +NextR));
				ELD(Rxz,index)=NextR;
			}
			else
				ELD(Sigma_xz,index)+= DT*(Miu*Dx );
        	accum_xz+=ELD(Sigma_xz,index);
  			
  		}
        // else
        //     ELD(Rxz,index)=0.0;
 
  		if (RigidityYZ!=0.0 )
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(Y))
				Dy=EL(Vz,i,j+1,k)-EL(Vz,i,j,k);
			else
				Dy=CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dy+=EL(Vy,i,j,k+1)-EL(Vy,i,j,k);
			else
				Dy+=CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
					CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1));

  			Miu=RigidityYZ*(1.0+TauShearYZ);
			
			if (TauShearYZ!=0)
			{
				MiuComp=RigidityYZ*(TauShearYZ*OneOverTauSigma);

				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryz,index) - DT*MiuComp*Dy)
					/(1+DT*0.5*OneOverTauSigma);

				ELD(Sigma_yz,index)+= DT*(Miu*Dy + 0.5*(ELD(Ryz,index) +NextR));
				ELD(Ryz,index)=NextR;
			}
			else 
				ELD(Sigma_yz,index)+= DT*(Miu*Dy );
        	accum_yz+=ELD(Sigma_yz,index);

  		}
        //   else
        //       ELD(Ryz,index)=0.0;

		if ((nStep < LengthSource) && TypeSource>=2) //Source is stress
  		{
  			index=IndN1N2N3(i,j,k,0);
  			source=ELD(SourceMap,index);
  			if (source>0)
  			{
  			  source--; //need to use C index
  			  value=ELD(SourceFunctions,nStep*NumberSources+source)*ELD(Ox,index); // We use Ox as mechanism to provide weighted arrays
				index=Ind_Sigma_xx(i,j,k);
                if ((TypeSource-2)==0)
                {
                    ELD(Sigma_xx,index)+=value;
                    ELD(Sigma_yy,index)+=value;
                    ELD(Sigma_zz,index)+=value;
                }
                else
                {
                   ELD(Sigma_xx,index)=value;
                   ELD(Sigma_yy,index)=value;
                   ELD(Sigma_zz,index)=value;
                }

  			}
  		}
	#endif
	}
  }
  #if defined(_ST_MAIN) 
  if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
  {
	
    accum_xx/=ZoneCount;
    accum_yy/=ZoneCount;
    accum_zz/=ZoneCount;
	accum_xy/=ZoneCount;
	accum_xz/=ZoneCount;
	accum_yz/=ZoneCount;
	
    CurZone=0;
    index=IndN1N2N3(i,j,k,0);
    index2=N1*N2*N3;


    if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
    {
		if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)+=accum_xx*accum_xx;
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)+=accum_yy*accum_yy;
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)+=accum_zz*accum_zz;
		if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)+=accum_p*accum_p;
		if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)+=accum_xy*accum_xy;
		if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)+=accum_xz*accum_xz;
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)+=accum_yz*accum_yz;
		
		
    }
    if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
        index+=index2*NumberSelRMSPeakMaps;
    if (SelRMSorPeak & SEL_PEAK)
    {
		
        if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)=accum_xx>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx) ? accum_xx: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx);
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)=accum_yy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy) ? accum_yy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy);
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)=accum_zz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz) ? accum_zz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz);
        if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)=accum_p > ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure) ? accum_p :ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure);
	    if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)=accum_xy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy) ? accum_xy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy);
        if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)=accum_xz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz) ? accum_xz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz);
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)=accum_yz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz) ? accum_yz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz);
		
		
    }
}
 #endif


#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_K_TOP
#endif
#undef _ST_PML
//MLX_BLOCK_PML_6_STRESS_END
#endif
//MLX_BLOCK_MAIN_1_STRESS_START
#if ((defined(MLX)) && defined(MLX_MAIN_1_STRESS)) || !defined(MLX)
#define _ST_MAIN
#define _MAIN_KERNEL
#if defined(OPENCL) || (defined(CUDA) && !defined(USE_MINI_KERNELS_CUDA)) || (defined(METAL) && defined(METAL_SINGLE_KERNEL))
#define _ST_PML
#endif
#ifdef CUDA
extern "C" __global__ void MAIN_1_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void MAIN_1_StressKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if defined(METAL) && !defined(MLX)
kernel void MAIN_1_StressKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else	
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#ifdef METAL_SINGLE_KERNEL
	#define nN1 (N1)
	#define nN2 (N2)
	#define nN3 (N3)
	#else
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (N3-PML_Thickness*2)
	#endif
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#ifdef METAL_SINGLE_KERNEL
	#define nN1 (N1)
	#define nN2 (N2)
	#define nN3 (N3)
	#else
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (N3-PML_Thickness*2)
	#endif
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
	
#if defined(_ST_PML)
	mexType Diff;
	mexType Diff2;
	mexType Diff3;
#endif

#if defined(_ST_MAIN)
	mexType Dx;
	mexType Dy;
	mexType Dz;
#endif


	mexType value;

	mexType m1;
	mexType m2;
	mexType m3;
	mexType m4;

	mexType RigidityXY=0.0;
	mexType RigidityXZ=0.0;
	mexType RigidityYZ=0.0;
	mexType TauShearXY=0.0;
	mexType TauShearXZ=0.0;
	mexType TauShearYZ=0.0;

#if defined(_ST_MAIN)
	mexType LambdaMiu;
	mexType LambdaMiuComp;
	mexType dFirstPart;
	mexType dFirstPartForR;
	mexType accum_xx=0.0;
	mexType accum_yy=0.0;
	mexType accum_zz=0.0;
	mexType accum_p=0.0;
	_PT source;
	_PT bAttenuating=1;
	mexType Miu;
	mexType MiuComp;
	mexType OneOverTauSigma;
	mexType NextR;
	mexType accum_xy=0.0;
	mexType accum_xz=0.0;
	mexType accum_yz=0.0;
#endif


#ifdef USE_2ND_ORDER_EDGES
    interface_t interfaceZ=inside, interfaceY=inside, interfaceX=inside;
#endif

_PT index2;
_PT index;
_PT  MaterialID;

_PT CurZone;

for ( CurZone=0;CurZone<ZoneCount;CurZone++)
  {
	  index=Ind_MaterialMap(i,j,k);
      MaterialID=ELD(MaterialMap,index);

	  	m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j+1,k));
   		value=m1*m2*m3*m4;
  		RigidityXY =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
      
	    #if  defined(_ST_MAIN) 
  		TauShearXY = value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j+1,k)))
  							 : ELD(TauShear,MaterialID);

	   #endif
	    m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k));
  		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i+1,j,k+1));

  		value=m1*m2*m3*m4;
  		RigidityXZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
	   #if defined(_ST_MAIN)
  		TauShearXZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i+1,j,k+1)))
  							 : ELD(TauShear,MaterialID);

		#endif
		m1=ELD(MiuMatOverH,MaterialID);
  		m2=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k));
		m3=ELD(MiuMatOverH,EL(MaterialMap,i,j,k+1));
  		m4=ELD(MiuMatOverH,EL(MaterialMap,i,j+1,k+1));

        value=m1*m2*m3*m4;

  		RigidityYZ =value !=0.0 ? 4.0/(1.0/m1+1.0/m2+1.0/m3+1.0/m4):0.0;
		
		#if  defined(_ST_MAIN)
  		TauShearYZ= value!=0.0 ? 0.25*(ELD(TauShear,MaterialID) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k)) +
  							 ELD(TauShear,EL(MaterialMap,i,j,k+1)) +
  							 ELD(TauShear,EL(MaterialMap,i,j+1,k+1)))
  							 : ELD(TauShear,MaterialID);
		#endif

  	
  	if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 ||  IsOnPML_K(k)==1)//We are in the PML borders
  	 {
		#if defined(_ST_PML)
  		if (i<N1-1 && j <N2-1 && k < N3-1)
  		{

  			Diff= i>1 && i <N1-1 ? CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k)) -
  			                       CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k))
  			      : i>0 && i <N1 ? (EL(Vx,i,j,k)-EL(Vx,i-1,j,k))  :0;

			Diff2= j>1 && j < N2-1 ? CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
  									CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k))
  			        : j>0 && j < N2 ? EL(Vy,i,j,k)-EL(Vy,i,j-1,k):0;

			Diff3= k>1 && k < N3-1 ? CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1)) -
  									CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2))
  			                       :k>0 && k < N3 ? EL(Vz,i,j,k)-EL(Vz,i,j,k-1) : 0;
  			
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_x_xx,index2) =InvDXDT_I*(
  											ELD(Sigma_x_xx,index2)*DXDT_I+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff);
			index2=Ind_Sigma_y_xx(i,j,k);
  			ELD(Sigma_y_xx,index2) =InvDXDT_J*(
  											ELD(Sigma_y_xx,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_xx(i,j,k);
  			ELD(Sigma_z_xx,index2) =InvDXDT_K*(
  											ELD(Sigma_z_xx,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_xx,index)= ELD(Sigma_x_xx,index2) + ELD(Sigma_y_xx,index2)+ ELD(Sigma_z_xx,index2);

			index2=Ind_Sigma_x_yy(i,j,k);
  			ELD(Sigma_x_yy,index2) =InvDXDT_I*(
  											ELD(Sigma_x_yy,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);

			index2=Ind_Sigma_y_yy(i,j,k);
  			ELD(Sigma_y_yy,index2) =InvDXDT_J*(
  											ELD(Sigma_y_yy,index2)*DXDT_J+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff2);

			index2=Ind_Sigma_z_yy(i,j,k);
  			ELD(Sigma_z_yy,index2) =InvDXDT_K*(
  											ELD(Sigma_z_yy,index2)*DXDT_K+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_yy,index)= ELD(Sigma_x_yy,index2) + ELD(Sigma_y_yy,index2)+ ELD(Sigma_z_yy,index2);


  			index2=Ind_Sigma_x_zz(i,j,k);
  			ELD(Sigma_x_zz,index2) =InvDXDT_I*(
  											ELD(Sigma_x_zz,index2)*DXDT_I+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff);




  			index2=Ind_Sigma_y_zz(i,j,k);
  			ELD(Sigma_y_zz,index2) =InvDXDT_J*(
  											ELD(Sigma_y_zz,index2)*DXDT_J+
  											ELD(LambdaMatOverH,MaterialID)*
  											Diff2);



  			index2=Ind_Sigma_z_zz(i,j,k);
  			ELD(Sigma_z_zz,index2) =InvDXDT_K*(
  											ELD(Sigma_z_zz,index2)*DXDT_K+
  											ELD(LambdaMiuMatOverH,MaterialID)*
  											Diff3);

			index=Ind_Sigma_xx(i,j,k);
  			index2=Ind_Sigma_x_xx(i,j,k);
  			ELD(Sigma_zz,index)= ELD(Sigma_x_zz,index2) + ELD(Sigma_y_zz,index2)+ ELD(Sigma_z_zz,index2);

  			index2=Ind_Sigma_x_xy(i,j,k);

  			Diff= i >0 && i<N1-2 ? CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k)) -
  			                   CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k))
  			                    :i<N1-1 ? EL(Vy,i+1,j,k)-EL(Vy,i,j,k):0;

  			ELD(Sigma_x_xy,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xy,index2)*DXDThp_I+
  											RigidityXY*
  											Diff);
			index2=Ind_Sigma_y_xy(i,j,k);

  			Diff=j > 0 && j<N2-2 ? CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k) )-
  			                       CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k) )
  			                       :j<N2-1 ? EL(Vx,i,j+1,k)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_y_xy,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_xy,index2)*DXDThp_J+
  											RigidityXY*
  											Diff);
			index=Ind_Sigma_xy(i,j,k);

			ELD(Sigma_xy,index)= ELD(Sigma_x_xy,Ind_Sigma_x_xy(i,j,k)) + ELD(Sigma_y_xy,index2);

  			index2=Ind_Sigma_x_xz(i,j,k);

  			Diff= i>0 && i<N1-2 ? CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k)) -
  								  CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k))
  								  :i<N1-1 ? EL(Vz,i+1,j,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_x_xz,index2) =InvDXDThp_I*(
  											ELD(Sigma_x_xz,index2)*DXDThp_I+
  											RigidityXZ*
  											Diff);



  			index2=Ind_Sigma_z_xz(i,j,k);


  			Diff=k >0 && k < N3-2 ? CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k)) -
  			                        CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1)):
                                      k < N3-1 ? EL(Vx,i,j,k+1)-EL(Vx,i,j,k) :0;

  			ELD(Sigma_z_xz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_xz,index2)*DXDThp_K+
  											RigidityXZ*
  											Diff);
			index=Ind_Sigma_xz(i,j,k);

  		    ELD(Sigma_xz,index)= ELD(Sigma_x_xz,Ind_Sigma_x_xz(i,j,k)) + ELD(Sigma_z_xz,index2);

  			index2=Ind_Sigma_y_yz(i,j,k);

  			Diff=j>0 && j<N2-2 ? CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k)) -
  							     CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k))
  							     :j<N2-1 ? EL(Vz,i,j+1,k)-EL(Vz,i,j,k):0;

  			ELD(Sigma_y_yz,index2) =InvDXDThp_J*(
  											ELD(Sigma_y_yz,index2)*DXDThp_J+
  											RigidityYZ*
  											Diff);

  			

  			index2=Ind_Sigma_z_yz(i,j,k);

  			Diff=k>0 && k < N3-2 ? CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
  			                       CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1))
  			                       :k < N3-1 ? EL(Vy,i,j,k+1)-EL(Vy,i,j,k):0;
  			ELD(Sigma_z_yz,index2) =InvDXDThp_K*(
  											ELD(Sigma_z_yz,index2)*DXDThp_K+
  											RigidityYZ*
  											Diff);

			index=Ind_Sigma_yz(i,j,k);
	
			ELD(Sigma_yz,index)= ELD(Sigma_y_yz,Ind_Sigma_y_yz(i,j,k)) + ELD(Sigma_z_yz,index2);

		  }	 
		#endif  
	 }
	else
	{
#if defined(_ST_MAIN)
  		//We are in the center, no need to check any limits, the use of the PML simplify this
  		index=Ind_Sigma_xx(i,j,k);

		if (REQUIRES_2ND_ORDER_M(X))
			Dx=EL(Vx,i,j,k)-EL(Vx,i-1,j,k);
		else
			Dx=CA*(EL(Vx,i,j,k)-EL(Vx,i-1,j,k))-
				CB*(EL(Vx,i+1,j,k)-EL(Vx,i-2,j,k));

		if REQUIRES_2ND_ORDER_M(Y)
			Dy=EL(Vy,i,j,k)-EL(Vy,i,j-1,k);
		else
			Dy=CA*(EL(Vy,i,j,k)-EL(Vy,i,j-1,k))-
				CB*(EL(Vy,i,j+1,k)-EL(Vy,i,j-2,k));

		if REQUIRES_2ND_ORDER_M(Z)
			Dz=EL(Vz,i,j,k)-EL(Vz,i,j,k-1);
		else
			Dz=CA*(EL(Vz,i,j,k)-EL(Vz,i,j,k-1))-
              CB*(EL(Vz,i,j,k+1)-EL(Vz,i,j,k-2));

		
		//We will use the particle displacement to estimate the acoustic pressure, and using the conservation of mass formula
		//We can use the stress kernel as V matrices are not being modified in this kernel,
		// and the spatial derivatives are the same ones required for pressure calculation
        // partial(p)/partial(t) = \rho c^2 div(V)
        //it is important to mention that the Python function will need still to multiply the result for the maps of (speed of sound)^2 and density, 
		// and divide by the spatial step.
		EL(Pressure,i,j,k)+=DT*(Dx+Dy+Dz);
        accum_p+=EL(Pressure,i,j,k);


  		LambdaMiu=ELD(LambdaMiuMatOverH,MaterialID)*(1.0+ELD(TauLong,MaterialID));
  		Miu=2.0*ELD(MiuMatOverH,MaterialID)*(1.0+ELD(TauShear,MaterialID));
  		OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
		dFirstPart=LambdaMiu*(Dx+Dy+Dz);
		
		if (ELD(TauLong,MaterialID)!=0.0 || ELD(TauShear,MaterialID)!=0.0) // We avoid unnecessary calculations if there is no attenuation
		{
			
			LambdaMiuComp=DT*ELD(LambdaMiuMatOverH,MaterialID)*(ELD(TauLong,MaterialID)*OneOverTauSigma);
			dFirstPartForR=LambdaMiuComp*(Dx+Dy+Dz);
			MiuComp=DT*2.0*ELD(MiuMatOverH,MaterialID)*(ELD(TauShear,MaterialID)*OneOverTauSigma);
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxx,index) - dFirstPartForR + MiuComp*(Dy+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);

			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz) + 0.5*(ELD(Rxx,index) + NextR));
			ELD(Rxx,index)=NextR;
		}
		else
		{
			bAttenuating=0;
			ELD(Sigma_xx,index)+=	DT*(dFirstPart - Miu*(Dy+Dz));
		}
  		
	    accum_xx+=ELD(Sigma_xx,index);

		if (bAttenuating==1)
		{
  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryy,index) - dFirstPartForR + MiuComp*(Dx+Dz))
  		    	  /(1+DT*0.5*OneOverTauSigma);
				
  			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz) + 0.5*(ELD(Ryy,index) + NextR));
			ELD(Ryy,index)=NextR;
		}
		else
			ELD(Sigma_yy,index)+=	DT*(dFirstPart - Miu*(Dx+Dz));
      	
		accum_yy+=ELD(Sigma_yy,index);

  		if (bAttenuating==1)
		{
			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rzz,index) - dFirstPartForR +MiuComp*(Dx+Dy))
				/(1+DT*0.5*OneOverTauSigma);
  			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy) + 0.5*(ELD(Rzz,index) + NextR));
			ELD(Rzz,index)=NextR;
		}
		else
			ELD(Sigma_zz,index)+=	DT*(dFirstPart - Miu*(Dx+Dy));

      	accum_zz+=ELD(Sigma_zz,index);


  		index=Ind_Sigma_xy(i,j,k);

		if (RigidityXY!=0.0)
  		{
			  OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
              if (REQUIRES_2ND_ORDER_P(X))
                  Dx=EL(Vy,i+1,j,k)-EL(Vy,i,j,k);
              else
                  Dx=CA*(EL(Vy,i+1,j,k)-EL(Vy,i,j,k))-
                     CB*(EL(Vy,i+2,j,k)-EL(Vy,i-1,j,k));


              if (REQUIRES_2ND_ORDER_P(Y))
                  Dx+=EL(Vx,i,j+1,k)-EL(Vx,i,j,k);
              else
                  Dx+=CA*(EL(Vx,i,j+1,k)-EL(Vx,i,j,k))-
                      CB*(EL(Vx,i,j+2,k)-EL(Vx,i,j-1,k));

  			Miu=RigidityXY*(1.0+TauShearXY);

			if (TauShearXY!=0.0)
			{
				MiuComp=RigidityXY*(TauShearXY*OneOverTauSigma);
				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxy,index) - DT*MiuComp*Dx)
  		          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xy,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxy,index) +NextR));
				ELD(Rxy,index)=NextR;
			}
			else
				ELD(Sigma_xy,index)+= DT*(Miu*Dx );
        	
			accum_xy+=ELD(Sigma_xy,index);

  		}
        // else
        //     ELD(Rxy,index)=0.0;

		if (RigidityXZ!=0.0)
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(X))
				Dx=EL(Vz,i+1,j,k)-EL(Vz,i,j,k);
			else
				Dx=CA*(EL(Vz,i+1,j,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i+2,j,k)-EL(Vz,i-1,j,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dx+=EL(Vx,i,j,k+1)-EL(Vx,i,j,k);
			else
				Dx+=CA*(EL(Vx,i,j,k+1)-EL(Vx,i,j,k))-
					CB*(EL(Vx,i,j,k+2)-EL(Vx,i,j,k-1));

	  		Miu=RigidityXZ*(1.0+TauShearXZ);

			if (TauShearXZ!=0.0)
			{
  				MiuComp=RigidityXZ*(TauShearXZ*OneOverTauSigma);
	  			NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Rxz,index) - DT*MiuComp*Dx)
  			          /(1+DT*0.5*OneOverTauSigma);
				ELD(Sigma_xz,index)+= DT*(Miu*Dx + 0.5*(ELD(Rxz,index) +NextR));
				ELD(Rxz,index)=NextR;
			}
			else
				ELD(Sigma_xz,index)+= DT*(Miu*Dx );
        	accum_xz+=ELD(Sigma_xz,index);
  			
  		}
        // else
        //     ELD(Rxz,index)=0.0;
 
  		if (RigidityYZ!=0.0 )
  		{
			OneOverTauSigma=ELD(OneOverTauSigma,MaterialID);
			if (REQUIRES_2ND_ORDER_P(Y))
				Dy=EL(Vz,i,j+1,k)-EL(Vz,i,j,k);
			else
				Dy=CA*(EL(Vz,i,j+1,k)-EL(Vz,i,j,k))-
					CB*(EL(Vz,i,j+2,k)-EL(Vz,i,j-1,k));

			if (REQUIRES_2ND_ORDER_P(Z))
				Dy+=EL(Vy,i,j,k+1)-EL(Vy,i,j,k);
			else
				Dy+=CA*(EL(Vy,i,j,k+1)-EL(Vy,i,j,k))-
					CB*(EL(Vy,i,j,k+2)-EL(Vy,i,j,k-1));

  			Miu=RigidityYZ*(1.0+TauShearYZ);
			
			if (TauShearYZ!=0)
			{
				MiuComp=RigidityYZ*(TauShearYZ*OneOverTauSigma);

				NextR=( (1-DT*0.5*OneOverTauSigma)*ELD(Ryz,index) - DT*MiuComp*Dy)
					/(1+DT*0.5*OneOverTauSigma);

				ELD(Sigma_yz,index)+= DT*(Miu*Dy + 0.5*(ELD(Ryz,index) +NextR));
				ELD(Ryz,index)=NextR;
			}
			else 
				ELD(Sigma_yz,index)+= DT*(Miu*Dy );
        	accum_yz+=ELD(Sigma_yz,index);

  		}
        //   else
        //       ELD(Ryz,index)=0.0;

		if ((nStep < LengthSource) && TypeSource>=2) //Source is stress
  		{
  			index=IndN1N2N3(i,j,k,0);
  			source=ELD(SourceMap,index);
  			if (source>0)
  			{
  			  source--; //need to use C index
  			  value=ELD(SourceFunctions,nStep*NumberSources+source)*ELD(Ox,index); // We use Ox as mechanism to provide weighted arrays
				index=Ind_Sigma_xx(i,j,k);
                if ((TypeSource-2)==0)
                {
                    ELD(Sigma_xx,index)+=value;
                    ELD(Sigma_yy,index)+=value;
                    ELD(Sigma_zz,index)+=value;
                }
                else
                {
                   ELD(Sigma_xx,index)=value;
                   ELD(Sigma_yy,index)=value;
                   ELD(Sigma_zz,index)=value;
                }

  			}
  		}
	#endif
	}
  }
  #if defined(_ST_MAIN) 
  if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
  {
	
    accum_xx/=ZoneCount;
    accum_yy/=ZoneCount;
    accum_zz/=ZoneCount;
	accum_xy/=ZoneCount;
	accum_xz/=ZoneCount;
	accum_yz/=ZoneCount;
	
    CurZone=0;
    index=IndN1N2N3(i,j,k,0);
    index2=N1*N2*N3;


    if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
    {
		if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)+=accum_xx*accum_xx;
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)+=accum_yy*accum_yy;
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)+=accum_zz*accum_zz;
		if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)+=accum_p*accum_p;
		if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)+=accum_xy*accum_xy;
		if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)+=accum_xz*accum_xz;
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)+=accum_yz*accum_yz;
		
		
    }
    if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
        index+=index2*NumberSelRMSPeakMaps;
    if (SelRMSorPeak & SEL_PEAK)
    {
		
        if (IS_Sigmaxx_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx)=accum_xx>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx) ? accum_xx: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxx);
        if (IS_Sigmayy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy)=accum_yy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy) ? accum_yy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayy);
        if (IS_Sigmazz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz)=accum_zz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz) ? accum_zz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmazz);
        if (IS_Pressure_SELECTED(SelMapsRMSPeak))
			ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure)=accum_p > ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure) ? accum_p :ELD(SqrAcc,index+index2*IndexRMSPeak_Pressure);
	    if (IS_Sigmaxy_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy)=accum_xy>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy) ? accum_xy: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxy);
        if (IS_Sigmaxz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz)=accum_xz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz) ? accum_xz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmaxz);
        if (IS_Sigmayz_SELECTED(SelMapsRMSPeak))
            ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz)=accum_yz>ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz) ? accum_yz: ELD(SqrAcc,index+index2*IndexRMSPeak_Sigmayz);
		
		
    }
}
 #endif


#if !defined(MLX)
}
#endif
#if defined(OPENCL) || (defined(CUDA) && !defined(USE_MINI_KERNELS_CUDA)) || (defined(METAL) && defined(METAL_SINGLE_KERNEL))
#undef _ST_PML
#endif
#undef _MAIN_KERNEL
#undef _ST_MAIN
#endif
//MLX_BLOCK_MAIN_1_STRESS_END
// PML
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
//MLX_BLOCK_PML_1_PARTICLE_START
#define _PR_PML
#if ((defined(MLX)) && defined(MLX_PML_1_PARTICLE)) || !defined(MLX)
#define _PML_KERNEL_I_BOTTOM
#ifdef CUDA
extern "C" __global__ void PML_1_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_1_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_1_ParticleKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else	
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (PML_Thickness)
	#define nN2 (N2)
	#define nN3 (N3)
    _PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (PML_Thickness)
	#define nN2 (N2)
	#define nN3 (N3)
    _PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
#if defined(_PR_MAIN)
	_PT source;
	mexType value;
#endif

	mexType AvgInvRhoI;

#if defined(_PR_PML)
	mexType Diff;
#endif
#if defined(_PR_MAIN) 
	mexType accum_x=0.0;
	mexType Dx;
	mexType accum_y=0.0;
	mexType AvgInvRhoJ;
	mexType Dy;
	mexType accum_z=0.0;
	mexType AvgInvRhoK;
	mexType Dz;
#endif
_PT index;
_PT index2;
_PT  CurZone;
	for (   CurZone=0;CurZone<ZoneCount;CurZone++)
		{
		  if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 || IsOnPML_K(k)==1)
			{
			#if defined(_PR_PML)	
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=ELD(InvRhoMatH,ELD(MaterialMap,index));
				//In the PML
				// For coeffs. for V_x
				if (i<N1-1 && j <N2-1 && k<N3-1)
				{
    				index=Ind_V_x_x(i,j,k);


		            Diff= i>0 && i<N1-2 ? CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
		                                  CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k))
					                      :i<N1-1 ? EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k):0;

					ELD(V_x_x,index) =InvDXDThp_I*(ELD(V_x_x,index)*DXDThp_I+
													AvgInvRhoI*
													Diff);

					index=Ind_V_y_x(i,j,k);
					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
					                      CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k))
					                      :j>0 && j<N2 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k):0;

					ELD(V_y_x,index) =InvDXDT_J*(
													ELD(V_y_x,index)*DXDT_J+
													AvgInvRhoI*
													Diff);
					index=Ind_V_z_x(i,j,k);
					Diff= k >1 && k < N3-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
					                         CB*( EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2)) :
		                                     k >0 && k < N3 ?  EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1):0;

					ELD(V_z_x,index) =InvDXDT_K*(
													ELD(V_z_x,index)*DXDT_K+
													AvgInvRhoI*
													Diff);

					
					index=Ind_V_x(i,j,k);
					index2=Ind_V_x_x(i,j,k);
					ELD(Vx,index)=ELD(V_x_x,index2)+ELD(V_y_x,index2)+ELD(V_z_x,index2);
				

				// For coeffs. for V_y

					index=Ind_V_x_y(i,j,k);

					Diff= i>1 && i<N1-1 ? CA *(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k)) -
					                      CB *(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k))
					                      :i>0 && i<N1 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k):0;

					ELD(V_x_y,index) =InvDXDT_I*(
													ELD(V_x_y,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_y(i,j,k);
					Diff= j>0 && j < N2-2 ? CA*( EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k)) -
					                        CB*( EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k))
					                        :j < N2-1 ? EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k):0;

					ELD(V_y_y,index) =InvDXDThp_J*(
												ELD(V_y_y,index)*DXDThp_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= k>1  && k <N3-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1) )-
					                        CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2) )
					                        :k>0  && k <N3 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1):0;

					ELD(V_z_y,index) =InvDXDT_K*(
												ELD(V_z_y,index)*DXDT_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_y(i,j,k);
					index2=Ind_V_y_y(i,j,k);
					ELD(Vy,index)=ELD(V_x_y,index2)+ELD(V_y_y,index2)+ELD(V_z_y,index2);

		

					index=Ind_V_x_z(i,j,k);

					Diff= i> 1 && i <N1-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k)) -
					                        CB*( EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k))
					                        :i> 0 && i <N1 ? EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k):0;

					ELD(V_x_z,index) =InvDXDT_I*(
													ELD(V_x_z,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k)) -
					                      CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k)):
		                                  j>0 && j<N2 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k):0;

					ELD(V_y_z,index) =InvDXDT_J*(
												ELD(V_y_z,index)*DXDT_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_z_z(i,j,k);

					Diff= k>0 && k< N3-2 ? CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) )-
					                       CB*(EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1) ):
		                                   k< N3-1 ? EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) :0;

					ELD(V_z_z,index) =InvDXDThp_K*(
												ELD(V_z_z,index)*DXDThp_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_z(i,j,k);
					index2=Ind_V_z_z(i,j,k);
					ELD(Vz,index)=ELD(V_x_z,index2)+ELD(V_y_z,index2)+ELD(V_z_z,index2);
		
				 }
			#endif
			}
		else
			{

	#if defined(_PR_MAIN) 
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i+1,j,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dx=CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
						CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k));

				Dx+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
						CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k));

				Dx+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
						CB*(EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2));

				EL(Vx,i,j,k)+=DT*AvgInvRhoI*Dx;
				accum_x+=EL(Vx,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoJ=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j+1,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dy=CA*(EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k) )-
						CB*(EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k));

				Dy+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k))-
						CB*(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k));

				Dy+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1))-
					CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2));
				
				EL(Vy,i,j,k)+=DT*AvgInvRhoJ*Dy;
				accum_y+=EL(Vy,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoK=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j,k+1))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				Dz=CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k))-
						CB*( EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1));

				Dz+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k))-
					CB*(EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k));

				Dz+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k))-
					CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k));

				EL(Vz,i,j,k)+=DT*AvgInvRhoK*Dz;
				accum_z+=EL(Vz,i,j,k);
			
				if ((nStep < LengthSource) && TypeSource<2) //Source is particle displacement
				{
					index=IndN1N2N3(i,j,k,0);
					source=ELD(SourceMap,index);
					if (source>0)
					{
						source--; //need to use C index
						value=ELD(SourceFunctions,nStep*NumberSources+source);
						if (TypeSource==0)
						{
							EL(Vx,i,j,k)+=value*ELD(Ox,index);
							EL(Vy,i,j,k)+=value*ELD(Oy,index);
							EL(Vz,i,j,k)+=value*ELD(Oz,index);
							
						}
						else
						{
							EL(Vx,i,j,k)=value*ELD(Ox,index);
							EL(Vy,i,j,k)=value*ELD(Oy,index);
							EL(Vz,i,j,k)=value*ELD(Oz,index);
							
						}
  					}		
				}
		#endif
			}
		}
	#if defined(_PR_MAIN) 
	if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
	{
		if (ZoneCount>1)
		{
			accum_x/=ZoneCount;
			accum_y/=ZoneCount;
			accum_z/=ZoneCount;
		}
		CurZone=0;
		index=IndN1N2N3(i,j,k,0);
		index2=N1*N2*N3;
		if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)+=accum_x*accum_x;
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)+=accum_y*accum_y;
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)+=accum_z*accum_z;
			
		}
		if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
				index+=index2*NumberSelRMSPeakMaps;
		if (SelRMSorPeak & SEL_PEAK)
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)=accum_x > ELD(SqrAcc,index+index2*IndexRMSPeak_Vx) ? accum_x : ELD(SqrAcc,index+index2*IndexRMSPeak_Vx);
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)=accum_y > ELD(SqrAcc,index+index2*IndexRMSPeak_Vy) ? accum_y : ELD(SqrAcc,index+index2*IndexRMSPeak_Vy);
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)=accum_z > ELD(SqrAcc,index+index2*IndexRMSPeak_Vz) ? accum_z : ELD(SqrAcc,index+index2*IndexRMSPeak_Vz);
			
		}

	}
	#endif

		
		
#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_I_BOTTOM
#endif
#undef _PR_PML
//MLX_BLOCK_PML_1_PARTICLE_END
//MLX_BLOCK_PML_2_PARTICLE_START
#define _PR_PML
#if ((defined(MLX)) && defined(MLX_PML_2_PARTICLE)) || !defined(MLX)
#define _PML_KERNEL_I_TOP
#ifdef CUDA
extern "C" __global__ void PML_2_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_2_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_2_ParticleKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else	
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (PML_Thickness)
	#define nN2 (N2)
	#define nN3 (N3)
    _PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (PML_Thickness)
	#define nN2 (N2)
	#define nN3 (N3)
    _PT k = (_PT) ( thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) (( thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) ( thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
#if defined(_PR_MAIN)
	_PT source;
	mexType value;
#endif

	mexType AvgInvRhoI;

#if defined(_PR_PML)
	mexType Diff;
#endif
#if defined(_PR_MAIN) 
	mexType accum_x=0.0;
	mexType Dx;
	mexType accum_y=0.0;
	mexType AvgInvRhoJ;
	mexType Dy;
	mexType accum_z=0.0;
	mexType AvgInvRhoK;
	mexType Dz;
#endif
_PT index;
_PT index2;
_PT  CurZone;
	for (   CurZone=0;CurZone<ZoneCount;CurZone++)
		{
		  if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 || IsOnPML_K(k)==1)
			{
			#if defined(_PR_PML)	
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=ELD(InvRhoMatH,ELD(MaterialMap,index));
				//In the PML
				// For coeffs. for V_x
				if (i<N1-1 && j <N2-1 && k<N3-1)
				{
    				index=Ind_V_x_x(i,j,k);


		            Diff= i>0 && i<N1-2 ? CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
		                                  CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k))
					                      :i<N1-1 ? EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k):0;

					ELD(V_x_x,index) =InvDXDThp_I*(ELD(V_x_x,index)*DXDThp_I+
													AvgInvRhoI*
													Diff);

					index=Ind_V_y_x(i,j,k);
					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
					                      CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k))
					                      :j>0 && j<N2 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k):0;

					ELD(V_y_x,index) =InvDXDT_J*(
													ELD(V_y_x,index)*DXDT_J+
													AvgInvRhoI*
													Diff);
					index=Ind_V_z_x(i,j,k);
					Diff= k >1 && k < N3-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
					                         CB*( EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2)) :
		                                     k >0 && k < N3 ?  EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1):0;

					ELD(V_z_x,index) =InvDXDT_K*(
													ELD(V_z_x,index)*DXDT_K+
													AvgInvRhoI*
													Diff);

					
					index=Ind_V_x(i,j,k);
					index2=Ind_V_x_x(i,j,k);
					ELD(Vx,index)=ELD(V_x_x,index2)+ELD(V_y_x,index2)+ELD(V_z_x,index2);
				

				// For coeffs. for V_y

					index=Ind_V_x_y(i,j,k);

					Diff= i>1 && i<N1-1 ? CA *(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k)) -
					                      CB *(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k))
					                      :i>0 && i<N1 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k):0;

					ELD(V_x_y,index) =InvDXDT_I*(
													ELD(V_x_y,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_y(i,j,k);
					Diff= j>0 && j < N2-2 ? CA*( EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k)) -
					                        CB*( EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k))
					                        :j < N2-1 ? EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k):0;

					ELD(V_y_y,index) =InvDXDThp_J*(
												ELD(V_y_y,index)*DXDThp_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= k>1  && k <N3-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1) )-
					                        CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2) )
					                        :k>0  && k <N3 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1):0;

					ELD(V_z_y,index) =InvDXDT_K*(
												ELD(V_z_y,index)*DXDT_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_y(i,j,k);
					index2=Ind_V_y_y(i,j,k);
					ELD(Vy,index)=ELD(V_x_y,index2)+ELD(V_y_y,index2)+ELD(V_z_y,index2);

		

					index=Ind_V_x_z(i,j,k);

					Diff= i> 1 && i <N1-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k)) -
					                        CB*( EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k))
					                        :i> 0 && i <N1 ? EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k):0;

					ELD(V_x_z,index) =InvDXDT_I*(
													ELD(V_x_z,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k)) -
					                      CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k)):
		                                  j>0 && j<N2 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k):0;

					ELD(V_y_z,index) =InvDXDT_J*(
												ELD(V_y_z,index)*DXDT_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_z_z(i,j,k);

					Diff= k>0 && k< N3-2 ? CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) )-
					                       CB*(EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1) ):
		                                   k< N3-1 ? EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) :0;

					ELD(V_z_z,index) =InvDXDThp_K*(
												ELD(V_z_z,index)*DXDThp_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_z(i,j,k);
					index2=Ind_V_z_z(i,j,k);
					ELD(Vz,index)=ELD(V_x_z,index2)+ELD(V_y_z,index2)+ELD(V_z_z,index2);
		
				 }
			#endif
			}
		else
			{

	#if defined(_PR_MAIN) 
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i+1,j,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dx=CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
						CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k));

				Dx+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
						CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k));

				Dx+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
						CB*(EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2));

				EL(Vx,i,j,k)+=DT*AvgInvRhoI*Dx;
				accum_x+=EL(Vx,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoJ=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j+1,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dy=CA*(EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k) )-
						CB*(EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k));

				Dy+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k))-
						CB*(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k));

				Dy+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1))-
					CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2));
				
				EL(Vy,i,j,k)+=DT*AvgInvRhoJ*Dy;
				accum_y+=EL(Vy,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoK=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j,k+1))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				Dz=CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k))-
						CB*( EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1));

				Dz+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k))-
					CB*(EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k));

				Dz+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k))-
					CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k));

				EL(Vz,i,j,k)+=DT*AvgInvRhoK*Dz;
				accum_z+=EL(Vz,i,j,k);
			
				if ((nStep < LengthSource) && TypeSource<2) //Source is particle displacement
				{
					index=IndN1N2N3(i,j,k,0);
					source=ELD(SourceMap,index);
					if (source>0)
					{
						source--; //need to use C index
						value=ELD(SourceFunctions,nStep*NumberSources+source);
						if (TypeSource==0)
						{
							EL(Vx,i,j,k)+=value*ELD(Ox,index);
							EL(Vy,i,j,k)+=value*ELD(Oy,index);
							EL(Vz,i,j,k)+=value*ELD(Oz,index);
							
						}
						else
						{
							EL(Vx,i,j,k)=value*ELD(Ox,index);
							EL(Vy,i,j,k)=value*ELD(Oy,index);
							EL(Vz,i,j,k)=value*ELD(Oz,index);
							
						}
  					}		
				}
		#endif
			}
		}
	#if defined(_PR_MAIN) 
	if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
	{
		if (ZoneCount>1)
		{
			accum_x/=ZoneCount;
			accum_y/=ZoneCount;
			accum_z/=ZoneCount;
		}
		CurZone=0;
		index=IndN1N2N3(i,j,k,0);
		index2=N1*N2*N3;
		if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)+=accum_x*accum_x;
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)+=accum_y*accum_y;
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)+=accum_z*accum_z;
			
		}
		if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
				index+=index2*NumberSelRMSPeakMaps;
		if (SelRMSorPeak & SEL_PEAK)
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)=accum_x > ELD(SqrAcc,index+index2*IndexRMSPeak_Vx) ? accum_x : ELD(SqrAcc,index+index2*IndexRMSPeak_Vx);
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)=accum_y > ELD(SqrAcc,index+index2*IndexRMSPeak_Vy) ? accum_y : ELD(SqrAcc,index+index2*IndexRMSPeak_Vy);
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)=accum_z > ELD(SqrAcc,index+index2*IndexRMSPeak_Vz) ? accum_z : ELD(SqrAcc,index+index2*IndexRMSPeak_Vz);
			
		}

	}
	#endif

		
		
#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_I_TOP
#endif
#undef _PR_PML
//MLX_BLOCK_PML_2_PARTICLE_END
//MLX_BLOCK_PML_3_PARTICLE_START
#define _PR_PML
#if ((defined(MLX)) && defined(MLX_PML_3_PARTICLE)) || !defined(MLX)
#define _PML_KERNEL_J_BOTTOM
#ifdef CUDA
extern "C" __global__ void PML_3_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_3_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_3_ParticleKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else	
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (PML_Thickness)
	#define nN3 (N3)
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (PML_Thickness)
	#define nN3 (N3)
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
#if defined(_PR_MAIN)
	_PT source;
	mexType value;
#endif

	mexType AvgInvRhoI;

#if defined(_PR_PML)
	mexType Diff;
#endif
#if defined(_PR_MAIN) 
	mexType accum_x=0.0;
	mexType Dx;
	mexType accum_y=0.0;
	mexType AvgInvRhoJ;
	mexType Dy;
	mexType accum_z=0.0;
	mexType AvgInvRhoK;
	mexType Dz;
#endif
_PT index;
_PT index2;
_PT  CurZone;
	for (   CurZone=0;CurZone<ZoneCount;CurZone++)
		{
		  if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 || IsOnPML_K(k)==1)
			{
			#if defined(_PR_PML)	
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=ELD(InvRhoMatH,ELD(MaterialMap,index));
				//In the PML
				// For coeffs. for V_x
				if (i<N1-1 && j <N2-1 && k<N3-1)
				{
    				index=Ind_V_x_x(i,j,k);


		            Diff= i>0 && i<N1-2 ? CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
		                                  CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k))
					                      :i<N1-1 ? EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k):0;

					ELD(V_x_x,index) =InvDXDThp_I*(ELD(V_x_x,index)*DXDThp_I+
													AvgInvRhoI*
													Diff);

					index=Ind_V_y_x(i,j,k);
					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
					                      CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k))
					                      :j>0 && j<N2 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k):0;

					ELD(V_y_x,index) =InvDXDT_J*(
													ELD(V_y_x,index)*DXDT_J+
													AvgInvRhoI*
													Diff);
					index=Ind_V_z_x(i,j,k);
					Diff= k >1 && k < N3-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
					                         CB*( EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2)) :
		                                     k >0 && k < N3 ?  EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1):0;

					ELD(V_z_x,index) =InvDXDT_K*(
													ELD(V_z_x,index)*DXDT_K+
													AvgInvRhoI*
													Diff);

					
					index=Ind_V_x(i,j,k);
					index2=Ind_V_x_x(i,j,k);
					ELD(Vx,index)=ELD(V_x_x,index2)+ELD(V_y_x,index2)+ELD(V_z_x,index2);
				

				// For coeffs. for V_y

					index=Ind_V_x_y(i,j,k);

					Diff= i>1 && i<N1-1 ? CA *(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k)) -
					                      CB *(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k))
					                      :i>0 && i<N1 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k):0;

					ELD(V_x_y,index) =InvDXDT_I*(
													ELD(V_x_y,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_y(i,j,k);
					Diff= j>0 && j < N2-2 ? CA*( EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k)) -
					                        CB*( EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k))
					                        :j < N2-1 ? EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k):0;

					ELD(V_y_y,index) =InvDXDThp_J*(
												ELD(V_y_y,index)*DXDThp_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= k>1  && k <N3-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1) )-
					                        CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2) )
					                        :k>0  && k <N3 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1):0;

					ELD(V_z_y,index) =InvDXDT_K*(
												ELD(V_z_y,index)*DXDT_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_y(i,j,k);
					index2=Ind_V_y_y(i,j,k);
					ELD(Vy,index)=ELD(V_x_y,index2)+ELD(V_y_y,index2)+ELD(V_z_y,index2);

		

					index=Ind_V_x_z(i,j,k);

					Diff= i> 1 && i <N1-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k)) -
					                        CB*( EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k))
					                        :i> 0 && i <N1 ? EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k):0;

					ELD(V_x_z,index) =InvDXDT_I*(
													ELD(V_x_z,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k)) -
					                      CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k)):
		                                  j>0 && j<N2 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k):0;

					ELD(V_y_z,index) =InvDXDT_J*(
												ELD(V_y_z,index)*DXDT_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_z_z(i,j,k);

					Diff= k>0 && k< N3-2 ? CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) )-
					                       CB*(EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1) ):
		                                   k< N3-1 ? EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) :0;

					ELD(V_z_z,index) =InvDXDThp_K*(
												ELD(V_z_z,index)*DXDThp_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_z(i,j,k);
					index2=Ind_V_z_z(i,j,k);
					ELD(Vz,index)=ELD(V_x_z,index2)+ELD(V_y_z,index2)+ELD(V_z_z,index2);
		
				 }
			#endif
			}
		else
			{

	#if defined(_PR_MAIN) 
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i+1,j,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dx=CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
						CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k));

				Dx+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
						CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k));

				Dx+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
						CB*(EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2));

				EL(Vx,i,j,k)+=DT*AvgInvRhoI*Dx;
				accum_x+=EL(Vx,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoJ=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j+1,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dy=CA*(EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k) )-
						CB*(EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k));

				Dy+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k))-
						CB*(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k));

				Dy+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1))-
					CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2));
				
				EL(Vy,i,j,k)+=DT*AvgInvRhoJ*Dy;
				accum_y+=EL(Vy,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoK=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j,k+1))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				Dz=CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k))-
						CB*( EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1));

				Dz+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k))-
					CB*(EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k));

				Dz+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k))-
					CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k));

				EL(Vz,i,j,k)+=DT*AvgInvRhoK*Dz;
				accum_z+=EL(Vz,i,j,k);
			
				if ((nStep < LengthSource) && TypeSource<2) //Source is particle displacement
				{
					index=IndN1N2N3(i,j,k,0);
					source=ELD(SourceMap,index);
					if (source>0)
					{
						source--; //need to use C index
						value=ELD(SourceFunctions,nStep*NumberSources+source);
						if (TypeSource==0)
						{
							EL(Vx,i,j,k)+=value*ELD(Ox,index);
							EL(Vy,i,j,k)+=value*ELD(Oy,index);
							EL(Vz,i,j,k)+=value*ELD(Oz,index);
							
						}
						else
						{
							EL(Vx,i,j,k)=value*ELD(Ox,index);
							EL(Vy,i,j,k)=value*ELD(Oy,index);
							EL(Vz,i,j,k)=value*ELD(Oz,index);
							
						}
  					}		
				}
		#endif
			}
		}
	#if defined(_PR_MAIN) 
	if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
	{
		if (ZoneCount>1)
		{
			accum_x/=ZoneCount;
			accum_y/=ZoneCount;
			accum_z/=ZoneCount;
		}
		CurZone=0;
		index=IndN1N2N3(i,j,k,0);
		index2=N1*N2*N3;
		if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)+=accum_x*accum_x;
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)+=accum_y*accum_y;
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)+=accum_z*accum_z;
			
		}
		if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
				index+=index2*NumberSelRMSPeakMaps;
		if (SelRMSorPeak & SEL_PEAK)
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)=accum_x > ELD(SqrAcc,index+index2*IndexRMSPeak_Vx) ? accum_x : ELD(SqrAcc,index+index2*IndexRMSPeak_Vx);
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)=accum_y > ELD(SqrAcc,index+index2*IndexRMSPeak_Vy) ? accum_y : ELD(SqrAcc,index+index2*IndexRMSPeak_Vy);
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)=accum_z > ELD(SqrAcc,index+index2*IndexRMSPeak_Vz) ? accum_z : ELD(SqrAcc,index+index2*IndexRMSPeak_Vz);
			
		}

	}
	#endif

		
		
#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_J_BOTTOM
#endif
#undef _PR_PML
//MLX_BLOCK_PML_3_PARTICLE_END
//MLX_BLOCK_PML_4_PARTICLE_START
#define _PR_PML
#if ((defined(MLX)) && defined(MLX_PML_4_PARTICLE)) || !defined(MLX)
#define _PML_KERNEL_J_TOP
#ifdef CUDA
extern "C" __global__ void PML_4_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_4_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_4_ParticleKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else	
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (PML_Thickness)
	#define nN3 (N3)
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (PML_Thickness)
	#define nN3 (N3)
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
#if defined(_PR_MAIN)
	_PT source;
	mexType value;
#endif

	mexType AvgInvRhoI;

#if defined(_PR_PML)
	mexType Diff;
#endif
#if defined(_PR_MAIN) 
	mexType accum_x=0.0;
	mexType Dx;
	mexType accum_y=0.0;
	mexType AvgInvRhoJ;
	mexType Dy;
	mexType accum_z=0.0;
	mexType AvgInvRhoK;
	mexType Dz;
#endif
_PT index;
_PT index2;
_PT  CurZone;
	for (   CurZone=0;CurZone<ZoneCount;CurZone++)
		{
		  if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 || IsOnPML_K(k)==1)
			{
			#if defined(_PR_PML)	
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=ELD(InvRhoMatH,ELD(MaterialMap,index));
				//In the PML
				// For coeffs. for V_x
				if (i<N1-1 && j <N2-1 && k<N3-1)
				{
    				index=Ind_V_x_x(i,j,k);


		            Diff= i>0 && i<N1-2 ? CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
		                                  CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k))
					                      :i<N1-1 ? EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k):0;

					ELD(V_x_x,index) =InvDXDThp_I*(ELD(V_x_x,index)*DXDThp_I+
													AvgInvRhoI*
													Diff);

					index=Ind_V_y_x(i,j,k);
					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
					                      CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k))
					                      :j>0 && j<N2 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k):0;

					ELD(V_y_x,index) =InvDXDT_J*(
													ELD(V_y_x,index)*DXDT_J+
													AvgInvRhoI*
													Diff);
					index=Ind_V_z_x(i,j,k);
					Diff= k >1 && k < N3-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
					                         CB*( EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2)) :
		                                     k >0 && k < N3 ?  EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1):0;

					ELD(V_z_x,index) =InvDXDT_K*(
													ELD(V_z_x,index)*DXDT_K+
													AvgInvRhoI*
													Diff);

					
					index=Ind_V_x(i,j,k);
					index2=Ind_V_x_x(i,j,k);
					ELD(Vx,index)=ELD(V_x_x,index2)+ELD(V_y_x,index2)+ELD(V_z_x,index2);
				

				// For coeffs. for V_y

					index=Ind_V_x_y(i,j,k);

					Diff= i>1 && i<N1-1 ? CA *(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k)) -
					                      CB *(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k))
					                      :i>0 && i<N1 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k):0;

					ELD(V_x_y,index) =InvDXDT_I*(
													ELD(V_x_y,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_y(i,j,k);
					Diff= j>0 && j < N2-2 ? CA*( EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k)) -
					                        CB*( EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k))
					                        :j < N2-1 ? EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k):0;

					ELD(V_y_y,index) =InvDXDThp_J*(
												ELD(V_y_y,index)*DXDThp_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= k>1  && k <N3-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1) )-
					                        CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2) )
					                        :k>0  && k <N3 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1):0;

					ELD(V_z_y,index) =InvDXDT_K*(
												ELD(V_z_y,index)*DXDT_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_y(i,j,k);
					index2=Ind_V_y_y(i,j,k);
					ELD(Vy,index)=ELD(V_x_y,index2)+ELD(V_y_y,index2)+ELD(V_z_y,index2);

		

					index=Ind_V_x_z(i,j,k);

					Diff= i> 1 && i <N1-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k)) -
					                        CB*( EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k))
					                        :i> 0 && i <N1 ? EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k):0;

					ELD(V_x_z,index) =InvDXDT_I*(
													ELD(V_x_z,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k)) -
					                      CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k)):
		                                  j>0 && j<N2 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k):0;

					ELD(V_y_z,index) =InvDXDT_J*(
												ELD(V_y_z,index)*DXDT_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_z_z(i,j,k);

					Diff= k>0 && k< N3-2 ? CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) )-
					                       CB*(EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1) ):
		                                   k< N3-1 ? EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) :0;

					ELD(V_z_z,index) =InvDXDThp_K*(
												ELD(V_z_z,index)*DXDThp_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_z(i,j,k);
					index2=Ind_V_z_z(i,j,k);
					ELD(Vz,index)=ELD(V_x_z,index2)+ELD(V_y_z,index2)+ELD(V_z_z,index2);
		
				 }
			#endif
			}
		else
			{

	#if defined(_PR_MAIN) 
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i+1,j,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dx=CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
						CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k));

				Dx+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
						CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k));

				Dx+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
						CB*(EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2));

				EL(Vx,i,j,k)+=DT*AvgInvRhoI*Dx;
				accum_x+=EL(Vx,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoJ=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j+1,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dy=CA*(EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k) )-
						CB*(EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k));

				Dy+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k))-
						CB*(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k));

				Dy+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1))-
					CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2));
				
				EL(Vy,i,j,k)+=DT*AvgInvRhoJ*Dy;
				accum_y+=EL(Vy,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoK=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j,k+1))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				Dz=CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k))-
						CB*( EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1));

				Dz+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k))-
					CB*(EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k));

				Dz+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k))-
					CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k));

				EL(Vz,i,j,k)+=DT*AvgInvRhoK*Dz;
				accum_z+=EL(Vz,i,j,k);
			
				if ((nStep < LengthSource) && TypeSource<2) //Source is particle displacement
				{
					index=IndN1N2N3(i,j,k,0);
					source=ELD(SourceMap,index);
					if (source>0)
					{
						source--; //need to use C index
						value=ELD(SourceFunctions,nStep*NumberSources+source);
						if (TypeSource==0)
						{
							EL(Vx,i,j,k)+=value*ELD(Ox,index);
							EL(Vy,i,j,k)+=value*ELD(Oy,index);
							EL(Vz,i,j,k)+=value*ELD(Oz,index);
							
						}
						else
						{
							EL(Vx,i,j,k)=value*ELD(Ox,index);
							EL(Vy,i,j,k)=value*ELD(Oy,index);
							EL(Vz,i,j,k)=value*ELD(Oz,index);
							
						}
  					}		
				}
		#endif
			}
		}
	#if defined(_PR_MAIN) 
	if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
	{
		if (ZoneCount>1)
		{
			accum_x/=ZoneCount;
			accum_y/=ZoneCount;
			accum_z/=ZoneCount;
		}
		CurZone=0;
		index=IndN1N2N3(i,j,k,0);
		index2=N1*N2*N3;
		if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)+=accum_x*accum_x;
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)+=accum_y*accum_y;
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)+=accum_z*accum_z;
			
		}
		if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
				index+=index2*NumberSelRMSPeakMaps;
		if (SelRMSorPeak & SEL_PEAK)
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)=accum_x > ELD(SqrAcc,index+index2*IndexRMSPeak_Vx) ? accum_x : ELD(SqrAcc,index+index2*IndexRMSPeak_Vx);
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)=accum_y > ELD(SqrAcc,index+index2*IndexRMSPeak_Vy) ? accum_y : ELD(SqrAcc,index+index2*IndexRMSPeak_Vy);
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)=accum_z > ELD(SqrAcc,index+index2*IndexRMSPeak_Vz) ? accum_z : ELD(SqrAcc,index+index2*IndexRMSPeak_Vz);
			
		}

	}
	#endif

		
		
#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_J_TOP
#endif
#undef _PR_PML
//MLX_BLOCK_PML_4_PARTICLE_END
//MLX_BLOCK_PML_5_PARTICLE_START
#define _PR_PML
#if ((defined(MLX)) && defined(MLX_PML_5_PARTICLE)) || !defined(MLX)
#define _PML_KERNEL_K_BOTTOM
#ifdef CUDA
extern "C" __global__ void PML_5_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_5_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_5_ParticleKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else	
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (PML_Thickness)
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (PML_Thickness)
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
#if defined(_PR_MAIN)
	_PT source;
	mexType value;
#endif

	mexType AvgInvRhoI;

#if defined(_PR_PML)
	mexType Diff;
#endif
#if defined(_PR_MAIN) 
	mexType accum_x=0.0;
	mexType Dx;
	mexType accum_y=0.0;
	mexType AvgInvRhoJ;
	mexType Dy;
	mexType accum_z=0.0;
	mexType AvgInvRhoK;
	mexType Dz;
#endif
_PT index;
_PT index2;
_PT  CurZone;
	for (   CurZone=0;CurZone<ZoneCount;CurZone++)
		{
		  if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 || IsOnPML_K(k)==1)
			{
			#if defined(_PR_PML)	
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=ELD(InvRhoMatH,ELD(MaterialMap,index));
				//In the PML
				// For coeffs. for V_x
				if (i<N1-1 && j <N2-1 && k<N3-1)
				{
    				index=Ind_V_x_x(i,j,k);


		            Diff= i>0 && i<N1-2 ? CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
		                                  CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k))
					                      :i<N1-1 ? EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k):0;

					ELD(V_x_x,index) =InvDXDThp_I*(ELD(V_x_x,index)*DXDThp_I+
													AvgInvRhoI*
													Diff);

					index=Ind_V_y_x(i,j,k);
					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
					                      CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k))
					                      :j>0 && j<N2 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k):0;

					ELD(V_y_x,index) =InvDXDT_J*(
													ELD(V_y_x,index)*DXDT_J+
													AvgInvRhoI*
													Diff);
					index=Ind_V_z_x(i,j,k);
					Diff= k >1 && k < N3-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
					                         CB*( EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2)) :
		                                     k >0 && k < N3 ?  EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1):0;

					ELD(V_z_x,index) =InvDXDT_K*(
													ELD(V_z_x,index)*DXDT_K+
													AvgInvRhoI*
													Diff);

					
					index=Ind_V_x(i,j,k);
					index2=Ind_V_x_x(i,j,k);
					ELD(Vx,index)=ELD(V_x_x,index2)+ELD(V_y_x,index2)+ELD(V_z_x,index2);
				

				// For coeffs. for V_y

					index=Ind_V_x_y(i,j,k);

					Diff= i>1 && i<N1-1 ? CA *(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k)) -
					                      CB *(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k))
					                      :i>0 && i<N1 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k):0;

					ELD(V_x_y,index) =InvDXDT_I*(
													ELD(V_x_y,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_y(i,j,k);
					Diff= j>0 && j < N2-2 ? CA*( EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k)) -
					                        CB*( EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k))
					                        :j < N2-1 ? EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k):0;

					ELD(V_y_y,index) =InvDXDThp_J*(
												ELD(V_y_y,index)*DXDThp_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= k>1  && k <N3-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1) )-
					                        CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2) )
					                        :k>0  && k <N3 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1):0;

					ELD(V_z_y,index) =InvDXDT_K*(
												ELD(V_z_y,index)*DXDT_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_y(i,j,k);
					index2=Ind_V_y_y(i,j,k);
					ELD(Vy,index)=ELD(V_x_y,index2)+ELD(V_y_y,index2)+ELD(V_z_y,index2);

		

					index=Ind_V_x_z(i,j,k);

					Diff= i> 1 && i <N1-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k)) -
					                        CB*( EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k))
					                        :i> 0 && i <N1 ? EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k):0;

					ELD(V_x_z,index) =InvDXDT_I*(
													ELD(V_x_z,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k)) -
					                      CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k)):
		                                  j>0 && j<N2 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k):0;

					ELD(V_y_z,index) =InvDXDT_J*(
												ELD(V_y_z,index)*DXDT_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_z_z(i,j,k);

					Diff= k>0 && k< N3-2 ? CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) )-
					                       CB*(EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1) ):
		                                   k< N3-1 ? EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) :0;

					ELD(V_z_z,index) =InvDXDThp_K*(
												ELD(V_z_z,index)*DXDThp_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_z(i,j,k);
					index2=Ind_V_z_z(i,j,k);
					ELD(Vz,index)=ELD(V_x_z,index2)+ELD(V_y_z,index2)+ELD(V_z_z,index2);
		
				 }
			#endif
			}
		else
			{

	#if defined(_PR_MAIN) 
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i+1,j,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dx=CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
						CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k));

				Dx+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
						CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k));

				Dx+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
						CB*(EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2));

				EL(Vx,i,j,k)+=DT*AvgInvRhoI*Dx;
				accum_x+=EL(Vx,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoJ=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j+1,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dy=CA*(EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k) )-
						CB*(EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k));

				Dy+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k))-
						CB*(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k));

				Dy+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1))-
					CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2));
				
				EL(Vy,i,j,k)+=DT*AvgInvRhoJ*Dy;
				accum_y+=EL(Vy,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoK=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j,k+1))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				Dz=CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k))-
						CB*( EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1));

				Dz+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k))-
					CB*(EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k));

				Dz+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k))-
					CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k));

				EL(Vz,i,j,k)+=DT*AvgInvRhoK*Dz;
				accum_z+=EL(Vz,i,j,k);
			
				if ((nStep < LengthSource) && TypeSource<2) //Source is particle displacement
				{
					index=IndN1N2N3(i,j,k,0);
					source=ELD(SourceMap,index);
					if (source>0)
					{
						source--; //need to use C index
						value=ELD(SourceFunctions,nStep*NumberSources+source);
						if (TypeSource==0)
						{
							EL(Vx,i,j,k)+=value*ELD(Ox,index);
							EL(Vy,i,j,k)+=value*ELD(Oy,index);
							EL(Vz,i,j,k)+=value*ELD(Oz,index);
							
						}
						else
						{
							EL(Vx,i,j,k)=value*ELD(Ox,index);
							EL(Vy,i,j,k)=value*ELD(Oy,index);
							EL(Vz,i,j,k)=value*ELD(Oz,index);
							
						}
  					}		
				}
		#endif
			}
		}
	#if defined(_PR_MAIN) 
	if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
	{
		if (ZoneCount>1)
		{
			accum_x/=ZoneCount;
			accum_y/=ZoneCount;
			accum_z/=ZoneCount;
		}
		CurZone=0;
		index=IndN1N2N3(i,j,k,0);
		index2=N1*N2*N3;
		if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)+=accum_x*accum_x;
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)+=accum_y*accum_y;
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)+=accum_z*accum_z;
			
		}
		if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
				index+=index2*NumberSelRMSPeakMaps;
		if (SelRMSorPeak & SEL_PEAK)
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)=accum_x > ELD(SqrAcc,index+index2*IndexRMSPeak_Vx) ? accum_x : ELD(SqrAcc,index+index2*IndexRMSPeak_Vx);
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)=accum_y > ELD(SqrAcc,index+index2*IndexRMSPeak_Vy) ? accum_y : ELD(SqrAcc,index+index2*IndexRMSPeak_Vy);
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)=accum_z > ELD(SqrAcc,index+index2*IndexRMSPeak_Vz) ? accum_z : ELD(SqrAcc,index+index2*IndexRMSPeak_Vz);
			
		}

	}
	#endif

		
		
#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_K_BOTTOM
#endif
#undef _PR_PML
//MLX_BLOCK_PML_5_PARTICLE_END
//MLX_BLOCK_PML_6_PARTICLE_START
#define _PR_PML
#if ((defined(MLX)) && defined(MLX_PML_6_PARTICLE)) || !defined(MLX)
#define _PML_KERNEL_K_TOP
#ifdef CUDA
extern "C" __global__ void PML_6_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,unsigned int nStep, unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void PML_6_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep, unsigned int TypeSource)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
  _PT k = (_PT) get_global_id(2);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) && !defined(MLX)
kernel void PML_6_ParticleKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else	
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (PML_Thickness)
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (PML_Thickness)
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
#if defined(_PR_MAIN)
	_PT source;
	mexType value;
#endif

	mexType AvgInvRhoI;

#if defined(_PR_PML)
	mexType Diff;
#endif
#if defined(_PR_MAIN) 
	mexType accum_x=0.0;
	mexType Dx;
	mexType accum_y=0.0;
	mexType AvgInvRhoJ;
	mexType Dy;
	mexType accum_z=0.0;
	mexType AvgInvRhoK;
	mexType Dz;
#endif
_PT index;
_PT index2;
_PT  CurZone;
	for (   CurZone=0;CurZone<ZoneCount;CurZone++)
		{
		  if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 || IsOnPML_K(k)==1)
			{
			#if defined(_PR_PML)	
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=ELD(InvRhoMatH,ELD(MaterialMap,index));
				//In the PML
				// For coeffs. for V_x
				if (i<N1-1 && j <N2-1 && k<N3-1)
				{
    				index=Ind_V_x_x(i,j,k);


		            Diff= i>0 && i<N1-2 ? CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
		                                  CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k))
					                      :i<N1-1 ? EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k):0;

					ELD(V_x_x,index) =InvDXDThp_I*(ELD(V_x_x,index)*DXDThp_I+
													AvgInvRhoI*
													Diff);

					index=Ind_V_y_x(i,j,k);
					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
					                      CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k))
					                      :j>0 && j<N2 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k):0;

					ELD(V_y_x,index) =InvDXDT_J*(
													ELD(V_y_x,index)*DXDT_J+
													AvgInvRhoI*
													Diff);
					index=Ind_V_z_x(i,j,k);
					Diff= k >1 && k < N3-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
					                         CB*( EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2)) :
		                                     k >0 && k < N3 ?  EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1):0;

					ELD(V_z_x,index) =InvDXDT_K*(
													ELD(V_z_x,index)*DXDT_K+
													AvgInvRhoI*
													Diff);

					
					index=Ind_V_x(i,j,k);
					index2=Ind_V_x_x(i,j,k);
					ELD(Vx,index)=ELD(V_x_x,index2)+ELD(V_y_x,index2)+ELD(V_z_x,index2);
				

				// For coeffs. for V_y

					index=Ind_V_x_y(i,j,k);

					Diff= i>1 && i<N1-1 ? CA *(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k)) -
					                      CB *(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k))
					                      :i>0 && i<N1 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k):0;

					ELD(V_x_y,index) =InvDXDT_I*(
													ELD(V_x_y,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_y(i,j,k);
					Diff= j>0 && j < N2-2 ? CA*( EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k)) -
					                        CB*( EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k))
					                        :j < N2-1 ? EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k):0;

					ELD(V_y_y,index) =InvDXDThp_J*(
												ELD(V_y_y,index)*DXDThp_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= k>1  && k <N3-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1) )-
					                        CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2) )
					                        :k>0  && k <N3 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1):0;

					ELD(V_z_y,index) =InvDXDT_K*(
												ELD(V_z_y,index)*DXDT_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_y(i,j,k);
					index2=Ind_V_y_y(i,j,k);
					ELD(Vy,index)=ELD(V_x_y,index2)+ELD(V_y_y,index2)+ELD(V_z_y,index2);

		

					index=Ind_V_x_z(i,j,k);

					Diff= i> 1 && i <N1-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k)) -
					                        CB*( EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k))
					                        :i> 0 && i <N1 ? EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k):0;

					ELD(V_x_z,index) =InvDXDT_I*(
													ELD(V_x_z,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k)) -
					                      CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k)):
		                                  j>0 && j<N2 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k):0;

					ELD(V_y_z,index) =InvDXDT_J*(
												ELD(V_y_z,index)*DXDT_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_z_z(i,j,k);

					Diff= k>0 && k< N3-2 ? CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) )-
					                       CB*(EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1) ):
		                                   k< N3-1 ? EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) :0;

					ELD(V_z_z,index) =InvDXDThp_K*(
												ELD(V_z_z,index)*DXDThp_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_z(i,j,k);
					index2=Ind_V_z_z(i,j,k);
					ELD(Vz,index)=ELD(V_x_z,index2)+ELD(V_y_z,index2)+ELD(V_z_z,index2);
		
				 }
			#endif
			}
		else
			{

	#if defined(_PR_MAIN) 
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i+1,j,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dx=CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
						CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k));

				Dx+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
						CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k));

				Dx+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
						CB*(EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2));

				EL(Vx,i,j,k)+=DT*AvgInvRhoI*Dx;
				accum_x+=EL(Vx,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoJ=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j+1,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dy=CA*(EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k) )-
						CB*(EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k));

				Dy+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k))-
						CB*(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k));

				Dy+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1))-
					CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2));
				
				EL(Vy,i,j,k)+=DT*AvgInvRhoJ*Dy;
				accum_y+=EL(Vy,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoK=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j,k+1))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				Dz=CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k))-
						CB*( EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1));

				Dz+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k))-
					CB*(EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k));

				Dz+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k))-
					CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k));

				EL(Vz,i,j,k)+=DT*AvgInvRhoK*Dz;
				accum_z+=EL(Vz,i,j,k);
			
				if ((nStep < LengthSource) && TypeSource<2) //Source is particle displacement
				{
					index=IndN1N2N3(i,j,k,0);
					source=ELD(SourceMap,index);
					if (source>0)
					{
						source--; //need to use C index
						value=ELD(SourceFunctions,nStep*NumberSources+source);
						if (TypeSource==0)
						{
							EL(Vx,i,j,k)+=value*ELD(Ox,index);
							EL(Vy,i,j,k)+=value*ELD(Oy,index);
							EL(Vz,i,j,k)+=value*ELD(Oz,index);
							
						}
						else
						{
							EL(Vx,i,j,k)=value*ELD(Ox,index);
							EL(Vy,i,j,k)=value*ELD(Oy,index);
							EL(Vz,i,j,k)=value*ELD(Oz,index);
							
						}
  					}		
				}
		#endif
			}
		}
	#if defined(_PR_MAIN) 
	if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
	{
		if (ZoneCount>1)
		{
			accum_x/=ZoneCount;
			accum_y/=ZoneCount;
			accum_z/=ZoneCount;
		}
		CurZone=0;
		index=IndN1N2N3(i,j,k,0);
		index2=N1*N2*N3;
		if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)+=accum_x*accum_x;
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)+=accum_y*accum_y;
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)+=accum_z*accum_z;
			
		}
		if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
				index+=index2*NumberSelRMSPeakMaps;
		if (SelRMSorPeak & SEL_PEAK)
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)=accum_x > ELD(SqrAcc,index+index2*IndexRMSPeak_Vx) ? accum_x : ELD(SqrAcc,index+index2*IndexRMSPeak_Vx);
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)=accum_y > ELD(SqrAcc,index+index2*IndexRMSPeak_Vy) ? accum_y : ELD(SqrAcc,index+index2*IndexRMSPeak_Vy);
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)=accum_z > ELD(SqrAcc,index+index2*IndexRMSPeak_Vz) ? accum_z : ELD(SqrAcc,index+index2*IndexRMSPeak_Vz);
			
		}

	}
	#endif

		
		
#if !defined(MLX)
}
#endif
#undef _PML_KERNEL_K_TOP
#endif
#undef _PR_PML
//MLX_BLOCK_PML_6_PARTICLE_END
#endif
//MLX_BLOCK_MAIN_1_PARTICLE_START
#if ((defined(MLX)) && defined(MLX_MAIN_1_PARTICLE)) || !defined(MLX)
#define _PR_MAIN
#define _MAIN_KERNEL
#if defined(OPENCL) || (defined(CUDA) && !defined(USE_MINI_KERNELS_CUDA)) || (defined(METAL) && defined(METAL_SINGLE_KERNEL))
#define _PR_PML
#endif
#if defined(CUDA)
extern "C" __global__ void MAIN_1_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
			,unsigned int nStep,unsigned int TypeSource)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
    _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
    _PT k = (_PT) (blockIdx.z * blockDim.z + threadIdx.z);
#endif
#ifdef OPENCL
__kernel void MAIN_1_ParticleKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	, unsigned int nStep,
	unsigned int TypeSource)
{
	_PT i = (_PT) get_global_id(0);
	_PT j = (_PT) get_global_id(1);
	_PT k = (_PT) get_global_id(2);
#endif
#if defined(METAL) && !defined(MLX)
kernel void MAIN_1_ParticleKernel(
	METAL_PARAMS
	#ifndef METALCOMPUTE
  	_PT i = (_PT) gid.x;
  	_PT j = (_PT) gid.y;
  	_PT k = (_PT) gid.z;
	#else
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#ifdef METAL_SINGLE_KERNEL
	#define nN1 (N1)
	#define nN2 (N2)
	#define nN3 (N3)
	#else
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (N3-PML_Thickness*2)
	#endif
	_PT k = (_PT) (gid/(nN1*nN2));
  	_PT j = (_PT) ((gid - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (gid - k*nN1*nN2-j*nN1);
	#endif
#endif
#if defined(MLX)
	#ifdef nN1
	#undef nN1
	#endif
	#ifdef nN2
	#undef nN2
	#endif
	#ifdef nN3
	#undef nN3
	#endif
	#ifdef METAL_SINGLE_KERNEL
	#define nN1 (N1)
	#define nN2 (N2)
	#define nN3 (N3)
	#else
	#define nN1 (N1-PML_Thickness*2)
	#define nN2 (N2-PML_Thickness*2)
	#define nN3 (N3-PML_Thickness*2)
	#endif
	_PT k = (_PT) (thread_position_in_grid.x/(nN1*nN2));
  	_PT j = (_PT) ((thread_position_in_grid.x - k*nN1*nN2)/nN1);
  	_PT i = (_PT) (thread_position_in_grid.x - k*nN1*nN2-j*nN1);
#endif
#if (defined(METAL) && !defined(METAL_SINGLE_KERNEL)) || defined(USE_MINI_KERNELS_CUDA)
#if defined(_PML_KERNEL_I_BOTTOM) 
//  i go from 0 to PML 
//  j go from  0 to  N2
//  k go from  0 to N3
// so no initial corrections on indices
#endif
#if defined(_PML_KERNEL_I_TOP)
i+=Limit_I_up_PML;
//  i go from  N1 - PML to N1
//  j go from  0 to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_J_BOTTOM)
i+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  0 to PML
//  k go from  0 to N3

#endif

#if defined(_PML_KERNEL_J_TOP)
i+=PML_Thickness;
j+=Limit_J_up_PML;
//  i go from  PML to N1 - PML
//  j go from  N2 - PML to N2
//  k go from  0 to N3
#endif

#if defined(_PML_KERNEL_K_BOTTOM)
i+=PML_Thickness;
j+=PML_Thickness;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  0 to PML

#endif

#if defined(_PML_KERNEL_K_TOP)
i+=PML_Thickness;
j+=PML_Thickness;
k+=Limit_K_up_PML;
//  i go from  PML to N1 - PML
//  j go from  PML to N2 - PML
//  k go from  N3 - PML to N3
#endif

#if defined(_MAIN_KERNEL) 
	i+=PML_Thickness;
	j+=PML_Thickness;
	k+=PML_Thickness;
#endif
#endif

#if defined(OPENCL) || defined(METAL) || defined(CUDA)
if (i>=N1 || j >=N2  || k>=N3)
	return;
#endif
#if defined(_PR_MAIN)
	_PT source;
	mexType value;
#endif

	mexType AvgInvRhoI;

#if defined(_PR_PML)
	mexType Diff;
#endif
#if defined(_PR_MAIN) 
	mexType accum_x=0.0;
	mexType Dx;
	mexType accum_y=0.0;
	mexType AvgInvRhoJ;
	mexType Dy;
	mexType accum_z=0.0;
	mexType AvgInvRhoK;
	mexType Dz;
#endif
_PT index;
_PT index2;
_PT  CurZone;
	for (   CurZone=0;CurZone<ZoneCount;CurZone++)
		{
		  if (IsOnPML_I(i)==1 || IsOnPML_J(j)==1 || IsOnPML_K(k)==1)
			{
			#if defined(_PR_PML)	
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=ELD(InvRhoMatH,ELD(MaterialMap,index));
				//In the PML
				// For coeffs. for V_x
				if (i<N1-1 && j <N2-1 && k<N3-1)
				{
    				index=Ind_V_x_x(i,j,k);


		            Diff= i>0 && i<N1-2 ? CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
		                                  CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k))
					                      :i<N1-1 ? EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k):0;

					ELD(V_x_x,index) =InvDXDThp_I*(ELD(V_x_x,index)*DXDThp_I+
													AvgInvRhoI*
													Diff);

					index=Ind_V_y_x(i,j,k);
					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
					                      CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k))
					                      :j>0 && j<N2 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k):0;

					ELD(V_y_x,index) =InvDXDT_J*(
													ELD(V_y_x,index)*DXDT_J+
													AvgInvRhoI*
													Diff);
					index=Ind_V_z_x(i,j,k);
					Diff= k >1 && k < N3-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
					                         CB*( EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2)) :
		                                     k >0 && k < N3 ?  EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1):0;

					ELD(V_z_x,index) =InvDXDT_K*(
													ELD(V_z_x,index)*DXDT_K+
													AvgInvRhoI*
													Diff);

					
					index=Ind_V_x(i,j,k);
					index2=Ind_V_x_x(i,j,k);
					ELD(Vx,index)=ELD(V_x_x,index2)+ELD(V_y_x,index2)+ELD(V_z_x,index2);
				

				// For coeffs. for V_y

					index=Ind_V_x_y(i,j,k);

					Diff= i>1 && i<N1-1 ? CA *(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k)) -
					                      CB *(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k))
					                      :i>0 && i<N1 ? EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k):0;

					ELD(V_x_y,index) =InvDXDT_I*(
													ELD(V_x_y,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_y(i,j,k);
					Diff= j>0 && j < N2-2 ? CA*( EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k)) -
					                        CB*( EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k))
					                        :j < N2-1 ? EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k):0;

					ELD(V_y_y,index) =InvDXDThp_J*(
												ELD(V_y_y,index)*DXDThp_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= k>1  && k <N3-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1) )-
					                        CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2) )
					                        :k>0  && k <N3 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1):0;

					ELD(V_z_y,index) =InvDXDT_K*(
												ELD(V_z_y,index)*DXDT_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_y(i,j,k);
					index2=Ind_V_y_y(i,j,k);
					ELD(Vy,index)=ELD(V_x_y,index2)+ELD(V_y_y,index2)+ELD(V_z_y,index2);

		

					index=Ind_V_x_z(i,j,k);

					Diff= i> 1 && i <N1-1 ? CA*( EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k)) -
					                        CB*( EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k))
					                        :i> 0 && i <N1 ? EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k):0;

					ELD(V_x_z,index) =InvDXDT_I*(
													ELD(V_x_z,index)*DXDT_I+
													AvgInvRhoI*
													Diff);
					index=Ind_V_y_z(i,j,k);

					Diff= j>1 && j<N2-1 ? CA*(EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k)) -
					                      CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k)):
		                                  j>0 && j<N2 ? EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k):0;

					ELD(V_y_z,index) =InvDXDT_J*(
												ELD(V_y_z,index)*DXDT_J+
												AvgInvRhoI*
												Diff);
					index=Ind_V_z_z(i,j,k);

					Diff= k>0 && k< N3-2 ? CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) )-
					                       CB*(EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1) ):
		                                   k< N3-1 ? EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k) :0;

					ELD(V_z_z,index) =InvDXDThp_K*(
												ELD(V_z_z,index)*DXDThp_K+
												AvgInvRhoI*
												Diff);

					index=Ind_V_z(i,j,k);
					index2=Ind_V_z_z(i,j,k);
					ELD(Vz,index)=ELD(V_x_z,index2)+ELD(V_y_z,index2)+ELD(V_z_z,index2);
		
				 }
			#endif
			}
		else
			{

	#if defined(_PR_MAIN) 
				index=Ind_MaterialMap(i,j,k);
				AvgInvRhoI=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i+1,j,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dx=CA*(EL(Sigma_xx,i+1,j,k)-EL(Sigma_xx,i,j,k))-
						CB*(EL(Sigma_xx,i+2,j,k)-EL(Sigma_xx,i-1,j,k));

				Dx+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i,j-1,k))-
						CB*(EL(Sigma_xy,i,j+1,k)-EL(Sigma_xy,i,j-2,k));

				Dx+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i,j,k-1))-
						CB*(EL(Sigma_xz,i,j,k+1)-EL(Sigma_xz,i,j,k-2));

				EL(Vx,i,j,k)+=DT*AvgInvRhoI*Dx;
				accum_x+=EL(Vx,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoJ=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j+1,k))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				
				Dy=CA*(EL(Sigma_yy,i,j+1,k)-EL(Sigma_yy,i,j,k) )-
						CB*(EL(Sigma_yy,i,j+2,k)-EL(Sigma_yy,i,j-1,k));

				Dy+=CA*(EL(Sigma_xy,i,j,k)-EL(Sigma_xy,i-1,j,k))-
						CB*(EL(Sigma_xy,i+1,j,k)-EL(Sigma_xy,i-2,j,k));

				Dy+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j,k-1))-
					CB*(EL(Sigma_yz,i,j,k+1)-EL(Sigma_yz,i,j,k-2));
				
				EL(Vy,i,j,k)+=DT*AvgInvRhoJ*Dy;
				accum_y+=EL(Vy,i,j,k);

				//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
				AvgInvRhoK=0.5*(ELD(InvRhoMatH,EL(MaterialMap,i,j,k+1))+ELD(InvRhoMatH,ELD(MaterialMap,index)));
				Dz=CA*(EL(Sigma_zz,i,j,k+1)-EL(Sigma_zz,i,j,k))-
						CB*( EL(Sigma_zz,i,j,k+2)-EL(Sigma_zz,i,j,k-1));

				Dz+=CA*(EL(Sigma_xz,i,j,k)-EL(Sigma_xz,i-1,j,k))-
					CB*(EL(Sigma_xz,i+1,j,k)-EL(Sigma_xz,i-2,j,k));

				Dz+=CA*( EL(Sigma_yz,i,j,k)-EL(Sigma_yz,i,j-1,k))-
					CB*(EL(Sigma_yz,i,j+1,k)-EL(Sigma_yz,i,j-2,k));

				EL(Vz,i,j,k)+=DT*AvgInvRhoK*Dz;
				accum_z+=EL(Vz,i,j,k);
			
				if ((nStep < LengthSource) && TypeSource<2) //Source is particle displacement
				{
					index=IndN1N2N3(i,j,k,0);
					source=ELD(SourceMap,index);
					if (source>0)
					{
						source--; //need to use C index
						value=ELD(SourceFunctions,nStep*NumberSources+source);
						if (TypeSource==0)
						{
							EL(Vx,i,j,k)+=value*ELD(Ox,index);
							EL(Vy,i,j,k)+=value*ELD(Oy,index);
							EL(Vz,i,j,k)+=value*ELD(Oz,index);
							
						}
						else
						{
							EL(Vx,i,j,k)=value*ELD(Ox,index);
							EL(Vy,i,j,k)=value*ELD(Oy,index);
							EL(Vz,i,j,k)=value*ELD(Oz,index);
							
						}
  					}		
				}
		#endif
			}
		}
	#if defined(_PR_MAIN) 
	if (IsOnPML_I(i)==0 && IsOnPML_J(j)==0 && IsOnPML_K(k)==0 && nStep>=SensorStart*SensorSubSampling)
	{
		if (ZoneCount>1)
		{
			accum_x/=ZoneCount;
			accum_y/=ZoneCount;
			accum_z/=ZoneCount;
		}
		CurZone=0;
		index=IndN1N2N3(i,j,k,0);
		index2=N1*N2*N3;
		if ((SelRMSorPeak & SEL_RMS) ) //RMS was selected, and it is always at the location 0 of dim 5
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)+=accum_x*accum_x;
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)+=accum_y*accum_y;
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
				ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)+=accum_z*accum_z;
			
		}
		if ((SelRMSorPeak & SEL_RMS) && (SelRMSorPeak & SEL_PEAK) ) //If both PEAK and RMS were selected we save in the far part of the array
				index+=index2*NumberSelRMSPeakMaps;
		if (SelRMSorPeak & SEL_PEAK)
		{
			if (IS_Vx_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vx)=accum_x > ELD(SqrAcc,index+index2*IndexRMSPeak_Vx) ? accum_x : ELD(SqrAcc,index+index2*IndexRMSPeak_Vx);
			if (IS_Vy_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vy)=accum_y > ELD(SqrAcc,index+index2*IndexRMSPeak_Vy) ? accum_y : ELD(SqrAcc,index+index2*IndexRMSPeak_Vy);
			if (IS_Vz_SELECTED(SelMapsRMSPeak))
					ELD(SqrAcc,index+index2*IndexRMSPeak_Vz)=accum_z > ELD(SqrAcc,index+index2*IndexRMSPeak_Vz) ? accum_z : ELD(SqrAcc,index+index2*IndexRMSPeak_Vz);
			
		}

	}
	#endif

		
		
#if !defined(MLX)
}
#endif
#if defined(OPENCL) || (defined(CUDA) && !defined(USE_MINI_KERNELS_CUDA)) || (defined(METAL) && defined(METAL_SINGLE_KERNEL))
#undef _PR_PML
#endif
#undef _PR_MAIN
#undef _MAIN_KERNEL
#endif
//MLX_BLOCK_MAIN_1_PARTICLE_END
//MLX_BLOCK_SNAPSHOT_START
#if ((defined(MLX)) && defined(MLX_SNAPSHOT)) || !defined(MLX)
#if defined(CUDA)
extern "C" __global__ void SnapShot(unsigned int SelK,mexType * Snapshots_pr,mexType * Sigma_xx_pr,mexType * Sigma_yy_pr,mexType * Sigma_zz_pr,unsigned int CurrSnap)
{
	_PT i = (_PT) (blockIdx.x * blockDim.x + threadIdx.x);
  _PT j = (_PT) (blockIdx.y * blockDim.y + threadIdx.y);
#endif
#ifdef OPENCL
__kernel void SnapShot(unsigned int SelK,__global mexType * Snapshots_pr,__global mexType * Sigma_xx_pr,__global mexType * Sigma_yy_pr,__global mexType * Sigma_zz_pr,unsigned int CurrSnap)
{
  _PT i = (_PT) get_global_id(0);
  _PT j = (_PT) get_global_id(1);
#endif
#if defined(METAL) && !defined(MLX)
#define Sigma_xx_pr k_Sigma_xx_pr
#define Sigma_yy_pr k_Sigma_yy_pr
#define Sigma_zz_pr k_Sigma_zz_pr

kernel void SnapShot(
	const device unsigned int *p_CONSTANT_BUFFER_UINT [[ buffer(0) ]],
	const device mexType * p_CONSTANT_BUFFER_MEX [[ buffer(1) ]],
	const device unsigned int *p_INDEX_MEX [[ buffer(2) ]],
	const device unsigned int *p_INDEX_UINT [[ buffer(3) ]],
	const device unsigned int *p_UINT_BUFFER [[ buffer(4) ]],
	device mexType * p_MEX_BUFFER_0 [[ buffer(5) ]],
	device mexType * p_MEX_BUFFER_1 [[ buffer(6) ]],
	device mexType * p_MEX_BUFFER_2 [[ buffer(7) ]],
	device mexType * p_MEX_BUFFER_3 [[ buffer(8) ]],
	device mexType * p_MEX_BUFFER_4 [[ buffer(9) ]],
	device mexType * p_MEX_BUFFER_5 [[ buffer(10) ]],
	device mexType * p_MEX_BUFFER_6 [[ buffer(11) ]],
	device mexType * p_MEX_BUFFER_7 [[ buffer(12) ]],
	device mexType * p_MEX_BUFFER_8 [[ buffer(13) ]],
	device mexType * p_MEX_BUFFER_9 [[ buffer(14) ]],
	device mexType * p_MEX_BUFFER_10 [[ buffer(15) ]],
	device mexType * p_MEX_BUFFER_11 [[ buffer(16) ]],
	device mexType * Snapshots_pr [[ buffer(17) ]],
	uint2 gid[[thread_position_in_grid]])

	{
	_PT i = (_PT) gid.x;
	_PT j = (_PT) gid.y;
#endif
#if defined(MLX)
#define Sigma_xx_pr k_Sigma_xx_pr
#define Sigma_yy_pr k_Sigma_yy_pr
#define Sigma_zz_pr k_Sigma_zz_pr
	_PT i = (_PT) thread_position_in_grid.x;
  	_PT j = (_PT) thread_position_in_grid.y;
#endif

    if (i>=N1 || j >=N2)
		return;
#if !defined(MLX)
}
#endif
#endif
//MLX_BLOCK_SNAPSHOT_END
//MLX_BLOCK_SENSORS_START
#if ((defined(MLX)) && defined(MLX_SENSORS)) || !defined(MLX)
#if defined(CUDA)
extern "C" __global__ void SensorsKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
	,mexType * SensorOutput_pr,
	unsigned int * IndexSensorMap_pr,
	unsigned int nStep)
{
	unsigned int sj =blockIdx.x * blockDim.x + threadIdx.x;
#endif
#ifdef OPENCL
__kernel void SensorsKernel(
#ifdef CUDA
#define __predecorator 
#else
#define __predecorator __global
#endif
__predecorator mexType *V_x_x_pr,
__predecorator mexType *V_y_x_pr,
__predecorator mexType *V_z_x_pr,
__predecorator mexType *V_x_y_pr,
__predecorator mexType *V_y_y_pr,
__predecorator mexType *V_z_y_pr,
__predecorator mexType *V_x_z_pr,
__predecorator mexType *V_y_z_pr,
__predecorator mexType *V_z_z_pr,
__predecorator mexType *Vx_pr,
__predecorator mexType *Vy_pr,
__predecorator mexType *Vz_pr,
__predecorator mexType *Rxx_pr,
__predecorator mexType *Ryy_pr,
__predecorator mexType *Rzz_pr,
__predecorator mexType *Rxy_pr,
__predecorator mexType *Rxz_pr,
__predecorator mexType *Ryz_pr,
__predecorator mexType *Sigma_x_xx_pr,
__predecorator mexType *Sigma_y_xx_pr,
__predecorator mexType *Sigma_z_xx_pr,
__predecorator mexType *Sigma_x_yy_pr,
__predecorator mexType *Sigma_y_yy_pr,
__predecorator mexType *Sigma_z_yy_pr,
__predecorator mexType *Sigma_x_zz_pr,
__predecorator mexType *Sigma_y_zz_pr,
__predecorator mexType *Sigma_z_zz_pr,
__predecorator mexType *Sigma_x_xy_pr,
__predecorator mexType *Sigma_y_xy_pr,
__predecorator mexType *Sigma_x_xz_pr,
__predecorator mexType *Sigma_z_xz_pr,
__predecorator mexType *Sigma_y_yz_pr,
__predecorator mexType *Sigma_z_yz_pr,
__predecorator mexType *Sigma_xy_pr,
__predecorator mexType *Sigma_xz_pr,
__predecorator mexType *Sigma_yz_pr,
__predecorator mexType *Sigma_xx_pr,
__predecorator mexType *Sigma_yy_pr,
__predecorator mexType *Sigma_zz_pr,
__predecorator mexType *SourceFunctions_pr,
__predecorator mexType * LambdaMiuMatOverH_pr,
__predecorator mexType * LambdaMatOverH_pr,
__predecorator mexType * MiuMatOverH_pr,
__predecorator mexType * TauLong_pr,
__predecorator mexType * OneOverTauSigma_pr,
__predecorator mexType * TauShear_pr,
__predecorator mexType * InvRhoMatH_pr,
__predecorator mexType * SqrAcc_pr,
__predecorator unsigned int * MaterialMap_pr,
__predecorator unsigned int * SourceMap_pr,
__predecorator mexType * Ox_pr,
__predecorator mexType * Oy_pr,
__predecorator mexType * Oz_pr,
__predecorator mexType * Pressure_pr
		, __global mexType * SensorOutput_pr,
			__global unsigned int * IndexSensorMap_pr,
			unsigned int nStep)
{
	_PT sj =(_PT) get_global_id(0);
#endif
#if defined(METAL) && !defined(MLX)
#define IndexSensorMap_pr k_IndexSensorMap_pr
#ifndef METALCOMPUTE
kernel void SensorsKernel(
	const device unsigned int *p_CONSTANT_BUFFER_UINT [[ buffer(0) ]],
	const device mexType * p_CONSTANT_BUFFER_MEX [[ buffer(1) ]],
	const device unsigned int *p_INDEX_MEX [[ buffer(2) ]],
	const device unsigned int *p_INDEX_UINT [[ buffer(3) ]],
	const device unsigned int *p_UINT_BUFFER [[ buffer(4) ]],
	device mexType * p_MEX_BUFFER_0 [[ buffer(5) ]],
	device mexType * p_MEX_BUFFER_1 [[ buffer(6) ]],
	device mexType * p_MEX_BUFFER_2 [[ buffer(7) ]],
	device mexType * p_MEX_BUFFER_3 [[ buffer(8) ]],
	device mexType * p_MEX_BUFFER_4 [[ buffer(9) ]],
	device mexType * p_MEX_BUFFER_5 [[ buffer(10) ]],
	device mexType * p_MEX_BUFFER_6 [[ buffer(11) ]],
	device mexType * p_MEX_BUFFER_7 [[ buffer(12) ]],
	device mexType * p_MEX_BUFFER_8 [[ buffer(13) ]],
	device mexType * p_MEX_BUFFER_9 [[ buffer(14) ]],
	device mexType * p_MEX_BUFFER_10 [[ buffer(15) ]],
	device mexType * p_MEX_BUFFER_11 [[ buffer(16) ]],
	uint gid[[thread_position_in_grid]])
#else
kernel void SensorsKernel(
	const device unsigned int *p_CONSTANT_BUFFER_UINT [[ buffer(0) ]],
	const device unsigned int *p_INDEX_MEX [[ buffer(1) ]],
	const device unsigned int *p_INDEX_UINT [[ buffer(2) ]],
	const device unsigned int *p_UINT_BUFFER [[ buffer(3) ]],
	device mexType * p_MEX_BUFFER_0 [[ buffer(4) ]],
	device mexType * p_MEX_BUFFER_1 [[ buffer(5) ]],
	device mexType * p_MEX_BUFFER_2 [[ buffer(6) ]],
	device mexType * p_MEX_BUFFER_3 [[ buffer(7) ]],
	device mexType * p_MEX_BUFFER_4 [[ buffer(8) ]],
	device mexType * p_MEX_BUFFER_5 [[ buffer(9) ]],
	device mexType * p_MEX_BUFFER_6 [[ buffer(10) ]],
	device mexType * p_MEX_BUFFER_7 [[ buffer(11) ]],
	device mexType * p_MEX_BUFFER_8 [[ buffer(12) ]],
	device mexType * p_MEX_BUFFER_9 [[ buffer(13) ]],
	device mexType * p_MEX_BUFFER_10 [[ buffer(14) ]],
	device mexType * p_MEX_BUFFER_11 [[ buffer(15) ]],
	uint gid[[thread_position_in_grid]])
#endif
{
	_PT sj = (_PT) gid;
#endif
#if defined(MLX)
	#define IndexSensorMap_pr k_IndexSensorMap_pr
	_PT sj = (_PT) thread_position_in_grid.x;
#endif

	if (sj>=(_PT) NumberSensors)
		return;
_PT index=(((_PT)nStep)/((_PT)SensorSubSampling)-((_PT)SensorStart))*((_PT)NumberSensors)+(_PT)sj;
_PT  i,j,k;
_PT index2,index3,
    subarrsize=(((_PT)NumberSensors)*(((_PT)TimeSteps)/((_PT)SensorSubSampling)+1-((_PT)SensorStart)));
index2=IndexSensorMap_pr[sj]-1;

mexType accumX=0.0,accumY=0.0,accumZ=0.0,
        accumXX=0.0, accumYY=0.0, accumZZ=0.0,
        accumXY=0.0, accumXZ=0.0, accumYZ=0.0, accum_p=0;;
for (_PT CurZone=0;CurZone<ZoneCount;CurZone++)
  {
    k=index2/(N1*N2);
    j=index2%(N1*N2);
    i=j%(N1);
    j=j/N1;

    if ( IS_Vx_SELECTED(SelMapsSensors))
        accumX+=EL(Vx,i,j,k);
    if ( IS_Vy_SELECTED(SelMapsSensors))
        accumY+=EL(Vy,i,j,k);
    if (IS_Vz_SELECTED(SelMapsSensors))
        accumZ+=EL(Vz,i,j,k);

    index3=Ind_Sigma_xx(i,j,k);
  #ifdef METAL
    //No idea why in this kernel the ELD(SigmaXX...) macros do not expand correctly
    //So we go a bit more manual
  if (IS_Sigmaxx_SELECTED(SelMapsSensors))
      accumXX+=k_Sigma_xx_pr[index3];
  if (IS_Sigmayy_SELECTED(SelMapsSensors))
      accumYY+=k_Sigma_yy_pr[index3];
  if (IS_Sigmazz_SELECTED(SelMapsSensors))
      accumZZ+=k_Sigma_zz_pr[index3];
  if (IS_Pressure_SELECTED(SelMapsSensors))
      accum_p+=k_Pressure_pr[index3];
  index3=Ind_Sigma_xy(i,j,k);
  if (IS_Sigmaxy_SELECTED(SelMapsSensors))
      accumXY+=k_Sigma_xy_pr[index3];
  if (IS_Sigmaxz_SELECTED(SelMapsSensors))
      accumXZ+=k_Sigma_xz_pr[index3];
  if (IS_Sigmayz_SELECTED(SelMapsSensors))
      accumYZ+=k_Sigma_yz_pr[index3];
  
  #else
    if (IS_Sigmaxx_SELECTED(SelMapsSensors))
        accumXX+=ELD(Sigma_xx,index3);
    if (IS_Sigmayy_SELECTED(SelMapsSensors))
        accumYY+=ELD(Sigma_yy,index3);
    if (IS_Sigmazz_SELECTED(SelMapsSensors))
        accumZZ+=ELD(Sigma_zz,index3);
    if (IS_Pressure_SELECTED(SelMapsSensors))
        accum_p+=ELD(Pressure,index3);
    index3=Ind_Sigma_xy(i,j,k);
    if (IS_Sigmaxy_SELECTED(SelMapsSensors))
        accumXY+=ELD(Sigma_xy,index3);
    if (IS_Sigmaxz_SELECTED(SelMapsSensors))
        accumXZ+=ELD(Sigma_xz,index3);
    if (IS_Sigmayz_SELECTED(SelMapsSensors))
        accumYZ+=ELD(Sigma_yz,index3);
   #endif
  }
accumX/=ZoneCount;
accumY/=ZoneCount;
accumZ/=ZoneCount;
accumXX/=ZoneCount;
accumYY/=ZoneCount;
accumZZ/=ZoneCount;
accumXY/=ZoneCount;
accumXZ/=ZoneCount;
accumYZ/=ZoneCount;
accum_p/=ZoneCount;
//ELD(SensorOutput,index)=accumX*accumX+accumY*accumY+accumZ*accumZ;
if (IS_Vx_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Vx)=accumX;
if (IS_Vy_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Vy)=accumY;
if (IS_Vz_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Vz)=accumZ;
if (IS_Sigmaxx_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Sigmaxx)=accumXX;
if (IS_Sigmayy_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Sigmayy)=accumYY;
if (IS_Sigmazz_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Sigmazz)=accumZZ;
if (IS_Sigmaxy_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Sigmaxy)=accumXY;
if (IS_Sigmaxz_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Sigmaxz)=accumXZ;
if (IS_Sigmayz_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Sigmayz)=accumYZ;
if (IS_Pressure_SELECTED(SelMapsSensors))
    ELD(SensorOutput,index+subarrsize*IndexSensor_Pressure)=accum_p;

#if !defined(MLX)
}
#endif
#endif
//MLX_BLOCK_SENSORS_END