├── ExampleImages ├── CapillaryRise.gif ├── ContactAngle150M100.png └── DrainagePoreSpace.gif ├── IniFiles ├── RKtwophasesetup2D.ini ├── RKtwophasesetup3D.ini ├── efs2D.ini ├── shanchen2D.ini └── twophasesetup.ini ├── README.md ├── RKCG2D ├── AccelerateTransport2DRK.py ├── AcceleratedRKGPU2D.py ├── RKD2Q9.py ├── RKGPU2DBoundary.py └── Transport2DRK.py ├── ShanChen2D ├── AccelerateGPU2D.py ├── ExplicitD2Q9GPU.py ├── OptimizedD2Q9GPU.py ├── ShanChenD2Q9.py ├── SimpleD2Q9.py └── SimpleGeometry.py └── main.py /ExampleImages/CapillaryRise.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PorousMediaSimulation/openLBMPM/3d841891daafe7b6e9f65e51dd9bf20f2b0e1792/ExampleImages/CapillaryRise.gif -------------------------------------------------------------------------------- /ExampleImages/ContactAngle150M100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PorousMediaSimulation/openLBMPM/3d841891daafe7b6e9f65e51dd9bf20f2b0e1792/ExampleImages/ContactAngle150M100.png -------------------------------------------------------------------------------- /ExampleImages/DrainagePoreSpace.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PorousMediaSimulation/openLBMPM/3d841891daafe7b6e9f65e51dd9bf20f2b0e1792/ExampleImages/DrainagePoreSpace.gif -------------------------------------------------------------------------------- /IniFiles/RKtwophasesetup2D.ini: -------------------------------------------------------------------------------- 1 | [ImageSetup] 2 | Existance = 'no' 3 | 4 | [DomainSize] 5 | xDomain = 20 6 | yDomain = 200 7 | numBufferingLayers = 10 8 | ratioTopToBottom = 0.5 9 | 10 | [SurfaceTension] 11 | SurfaceTensionType = 'CSF' 12 | ;;'CSF'-> continuum surface force 13 | ;;'Perturbation' 14 | SurfaceTension = 0.1 15 | ContactAngle = 60 16 | WettingType = 2 17 | ;;1 - Y. Xu et al 2017 18 | ;;2 - T. Akai et al 2018 19 | 20 | [RKParameters] 21 | AlphaR = 0.44444444 22 | AlphaB = 0.44444444 23 | BetaThickness = 0.7 24 | AkR = 1.4e-1 25 | AkB = 1.4e-1 26 | DeltaValue = 0.98 27 | 28 | [FluidParameters] 29 | TauR = 1.0 30 | TauB = 1.0 31 | InitialRhoR = 1.0 32 | InitialRhoB = 1.0 33 | TauType = 2 34 | ;;1 - Y.Xu et al, 2017 35 | ;;2 - T. Akai et al, 2018 36 | 37 | [BodyForce] 38 | bodyForceX = 0.0 39 | bodyForceY = 0.0 40 | 41 | [SolidBoundarySetup] 42 | SolidColorDiff = 0.5 43 | 44 | [BoundaryCondition] 45 | BoundaryTypeInlet = 'Neumann' 46 | ;;'Dirichlet' 47 | ;;'Neumann' 48 | NeumannType = 'ZouHe' 49 | velocityYR = -1.0e-4 50 | densityBH = 5e-8 51 | densityRH = 1.00536 52 | ;;-5.0e-5 53 | ;;-2.5e-4 54 | ;;7.5e-4 55 | ;;-2.5e-3 56 | ;;-7.5e-5 57 | velocityYB = 0.0 58 | BoundaryTypeOutlet = 'Dirichlet' 59 | ;;'Dirichlet' 60 | densityBL = 1.0 61 | densityRL = 5e-8 62 | 63 | 64 | [GradientType] 65 | Type = 'Isotropic' 66 | ;;'Isotropic' 67 | 68 | [TimeSetup] 69 | TimeSteps = 500001 70 | TimeInterval = 2500 71 | 72 | [Parallelism] 73 | Parallel = 'yes' 74 | xDimension = 128 75 | ThreadsNum = 32 76 | 77 | [RelaxationType] 78 | Type = 'MRT' 79 | ;;MRT 80 | 81 | [CyclesSetup] 82 | IsCycle = 'no' 83 | LastStep = 100 84 | -------------------------------------------------------------------------------- /IniFiles/RKtwophasesetup3D.ini: -------------------------------------------------------------------------------- 1 | [ImageSetup] 2 | Existance = 'no' 3 | 4 | [DomainSize] 5 | xDomain = 32 6 | yDomain = 32 7 | zDomain = 96 8 | 9 | [RKParameters] 10 | AlphaR = 0. 11 | AlphaB = 0. 12 | BetaThickness = 1. 13 | AkR = 7.0e-3 14 | AkB = 7.0e-3 15 | DeltaValue = 0.98 16 | 17 | [FluidParameters] 18 | TauR = 1.0 19 | TauB = 1.0 20 | InitialRhoR = 1.0 21 | InitialRhoB = 1.0 22 | 23 | [BoundariesSetup] 24 | SolidRhoR = 0.7 25 | SolidRhoB = 0.0 26 | 27 | [BoundaryCondition] 28 | BoundaryTypeInlet = 'Neumann' 29 | NeumannType = 'ZouHe' 30 | velocityZR = 0.0 31 | ;;-2.5e-4 32 | ;;7.5e-4 33 | ;;-2.5e-3 34 | ;;-7.5e-5 35 | velocityZB = -1.0e-4 36 | BoundaryTypeOutlet = 'Dirichlet' 37 | densityBL = 1.0 38 | densityRL = 1.0e-8 39 | 40 | 41 | [GradientType] 42 | Type = 'Isotropic' 43 | ;;'Isotropic' 44 | 45 | [TimeSteps] 46 | TimeSteps = 1000 47 | 48 | [Parallelism] 49 | Parallel = 'yes' 50 | xDimension = 128 51 | ThreadsNum = 32 52 | 53 | [RelaxationType] 54 | Type = 'SRT' 55 | ;;MRT 56 | 57 | [CyclesSetup] 58 | IsCycle = 'no' 59 | LastStep = 350 -------------------------------------------------------------------------------- /IniFiles/efs2D.ini: -------------------------------------------------------------------------------- 1 | [FluidProperties] 2 | InitialDensities = 1.0,1.0 3 | ;;2.0,2.0,2.0 4 | ;;,2.0,2.0 5 | BackgroundDensities = 0.02,0.02 6 | FluidsTau = 1.,1. 7 | ;;0.55,0.801 8 | ;;fluid0Viscosity = 0.167 9 | ;;lu^2/ts 10 | ;;fluid1Viscosity = 0.167 11 | ;; lu^2/ts 12 | 13 | [EFSParameters] 14 | interactionFluid = 0.20 15 | ;;1.8 16 | ;;0.8,0.485,0.8 17 | ;;,0.485,0.485,0.8,0.8,0.485 18 | ;;0.17 19 | ;;0.2 20 | interactionSolid = -0.14,0.14 21 | ;;0.09,-0.09 22 | ;;negative for wetting fluid 23 | ;;positive for non-wetting fluid 24 | potentialType = 'Simple' 25 | 26 | [BoundaryDefinition] 27 | BoundaryTypeInlet = 'Neumann' 28 | ;;'Dirichlet' 29 | ;; 'Neumann' 30 | ;;'Periodic' 31 | ;;pressure boundary 32 | BoundaryMethod = 'ZouHe' 33 | ;;'Chang': Chang et.al 2009 34 | ;;'ZouHe' Zhou & He 2002 35 | BoundaryTypeOutlet = 'Dirichlet' 36 | ;;'Convective' 37 | ;;'Dirichlet' 38 | 39 | [VelocityBoundary] 40 | velocityX = 0.0,0.0 41 | ;;,0.0,0.0 42 | velocityY = 0.0,-5.03e-4 43 | 44 | [PressureBoundary] 45 | PressureInlet = 0.0, 0.0 46 | PressureOutlet = 1.0, 0.0 47 | 48 | [ForceScheme] 49 | ExplicitScheme = 4 50 | 51 | [BodyForce] 52 | Option = 'no' 53 | forceXG = 0.0 54 | forceYG = 0.0 55 | 56 | [Time] 57 | numberTimeStep = 30000 58 | ;;4184936 59 | ;4182600 60 | ;;20000 -------------------------------------------------------------------------------- /IniFiles/shanchen2D.ini: -------------------------------------------------------------------------------- 1 | [FluidProperties] 2 | InitialDensities = 1.0,1.0 3 | ;;2.0,2.0,2.0 4 | ;;,2.0,2.0 5 | BackgroundDensities = 0.06,0.06 6 | FluidsTau = 1.0,1.0 7 | 8 | [ShanChenParameters] 9 | interactionFluid = 3.8 10 | ;;0.8,0.485,0.8 11 | ;;,0.485,0.485,0.8,0.8,0.485 12 | ;;0.17 13 | ;;0.2 14 | interactionSolid = -0.40,0.40 15 | ;;,-0.1,-0.1 16 | ;;0.09,-0.09 17 | ;;negative for wetting fluid 18 | ;;positive for non-wetting fluid 19 | potentialType = 'Simple' 20 | 21 | [BoundaryDefinition] 22 | BoundaryTypeInlet = 'Neumann' 23 | ;;'Dirichlet' 24 | ;; 'Neumann' 25 | ;;'Periodic' 26 | ;;pressure boundary 27 | BoundaryMethod = 'ZouHe' 28 | ;;'Chang': Chang et.al 2009 29 | ;;'ZouHe' Zhou & He 2002 30 | BoundaryTypeOutlet = 'Convective' 31 | 32 | [VelocityBoundary] 33 | velocityX = 0.0,0.0 34 | ;;,0.0,0.0 35 | velocityY = 0.0,-1.01e-3 36 | 37 | [PressureBoundary] 38 | PressureInlet = 0.0, 0.0 39 | PressureOutlet = 1.0, 0.0 40 | 41 | 42 | [BodyForce] 43 | Option = 'no' 44 | forceXG = 0.0 45 | forceYG = 0.0 46 | 47 | [Time] 48 | numberTimeStep = 300000 49 | ;;4184936 50 | ;4182600 51 | ;;20000 52 | 53 | -------------------------------------------------------------------------------- /IniFiles/twophasesetup.ini: -------------------------------------------------------------------------------- 1 | [PictureSetup] 2 | Exist = 'yes' 3 | 4 | [SeparationBorder] 5 | xGrid = 32 6 | yGrid = 200 7 | 8 | [FluidsTypes] 9 | NumberOfFluids = 2 10 | 11 | [InterType] 12 | InteractionType = 'EFS' 13 | ;;ShanChen: original Shan-Chen Model 14 | ;;EFS: explicit forcing scheme 15 | 16 | [Parallelism] 17 | Parallel = 'yes' 18 | xDimension = 256 19 | ;;must be times of 32 20 | ThreadsNum = 32 21 | ;;parallelism from GPU 22 | 23 | [RelaxationType] 24 | Type = 'SRT' 25 | ;;options: SRT, TRT, MRT 26 | 27 | [DuplicateDomain] 28 | Option = 'no' 29 | 30 | [DICycles] 31 | Option = 'no' 32 | LastStep = 1105 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenLBMPM (In development) 2 | OpenLBMPM is an open source lattice Boltzmann method (LBM) package for multicomponent and multiphase (MCMP) flow and transport in porous media. Currently, it includes Shan-Chen method and color gradient method for MCMP system. The transport part does not include any chemical reactions and phase change, but they will be added later. 3 | 4 | D2Q9 and D3Q19 schemes are implemented to simulate fluid flow in 2D and 3D. To balance the accuracy and efficiency, D2Q5 and D3Q7 schemes are used to simulate the transport phenomena. 5 | 6 | There are two options for Shan-Chen method: (1) Original Shan-Chen method, which integrates the force term to the equilibrium velocity and cannot reach high viscosity ratio; (2) Explicit forcing model developed by M.Porter et al (2012), which is able to reach high viscosity ratio with the different isotropy values (M~1000). The last one has multi-relaxation-time collision operators to suppress spurious currents and keep numerical stability. For color gradient model, the methods developed by Liu et.al (2014), Huang et al (2014) and Takashi et al (2018) are included here. All of them have MRT collision operator option. 7 | 8 | # Required packages 9 | OpenLBMPM is accelerated by GPU parallel computation, so it needs several supporting packages: 10 | 11 | 1. [CUDA](https://developer.nvidia.com/cuda-downloads) 12 | 2. [Anaconda-python3.6](https://www.anaconda.com/download/#linux) 13 | 14 | # How to use the codes 15 | So far, there is no need to install this package and the codes are tested under the Linux environmenta (Kubuntu 16.04LTS). To run the simulation. Inputting 'python main.py' under the directory of OpenLBMPM will start the simulation. Then you can choose which kind of MCMP LBM is needed. The details on how to set up and run a simulation are shown below: 16 | 1. Use git clone to get the copy of this packaged 17 | 2. Set up the environmental variables in .bashrc (e.g., export PYTHONPATH=$PYTHONPATH:/PATH/PACKAGE/RKCG2D) for all LBM methods 18 | 3. Set up the geometry of the simulated domain in the file SimpleGeometry.py, which is usually not complicated or add the pore structure image to the designated folder (/home/$USER/StructureImage/) 19 | 4. Set up fluid properties, boundary conditions, and simulation time in the .ini file from the folder IniFiles. 20 | 5. Input python main.py to run the simulation 21 | 22 | # Structure of the folder for results 23 | When the script, main.py, starts to run, it checks whether there is a folder called 'LBMResults' existing or not. If not, the new folder is created automatically. Then all the results from the simulation are saved in this folder. The structure of this folder is: 24 | 25 | ''' 26 | 27 | ├── LBMResults 28 | 29 | ├──FluidsBDistributionAt0000%d.png 30 | ├──FluidsRdistributionAt0000%d.png 31 | ├──SimulationResultsRK.h5 32 | ''' 33 | 34 | .png files are shown the distribution of each fluid at a certain time step. .h5 file stores the densities and distribution functions of each fluid and the velocities in each direction. This file can be easily read using tables or h5py. 35 | 36 | # Types of boundary conditions 37 | 1. Contant pressure 38 | 2. Constant velocity 39 | 3. Convective boundary (only for the outlet) 40 | 4. Half-bounce back 41 | 42 | Constant pressure/velocity boundaries are implemented following Zou and He. The convective boundary is only the outlet of the simulated domain and it is equivalent to the free flux boundary condition. Half-bounce back boundary condition is for no-slip boundary between fluid and solid surface, which is an advantage of LBM to simulate flow and transport in pore space. 43 | 44 | 45 | **Buffering Layer:** *When fluid flow in pore structure is simulated, it is better to extend the simulated domain on the flow direction with a certain number of 'buffering layers' for minimizing the influence of boundaries.* 46 | 47 | # Types of MCMP LBM in this package 48 | 1. Original Shan-Chen model 49 | 2. Explicit force scheme model 50 | 3. Color gradient LBM 51 | 4. CSF-color gradient LBM (The best option) 52 | 53 | 54 | # Examples 55 | ## Contact angle 56 | Here the examples of contact angle from method 4 are shown. Compared to the other methods, this one can reach more accurate contact angle value without having unphysical mass diffusion layer on the solid phase surface. The contact angles are: (1) 150 degree; 57 | ![ContactAngle1](ExampleImages/ContactAngle150M100.png) 58 | ## Capillary Intrusion 59 | This is the example of capillary intrusion and the viscosity ratio here is 0.01 60 | ![CapillaryIntrusion](ExampleImages/CapillaryRise.gif) 61 | ## Drainage process 62 | This is the example of drainage process in pore space 63 | ![DrainageProcess](ExampleImages/DrainagePoreSpace.gif) 64 | -------------------------------------------------------------------------------- /RKCG2D/AccelerateTransport2DRK.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module for using CUDA in numba to accelerate the D2Q5 LBM for transport 3 | """ 4 | 5 | import sys, os 6 | 7 | import numpy as np 8 | import scipy as sp 9 | 10 | import math 11 | 12 | from numba import cuda, int64, float64 13 | from numba import cuda, jit 14 | 15 | #from accelerate import cuda as acuda 16 | #from accelerate import numba as anumba 17 | 18 | #""" 19 | #Calculate the neighboring nodes in transport scheme D2Q9 20 | #""" 21 | #@cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:, :], int64[:])') 22 | #def fillNeighboringNodesTransport(totalNodes, nx, ny, xDim, fluidNodes, domainNewIndex, \ 23 | # neighboringNodes): 24 | # tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 25 | # by = cuda.blockIdx.y 26 | # indices = by * xDim + bx * bDimX + tx 27 | # 28 | # if (indices < totalNodes): 29 | # tmpStart = 4 * indices 30 | # tmpLoc = fluidNodes[indices] 31 | # i = int(tmpLoc / nx); j = tmpLoc % nx 32 | # tmpF = j + 1 if j < nx - 1 else 0 33 | # tmpB = j - 1 if j > 0 else (nx - 1) 34 | # tmpU = i + 1 if i < ny - 1 else 0 35 | # tmpL = i - 1 if i > 0 else (ny - 1) 36 | # #Eastern node 37 | # neighboringNodes[tmpStart] = domainNewIndex[i, tmpF] 38 | # #Northern node 39 | # tmpStart += 1 40 | # neighboringNodes[tmpStart] = domainNewIndex[tmpU, j] 41 | # #Western node 42 | # tmpStart += 1 43 | # neighboringNodes[tmpStart] = domainNewIndex[i, tmpB] 44 | # #Southern node 45 | # tmpStart += 1 46 | # neighboringNodes[tmpStart] = domainNewIndex[tmpL, j] 47 | """ 48 | Calculate the neighboring nodes in transport scheme D2Q5 49 | """ 50 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:, :], int64[:])') 51 | def fillNeighboringNodesTransport(totalNodes, nx, ny, xDim, fluidNodes, domainNewIndex, \ 52 | neighboringNodes): 53 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 54 | by = cuda.blockIdx.y 55 | indices = by * xDim + bx * bDimX + tx 56 | 57 | if (indices < totalNodes): 58 | tmpStart = 4 * indices 59 | tmpLoc = fluidNodes[indices] 60 | i = int(tmpLoc / nx); j = tmpLoc % nx 61 | tmpF = j + 1 if j < nx - 1 else 0 62 | tmpB = j - 1 if j > 0 else (nx - 1) 63 | tmpU = i + 1 if i < ny - 1 else 0 64 | tmpL = i - 1 if i > 0 else (ny - 1) 65 | #Eastern node 66 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpF] 67 | #Northern node 68 | tmpStart += 1 69 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpB] 70 | #Western node 71 | tmpStart += 1 72 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, j] 73 | #Southern node 74 | tmpStart += 1 75 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, j] 76 | 77 | @cuda.jit('void(int64, int64, int64, int64, float64[:, :], float64[:, :, :])') 78 | def calConcentrationGPU(totalNodes, numTracers, xDim, numSchemes, tracerConc, \ 79 | tracerPDF): 80 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 81 | by = cuda.blockIdx.y 82 | 83 | indices = by * xDim + bx * bDimX + tx 84 | if (indices < totalNodes): 85 | for i in range(numTracers): 86 | tracerConc[i, indices] = 0. 87 | for j in range(numSchemes): 88 | tracerConc[i, indices] += tracerPDF[i, indices, j] 89 | 90 | """ 91 | Reaction part for tracer in bulk fluid 92 | """ 93 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:, :], \ 94 | float64[:, :], float64[:, :, :])') 95 | def calReactionTracersGPU(totalNodes, numTracers, xDim, reactionRate, diffJcoeffs, \ 96 | tracerConc, tracerPDF): 97 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 98 | by = cuda.blockIdx.y 99 | indices = by * xDim + bx * bDimX + tx 100 | 101 | if (indices < totalNodes): 102 | tmpReactionS = cuda.local.array(shape = (3,), dtype = float64) 103 | tmpReactionS[0] = -reactionRate[0] * tracerConc[0, indices] * tracerConc[1, indices] 104 | tmpReactionS[1] = -reactionRate[0] * tracerConc[0, indices] * tracerConc[1, indices] 105 | tmpReactionS[2] = reactionRate[0] * tracerConc[0, indices] * tracerConc[1, indices] 106 | for i in range(numTracers): 107 | for j in range(5): 108 | tracerPDF[i, indices, j] = tracerPDF[i, indices, j] + diffJcoeffs[i, j] * \ 109 | tmpReactionS[i] 110 | 111 | 112 | """ 113 | Collision process of transport phenomena without reaction 114 | """ 115 | @cuda.jit('void(int64, int64, int64, int64, float64[:], float64[:], float64[:], \ 116 | float64[:], float64[:], float64[:, :], float64[:, :], \ 117 | float64[:, :, :], float64[:, :, :])') 118 | def calCollisionTransportGPU(totalNodes, xDim, numTracers, numScheme, unitVX, unitVY, \ 119 | velocityVX, velocityVY, tauTransport, valueJDE, tracerConc, \ 120 | tracerPDF, tracerPDFNew): 121 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 122 | by = cuda.blockIdx.y 123 | indices = by * xDim + bx * bDimX + tx 124 | 125 | if (indices < totalNodes): 126 | for i in range(numTracers): 127 | for j in range(numScheme): 128 | tmpTracerEq = tracerConc[i, indices] * (valueJDE[i, j] + 1./2. * \ 129 | (unitVX[j] * velocityVX[indices] + unitVY[j] * \ 130 | velocityVY[indices])) 131 | tracerPDF[i, indices, j] = tracerPDF[i, indices, j] - 1./tauTransport[i] * \ 132 | (tracerPDF[i, indices, j] - tmpTracerEq) 133 | 134 | """ 135 | Streaming process of transport phenomena 136 | """ 137 | @cuda.jit('void(int64, int64, int64, int64[:], float64[:, :, :], \ 138 | float64[:, :, :])') 139 | def calStreamingTransportGPU(totalNodes, xDim, numTracers, neighboringNodes, \ 140 | tracerPDF, tracerPDFNew): 141 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 142 | by = cuda.blockIdx.y 143 | indices = by * xDim + bx * bDimX + tx 144 | 145 | if (indices < totalNodes): 146 | tmpStart = 4 * indices 147 | if neighboringNodes[tmpStart] != -1: 148 | tmpE = neighboringNodes[tmpStart] 149 | for j in range(numTracers): 150 | tracerPDFNew[j, tmpE, 1] = tracerPDF[j, indices, 1] 151 | elif neighboringNodes[tmpStart] == -1: 152 | for j in range(numTracers): 153 | tracerPDFNew[j, indices, 2] = tracerPDF[j, indices, 1] 154 | tmpStart += 1 155 | if neighboringNodes[tmpStart] != -1: 156 | tmpW = neighboringNodes[tmpStart] 157 | for j in range(numTracers): 158 | tracerPDFNew[j, tmpW, 2] = tracerPDF[j, indices, 2] 159 | elif neighboringNodes[tmpStart] == -1: 160 | for j in range(numTracers): 161 | tracerPDFNew[j, indices, 1] = tracerPDF[j, indices, 2] 162 | tmpStart += 1 163 | if neighboringNodes[tmpStart] != -1: 164 | tmpN = neighboringNodes[tmpStart] 165 | for j in range(numTracers): 166 | tracerPDFNew[j, tmpN, 3] = tracerPDF[j, indices, 3] 167 | elif neighboringNodes[tmpStart] == -1: 168 | for j in range(numTracers): 169 | tracerPDFNew[j, indices, 4] = tracerPDF[j, indices, 3] 170 | tmpStart += 1 171 | if neighboringNodes[tmpStart] != -1: 172 | tmpS = neighboringNodes[tmpStart] 173 | for j in range(numTracers): 174 | tracerPDFNew[j, tmpS, 4] = tracerPDF[j, indices, 4] 175 | elif neighboringNodes[tmpStart] == -1: 176 | for j in range(numTracers): 177 | tracerPDFNew[j, indices, 3] = tracerPDF[j, indices, 4] 178 | cuda.syncthreads() 179 | 180 | """ 181 | Calculate the streaming process 2 182 | """ 183 | @cuda.jit('void(int64, int64, int64, float64[:, :, :], float64[:, :, :])') 184 | def calStreamingTransport2GPU(totalNum, numTracers, xDim, tracerPDFNew, tracerPDF): 185 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 186 | by = cuda.blockIdx.y 187 | indices = by * xDim + bx * bDimX + tx 188 | 189 | if indices < totalNum: 190 | for i in range(numTracers): 191 | for j in range(1, 5): 192 | tracerPDF[i, indices, j] = tracerPDFNew[i, indices, j] 193 | """ 194 | Update the fluid distribution region 195 | """ 196 | @cuda.jit('void(int64, int64, float64, float64[:], boolean[:])') 197 | def calUpdateDistributionGPU(totalNodes, xDim, criteriaFluid, fluidRhoR, \ 198 | distriField): 199 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 200 | by = cuda.blockIdx.y 201 | indices = by * xDim + bx * bDimX + tx 202 | 203 | if (indices < totalNodes): 204 | if (fluidRhoR[indices] < criteriaFluid): 205 | distriField[indices] = 1 206 | else: 207 | distriField[indices] = 0 208 | 209 | 210 | 211 | """ 212 | Update the concentration on new fluid nodes with the method in Kang. et.al 2007 213 | """ 214 | @cuda.jit('void(int64, int64, int64, int64[:], int64[:], float64[:, :], \ 215 | boolean[:])') 216 | def calUpdateConcOnNewNodesGPU(totalNodes, xDim, numTracers, newFluidList, \ 217 | surroundingNodes, tracerConc, distrField): 218 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 219 | by = cuda.blockIdx.y 220 | indices = by * xDim + bx * bDimX + tx 221 | 222 | if (indices < totalNodes): 223 | for tmpNew in newFluidList: 224 | if indices == tmpNew: 225 | for i in range(numTracers): 226 | tmpTotalC = 0.; totalCount = 0 227 | tmpStart = indices * 8 228 | for j in range(8): 229 | tmpSurrounding = surroundingNodes[tmpStart] 230 | if (distrField[tmpSurrounding] == True and tmpSurrounding >= 0): 231 | tmpAddNeighboring = 0 232 | for m in newFluidList: 233 | if tmpSurrounding == m: 234 | tmpAddNeighboring += 1 235 | if tmpAddNeighboring == 0: 236 | tmpTotalC += tracerConc[i, tmpSurrounding] 237 | totalCount += 1 238 | tmpStart += 1 239 | tracerConc[i, indices] = tmpTotalC / totalCount 240 | 241 | """ 242 | Update the concentration on the old fluid nodes when displacement happens 243 | """ 244 | @cuda.jit('void(int64, int64, int64, int64[:], float64[:, :], float64[:, :, :])') 245 | def calUpdateConcOnOldNodesGPU(totalNodes, xDim, numTracers, oldFluidList, \ 246 | tracerConc, tracerPDF): 247 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 248 | by = cuda.blockIdx.y 249 | indices = by * xDim + bx * bDimX + tx 250 | 251 | if (indices < totalNodes): 252 | for tmpOld in oldFluidList: 253 | if indices == tmpOld: 254 | for i in range(numTracers): 255 | tracerConc[i, indices] = 0. 256 | for j in range(5): 257 | tracerPDF[i, indices, j] = 0. 258 | # if (transportDomain[indices] == False): 259 | # for i in range(numTracers): 260 | # tracerConc[i, indices] = 0. 261 | # for j in range(5): 262 | # tracerPDF[i, indices, j] = 0. 263 | """ 264 | Update the concentration on the old fluid nodes when displacement happens 265 | """ 266 | @cuda.jit('void(int64, int64, int64, boolean[:], float64[:, :], float64[:, :, :])') 267 | def calUpdateConcOnAllNewNodesGPU(totalNodes, xDim, numTracers, transportDomain, \ 268 | tracerConc, tracerPDF): 269 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 270 | by = cuda.blockIdx.y 271 | indices = by * xDim + bx * bDimX + tx 272 | 273 | if (indices < totalNodes): 274 | if (transportDomain[indices] == False): 275 | for i in range(numTracers): 276 | tracerConc[i, indices] = 0. 277 | for j in range(5): 278 | tracerPDF[i, indices, j] = 0. 279 | 280 | """ 281 | Update the concentration in the whole domain when the interface is moving 282 | """ 283 | @cuda.jit('void(int64, int64, int64, int64, float64, int64[:], float64[:], float64[:], float64[:], \ 284 | float64[:, :], float64[:, :], boolean[:])') 285 | def calUpdateConcWholeDomainGPU(totalNodes, nx, xDim, numTracers, randomPert, \ 286 | fluidNodes, sumOldConc, sumOldList, sumNewList, \ 287 | tracerConcNew, tracerConc, distrField): 288 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 289 | by = cuda.blockIdx.y 290 | indices = by * xDim + bx * bDimX + tx 291 | 292 | if (indices < totalNodes): 293 | # if (distrField[indices] == 1): 294 | for i in range(numTracers): 295 | tmpLeave = 0. 296 | # for j in range(nx): 297 | # if fluidNodes[j] < nx: 298 | # tmpLeave += tracerConc[i, j] 299 | tmpConc = (1. + randomPert) * tracerConc[i, indices] * \ 300 | (sumOldConc[i] / (sumNewList[i] + sumOldConc[i] - \ 301 | sumOldList[i] + tmpLeave)) 302 | tracerConcNew[i, indices] = tmpConc 303 | 304 | 305 | """ 306 | Deal with the interface boundary 307 | """ 308 | @cuda.jit('void(int64, int64, int64, int64, int64[:], float64[:], float64[:], \ 309 | float64[:, :], float64[:, :, :], boolean[:])') 310 | def calTransportInterfaceGPU(totalNodes, xDim, numTracers, numScheme, neighboringNodes, \ 311 | velocityVX, velocityVY, tracerConc, tracerPDF, distriField): 312 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 313 | by = cuda.blockIdx.y 314 | indices = by * xDim + bx * bDimX + tx 315 | 316 | if (indices < totalNodes): 317 | if distriField[indices] == 1: 318 | for i in range(numTracers): 319 | tmpStart = 4 * indices 320 | tmpDirection = 0 321 | for j in range(1, numScheme): 322 | tmpDirection += 1 323 | tmpIndices = neighboringNodes[tmpStart] 324 | if (tmpIndices >= 0 and distriField[tmpIndices] == 0): 325 | if tmpDirection == 1: 326 | # tmpNeighboring = neighboringNodes[tmpStart + 1] 327 | # if (tmpNeighboring >= 0 and distriField[tmpNeighboring] != 0): 328 | # tracerConc[i, indices] = tracerConc[i, tmpNeighboring] 329 | # tracerPDF[i, indices, tmpDirection + 2] = -velocityVX[indices] * \ 330 | # tracerConc[i, tmpNeighboring] + tracerPDF[i, indices, tmpDirection] 331 | tracerPDF[i, indices, tmpDirection + 1] = tracerPDF[i, tmpIndices, tmpDirection] 332 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 333 | # elif (tmpNeighboring >= 0 and distriField[tmpNeighboring] == 0): 334 | # tracerPDF[i, indices, tmpDirection + 1] = tracerPDF[i, tmpIndices, tmpDirection] 335 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 336 | # elif tmpNeighboring < 0: 337 | # tracerPDF[i, indices, tmpDirection + 1] = tracerPDF[i, tmpIndices, tmpDirection] 338 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 339 | elif tmpDirection == 2: 340 | # tmpNeighboring = neighboringNodes[tmpStart + 2] 341 | # if (tmpNeighboring >= 0 and distriField[tmpNeighboring] != 0): 342 | # tracerConc[i, indices] = tracerConc[i, tmpNeighboring] 343 | # tracerPDF[i, indices, tmpDirection + 2] = -velocityVY[indices] * \ 344 | # tracerConc[i, tmpNeighboring] + tracerPDF[i, indices, tmpDirection] 345 | tracerPDF[i, indices, tmpDirection - 1] = tracerPDF[i, tmpIndices, tmpDirection] 346 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 347 | # elif (tmpNeighboring >= 0 and distriField[tmpNeighboring] == 0): 348 | # tracerPDF[i, indices, tmpDirection + 2] = tracerPDF[i, tmpIndices, tmpDirection] 349 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 350 | # elif tmpNeighboring < 0: 351 | # tracerPDF[i, indices, tmpDirection + 2] = tracerPDF[i, tmpIndices, tmpDirection] 352 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 353 | elif tmpDirection == 3: 354 | # tmpNeighboring = neighboringNodes[tmpStart - 2] 355 | # if (tmpNeighboring >= 0 and distriField[tmpNeighboring] != 0): 356 | # tracerConc[i, indices] = tracerConc[i, tmpNeighboring] 357 | # tracerPDF[i, indices, tmpDirection - 2] = velocityVX[indices] * \ 358 | # tracerConc[i, tmpNeighboring] + tracerPDF[i, indices, tmpDirection] 359 | tracerPDF[i, indices, tmpDirection + 1] = tracerPDF[i, tmpIndices, tmpDirection] 360 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 361 | # elif (tmpNeighboring >= 0 and distriField[tmpNeighboring] == 0): 362 | # tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 363 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 364 | # elif tmpNeighboring < 0: 365 | # tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 366 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 367 | elif tmpDirection == 4: 368 | # tmpNeighboring = neighboringNodes[tmpStart - 2] 369 | # if (tmpNeighboring >= 0 and distriField[tmpNeighboring] != 0): 370 | # tracerConc[i, indices] = tracerConc[i, tmpNeighboring] 371 | # tracerPDF[i, indices, tmpDirection - 2] = velocityVY[indices] * \ 372 | # tracerConc[i, tmpNeighboring] + tracerPDF[i, indices, tmpDirection] 373 | tracerPDF[i, indices, tmpDirection - 1] = tracerPDF[i, tmpIndices, tmpDirection] 374 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 375 | # elif (tmpNeighboring >= 0 and distriField[tmpNeighboring] == 0): 376 | # tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 377 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 378 | # elif tmpNeighboring < 0: 379 | # tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 380 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 381 | tmpStart += 1 382 | # cuda.syncthreads() 383 | """ 384 | Update the distribution function for new nodes in transport domain 385 | """ 386 | @cuda.jit('void(int64, int64, int64, int64[:], float64[:], float64[:], \ 387 | float64[:], float64[:], float64[:, :], float64[:, :], \ 388 | float64[:, :], float64[:, :, :], boolean[:])') 389 | def calUpdatedPDFWithNewRho(totalNodes, xDim, numTracers, newList, \ 390 | unitX, unitY, velocityX, velocityY, tracerConc, \ 391 | tracerConcNew, valueJDE, tracerPDF, distrField): 392 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 393 | by = cuda.blockIdx.y 394 | indices = by * xDim + bx * bDimX + tx 395 | 396 | if (indices < totalNodes): 397 | if (distrField[indices] == 1): 398 | for tmpNew in newList: 399 | if indices == tmpNew: 400 | for i in range(numTracers): 401 | for j in range(5): 402 | tracerPDF[i, indices, j] = tracerConcNew[i, indices] * \ 403 | (valueJDE[i, j] + 1./2. * (unitX[j] * velocityX[indices] + \ 404 | unitY[j] * velocityY[indices])) 405 | else: 406 | for i in range(numTracers): 407 | tmpConcDiff = tracerConcNew[i, indices] - tracerConc[i, indices] 408 | for j in range(5): 409 | tmpConcRatio = tracerPDF[i, indices, j] / tracerConc[i, indices] 410 | tmpPDF = tracerPDF[i, indices, j] + tmpConcDiff * tmpConcRatio 411 | tracerPDF[i, indices, j] = tmpPDF 412 | cuda.syncthreads() 413 | 414 | """ 415 | Free flow boundary condition for tracer 416 | """ 417 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:], float64[:, :], \ 418 | float64[:, :, :])') 419 | def calFreeConcBoundary1(totalNodes, numTracers, nx, xDim, fluidNodes, neighboringNodes, \ 420 | tracerConc, tracerPDF): 421 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 422 | by = cuda.blockIdx.y 423 | indices = by * xDim + bx * bDimX + tx 424 | 425 | if (indices < totalNodes): 426 | tmpIndices = fluidNodes[indices] 427 | if (tmpIndices < 3 * nx and tmpIndices >= 2 * nx): 428 | tmpNeighbor = neighboringNodes[4 * indices + 2] 429 | for i in range(numTracers): 430 | # tracerConc[i, indices] = 0. 431 | for j in range(5): 432 | tracerPDF[i, indices, j] = tracerPDF[i, tmpNeighbor, j] 433 | cuda.syncthreads() 434 | 435 | """ 436 | Free flow boundary condition for tracer 437 | """ 438 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:], float64[:, :], \ 439 | float64[:, :, :])') 440 | def calFreeConcBoundary2(totalNodes, numTracers, nx, xDim, fluidNodes, neighboringNodes, \ 441 | tracerConc, tracerPDF): 442 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 443 | by = cuda.blockIdx.y 444 | indices = by * xDim + bx * bDimX + tx 445 | 446 | if (indices < totalNodes): 447 | tmpIndices = fluidNodes[indices] 448 | if (tmpIndices < 2 * nx and tmpIndices >= nx): 449 | tmpNeighbor = neighboringNodes[4 * indices + 2] 450 | for i in range(numTracers): 451 | # tracerConc[i, indices] = 0. 452 | for j in range(5): 453 | tracerPDF[i, indices, j] = tracerPDF[i, tmpNeighbor, j] 454 | cuda.syncthreads() 455 | 456 | """ 457 | Free flow boundary condition for tracer 458 | """ 459 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:], float64[:, :], \ 460 | float64[:, :, :])') 461 | def calFreeConcBoundary3(totalNodes, numTracers, nx, xDim, fluidNodes, neighboringNodes, \ 462 | tracerConc, tracerPDF): 463 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 464 | by = cuda.blockIdx.y 465 | indices = by * xDim + bx * bDimX + tx 466 | 467 | if (indices < totalNodes): 468 | tmpIndices = fluidNodes[indices] 469 | if (tmpIndices < nx and tmpIndices >= 0): 470 | tmpNeighbor = neighboringNodes[4 * indices + 2] 471 | for i in range(numTracers): 472 | # tracerConc[i, indices] = 0. 473 | for j in range(5): 474 | tracerPDF[i, indices, j] = tracerPDF[i, tmpNeighbor, j] 475 | # tracerConc[i, indices] += tracerPDF[i, indices, j] 476 | cuda.syncthreads() 477 | 478 | @cuda.jit('void(int64, int64, int64, int64, int64, int64[:], float64[:, :], \ 479 | float64[:,:,:], int64[:])') 480 | def calZeroConcenBoundary(totalNodes, numTracers, nx, ny, xDim, fluidNodes, tracerConc, \ 481 | tracerPDF, neighboringNodes): 482 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 483 | by = cuda.blockIdx.y 484 | indices = by * xDim + bx * bDimX + tx 485 | 486 | if (indices < totalNodes): 487 | tmpIndices = fluidNodes[indices] 488 | if (tmpIndices >= (ny - 2) * nx and tmpIndices < (ny - 1) * nx): 489 | tmpStart = 4 * indices + 3 490 | tmpL = neighboringNodes[tmpStart] 491 | 492 | for i in range(numTracers): 493 | tracerConc[i, indices] = 0. 494 | for j in range(5): 495 | tracerPDF[i, indices, j] = tracerPDF[i, tmpL, j] 496 | tracerConc[i, indices] += tracerPDF[i, indices, j] 497 | 498 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], boolean[:], float64[:], \ 499 | float64[:], float64[:], float64[:], float64[:], float64[:, :], float64[:, :, :])') 500 | def calUpdateConcInTransportDomainByV(totalNodes, numTracers, xDim, totalTracer, totalOld, \ 501 | transportDomain, physicalVX, physicalVY, \ 502 | unitVX, unitVY, weightsCoeff, tracerConc, tracerPDF): 503 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 504 | by = cuda.blockIdx.y 505 | indices = by * xDim + bx * bDimX + tx 506 | sharedWeights = cuda.shared.array(shape = (5,), dtype = float64) 507 | for i in range(5): 508 | sharedWeights[i] = weightsCoeff[i] 509 | if (indices < totalNodes): 510 | tmpVNorm = math.sqrt(physicalVX[indices] * physicalVX[indices] + \ 511 | physicalVY[indices] * physicalVY[indices]) 512 | if (transportDomain[indices] == 1 and tmpVNorm > 1e-10): 513 | for i in range(numTracers): 514 | tmpExtraConc = tracerConc[i, indices] * \ 515 | totalOld[i] / totalTracer[i] 516 | # if tracerConc[i, indices] > 1.0e-7: 517 | tracerConc[i, indices] += tmpExtraConc#totalOld[i] 518 | for j in range(5): 519 | tracerPDF[i, indices, j] = tracerConc[i, indices] * sharedWeights[j] * (1. + \ 520 | 3. * (unitVX[j] * physicalVX[indices] + unitVY[j] * \ 521 | physicalVY[indices])) 522 | # if (transportDomain[indices] == 1): 523 | # for i in range(numTracers): 524 | # if tracerConc[i, indices] < 0.: 525 | # tracerConc[i, indices] = 0. 526 | # for j in range(5): 527 | # tracerPDF[i, indices, j] = 0. 528 | 529 | """ 530 | Implement MRT scheme to the transport part (linear equilibrium function) 531 | """ 532 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:], \ 533 | float64[:], float64[:, :], float64[:, :, :], \ 534 | float64[:, :], float64[:, :, :], float64[:])') 535 | def calCollisionTransportLinearEqlMRTGPU(totalNodes, xDim, numTracers, unitVX, unitVY, \ 536 | velocityVX, velocityVY, tracerConc, tracerPDF, transportM, \ 537 | inverseRelaxationMS, weightsCoeff): 538 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 539 | by = cuda.blockIdx.y 540 | indices = by * xDim + bx * bDimX + tx 541 | 542 | # sharedTM = cuda.shared.array(shape=(5, 5), dtype = float64) 543 | # sharedWeights = cuda.shared.array(shape = (5,), dtype = float64) 544 | # sharedInverseTM = cuda.shared.array(shape = (5, 5), dtype = float64) 545 | # sharedCollisionS = cuda.shared.array(shape = (5, 5), dtype = float64) 546 | 547 | # for i in range(5): 548 | # for j in range(5): 549 | # sharedTM[i, j] = transportM[i, j] 550 | # for i in range(5): 551 | # sharedWeights[i] = weightsCoeff[i] 552 | # sharedInverseTM = inverseTransportM[i, j] 553 | if (indices < totalNodes): 554 | tmpEql = cuda.local.array(shape = (5,), dtype = float64) 555 | # tmpMEql = cuda.local.array(shape = (5, ), dtype = float64) 556 | tmpIMEql = cuda.local.array(shape = (5,), dtype = float64) 557 | # tmpPDFM = cuda.local.array(shape = (5,), dtype = float64) 558 | # tmpPDFIM = cuda.local.array(shape = (5,), dtype = float64) 559 | tmpDiff = cuda.local.array(shape = (5,), dtype = float64) 560 | for i in range(numTracers): 561 | for j in range(5): 562 | # tmpEql[j] = tracerConc[i, indices] * sharedWeights[j] * (1. + \ 563 | # 3. * (unitVX[j] * velocityVX[indices] + unitVY[j] * \ 564 | # velocityVY[indices])) 565 | tmpEql[j] = tracerConc[i, indices] * weightsCoeff[j] * (1. + \ 566 | 3. * (unitVX[j] * velocityVX[indices] + unitVY[j] * \ 567 | velocityVY[indices])) 568 | 569 | for j in range(5): 570 | tmpValueEql = 0.; tmpValuePDF = 0. 571 | for k in range(5): 572 | # tmpValueEql += sharedTM[j, k] * tmpEql[k] 573 | # tmpValuePDF += tracerPDF[i, indices, k] * sharedTM[j, k] 574 | tmpValueEql += transportM[j, k] * tmpEql[k] 575 | tmpValuePDF += tracerPDF[i, indices, k] * transportM[j, k] 576 | # tmpMEql[j] = tmpValueEql; tmpPDFM[j] = tmpValuePDF 577 | tmpDiff[j] = tmpValuePDF - tmpValueEql 578 | 579 | for j in range(5): 580 | # tmpValueEql = 0 581 | tmpValuePDF = 0. 582 | for k in range(5): 583 | # tmpValueEql += inverseRelaxationMS[i, j, k] * tmpMEql[k] 584 | # tmpValuePDF += inverseRelaxationMS[i, j, k] * tmpPDFM[k] 585 | tmpValuePDF += inverseRelaxationMS[i, j, k] * tmpDiff[k] 586 | tmpIMEql[j] = tmpValuePDF 587 | for j in range(5): 588 | tracerPDF[i, indices, j] = tracerPDF[i, indices, j] + tmpIMEql[j] 589 | 590 | """ 591 | Implement MRT scheme to the transport part (linear equilibrium function) 592 | """ 593 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:], \ 594 | float64[:], float64[:, :], float64[:, :, :], float64[:, :], \ 595 | float64[:, :, :], float64[:])') 596 | def calCollisionTransportQuadraticEqlMRTGPU(totalNodes, xDim, numTracers, unitVX, unitVY, \ 597 | velocityVX, velocityVY, tracerConc, tracerPDF, transportM, \ 598 | inverseRelaxationMS, weightsCoeff): 599 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 600 | by = cuda.blockIdx.y 601 | indices = by * xDim + bx * bDimX + tx 602 | 603 | sharedTM = cuda.shared.array(shape=(5, 5), dtype = float64) 604 | sharedWeights = cuda.shared.array(shape = (5,), dtype = float64) 605 | # sharedInverseTM = cuda.shared.array(shape = (5, 5), dtype = float64) 606 | # sharedCollisionS = cuda.shared.array(shape = (5, 5), dtype = float64) 607 | 608 | for i in range(5): 609 | for j in range(5): 610 | sharedTM[i, j] = transportM[i, j] 611 | for i in range(5): 612 | sharedWeights[i] = weightsCoeff[i] 613 | # sharedInverseTM = inverseTransportM[i, j] 614 | if (indices < totalNodes): 615 | tmpVX = 0.0 616 | tmpEql = cuda.local.array(shape = (5,), dtype = float64) 617 | tmpMEql = cuda.local.array(shape = (5, ), dtype = float64) 618 | tmpIMEql = cuda.local.array(shape = (5,), dtype = float64) 619 | tmpPDFM = cuda.local.array(shape = (5,), dtype = float64) 620 | tmpPDFIM = cuda.local.array(shape = (5,), dtype = float64) 621 | for i in range(numTracers): 622 | for j in range(5): 623 | # tmpEql[j] = tracerConc[i, indices] * sharedWeights[j] * (1. + \ 624 | # 3. * (unitVX[j] * velocityVX[indices] + unitVY[j] * \ 625 | # velocityVY[indices]) + 4.5 * (unitVX[j] * velocityVX[indices] + \ 626 | # unitVY[indices] * velocityVY[indices]) * (unitVX[j] * \ 627 | # velocityVX[indices] + unitVY[j] * velocityVY[indices]) - 1.5 * \ 628 | # (velocityVX[indices] * velocityVX[indices] + velocityVY[indices] * \ 629 | # velocityVY[indices])) 630 | tmpEql[j] = tracerConc[i, indices] * sharedWeights[j] * (1. + \ 631 | 3. * (unitVX[j] * tmpVX + unitVY[j] * \ 632 | velocityVY[indices]) + 4.5 * (unitVX[j] * tmpVX + \ 633 | unitVY[indices] * velocityVY[indices]) * (unitVX[j] * \ 634 | tmpVX + unitVY[j] * velocityVY[indices]) - 1.5 * \ 635 | (tmpVX * tmpVX + velocityVY[indices] * \ 636 | velocityVY[indices])) 637 | # (valueJDE[i, j] + 1./2. * \ 638 | # (unitVX[j] * velocityVX[indices] + unitVY[j] * \ 639 | # velocityVY[indices])) 640 | for j in range(5): 641 | tmpValueEql = 0.; tmpValuePDF = 0. 642 | for k in range(5): 643 | tmpValueEql += sharedTM[j, k] * tmpEql[k] 644 | tmpValuePDF += tracerPDF[i, indices, k] * sharedTM[j, k] 645 | tmpMEql[j] = tmpValueEql; tmpPDFM[j] = tmpValuePDF 646 | 647 | for j in range(5): 648 | tmpValueEql = 0.; tmpValuePDF = 0. 649 | for k in range(5): 650 | tmpValueEql += inverseRelaxationMS[i, j, k] * tmpMEql[k] 651 | tmpValuePDF += inverseRelaxationMS[i, j, k] * tmpPDFM[k] 652 | tmpIMEql[j] = tmpValueEql; tmpPDFIM[j] = tmpValuePDF 653 | tracerPDF[i, indices, j] = -tmpIMEql[j] + tmpPDFIM[j] + tracerPDF[i, \ 654 | indices, j] 655 | 656 | """ 657 | Implement constant concentration boundary with anti-bounce back mehod 658 | """ 659 | @cuda.jit('void(int64, int64, int64, int64, int64, int64[:], int64[:], float64[:],\ 660 | float64[:], float64[:, :, :])') 661 | def calAntiCollisionConcBoundary(totalNodes, xDim, numTracers, ny, nx, fluidNodes, \ 662 | neighboringTRNodes, concBoundary, weightsCoeff,\ 663 | tracerPDF): 664 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 665 | by = cuda.blockIdx.y 666 | indices = by * xDim + bx * bDimX + tx 667 | 668 | if (indices < totalNodes): 669 | tmpLoc = fluidNodes[indices] 670 | if (tmpLoc >=(ny - 2) * nx and tmpLoc < (ny - 1) * nx): 671 | for i in range(numTracers): 672 | tmpNewPDF = -tracerPDF[i, indices, 3] + 2. * weightsCoeff[3] * \ 673 | concBoundary[i] 674 | upperNeighbor = neighboringTRNodes[4 * indices + 2] 675 | tracerPDF[i, upperNeighbor, 4] = tmpNewPDF 676 | 677 | """ 678 | Implement constant concentration boundary condition with Inamuro's method 679 | """ 680 | @cuda.jit('void(int64, int64, int64, int64, int64, int64[:], int64[:], float64[:], \ 681 | float64[:], float64[:, :, :])') 682 | def calInamuroConstConcBoundary(totalNodes, xDim, numTracers, ny, nx, fluidNodes, \ 683 | neighboringTRNodes, concBoundary, weightsCoeff, \ 684 | tracerPDF): 685 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 686 | by = cuda.blockIdx.y 687 | indices = by * xDim + bx * bDimX + tx 688 | 689 | if (indices < totalNodes): 690 | tmpLoc = fluidNodes[indices] 691 | if (tmpLoc >=(ny - 1) * nx and tmpLoc < ny * nx): 692 | for i in range(numTracers): 693 | tmpSumPDF = tracerPDF[i, indices, 0] + tracerPDF[i, indices, 1] + \ 694 | tracerPDF[i, indices, 2] + tracerPDF[i, indices, 3] 695 | tmpUnknownConc = (concBoundary[i] - tmpSumPDF) / weightsCoeff[4] 696 | tracerPDF[i, indices, 4] = weightsCoeff[4] * tmpUnknownConc 697 | 698 | 699 | """ 700 | Implement D2Q9 for transport 701 | """ 702 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:], \ 703 | float64[:], float64[:], float64[:, :], float64[:, :, :], float64[:])') 704 | def calCollisionQ9(totalNodes, xDim, numTracers, unitVX, unitVY, \ 705 | velocityVX, velocityVY, tauDiff, tracerConc, tracerPDF, weightsCoeff): 706 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 707 | by = cuda.blockIdx.y 708 | indices = by * xDim + bx * bDimX + tx 709 | 710 | sharedWeights = cuda.shared.array(shape = (9,), dtype = float64) 711 | for i in range(9): 712 | sharedWeights[i] = weightsCoeff[i] 713 | # sharedInverseTM = cuda.shared.array(shape = (5, 5), dtype = float64) 714 | # sharedCollisionS = cuda.shared.array(shape = (5, 5), dtype = float64) 715 | 716 | # sharedInverseTM = inverseTransportM[i, j] 717 | if (indices < totalNodes): 718 | for i in range(numTracers): 719 | for j in range(9): 720 | tmpEql = tracerConc[i, indices] * sharedWeights[j] * (1. + \ 721 | 3. * (unitVX[j] * velocityVX[indices] + unitVY[j] * \ 722 | velocityVY[indices])) 723 | # + 4.5 * (unitVX[j] * velocityVX[indices] + \ 724 | # unitVY[indices] * velocityVY[indices]) * (unitVX[j] * \ 725 | # velocityVX[indices] + unitVY[j] * velocityVY[indices]) - 1.5 * \ 726 | # (velocityVX[indices] * velocityVX[indices] + velocityVY[indices] * \ 727 | # velocityVY[indices])) 728 | tracerPDF[i, indices, j] = -(tracerPDF[i, indices, j] - tmpEql)/tauDiff[i] + \ 729 | tracerPDF[i, indices, j] 730 | 731 | """ 732 | Calculate the streaming process1 733 | """ 734 | @cuda.jit('void(int64, int64, int64, int64[:], int64[:], float64[:, :, :], \ 735 | float64[:, :, :])') 736 | def calStreaming1GPU(totalNum, numFluids, xDim, fluidNodes, neighboringNodes, \ 737 | fluidPDF, fluidPDFNew): 738 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 739 | by = cuda.blockIdx.y 740 | indices = by * xDim + bx * bDimX + tx 741 | if (indices < totalNum): 742 | tmpArray = cuda.local.array(shape = (8, ), dtype = float64) 743 | for i in range(8): 744 | tmpArray[i] = 0. 745 | #Eastern node 746 | tmpStart = 8 * indices 747 | if (neighboringNodes[tmpStart] != -1): 748 | tmpE = neighboringNodes[tmpStart] 749 | for i in range(numFluids): 750 | fluidPDFNew[i, tmpE, 1] = fluidPDF[i, indices, 1] 751 | elif (neighboringNodes[tmpStart] == -1): 752 | for i in range(numFluids): 753 | fluidPDFNew[i, indices, 3] = fluidPDF[i, indices, 1] 754 | #Northern node 755 | tmpStart += 1 756 | if (neighboringNodes[tmpStart] != -1): 757 | tmpN = neighboringNodes[tmpStart] 758 | for i in range(numFluids): 759 | fluidPDFNew[i, tmpN, 2] = fluidPDF[i, indices, 2] 760 | elif (neighboringNodes[tmpStart] == -1): 761 | for i in range(numFluids): 762 | fluidPDFNew[i, indices, 4] = fluidPDF[i, indices, 2] 763 | #Western node 764 | tmpStart += 1 765 | if (neighboringNodes[tmpStart] != -1): 766 | tmpW = neighboringNodes[tmpStart] 767 | for i in range(numFluids): 768 | fluidPDFNew[i, tmpW, 3] = fluidPDF[i, indices, 3] 769 | elif (neighboringNodes[tmpStart] == -1): 770 | for i in range(numFluids): 771 | fluidPDFNew[i, indices, 1] = fluidPDF[i, indices, 3] 772 | #Southern node 773 | tmpStart += 1 774 | if (neighboringNodes[tmpStart] != -1): 775 | tmpS = neighboringNodes[tmpStart] 776 | for i in range(numFluids): 777 | fluidPDFNew[i, tmpS, 4] = fluidPDF[i, indices, 4] 778 | elif (neighboringNodes[tmpStart] == -1): 779 | for i in range(numFluids): 780 | fluidPDFNew[i, indices, 2] = fluidPDF[i, indices, 4] 781 | #Northeastern node 782 | tmpStart += 1 783 | if (neighboringNodes[tmpStart] != -1): 784 | tmpNE = neighboringNodes[tmpStart] 785 | for i in range(numFluids): 786 | fluidPDFNew[i, tmpNE, 5] = fluidPDF[i, indices, 5] 787 | elif (neighboringNodes[tmpStart] == -1): 788 | for i in range(numFluids): 789 | fluidPDFNew[i, indices, 7] = fluidPDF[i, indices, 5] 790 | #Northwestern node 791 | tmpStart += 1 792 | if (neighboringNodes[tmpStart] != -1): 793 | tmpNW = neighboringNodes[tmpStart] 794 | for i in range(numFluids): 795 | fluidPDFNew[i, tmpNW, 6] = fluidPDF[i, indices, 6] 796 | elif (neighboringNodes[tmpStart] == -1): 797 | for i in range(numFluids): 798 | fluidPDFNew[i, indices, 8] = fluidPDF[i, indices, 6] 799 | #Southwestern node 800 | tmpStart += 1 801 | if (neighboringNodes[tmpStart] != -1): 802 | tmpSW = neighboringNodes[tmpStart] 803 | for i in range(numFluids): 804 | fluidPDFNew[i, tmpSW, 7] = fluidPDF[i, indices, 7] 805 | elif (neighboringNodes[tmpStart] == -1): 806 | for i in range(numFluids): 807 | fluidPDFNew[i, indices, 5] = fluidPDF[i, indices, 7] 808 | #Sourtheastern node 809 | tmpStart += 1 810 | if (neighboringNodes[tmpStart] != -1): 811 | tmpSE = neighboringNodes[tmpStart] 812 | for i in range(numFluids): 813 | fluidPDFNew[i, tmpSE, 8] = fluidPDF[i, indices, 8] 814 | elif (neighboringNodes[tmpStart] == -1): 815 | for i in range(numFluids): 816 | fluidPDFNew[i, indices, 6] = fluidPDF[i, indices, 8] 817 | cuda.syncthreads() 818 | 819 | """ 820 | Calculate the streaming process 2 821 | """ 822 | @cuda.jit('void(int64, int64, int64, float64[:, :, :], float64[:, :, :])') 823 | def calStreaming2GPU(totalNum, numFluids, xDim, fluidPDFNew, fluidPDF): 824 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 825 | by = cuda.blockIdx.y 826 | indices = by * xDim + bx * bDimX + tx 827 | 828 | if (indices < totalNum): 829 | for i in range(numFluids): 830 | for j in range(1, 9): 831 | fluidPDF[i, indices, j] = fluidPDFNew[i, indices, j] 832 | cuda.syncthreads() 833 | 834 | """ 835 | Deal with the interface boundary 836 | """ 837 | @cuda.jit('void(int64, int64, int64, int64, int64[:], float64[:], float64[:], \ 838 | float64[:, :], float64[:, :, :], boolean[:])') 839 | def calTransportInterfaceQ9GPU(totalNodes, xDim, numTracers, numScheme, neighboringNodes, \ 840 | velocityVX, velocityVY, tracerConc, tracerPDF, distriField): 841 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 842 | by = cuda.blockIdx.y 843 | indices = by * xDim + bx * bDimX + tx 844 | 845 | if (indices < totalNodes): 846 | if distriField[indices] == 1: 847 | for i in range(numTracers): 848 | tmpStart = 8 * indices 849 | tmpDirection = 0 850 | for j in range(1, numScheme): 851 | tmpDirection += 1 852 | tmpIndices = neighboringNodes[tmpStart] 853 | if (tmpIndices >= 0 and distriField[tmpIndices] == 0): 854 | if tmpDirection == 1: 855 | # tmpNeighboring = neighboringNodes[tmpStart + 1] 856 | # if (tmpNeighboring >= 0 and distriField[tmpNeighboring] != 0): 857 | # tracerConc[i, indices] = tracerConc[i, tmpNeighboring] 858 | # tracerPDF[i, indices, tmpDirection + 2] = -velocityVX[indices] * \ 859 | # tracerConc[i, tmpNeighboring] + tracerPDF[i, indices, tmpDirection] 860 | tracerPDF[i, indices, tmpDirection + 2] = tracerPDF[i, tmpIndices, tmpDirection] 861 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 862 | # elif (tmpNeighboring >= 0 and distriField[tmpNeighboring] == 0): 863 | # tracerPDF[i, indices, tmpDirection + 1] = tracerPDF[i, tmpIndices, tmpDirection] 864 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 865 | # elif tmpNeighboring < 0: 866 | # tracerPDF[i, indices, tmpDirection + 1] = tracerPDF[i, tmpIndices, tmpDirection] 867 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 868 | elif tmpDirection == 2: 869 | # tmpNeighboring = neighboringNodes[tmpStart + 2] 870 | # if (tmpNeighboring >= 0 and distriField[tmpNeighboring] != 0): 871 | # tracerConc[i, indices] = tracerConc[i, tmpNeighboring] 872 | # tracerPDF[i, indices, tmpDirection + 2] = -velocityVY[indices] * \ 873 | # tracerConc[i, tmpNeighboring] + tracerPDF[i, indices, tmpDirection] 874 | tracerPDF[i, indices, tmpDirection + 2] = tracerPDF[i, tmpIndices, tmpDirection] 875 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 876 | # elif (tmpNeighboring >= 0 and distriField[tmpNeighboring] == 0): 877 | # tracerPDF[i, indices, tmpDirection + 2] = tracerPDF[i, tmpIndices, tmpDirection] 878 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 879 | # elif tmpNeighboring < 0: 880 | # tracerPDF[i, indices, tmpDirection + 2] = tracerPDF[i, tmpIndices, tmpDirection] 881 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 882 | elif tmpDirection == 3: 883 | # tmpNeighboring = neighboringNodes[tmpStart - 2] 884 | # if (tmpNeighboring >= 0 and distriField[tmpNeighboring] != 0): 885 | # tracerConc[i, indices] = tracerConc[i, tmpNeighboring] 886 | # tracerPDF[i, indices, tmpDirection - 2] = velocityVX[indices] * \ 887 | # tracerConc[i, tmpNeighboring] + tracerPDF[i, indices, tmpDirection] 888 | tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 889 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 890 | # elif (tmpNeighboring >= 0 and distriField[tmpNeighboring] == 0): 891 | # tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 892 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 893 | # elif tmpNeighboring < 0: 894 | # tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 895 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 896 | elif tmpDirection == 4: 897 | # tmpNeighboring = neighboringNodes[tmpStart - 2] 898 | # if (tmpNeighboring >= 0 and distriField[tmpNeighboring] != 0): 899 | # tracerConc[i, indices] = tracerConc[i, tmpNeighboring] 900 | # tracerPDF[i, indices, tmpDirection - 2] = velocityVY[indices] * \ 901 | # tracerConc[i, tmpNeighboring] + tracerPDF[i, indices, tmpDirection] 902 | tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 903 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 904 | # elif (tmpNeighboring >= 0 and distriField[tmpNeighboring] == 0): 905 | # tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 906 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 907 | # elif tmpNeighboring < 0: 908 | # tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 909 | # tracerPDF[i, tmpIndices, tmpDirection] = 0. 910 | elif tmpDirection == 5: 911 | tracerPDF[i, indices, tmpDirection + 2] = tracerPDF[i, tmpIndices, tmpDirection] 912 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 913 | elif tmpDirection == 6: 914 | tracerPDF[i, indices, tmpDirection + 2] = tracerPDF[i, tmpIndices, tmpDirection] 915 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 916 | elif tmpDirection == 7: 917 | tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 918 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 919 | elif tmpDirection == 8: 920 | tracerPDF[i, indices, tmpDirection - 2] = tracerPDF[i, tmpIndices, tmpDirection] 921 | tracerPDF[i, tmpIndices, tmpDirection] = 0. 922 | tmpStart += 1 923 | cuda.syncthreads() 924 | 925 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], boolean[:], float64[:], \ 926 | float64[:], float64[:], float64[:], float64[:], float64[:, :], float64[:, :, :])') 927 | def calUpdateConcInTransportDomainByVQ9(totalNodes, numTracers, xDim, totalTracer, totalOld, \ 928 | transportDomain, physicalVX, physicalVY, \ 929 | unitVX, unitVY, weightsCoeff, tracerConc, tracerPDF): 930 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 931 | by = cuda.blockIdx.y 932 | indices = by * xDim + bx * bDimX + tx 933 | sharedWeights = cuda.shared.array(shape = (5,), dtype = float64) 934 | for i in range(9): 935 | sharedWeights[i] = weightsCoeff[i] 936 | if (indices < totalNodes): 937 | tmpVNorm = math.sqrt(physicalVX[indices] * physicalVX[indices] + \ 938 | physicalVY[indices] * physicalVY[indices]) 939 | if (transportDomain[indices] == 1 and tmpVNorm > 1e-10): 940 | for i in range(numTracers): 941 | tmpExtraConc = tracerConc[i, indices] * \ 942 | totalOld[i] / totalTracer[i] 943 | tracerConc[i, indices] += tmpExtraConc 944 | for j in range(9): 945 | tracerPDF[i, indices, j] = tracerConc[i, indices] * sharedWeights[j] * (1. + \ 946 | 3. * (unitVX[j] * physicalVX[indices] + unitVY[j] * \ 947 | physicalVY[indices]) + 4.5 * (unitVX[j] * physicalVX[indices] + \ 948 | unitVY[indices] * physicalVY[indices]) * (unitVX[j] * \ 949 | physicalVX[indices] + unitVY[j] * physicalVY[indices]) - 1.5 * \ 950 | (physicalVX[indices] * physicalVX[indices] + physicalVY[indices] * \ 951 | physicalVY[indices])) 952 | 953 | """ 954 | Update the domain for the transport 955 | """ 956 | @cuda.jit('void(int64, int64, float64, float64[:], float64[:])') 957 | def calValueTransportDomain(totalNodes, xDim, critiriaValue, valueTransportDomain, \ 958 | fluidRhoR): 959 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 960 | by = cuda.blockIdx.y 961 | indices = by * xDim + bx * bDimX + tx 962 | 963 | if (indices < totalNodes): 964 | tmpRho = fluidRhoR[indices] 965 | if (tmpRho > critiriaValue): 966 | valueTransportDomain[indices] = -(1. - 1.) 967 | else: 968 | valueTransportDomain[indices] = -(1. - 0.) 969 | 970 | """ 971 | Update the tracer PDF due to the interface effect 972 | """ 973 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:], \ 974 | float64[:], float64[:], float64[:], float64[:], float64[:, :], \ 975 | float64[:, :, :])') 976 | def calTransportWithInterfaceD2Q5(totalNodes, xDim, numTracers, betaTracer, 977 | valueTransportDomain, unitEX, unitEY, gradientX,\ 978 | gradientY, weightsCoeff, tracerConc, tracerPDF): 979 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 980 | by = cuda.blockIdx.y 981 | indices = by * xDim + bx * bDimX + tx 982 | 983 | sharedEX = cuda.shared.array(shape = (4,), dtype = float64) 984 | sharedEY = cuda.shared.array(shape = (4,), dtype = float64) 985 | 986 | sharedEX[0] = unitEX[1]; sharedEX[1] = unitEX[3]; sharedEX[2] = unitEX[2] 987 | sharedEX[3] = unitEX[4] 988 | sharedEY[0] = unitEY[1]; sharedEY[1] = unitEY[3]; sharedEY[2] = unitEY[2] 989 | sharedEY[3] = unitEY[4] 990 | if (indices < totalNodes): 991 | 992 | tmpGradientNorm = math.sqrt(gradientX[indices] * gradientX[indices] + \ 993 | gradientY[indices] * gradientY[indices]) 994 | if tmpGradientNorm > 1.0e-8: 995 | unitGX = -gradientX[indices] / tmpGradientNorm 996 | unitGY = -gradientY[indices] / tmpGradientNorm 997 | unitGradNorm = math.sqrt(unitGX * unitGX + unitGY * unitGY) 998 | else: 999 | unitGX = 0.; unitGY = 0.; unitGradNorm = 0. 1000 | for i in range(numTracers): 1001 | for j in range(4): 1002 | tmpEq = weightsCoeff[j + 1] * tracerConc[i, indices] 1003 | tmpUnitNorm = math.sqrt(sharedEX[j] * sharedEX[j] + sharedEY[j] * \ 1004 | sharedEY[j]) 1005 | if (unitGradNorm > 1.0e-8 and tmpUnitNorm > 1.0e-8): 1006 | cosTheta = (sharedEX[j] * unitGX + sharedEY[j] * unitGY) / \ 1007 | (tmpUnitNorm * unitGradNorm) 1008 | else: 1009 | cosTheta = 0. 1010 | tracerPDF[i, indices, j + 1] = tracerPDF[i, indices, j + 1] + betaTracer[i] * \ 1011 | valueTransportDomain[indices] * tmpEq * cosTheta 1012 | 1013 | """ 1014 | Update the tracer PDF due to the interface effect 1015 | """ 1016 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:], \ 1017 | float64[:], float64[:], float64[:], float64[:], float64[:, :], \ 1018 | float64[:, :, :])') 1019 | def calTransportWithInterfaceD2Q9(totalNodes, xDim, numTracers, betaTracer, 1020 | valueTransportDomain, unitEX, unitEY, gradientX,\ 1021 | gradientY, weightsCoeff, tracerConc, tracerPDF): 1022 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 1023 | by = cuda.blockIdx.y 1024 | indices = by * xDim + bx * bDimX + tx 1025 | 1026 | if (indices < totalNodes): 1027 | tmpGradientNorm = math.sqrt(gradientX[indices] * gradientX[indices] + \ 1028 | gradientY[indices] * gradientY[indices]) 1029 | if tmpGradientNorm > 1.0e-8: 1030 | unitGX = -gradientX[indices] / tmpGradientNorm 1031 | unitGY = -gradientY[indices] / tmpGradientNorm 1032 | unitGradNorm = math.sqrt(unitGX * unitGX + unitGY * unitGY) 1033 | else: 1034 | unitGX = 0.; unitGY = 0.; unitGradNorm = 0. 1035 | for i in range(numTracers): 1036 | for j in range(1, 9): 1037 | tmpEq = weightsCoeff[j] * tracerConc[i, indices] 1038 | tmpUnitNorm = math.sqrt(unitEX[j] * unitEX[j] + unitEY[j] * unitEY[j]) 1039 | if (unitGradNorm > 1.0e-8 and tmpUnitNorm > 1.0e-8): 1040 | cosTheta = (unitEX[j] * unitGX + unitEY[j] * unitGY) / \ 1041 | (tmpUnitNorm * unitGradNorm) 1042 | else: 1043 | cosTheta = 0. 1044 | tracerPDF[i, indices, j] = tracerPDF[i, indices, j] + betaTracer[i] * \ 1045 | valueTransportDomain[indices] * tmpEq * cosTheta 1046 | 1047 | """ 1048 | Implement MRT scheme to the transport part (linear equilibrium function) 1049 | """ 1050 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:], \ 1051 | float64[:], float64[:, :], float64[:, :, :], \ 1052 | float64[:, :], float64[:, :, :], float64[:])') 1053 | def calCollisionTransportLinearEqlMRTGPUD2Q9(totalNodes, xDim, numTracers, unitVX, unitVY, \ 1054 | velocityVX, velocityVY, tracerConc, tracerPDF, transportM, \ 1055 | inverseRelaxationMS, weightsCoeff): 1056 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 1057 | by = cuda.blockIdx.y 1058 | indices = by * xDim + bx * bDimX + tx 1059 | 1060 | # sharedTM = cuda.shared.array(shape=(9, 9), dtype = float64) 1061 | # sharedWeights = cuda.shared.array(shape = (9,), dtype = float64) 1062 | # sharedInverseTM = cuda.shared.array(shape = (5, 5), dtype = float64) 1063 | # sharedCollisionS = cuda.shared.array(shape = (5, 5), dtype = float64) 1064 | 1065 | # for i in range(9): 1066 | # for j in range(9): 1067 | # sharedTM[i, j] = transportM[i, j] 1068 | # for i in range(9): 1069 | # sharedWeights[i] = weightsCoeff[i] 1070 | # sharedInverseTM = inverseTransportM[i, j] 1071 | if (indices < totalNodes): 1072 | tmpEql = cuda.local.array(shape = (9,), dtype = float64) 1073 | # tmpMEql = cuda.local.array(shape = (5, ), dtype = float64) 1074 | tmpIMEql = cuda.local.array(shape = (9,), dtype = float64) 1075 | # tmpPDFM = cuda.local.array(shape = (5,), dtype = float64) 1076 | # tmpPDFIM = cuda.local.array(shape = (5,), dtype = float64) 1077 | tmpDiff = cuda.local.array(shape = (9,), dtype = float64) 1078 | for i in range(numTracers): 1079 | for j in range(9): 1080 | # tmpEql[j] = tracerConc[i, indices] * sharedWeights[j] * (1. + \ 1081 | # 3. * (unitVX[j] * velocityVX[indices] + unitVY[j] * \ 1082 | # velocityVY[indices])) 1083 | tmpEql[j] = tracerConc[i, indices] * weightsCoeff[j] * (1. + \ 1084 | 3. * (unitVX[j] * velocityVX[indices] + unitVY[j] * \ 1085 | velocityVY[indices])) 1086 | 1087 | for j in range(9): 1088 | tmpValueEql = 0.; tmpValuePDF = 0. 1089 | for k in range(9): 1090 | # tmpValueEql += sharedTM[j, k] * tmpEql[k] 1091 | # tmpValuePDF += tracerPDF[i, indices, k] * sharedTM[j, k] 1092 | # tmpMEql[j] = tmpValueEql; tmpPDFM[j] = tmpValuePDF 1093 | tmpValueEql += transportM[j, k] * tmpEql[k] 1094 | tmpValuePDF += tracerPDF[i, indices, k] * transportM[j, k] 1095 | tmpDiff[j] = tmpValuePDF - tmpValueEql 1096 | 1097 | for j in range(9): 1098 | # tmpValueEql = 0 1099 | tmpValuePDF = 0. 1100 | for k in range(9): 1101 | # tmpValueEql += inverseRelaxationMS[i, j, k] * tmpMEql[k] 1102 | # tmpValuePDF += inverseRelaxationMS[i, j, k] * tmpPDFM[k] 1103 | tmpValuePDF += inverseRelaxationMS[i, j, k] * tmpDiff[k] 1104 | tmpIMEql[j] = tmpValuePDF 1105 | for j in range(9): 1106 | tracerPDF[i, indices, j] = tracerPDF[i, indices, j] + tmpIMEql[j] -------------------------------------------------------------------------------- /RKCG2D/RKGPU2DBoundary.py: -------------------------------------------------------------------------------- 1 | """ 2 | File includes the boundaries for the inlet and outlet of the domain, except bounce-back boundary condition. Currently, 3 | half bounce-back boundary condition is included in the streaming step. 4 | """ 5 | 6 | """ 7 | Calculate Neumann boundary condition with Zou-He method 8 | """ 9 | @cuda.jit('void(int64, int64, int64, int64, float64, float64, int64[:], \ 10 | float64[:], float64[:], float64[:, :], float64[:, :])') 11 | def constantVelocityZHBoundaryHigherRK(totalNodes, nx, ny, xDim, \ 12 | specificVYR, specificVYB, fluidNodes, fluidRhoR, \ 13 | fluidRhoB, fluidPDFR, fluidPDFB): 14 | tx = cuda.threadIdx.x; 15 | bx = cuda.blockIdx.x; 16 | bDimX = cuda.blockDim.x 17 | by = cuda.blockIdx.y 18 | indices = by * xDim + bx * bDimX + tx 19 | 20 | if (indices < totalNodes): 21 | tmpIndex = fluidNodes[indices] 22 | if (tmpIndex < (ny - 1) * nx and tmpIndex >= (ny - 2) * nx): 23 | fluidRhoR[indices] = (fluidPDFR[indices, 0] + fluidPDFR[indices, 1] + \ 24 | fluidPDFR[indices, 3] + 2. * (fluidPDFR[indices, 2] + \ 25 | fluidPDFR[indices, 5] + fluidPDFR[indices, 6])) / \ 26 | (1. + specificVYR) 27 | fluidPDFR[indices, 4] = fluidPDFR[indices, 2] - 2. / 3. * \ 28 | fluidRhoR[indices] * specificVYR 29 | fluidPDFR[indices, 7] = fluidPDFR[indices, 5] + \ 30 | (fluidPDFR[indices, 1] - fluidPDFR[indices, 3]) / 2. - \ 31 | 1. / 6. * fluidRhoR[indices] * specificVYR 32 | fluidPDFR[indices, 8] = fluidPDFR[indices, 6] - \ 33 | (fluidPDFR[indices, 1] - fluidPDFR[indices, 3]) / 2. - \ 34 | 1. / 6. * fluidRhoR[indices] * specificVYR 35 | 36 | fluidRhoB[indices] = (fluidPDFB[indices, 0] + fluidPDFB[indices, 1] + \ 37 | fluidPDFB[indices, 3] + 2. * (fluidPDFB[indices, 2] + \ 38 | fluidPDFB[indices, 5] + fluidPDFB[indices, 6])) / \ 39 | (1. + specificVYB) 40 | fluidPDFB[indices, 4] = fluidPDFB[indices, 2] - 2. / 3. * \ 41 | fluidRhoB[indices] * specificVYB 42 | fluidPDFB[indices, 7] = fluidPDFB[indices, 5] + \ 43 | (fluidPDFB[indices, 1] - fluidPDFB[indices, 3]) / 2. - \ 44 | 1. / 6. * fluidRhoB[indices] * specificVYB 45 | fluidPDFB[indices, 8] = fluidPDFB[indices, 6] - \ 46 | (fluidPDFB[indices, 1] - fluidPDFB[indices, 3]) / 2. - \ 47 | 1. / 6. * fluidRhoB[indices] * specificVYB 48 | cuda.syncthreads() 49 | 50 | 51 | """ 52 | Update the ghost points with constant velocity boundary 53 | """ 54 | 55 | 56 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:], \ 57 | float64[:], float64[:], float64[:, :], float64[:, :])') 58 | def ghostPointsConstantVelocityRK(totalNodes, nx, ny, xDim, fluidNodes, \ 59 | neighboringNodes, fluidRhoR, fluidRhoB, fluidPDFR, \ 60 | fluidPDFB): 61 | tx = cuda.threadIdx.x; 62 | bx = cuda.blockIdx.x; 63 | bDimX = cuda.blockDim.x 64 | by = cuda.blockIdx.y 65 | indices = by * xDim + bx * bDimX + tx 66 | 67 | if (indices < totalNodes): 68 | tmpIndex = fluidNodes[indices] 69 | if (tmpIndex < ny * nx and tmpIndex >= (ny - 1) * nx): 70 | tmpStart = 8 * indices + 3 71 | tmpL = neighboringNodes[tmpStart] 72 | 73 | fluidPDFR[indices, 0] = fluidPDFR[tmpL, 0] 74 | fluidPDFR[indices, 1] = fluidPDFR[tmpL, 1] 75 | fluidPDFR[indices, 2] = fluidPDFR[tmpL, 2] 76 | fluidPDFR[indices, 3] = fluidPDFR[tmpL, 3] 77 | fluidPDFR[indices, 4] = fluidPDFR[tmpL, 4] 78 | fluidPDFR[indices, 5] = fluidPDFR[tmpL, 5] 79 | fluidPDFR[indices, 6] = fluidPDFR[tmpL, 6] 80 | fluidPDFR[indices, 7] = fluidPDFR[tmpL, 7] 81 | fluidPDFR[indices, 8] = fluidPDFR[tmpL, 8] 82 | fluidRhoR[indices] = fluidPDFR[indices, 0] + fluidPDFR[indices, 1] + \ 83 | fluidPDFR[indices, 2] + fluidPDFR[indices, 3] + \ 84 | fluidPDFR[indices, 4] + fluidPDFR[indices, 5] + \ 85 | fluidPDFR[indices, 6] + fluidPDFR[indices, 7] + \ 86 | fluidPDFR[indices, 8] 87 | 88 | fluidPDFB[indices, 0] = fluidPDFB[tmpL, 0] 89 | fluidPDFB[indices, 1] = fluidPDFB[tmpL, 1] 90 | fluidPDFB[indices, 2] = fluidPDFB[tmpL, 2] 91 | fluidPDFB[indices, 3] = fluidPDFB[tmpL, 3] 92 | fluidPDFB[indices, 4] = fluidPDFB[tmpL, 4] 93 | fluidPDFB[indices, 5] = fluidPDFB[tmpL, 5] 94 | fluidPDFB[indices, 6] = fluidPDFB[tmpL, 6] 95 | fluidPDFB[indices, 7] = fluidPDFB[tmpL, 7] 96 | fluidPDFB[indices, 8] = fluidPDFB[tmpL, 8] 97 | fluidRhoB[indices] = fluidPDFB[indices, 0] + fluidPDFB[indices, 1] + \ 98 | fluidPDFB[indices, 2] + fluidPDFB[indices, 3] + \ 99 | fluidPDFB[indices, 4] + fluidPDFB[indices, 5] + \ 100 | fluidPDFB[indices, 6] + fluidPDFB[indices, 7] + \ 101 | fluidPDFB[indices, 8] 102 | cuda.syncthreads() 103 | 104 | 105 | """ 106 | Calculate the outlet boundary with convective flow method. 107 | """ 108 | 109 | 110 | @cuda.jit('void(int64, int64, int64, int64[:], int64[:], float64[:, :], float64[:, :], \ 111 | float64[:], float64[:])') 112 | def convectiveOutletGPU(totalNodes, nx, xDim, fluidNodes, neighboringNodes, \ 113 | fluidPDFR, fluidPDFB, fluidRhoR, fluidRhoB): 114 | tx = cuda.threadIdx.x; 115 | bx = cuda.blockIdx.x; 116 | bDimX = cuda.blockDim.x 117 | by = cuda.blockIdx.y 118 | indices = by * xDim + bx * bDimX + tx 119 | # calculate the average velocity 120 | tmpSumV = 0. 121 | tmpStart = 3 * nx 122 | 123 | if (indices < totalNodes): 124 | tmpIndex = fluidNodes[indices] 125 | if (tmpIndex < 3 * nx and tmpIndex >= 2 * nx): 126 | tmpNeighbor = neighboringNodes[8 * indices + 1] 127 | fluidRhoR[indices] = 0.; 128 | fluidRhoB[indices] = 0. 129 | for j in range(9): 130 | fluidPDFR[indices, j] = fluidPDFR[tmpNeighbor, j] 131 | fluidPDFB[indices, j] = fluidPDFB[tmpNeighbor, j] 132 | # fluidPDFR[indices, j] = fluidPDFR[indices + nx - 2, j] 133 | # fluidPDFB[indices, j] = fluidPDFB[indices + nx - 2, j] 134 | # (fluidPDFOld[i, indices, j] + \ 135 | # averageV * fluidPDFNew[i, indices + nx, j]) / (1. + \ 136 | # averageV) 137 | fluidRhoR[indices] += fluidPDFR[indices, j] 138 | fluidRhoB[indices] += fluidPDFB[indices, j] 139 | cuda.syncthreads() 140 | 141 | 142 | """ 143 | Calculate the outlet boundary ghost nodes in second layer with convective flow method. 144 | """ 145 | 146 | 147 | @cuda.jit('void(int64, int64, int64, int64[:], int64[:], float64[:, :], float64[:, :], \ 148 | float64[:], float64[:])') 149 | def convectiveOutletGhost2GPU(totalNodes, nx, xDim, fluidNodes, neighboringNodes, \ 150 | fluidPDFR, fluidPDFB, fluidRhoR, fluidRhoB): 151 | tx = cuda.threadIdx.x; 152 | bx = cuda.blockIdx.x; 153 | bDimX = cuda.blockDim.x 154 | by = cuda.blockIdx.y 155 | indices = by * xDim + bx * bDimX + tx 156 | # calculate the average velocity 157 | tmpSumV = 0. 158 | tmpStart = 3 * nx 159 | 160 | if (indices < totalNodes): 161 | tmpIndex = fluidNodes[indices] 162 | if (tmpIndex < 2 * nx and tmpIndex >= nx): 163 | tmpNeighbor = neighboringNodes[8 * indices + 1] 164 | fluidRhoR[indices] = 0.; 165 | fluidRhoB[indices] = 0. 166 | for j in range(9): 167 | fluidPDFR[indices, j] = fluidPDFR[tmpNeighbor, j] 168 | fluidPDFB[indices, j] = fluidPDFB[tmpNeighbor, j] 169 | # fluidPDFR[indices, j] = fluidPDFR[indices + nx -2, j] 170 | ## (fluidPDFOld[i, indices, j] + \ 171 | ## averageV * fluidPDFNew[i, indices + nx, j]) / (1. + \ 172 | ## averageV) 173 | # fluidPDFB[indices, j] = fluidPDFB[indices + nx -2, j] 174 | fluidRhoR[indices] += fluidPDFR[indices, j] 175 | fluidRhoB[indices] += fluidPDFB[indices, j] 176 | cuda.syncthreads() 177 | 178 | 179 | # 180 | """ 181 | Calculate the outlet boundary ghost nodes in first layer with convective flow method. 182 | """ 183 | 184 | 185 | @cuda.jit('void(int64, int64, int64, int64[:], int64[:], float64[:, :], float64[:, :], \ 186 | float64[:], float64[:])') 187 | def convectiveOutletGhost3GPU(totalNodes, nx, xDim, fluidNodes, neighboringNodes, \ 188 | fluidPDFR, fluidPDFB, fluidRhoR, fluidRhoB): 189 | tx = cuda.threadIdx.x; 190 | bx = cuda.blockIdx.x; 191 | bDimX = cuda.blockDim.x 192 | by = cuda.blockIdx.y 193 | indices = by * xDim + bx * bDimX + tx 194 | # calculate the average velocity 195 | tmpSumV = 0. 196 | tmpStart = 3 * nx 197 | 198 | if (indices < totalNodes): 199 | tmpIndex = fluidNodes[indices] 200 | if (tmpIndex < nx and tmpIndex >= 0): 201 | tmpNeighbor = neighboringNodes[8 * indices + 1] 202 | fluidRhoR[indices] = 0.; 203 | fluidRhoB[indices] = 0. 204 | for j in range(9): 205 | fluidPDFR[indices, j] = fluidPDFR[tmpNeighbor, j] 206 | fluidPDFB[indices, j] = fluidPDFB[tmpNeighbor, j] 207 | # (fluidPDFOld[i, indices, j] + \ 208 | # averageV * fluidPDFNew[i, indices + nx, j]) / (1. + \ 209 | # averageV) 210 | fluidRhoR[indices] += fluidPDFR[indices, j] 211 | fluidRhoB[indices] += fluidPDFB[indices, j] 212 | cuda.syncthreads() 213 | 214 | 215 | """ 216 | Calculate the boundary flow from convective-average method 217 | """ 218 | 219 | 220 | @cuda.jit("void(int64, int64, int64, int64[:], int64[:], float64[:], float64[:, :], float64[:, :], \ 221 | float64[:, :], float64[:, :])") 222 | def convectiveAverageBoundaryGPU(totalNodes, nx, xDim, fluidNodes, neighboringNodes, normalVelocity, \ 223 | fluidPDFR, fluidPDFB, fluidPDFROld, fluidPDFBOld): 224 | tx = cuda.threadIdx.x; 225 | bx = cuda.blockIdx.x; 226 | bDimX = cuda.blockDim.x 227 | by = cuda.blockIdx.y 228 | indices = by * xDim + bx * bDimX + tx 229 | 230 | if indices < totalNodes: 231 | # tmpSumVNorm = 0. 232 | # for i in range(nx - 2): 233 | # tmpSumVNorm += normalVelocity[3 * (nx - 2) + i] 234 | # averageNormalV = tmpSumVNorm / (nx - 2) 235 | # for Nth layer 236 | tmpIndex = fluidNodes[indices] 237 | if (tmpIndex < 3 * nx and tmpIndex >= 2 * nx): 238 | tmpNeighbor = neighboringNodes[8 * indices + 1] 239 | averageNormalV = abs(normalVelocity[tmpNeighbor]) 240 | for j in range(9): 241 | fluidPDFR[indices, j] = (fluidPDFROld[indices, j] + averageNormalV * \ 242 | fluidPDFR[tmpNeighbor, j]) / (1. + averageNormalV) 243 | fluidPDFB[indices, j] = (fluidPDFBOld[indices, j] + averageNormalV * \ 244 | fluidPDFB[tmpNeighbor, j]) / (1. + averageNormalV) 245 | normalVelocity[indices] = normalVelocity[tmpNeighbor] 246 | cuda.syncthreads() 247 | 248 | 249 | """ 250 | Calculate the boundary flow from convective-average method 251 | """ 252 | @cuda.jit("void(int64, int64, int64, int64[:], int64[:], float64[:], float64[:, :], float64[:, :], \ 253 | float64[:, :], float64[:, :])") 254 | def convectiveAverageBoundaryGPU2(totalNodes, nx, xDim, fluidNodes, neighboringNodes, normalVelocity, \ 255 | fluidPDFR, fluidPDFB, fluidPDFROld, fluidPDFBOld): 256 | tx = cuda.threadIdx.x; 257 | bx = cuda.blockIdx.x; 258 | bDimX = cuda.blockDim.x 259 | by = cuda.blockIdx.y 260 | indices = by * xDim + bx * bDimX + tx 261 | 262 | if indices < totalNodes: 263 | # tmpSumVNorm = 0. 264 | # for i in range(nx - 2): 265 | # tmpSumVNorm += normalVelocity[3 * (nx - 2) + i] 266 | # averageNormalV = tmpSumVNorm / (nx - 2) 267 | # #for Nth layer 268 | tmpIndex = fluidNodes[indices] 269 | if (tmpIndex < 2 * nx and tmpIndex >= nx): 270 | tmpNeighbor1 = neighboringNodes[8 * indices + 1] 271 | tmpNeighbor = neighboringNodes[8 * tmpNeighbor1 + 1] 272 | # averageNormalV = abs(normalVelocity[indices + 2 * (nx - 2)]) 273 | averageNormalV = abs(normalVelocity[tmpNeighbor]) 274 | for j in range(9): 275 | fluidPDFR[indices, j] = (fluidPDFROld[indices, j] + averageNormalV * \ 276 | fluidPDFR[tmpNeighbor1, j]) / (1. + averageNormalV) 277 | fluidPDFB[indices, j] = (fluidPDFBOld[indices, j] + averageNormalV * \ 278 | fluidPDFB[tmpNeighbor1, j]) / (1. + averageNormalV) 279 | # normalVelocity[indices] = normalVelocity[indices + 2 * (nx - 2)] 280 | normalVelocity[indices] = normalVelocity[tmpNeighbor] 281 | cuda.syncthreads() 282 | 283 | 284 | """ 285 | Calculate the boundary flow from convective-average method 286 | """ 287 | @cuda.jit("void(int64, int64, int64, int64[:], int64[:], float64[:], float64[:, :], float64[:, :], \ 288 | float64[:, :], float64[:, :])") 289 | def convectiveAverageBoundaryGPU3(totalNodes, nx, xDim, fluidNodes, neighboringNodes, normalVelocity, \ 290 | fluidPDFR, fluidPDFB, fluidPDFROld, fluidPDFBOld): 291 | tx = cuda.threadIdx.x; 292 | bx = cuda.blockIdx.x; 293 | bDimX = cuda.blockDim.x 294 | by = cuda.blockIdx.y 295 | indices = by * xDim + bx * bDimX + tx 296 | 297 | if indices < totalNodes: 298 | # tmpSumVNorm = 0. 299 | # for i in range(nx - 2): 300 | # tmpSumVNorm += normalVelocity[3 * (nx - 2) + i] 301 | # averageNormalV = tmpSumVNorm / (nx - 2) 302 | # for Nth layer 303 | tmpIndex = fluidNodes[indices] 304 | if (tmpIndex < nx and tmpIndex >= 0): 305 | tmpNeighbor2 = neighboringNodes[8 * indices + 1] 306 | tmpNeighbor1 = neighboringNodes[8 * tmpNeighbor2 + 1] 307 | tmpNeighbor = neighboringNodes[8 * tmpNeighbor1 + 1] 308 | # averageNormalV = abs(normalVelocity[indices + 3 * (nx - 2)]) 309 | averageNormalV = abs(normalVelocity[tmpNeighbor]) 310 | for j in range(9): 311 | fluidPDFR[indices, j] = (fluidPDFROld[indices, j] + averageNormalV * \ 312 | fluidPDFR[tmpNeighbor2, j]) / (1. + averageNormalV) 313 | fluidPDFB[indices, j] = (fluidPDFBOld[indices, j] + averageNormalV * \ 314 | fluidPDFB[tmpNeighbor2, j]) / (1. + averageNormalV) 315 | # normalVelocity[indices] = normalVelocity[indices + 3 * (nx - 2)] 316 | normalVelocity[indices] = normalVelocity[tmpNeighbor] 317 | cuda.syncthreads() 318 | 319 | 320 | """ 321 | Constant pressure boundary condition at the inlet of the domain 322 | """ 323 | @cuda.jit("void(int64, int64, int64, int64, float64, float64, int64[:], \ 324 | float64[:], float64[:], float64[:, :], float64[:, :])") 325 | def calConstPressureInletGPU(totalNodes, nx, ny, xDim, constPHB, constPHR, fluidNodes, \ 326 | fluidRhoB, fluidRhoR, fluidPDFB, fluidPDFR): 327 | tx = cuda.threadIdx.x; 328 | bx = cuda.blockIdx.x; 329 | bDimX = cuda.blockDim.x 330 | by = cuda.blockIdx.y 331 | indices = by * xDim + bx * bDimX + tx 332 | 333 | if indices < totalNodes: 334 | tmpIndex = fluidNodes[indices] 335 | if tmpIndex >= (ny - 2) * nx and tmpIndex < (ny - 1) * nx: 336 | # for fluid B 337 | tmpVB = -1. + (fluidPDFB[indices, 0] + \ 338 | fluidPDFB[indices, 1] + fluidPDFB[indices, 3] + \ 339 | 2. * (fluidPDFB[indices, 2] + fluidPDFB[indices, 5] + \ 340 | fluidPDFB[indices, 6])) / constPHB 341 | fluidPDFB[indices, 4] = fluidPDFB[indices, 2] - 2. / 3. * \ 342 | constPHB * tmpVB 343 | fluidPDFB[indices, 7] = fluidPDFB[indices, 5] + 1. / 2. * \ 344 | (fluidPDFB[indices, 1] - fluidPDFB[indices, 3]) - \ 345 | 1. / 6. * constPHB * tmpVB 346 | fluidPDFB[indices, 8] = fluidPDFB[indices, 6] - 1. / 2. * \ 347 | (fluidPDFB[indices, 1] - fluidPDFB[indices, 3]) - \ 348 | 1. / 6. * constPHB * tmpVB 349 | fluidRhoB[indices] = constPHB 350 | # for fluid R 351 | tmpVR = -1. + (fluidPDFR[indices, 0] + \ 352 | fluidPDFR[indices, 1] + fluidPDFR[indices, 3] + \ 353 | 2. * (fluidPDFR[indices, 2] + fluidPDFR[indices, 5] + \ 354 | fluidPDFR[indices, 6])) / constPHR 355 | fluidPDFR[indices, 4] = fluidPDFR[indices, 2] - 2. / 3. * \ 356 | constPHR * tmpVR 357 | fluidPDFR[indices, 7] = fluidPDFR[indices, 5] + 1. / 2. * \ 358 | (fluidPDFR[indices, 1] - fluidPDFR[indices, 3]) - \ 359 | 1. / 6. * constPHR * tmpVR 360 | fluidPDFR[indices, 8] = fluidPDFR[indices, 6] - 1. / 2. * \ 361 | (fluidPDFR[indices, 1] - fluidPDFR[indices, 3]) - \ 362 | 1. / 6. * constPHR * tmpVR 363 | fluidRhoR[indices] = constPHR 364 | 365 | 366 | """ 367 | Ghost nodes on the inlet boundary for the constant pressure condition 368 | """ 369 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:], \ 370 | float64[:], float64[:], float64[:, :], float64[:, :])') 371 | def ghostPointsConstPressureInletRK(totalNodes, nx, ny, xDim, fluidNodes, \ 372 | neighboringNodes, fluidRhoR, fluidRhoB, fluidPDFR, \ 373 | fluidPDFB): 374 | tx = cuda.threadIdx.x; 375 | bx = cuda.blockIdx.x; 376 | bDimX = cuda.blockDim.x 377 | by = cuda.blockIdx.y 378 | indices = by * xDim + bx * bDimX + tx 379 | 380 | if (indices < totalNodes): 381 | tmpIndex = fluidNodes[indices] 382 | if tmpIndex >= (ny - 1) * nx and tmpIndex < ny * nx: 383 | tmpStart = 8 * indices + 3 384 | tmpH = neighboringNodes[tmpStart] 385 | fluidPDFR[indices, 0] = fluidPDFR[tmpH, 0] 386 | fluidPDFR[indices, 1] = fluidPDFR[tmpH, 1] 387 | fluidPDFR[indices, 2] = fluidPDFR[tmpH, 2] 388 | fluidPDFR[indices, 3] = fluidPDFR[tmpH, 3] 389 | fluidPDFR[indices, 4] = fluidPDFR[tmpH, 4] 390 | fluidPDFR[indices, 5] = fluidPDFR[tmpH, 5] 391 | fluidPDFR[indices, 6] = fluidPDFR[tmpH, 6] 392 | fluidPDFR[indices, 7] = fluidPDFR[tmpH, 7] 393 | fluidPDFR[indices, 8] = fluidPDFR[tmpH, 8] 394 | fluidRhoR[indices] = fluidRhoR[tmpH] 395 | 396 | fluidPDFB[indices, 0] = fluidPDFB[tmpH, 0] 397 | fluidPDFB[indices, 1] = fluidPDFB[tmpH, 1] 398 | fluidPDFB[indices, 2] = fluidPDFB[tmpH, 2] 399 | fluidPDFB[indices, 3] = fluidPDFB[tmpH, 3] 400 | fluidPDFB[indices, 4] = fluidPDFB[tmpH, 4] 401 | fluidPDFB[indices, 5] = fluidPDFB[tmpH, 5] 402 | fluidPDFB[indices, 6] = fluidPDFB[tmpH, 6] 403 | fluidPDFB[indices, 7] = fluidPDFB[tmpH, 7] 404 | fluidPDFB[indices, 8] = fluidPDFB[tmpH, 8] 405 | fluidRhoB[indices] = fluidRhoB[tmpH] 406 | cuda.syncthreads() 407 | 408 | 409 | """ 410 | Constant pressure boundary condition at the outlet of the domain 411 | """ 412 | @cuda.jit("void(int64, int64, int64, float64, float64, int64[:], \ 413 | float64[:], float64[:], float64[:, :], float64[:, :])") 414 | def calConstPressureLowerGPU(totalNodes, nx, xDim, constPLB, constPLR, fluidNodes, \ 415 | fluidRhoB, fluidRhoR, fluidPDFB, fluidPDFR): 416 | tx = cuda.threadIdx.x; 417 | bx = cuda.blockIdx.x; 418 | bDimX = cuda.blockDim.x 419 | by = cuda.blockIdx.y 420 | indices = by * xDim + bx * bDimX + tx 421 | 422 | if indices < totalNodes: 423 | tmpIndex = fluidNodes[indices] 424 | if tmpIndex >= nx and tmpIndex < 2 * nx: 425 | # for fluid B 426 | tmpVB = 1. - 1. / constPLB * (fluidPDFB[indices, 0] + fluidPDFB[indices, 1] + \ 427 | fluidPDFB[indices, 3] + 2. * (fluidPDFB[indices, 4] + \ 428 | fluidPDFB[indices, 7] + fluidPDFB[indices, 8])) 429 | fluidPDFB[indices, 2] = fluidPDFB[indices, 4] + 2. / 3. * (constPLB * tmpVB) 430 | fluidPDFB[indices, 5] = fluidPDFB[indices, 7] + 0.5 * (fluidPDFB[indices, 3] - \ 431 | fluidPDFB[indices, 1]) + 1. / 6. * constPLB * tmpVB 432 | fluidPDFB[indices, 6] = fluidPDFB[indices, 8] + 0.5 * (fluidPDFB[indices, 1] - \ 433 | fluidPDFB[indices, 3]) + 1. / 6. * constPLB * tmpVB 434 | fluidRhoB[indices] = constPLB 435 | # for fluid R 436 | tmpVR = 1. - 1. / constPLR * (fluidPDFR[indices, 0] + fluidPDFR[indices, 1] + \ 437 | fluidPDFR[indices, 3] + 2. * (fluidPDFR[indices, 4] + \ 438 | fluidPDFR[indices, 7] + fluidPDFR[indices, 8])) 439 | fluidPDFR[indices, 2] = fluidPDFR[indices, 4] + 2. / 3. * constPLR * tmpVR 440 | fluidPDFR[indices, 5] = fluidPDFR[indices, 7] + 0.5 * (fluidPDFR[indices, 3] - \ 441 | fluidPDFR[indices, 1]) + 1. / 6. * constPLR * tmpVR 442 | fluidPDFR[indices, 6] = fluidPDFR[indices, 8] + 0.5 * (fluidPDFR[indices, 1] - \ 443 | fluidPDFR[indices, 3]) + 1. / 6. * constPLR * tmpVR 444 | fluidRhoR[indices] = constPLR 445 | 446 | 447 | """ 448 | Ghost nodes on the lower boundary for the constant pressure condition 449 | """ 450 | @cuda.jit('void(int64, int64, int64, int64[:], int64[:], \ 451 | float64[:], float64[:], float64[:, :], float64[:, :])') 452 | def ghostPointsConstPressureLowerRK(totalNodes, nx, xDim, fluidNodes, \ 453 | neighboringNodes, fluidRhoR, fluidRhoB, fluidPDFR, \ 454 | fluidPDFB): 455 | tx = cuda.threadIdx.x; 456 | bx = cuda.blockIdx.x; 457 | bDimX = cuda.blockDim.x 458 | by = cuda.blockIdx.y 459 | indices = by * xDim + bx * bDimX + tx 460 | 461 | if (indices < totalNodes): 462 | tmpIndex = fluidNodes[indices] 463 | if tmpIndex < nx: 464 | tmpStart = 8 * indices + 1 465 | tmpL = neighboringNodes[tmpStart] 466 | 467 | fluidPDFR[indices, 0] = fluidPDFR[tmpL, 0] 468 | fluidPDFR[indices, 1] = fluidPDFR[tmpL, 1] 469 | fluidPDFR[indices, 2] = fluidPDFR[tmpL, 2] 470 | fluidPDFR[indices, 3] = fluidPDFR[tmpL, 3] 471 | fluidPDFR[indices, 4] = fluidPDFR[tmpL, 4] 472 | fluidPDFR[indices, 5] = fluidPDFR[tmpL, 5] 473 | fluidPDFR[indices, 6] = fluidPDFR[tmpL, 6] 474 | fluidPDFR[indices, 7] = fluidPDFR[tmpL, 7] 475 | fluidPDFR[indices, 8] = fluidPDFR[tmpL, 8] 476 | fluidRhoR[indices] = fluidRhoR[tmpL] 477 | 478 | fluidPDFB[indices, 0] = fluidPDFB[tmpL, 0] 479 | fluidPDFB[indices, 1] = fluidPDFB[tmpL, 1] 480 | fluidPDFB[indices, 2] = fluidPDFB[tmpL, 2] 481 | fluidPDFB[indices, 3] = fluidPDFB[tmpL, 3] 482 | fluidPDFB[indices, 4] = fluidPDFB[tmpL, 4] 483 | fluidPDFB[indices, 5] = fluidPDFB[tmpL, 5] 484 | fluidPDFB[indices, 6] = fluidPDFB[tmpL, 6] 485 | fluidPDFB[indices, 7] = fluidPDFB[tmpL, 7] 486 | fluidPDFB[indices, 8] = fluidPDFB[tmpL, 8] 487 | fluidRhoB[indices] = fluidRhoB[tmpL] 488 | cuda.syncthreads() 489 | 490 | 491 | """ 492 | Constant pressure boundary condition on the inlet of the domain 493 | """ 494 | @cuda.jit("void(int64, int64, int64, int64, float64, float64, int64[:], \ 495 | float64[:, :], float64[:, :])") 496 | def calConstPressureHighGPU(totalNodes, nx, ny, xDim, constPHB, constPHR, fluidNodes, \ 497 | fluidPDFB, fluidPDFR): 498 | tx = cuda.threadIdx.x; 499 | bx = cuda.blockIdx.x; 500 | bDimX = cuda.blockDim.x 501 | by = cuda.blockIdx.y 502 | indices = by * xDim + bx * bDimX + tx 503 | 504 | if indices < totalNodes: 505 | tmpIndex = fluidNodes[indices] 506 | if tmpIndex >= (ny - 1) * nx and tmpIndex < ny * nx: 507 | # for fluid B 508 | tmpVB = -1. + 1. / constPHB * (fluidPDFB[indices, 0] + fluidPDFB[indices, 1] + \ 509 | fluidPDFB[indices, 3] + 2. * (fluidPDFB[indices, 2] + \ 510 | fluidPDFB[indices, 5] + fluidPDFB[indices, 6])) 511 | fluidPDFB[indices, 4] = fluidPDFB[indices, 2] - 2. / 3. * constPHB * \ 512 | tmpVB 513 | fluidPDFB[indices, 7] = fluidPDFB[indices, 5] - 0.5 * (fluidPDFB[indices, 3] - \ 514 | fluidPDFB[indices, 1]) - 1. / 6. * constPHB * tmpVB 515 | fluidPDFB[indices, 8] = fluidPDFB[indices, 6] - 0.5 * (fluidPDFB[indices, 1] - \ 516 | fluidPDFB[indices, 3]) - 1. / 6. * constPHB * tmpVB 517 | # for fluid R 518 | tmpVR = -1. + 1. / constPHR * (fluidPDFR[indices, 0] + fluidPDFR[indices, 1] + \ 519 | fluidPDFR[indices, 3] + 2. * (fluidPDFR[indices, 2] + \ 520 | fluidPDFR[indices, 5] + fluidPDFR[indices, 6])) 521 | fluidPDFR[indices, 4] = fluidPDFR[indices, 2] - 2. / 3. * constPHR * \ 522 | tmpVR 523 | fluidPDFR[indices, 7] = fluidPDFR[indices, 5] - 0.5 * (fluidPDFR[indices, 3] - \ 524 | fluidPDFR[indices, 1]) - 1. / 6. * constPHR * tmpVR 525 | fluidPDFR[indices, 8] = fluidPDFR[indices, 6] - 0.5 * (fluidPDFR[indices, 1] - \ 526 | fluidPDFR[indices, 3]) - 1. / 6. * constPHR * tmpVR 527 | 528 | 529 | """ 530 | Calculate Neumann boundary condition with Zou-He method, but no flow for the 531 | other fluid 532 | """ 533 | @cuda.jit('void(int64, int64, int64, int64, float64, float64, int64[:], \ 534 | int64[:], float64[:], float64[:], float64[:, :], float64[:, :])') 535 | def constantVelocityZHBoundaryHigherNewRK(totalNodes, nx, ny, xDim, \ 536 | specificVYR, specificVYB, fluidNodes, \ 537 | neighboringNodes, fluidRhoR, \ 538 | fluidRhoB, fluidPDFR, fluidPDFB): 539 | tx = cuda.threadIdx.x; 540 | bx = cuda.blockIdx.x; 541 | bDimX = cuda.blockDim.x 542 | by = cuda.blockIdx.y 543 | indices = by * xDim + bx * bDimX + tx 544 | 545 | if (indices < totalNodes): 546 | tmpStart = 8 * indices 547 | tmpIndex = fluidNodes[indices] 548 | if (tmpIndex < (ny - 1) * nx and tmpIndex >= (ny - 2) * nx): 549 | fluidRhoR[indices] = (fluidPDFR[indices, 0] + fluidPDFR[indices, 1] + \ 550 | fluidPDFR[indices, 3] + 2. * (fluidPDFR[indices, 2] + \ 551 | fluidPDFR[indices, 5] + fluidPDFR[indices, 6])) / \ 552 | (1. + specificVYR) 553 | fluidPDFR[indices, 4] = fluidPDFR[indices, 2] - 2. / 3. * \ 554 | fluidRhoR[indices] * specificVYR 555 | fluidPDFR[indices, 7] = fluidPDFR[indices, 5] + \ 556 | (fluidPDFR[indices, 1] - fluidPDFR[indices, 3]) / 2. - \ 557 | 1. / 6. * fluidRhoR[indices] * specificVYR 558 | fluidPDFR[indices, 8] = fluidPDFR[indices, 6] - \ 559 | (fluidPDFR[indices, 1] - fluidPDFR[indices, 3]) / 2. - \ 560 | 1. / 6. * fluidRhoR[indices] * specificVYR 561 | 562 | # for retreating fluid 563 | tmpUpper = neighboringNodes[tmpStart + 1] 564 | fluidPDFB[indices, 4] = fluidPDFB[tmpUpper, 2] 565 | tmpFor7 = neighboringNodes[tmpUpper * 8] 566 | tmpFor8 = neighboringNodes[tmpUpper * 8 + 2] 567 | if tmpFor7 >= 0: 568 | fluidPDFB[indices, 7] = fluidPDFB[tmpFor7, 5] 569 | if tmpFor8 >= 0: 570 | fluidPDFB[indices, 8] = fluidPDFB[tmpFor8, 6] 571 | 572 | 573 | """ 574 | Constant pressure boundary condition at the outlet of the domain 575 | """ 576 | 577 | 578 | @cuda.jit("void(int64, int64, int64, float64, int64[:], \ 579 | float64[:, :], float64[:], float64[:], float64[:], \ 580 | float64[:, :], float64[:, :])") 581 | def calConstPressureLowerGPUTotal(totalNodes, nx, xDim, constPL, fluidNodes, \ 582 | fluidPDFTotal, physicalVY, fluidRhoR, \ 583 | fluidRhoB, fluidPDFR, fluidPDFB): 584 | tx = cuda.threadIdx.x; 585 | bx = cuda.blockIdx.x; 586 | bDimX = cuda.blockDim.x 587 | by = cuda.blockIdx.y 588 | indices = by * xDim + bx * bDimX + tx 589 | 590 | if indices < totalNodes: 591 | # if indices < 2 * nx and indices >= nx: 592 | tmpIndex = fluidNodes[indices] 593 | if tmpIndex >= nx and tmpIndex < 2 * nx: 594 | # for fluid B 595 | tmpV = 1. - 1. / constPL * (fluidPDFTotal[indices, 0] + fluidPDFTotal[indices, 1] + \ 596 | fluidPDFTotal[indices, 3] + 2. * (fluidPDFTotal[indices, 4] + \ 597 | fluidPDFTotal[indices, 7] + fluidPDFTotal[ 598 | indices, 8])) 599 | fluidPDFTotal[indices, 2] = fluidPDFTotal[indices, 4] + 2. / 3. * (constPL * tmpV) 600 | fluidPDFTotal[indices, 5] = fluidPDFTotal[indices, 7] + 0.5 * (fluidPDFTotal[indices, 3] - \ 601 | fluidPDFTotal[ 602 | indices, 1]) + 1. / 6. * constPL * tmpV 603 | fluidPDFTotal[indices, 6] = fluidPDFTotal[indices, 8] + 0.5 * (fluidPDFTotal[indices, 1] - \ 604 | fluidPDFTotal[ 605 | indices, 3]) + 1. / 6. * constPL * tmpV 606 | physicalVY[indices] = tmpV 607 | # fluid R 608 | ratioR = fluidRhoR[indices] / (fluidRhoR[indices] + fluidRhoB[indices]) 609 | fluidPDFR[indices, 2] = ratioR * fluidPDFTotal[indices, 2] 610 | fluidPDFR[indices, 5] = ratioR * fluidPDFTotal[indices, 5] 611 | fluidPDFR[indices, 6] = ratioR * fluidPDFTotal[indices, 6] 612 | # fluid B 613 | ratioB = fluidRhoB[indices] / (fluidRhoR[indices] + fluidRhoB[indices]) 614 | fluidPDFB[indices, 2] = ratioB * fluidPDFTotal[indices, 2] 615 | fluidPDFB[indices, 5] = ratioB * fluidPDFTotal[indices, 5] 616 | fluidPDFB[indices, 6] = ratioB * fluidPDFTotal[indices, 6] 617 | cuda.syncthreads() 618 | 619 | 620 | @cuda.jit('void(int64, int64, int64, int64, float64, int64[:], \ 621 | int64[:], float64[:], float64[:], float64[:, :], float64[:, :], \ 622 | float64[:, :], float64[:])') 623 | def constantTotalVelocityInlet(totalNodes, nx, ny, xDim, \ 624 | specificVY, fluidNodes, \ 625 | neighboringNodes, fluidRhoR, \ 626 | fluidRhoB, fluidPDFR, fluidPDFB, fluidPDFTotal, 627 | physicalVY): 628 | tx = cuda.threadIdx.x; 629 | bx = cuda.blockIdx.x; 630 | bDimX = cuda.blockDim.x 631 | by = cuda.blockIdx.y 632 | indices = by * xDim + bx * bDimX + tx 633 | 634 | # if (indices < totalNodes - nx and indices >= totalNodes - 2 * nx): 635 | if indices < totalNodes: 636 | tmpStart = 8 * indices 637 | tmpIndex = fluidNodes[indices] 638 | if (tmpIndex < (ny - 1) * nx and tmpIndex >= (ny - 2) * nx): 639 | tmpTotalRho = (fluidPDFTotal[indices, 0] + fluidPDFTotal[indices, 1] + \ 640 | fluidPDFTotal[indices, 3] + 2. * (fluidPDFTotal[indices, 2] + \ 641 | fluidPDFTotal[indices, 5] + fluidPDFTotal[indices, 6])) / \ 642 | (1. + specificVY) 643 | # fluidPDFTotal[indices, 4] = fluidPDFTotal[indices, 2] - 2./3. * \ 644 | # tmpTotalRho * specificVY 645 | # fluidPDFTotal[indices, 7] = fluidPDFTotal[indices, 5] + \ 646 | # (fluidPDFTotal[indices, 1] - fluidPDFTotal[indices, 3]) / 2. - \ 647 | # 1./6. * tmpTotalRho * specificVY 648 | # fluidPDFTotal[indices, 8] = fluidPDFTotal[indices, 6] - \ 649 | # (fluidPDFTotal[indices, 1] - fluidPDFTotal[indices, 3]) / 2. - \ 650 | # 1./6. * tmpTotalRho * specificVY 651 | tmpEq2 = tmpTotalRho * 1. / 9. * (1. + 3. * (1. * specificVY) + 4.5 * (0. + \ 652 | 1. * specificVY) * ( 653 | 0. + 1. * specificVY) - 1.5 * (specificVY * \ 654 | specificVY)) 655 | tmpEq4 = tmpTotalRho * 1. / 9. * (1. + 3. * (-1. * specificVY) + 4.5 * (0. + \ 656 | (-1.) * specificVY) * ( 657 | 0. + (-1.) * specificVY) - 1.5 * (specificVY * \ 658 | specificVY)) 659 | fluidPDFTotal[indices, 4] = tmpEq4 + (fluidPDFTotal[indices, 2] - tmpEq2) 660 | 661 | tmpEq5 = tmpTotalRho * 1. / 36. * (1. + 3. * (1. * specificVY + 1. * 0.) + \ 662 | 4.5 * (1. * specificVY + 1. * 0.) * (1. * specificVY + 1. * 0.) - \ 663 | 1.5 * (specificVY * specificVY)) 664 | tmpEq7 = tmpTotalRho * 1. / 36. * (1. + 3. * ((-1.) * specificVY + (-1.) * \ 665 | 0.) + 4.5 * ((-1.) * specificVY + (-1.) * 0.) * ( 666 | (-1.) * specificVY + \ 667 | (-1.) * 0.) - 1.5 * (specificVY * specificVY)) 668 | fluidPDFTotal[indices, 7] = tmpEq7 + (fluidPDFTotal[indices, 5] - tmpEq5) 669 | 670 | tmpEq6 = tmpTotalRho * 1. / 36. * (1. + 3. * ((1.) * specificVY + (-1.) * 0.) + \ 671 | 4.5 * ((1.) * specificVY + (-1.) * 0.) * (1. * specificVY + \ 672 | (-1.) * 0.) - 1.5 * ( 673 | specificVY * specificVY)) 674 | tmpEq8 = tmpTotalRho * 1. / 36. * (1. + 3. * ((-1.) * specificVY + (1.) * 0.) + \ 675 | 4.5 * ((-1.) * specificVY + 1. * 0.) * ((-1.) * specificVY + 1. * 0.) - \ 676 | 1.5 * (specificVY * specificVY)) 677 | fluidPDFTotal[indices, 8] = tmpEq8 + (fluidPDFTotal[indices, 6] - tmpEq6) 678 | 679 | # for fluid R 680 | ratioR = fluidRhoR[indices] / (fluidRhoR[indices] + fluidRhoB[indices]) 681 | fluidRhoR[indices] = ratioR * tmpTotalRho 682 | fluidPDFR[indices, 4] = ratioR * fluidPDFTotal[indices, 4] 683 | fluidPDFR[indices, 7] = ratioR * fluidPDFTotal[indices, 7] 684 | fluidPDFR[indices, 8] = ratioR * fluidPDFTotal[indices, 8] 685 | 686 | # for fluidB 687 | ratioB = fluidRhoB[indices] / (fluidRhoR[indices] + fluidRhoB[indices]) 688 | fluidRhoB[indices] = ratioB * tmpTotalRho 689 | fluidPDFB[indices, 4] = ratioB * fluidPDFTotal[indices, 4] 690 | fluidPDFB[indices, 7] = ratioB * fluidPDFTotal[indices, 7] 691 | fluidPDFB[indices, 8] = ratioB * fluidPDFTotal[indices, 8] 692 | 693 | physicalVY[indices] = specificVY -------------------------------------------------------------------------------- /ShanChen2D/ExplicitD2Q9GPU.py: -------------------------------------------------------------------------------- 1 | """ 2 | File for explicit force scheme of D2Q9 Shan-Chen model LBM. The isotropy here 3 | can be 4, 8 and 10. MRT scheme is also included 4 | """ 5 | 6 | import numpy as np 7 | import scipy as sp 8 | from math import sqrt 9 | 10 | from numba import cuda, int64, float64 11 | from numba import cuda, jit 12 | 13 | 14 | """ 15 | The calculation for the pressures in the domain. 16 | """ 17 | @cuda.jit('void(int64, int64, int64, float64[:, :], float64[:, :], float64[:, :], \ 18 | float64[:])') 19 | def calMacroPressureEX(totalNodes, numFluids, xDim, interactionCoeff, fluidRho, \ 20 | fluidPotential, fluidPressure): 21 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 22 | by = cuda.blockIdx.y 23 | indices = by * xDim + bx * bDimX + tx 24 | 25 | if (indices < totalNodes): 26 | tmpPart1 = 0.; tmpPart2 = 0. 27 | for i in range(numFluids): 28 | tmpPart1 += fluidRho[i, indices] 29 | for j in range(numFluids): 30 | tmpPart2 = interactionCoeff[i, j] * fluidPotential[i, indices] * \ 31 | fluidPotential[j, indices] 32 | fluidPressure[indices] = 1./3. * tmpPart1 + 3. * tmpPart2 33 | 34 | """ 35 | P-R equation of state for effective mass 36 | """ 37 | @cuda.jit('void(int64, int64, int64, float64, float64[:, :], float64[:, :], float64[:, :])') 38 | def calEffectiveMassPR(totalNodes, numFluids, xDim, temperature, interactionCoeff, \ 39 | fluidRho, fluidPsi): 40 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 41 | by = cuda.blockIdx.y 42 | indices = by * xDim + bx * bDimX + tx 43 | 44 | 45 | 46 | """ 47 | The explicit scheme for isotropy is 4 48 | """ 49 | @cuda.jit('void(int64, int64, int64, int64[:], int64[:], float64[:], float64[:, :], \ 50 | float64[:], float64[:, :], float64[:, :], float64[:, :])') 51 | def calExplicit4thOrderScheme(totalNodes, numFluids, xDim, fluidNodes, \ 52 | neighboringNodes, weightInter, interactionCoeff, \ 53 | interactionSolid, fluidPotential, forceX, forceY): 54 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 55 | by = cuda.blockIdx.y 56 | indices = by * xDim + bx * bDimX + tx 57 | 58 | if (indices < totalNodes): 59 | for i in range(numFluids): 60 | forceX[i, indices] = 0.; tmpGradX = 0.; tmpFXS = 0.; sumWeightX = 0. 61 | tmpFXF = 0.; sumWeightSX = 0. 62 | forceY[i, indices] = 0.; tmpGradY = 0.; tmpFYS = 0.; sumWeightY = 0 63 | tmpFYF = 0.; sumWeightSY = 0. 64 | tmpStart = indices * 8 65 | if (neighboringNodes[tmpStart] != -1): 66 | tmpE = neighboringNodes[tmpStart] 67 | for j in range(numFluids): 68 | tmpGradX += weightInter[0] *(fluidPotential[j, tmpE] - \ 69 | fluidPotential[j, indices]) * (1.) * interactionCoeff[i, j] 70 | sumWeightX += weightInter[0] 71 | elif (neighboringNodes[tmpStart] == -1): 72 | tmpFXS += -weightInter[0] * interactionSolid[i] * \ 73 | fluidPotential[i, indices] * (1.) 74 | # tmpFXS += -1./9. * interactionSolid[i] * \ 75 | # fluidPotential[i, indices] * (1.) 76 | sumWeightSX += weightInter[0] 77 | #Northern point 78 | tmpStart += 1 79 | if (neighboringNodes[tmpStart] != -1): 80 | tmpN = neighboringNodes[tmpStart] 81 | for j in range(numFluids): 82 | tmpGradY += weightInter[1] * (fluidPotential[j, tmpN] - \ 83 | fluidPotential[j, indices]) * (1.) * interactionCoeff[i, j] 84 | sumWeightY += weightInter[1] 85 | elif (neighboringNodes[tmpStart] == -1): 86 | tmpFYS += -weightInter[1] * interactionSolid[i] * \ 87 | fluidPotential[i, indices] * (1.) 88 | # tmpFYS += -1./9. * interactionSolid[i] * \ 89 | # fluidPotential[i, indices] * (1.) 90 | sumWeightSY += weightInter[1] 91 | #Western Point 92 | tmpStart += 1 93 | if (neighboringNodes[tmpStart] != -1): 94 | tmpW = neighboringNodes[tmpStart] 95 | for j in range(numFluids): 96 | tmpGradX += weightInter[2] * (fluidPotential[j, tmpW] - \ 97 | fluidPotential[j, indices]) * (-1.) * interactionCoeff[i, j] 98 | sumWeightX += weightInter[2] 99 | elif(neighboringNodes[tmpStart] == -1): 100 | tmpFXS += -weightInter[2] * interactionSolid[i] * \ 101 | fluidPotential[i, indices] * (-1.) 102 | # tmpFXS += -1./9. * interactionSolid[i] * \ 103 | # fluidPotential[i, indices] * (-1.) 104 | sumWeightSX += weightInter[2] 105 | #Southern point 106 | tmpStart += 1 107 | if (neighboringNodes[tmpStart] != -1): 108 | tmpS = neighboringNodes[tmpStart] 109 | for j in range(numFluids): 110 | tmpGradY += weightInter[3] * (fluidPotential[j, tmpS] - \ 111 | fluidPotential[j, indices]) * (-1.) * interactionCoeff[i, j] 112 | sumWeightY += weightInter[3] 113 | elif (neighboringNodes[tmpStart] == -1): 114 | tmpFYS += -weightInter[3] * interactionSolid[i] * \ 115 | fluidPotential[i, indices] * (-1.) 116 | # tmpFYS += -1./9. * interactionSolid[i] * \ 117 | # fluidPotential[i, indices] * (-1.) 118 | sumWeightSY += weightInter[3] 119 | #Northeastern point 120 | tmpStart += 1 121 | if (neighboringNodes[tmpStart] != -1): 122 | tmpNE = neighboringNodes[tmpStart] 123 | for j in range(numFluids): 124 | tmpGradX += weightInter[4] * (fluidPotential[j, tmpNE] - \ 125 | fluidPotential[j, indices]) * (1.) * interactionCoeff[i, j] 126 | tmpGradY += weightInter[4] * (fluidPotential[j, tmpNE] - \ 127 | fluidPotential[j, indices]) * (1.) * interactionCoeff[i, j] 128 | sumWeightX += weightInter[4] 129 | sumWeightY += weightInter[4] 130 | elif(neighboringNodes[tmpStart] == -1): 131 | tmpFXS += -weightInter[4] * interactionSolid[i] * \ 132 | fluidPotential[i, indices] * (1.) 133 | tmpFYS += -weightInter[4] * interactionSolid[i] * \ 134 | fluidPotential[i, indices] * (1.) 135 | # tmpFXS += -1./36. * interactionSolid[i] * \ 136 | # fluidPotential[i, indices] * (1.) 137 | # tmpFYS += -1./36. * interactionSolid[i] * \ 138 | # fluidPotential[i, indices] * (1.) 139 | sumWeightSX += weightInter[4] 140 | sumWeightSY += weightInter[4] 141 | #Northwestern point 142 | tmpStart += 1 143 | if (neighboringNodes[tmpStart] != -1): 144 | tmpNW = neighboringNodes[tmpStart] 145 | for j in range(numFluids): 146 | tmpGradX += weightInter[5] * (fluidPotential[j, tmpNW] - \ 147 | fluidPotential[j, indices]) * (-1.) * interactionCoeff[i, j] 148 | tmpGradY += weightInter[5] * (fluidPotential[j, tmpNW] - \ 149 | fluidPotential[j, indices]) * (1.) * interactionCoeff[i, j] 150 | sumWeightX += weightInter[5] 151 | sumWeightY += weightInter[5] 152 | elif (neighboringNodes[tmpStart] == -1): 153 | tmpFXS += -weightInter[5] * interactionSolid[i] * \ 154 | fluidPotential[i, indices] * (-1.) 155 | tmpFYS += -weightInter[5] * interactionSolid[i] * \ 156 | fluidPotential[i, indices] * (1.) 157 | # tmpFXS += -1/36. * interactionSolid[i] * \ 158 | # fluidPotential[i, indices] * (-1.) 159 | # tmpFYS += -1./36. * interactionSolid[i] * \ 160 | # fluidPotential[i, indices] * (1.) 161 | sumWeightSX += weightInter[5] 162 | sumWeightSY += weightInter[5] 163 | #Southwestern point 164 | tmpStart += 1 165 | if (neighboringNodes[tmpStart] != -1): 166 | tmpSW = neighboringNodes[tmpStart] 167 | for j in range(numFluids): 168 | tmpGradX += weightInter[6] * (fluidPotential[j, tmpSW] - \ 169 | fluidPotential[j, indices]) * (-1.) * interactionCoeff[i, j] 170 | tmpGradY += weightInter[6] * (fluidPotential[j, tmpSW] - \ 171 | fluidPotential[j, indices]) * (-1.) * interactionCoeff[i, j] 172 | sumWeightX += weightInter[6] 173 | sumWeightY += weightInter[6] 174 | elif (neighboringNodes[tmpStart] == -1): 175 | tmpFXS += -weightInter[6] * interactionSolid[i] * \ 176 | fluidPotential[i, indices] * (-1.) 177 | tmpFYS += -weightInter[6] * interactionSolid[i] * \ 178 | fluidPotential[i, indices] * (-1.) 179 | # tmpFXS += -1./36. * interactionSolid[i] * \ 180 | # fluidPotential[i, indices] * (-1.) 181 | # tmpFYS += -1./36. * interactionSolid[i] * \ 182 | # fluidPotential[i, indices] * (-1.) 183 | sumWeightSX += weightInter[6] 184 | sumWeightSY += weightInter[6] 185 | #Southeastern point 186 | tmpStart += 1 187 | if (neighboringNodes[tmpStart] != -1): 188 | tmpSE = neighboringNodes[tmpStart] 189 | for j in range(numFluids): 190 | tmpGradX += weightInter[7] * (fluidPotential[j, tmpSE] - \ 191 | fluidPotential[j, indices]) * (1.) * interactionCoeff[i, j] 192 | tmpGradY += weightInter[7] * (fluidPotential[j, tmpSE] - \ 193 | fluidPotential[j, indices]) * (-1.) * interactionCoeff[i, j] 194 | sumWeightX += weightInter[7] 195 | sumWeightY += weightInter[7] 196 | elif (neighboringNodes[tmpStart] == -1): 197 | tmpFXS += -weightInter[7] * interactionSolid[i] * \ 198 | fluidPotential[i, indices] * (1.) 199 | tmpFYS += -weightInter[7] * interactionSolid[i] * \ 200 | fluidPotential[i, indices] * (-1.) 201 | # tmpFXS += -1./36. * interactionSolid[i] * \ 202 | # fluidPotential[i, indices] * (1.) 203 | # tmpFYS += -1./36. * interactionSolid[i] * \ 204 | # fluidPotential[i, indices] * (-1.) 205 | sumWeightSX += weightInter[7] 206 | sumWeightSY += weightInter[7] 207 | # if (sumWeightX > 1e-12): 208 | tmpFXF = -6.0 * fluidPotential[i, indices] * tmpGradX #/ sumWeightX 209 | forceX[i, indices] += tmpFXF 210 | # if (sumWeightY > 1e-12): 211 | tmpFYF = -6.0 * fluidPotential[i, indices] * tmpGradY #/ sumWeightY 212 | forceY[i, indices] += tmpFYF 213 | # if (sumWeightSX > 1e-12): 214 | forceX[i, indices] += tmpFXS 215 | # if (sumWeightSY > 1e-12): 216 | forceY[i, indices] += tmpFYS 217 | cuda.syncthreads() 218 | 219 | """ 220 | Calculate the equilibrium function in each direction 221 | """ 222 | """ 223 | Calculate the equilibrium function for collision process (most common f_eq) 224 | """ 225 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:], float64[:, :], float64[:], \ 226 | float64[:], float64[:, :, :])') 227 | def calEquilibriumFuncEFGPU(totalNum, numFluids, xDim, weightCoeff, EX, EY, \ 228 | fluidRho, equilibriumVX, equilibriumVY, fEq): 229 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 230 | by = cuda.blockIdx.y 231 | indices = by * xDim + bx * bDimX + tx 232 | sharedWeightCoeff = cuda.shared.array(shape = (9, ), dtype = float64) 233 | tmpEX = cuda.shared.array(shape = (9,), dtype = float64) 234 | tmpEY = cuda.shared.array(shape = (9,), dtype = float64) 235 | for i in range(9): 236 | sharedWeightCoeff[i] = weightCoeff[i] 237 | tmpEX[i] = EX[i] 238 | tmpEY[i] = EY[i] 239 | if (indices < totalNum): 240 | for i in range(numFluids): 241 | for j in range(9): 242 | fEq[i, indices, j] = sharedWeightCoeff[j] * fluidRho[i, indices] * \ 243 | (1. + 3. * (tmpEX[j] * equilibriumVX[indices] + tmpEY[j] * \ 244 | equilibriumVY[indices]) + 9./2. * ((tmpEX[j] * equilibriumVX[indices] + \ 245 | tmpEY[j] * equilibriumVY[indices]) * (tmpEX[j] * equilibriumVX[indices] + \ 246 | tmpEY[j] * equilibriumVY[indices])) - 3./2. * (equilibriumVX[indices] * \ 247 | equilibriumVX[indices] + equilibriumVY[indices] * equilibriumVY[indices])) 248 | cuda.syncthreads() 249 | """ 250 | Calculate the PDF of force term 251 | """ 252 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:], float64[:], \ 253 | float64[:, :], float64[:, :], float64[:, :], float64[:, :, :], \ 254 | float64[:, :, :])') 255 | def calForceDistrGPU(totalNodes, numFluids, xDim, EX, EY, equilibriumVX, \ 256 | equilibriumVY, fluidRho, forceX, forceY, fEq, fForce): 257 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 258 | by = cuda.blockIdx.y 259 | indices = by * xDim + bx * bDimX + tx 260 | tmpEX = cuda.shared.array(shape = (9,), dtype = float64) 261 | tmpEY = cuda.shared.array(shape = (9,), dtype = float64) 262 | for i in range(9): 263 | tmpEX[i] = EX[i] 264 | tmpEY[i] = EY[i] 265 | if (indices < totalNodes): 266 | for i in range(numFluids): 267 | for j in range(9): 268 | fForce[i, indices, j] = ((forceX[i, indices] * (tmpEX[j] - \ 269 | equilibriumVX[indices])) + (forceY[i, indices] * (tmpEY[j] - \ 270 | equilibriumVY[indices]))) * fEq[i, indices, j] / (1./3. * \ 271 | fluidRho[i, indices]) 272 | cuda.syncthreads() 273 | 274 | """ 275 | Transform the original fluid PDF 276 | """ 277 | @cuda.jit('void(int64, int64, int64, float64[:, :, :], float64[:, :, :])') 278 | def transformPDFGPU(totalNodes, numFluids, xDim, fluidPDF, fForce): 279 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 280 | by = cuda.blockIdx.y 281 | indices = by * xDim + bx * bDimX + tx 282 | 283 | if (indices < totalNodes): 284 | for i in range(numFluids): 285 | for j in range(9): 286 | fluidPDF[i, indices, j] = fluidPDF[i, indices, j] - 1./2. * \ 287 | fForce[i, indices, j] 288 | 289 | """ 290 | Calculate collision process in the explicit scheme 291 | """ 292 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:, :, :], float64[:, :, :], \ 293 | float64[:, :, :])') 294 | def calCollisionEXGPU(totalNodes, numFluids, xDim, tau, fluidPDF, fEq, fForce): 295 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 296 | by = cuda.blockIdx.y 297 | indices = by * xDim + bx * bDimX + tx 298 | 299 | if (indices < totalNodes): 300 | for i in range(numFluids): 301 | for j in range(9): 302 | fluidPDF[i, indices, j] = fluidPDF[i, indices, j] + 1./tau[i] * \ 303 | (fEq[i, indices, j] - fluidPDF[i, indices, j] - 1./2. * \ 304 | fForce[i, indices, j]) + 1. * fForce[i, indices, j] 305 | 306 | """ 307 | Calculate the velocity of each component in the domain 308 | """ 309 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:, :], \ 310 | float64[:, :], float64[:, :, :], float64[:], float64[:])') 311 | def calTotalVelocityGPU(totalNodes, numFluids, xDim, EX, EY, forceX, \ 312 | forceY, fluidPDF, totalVX, totalVY): 313 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 314 | by = cuda.blockIdx.y 315 | indices = by * xDim + bx * bDimX + tx 316 | tmpEX = cuda.shared.array(shape = (9,), dtype = float64) 317 | tmpEY = cuda.shared.array(shape = (9,), dtype = float64) 318 | for i in range(9): 319 | tmpEX[i] = EX[i] 320 | tmpEY[i] = EY[i] 321 | if (indices < totalNodes): 322 | tmpMomentumX = 0.; tmpMomentumY = 0.; tmpRho = 0. 323 | for i in range(numFluids): 324 | for j in range(9): 325 | tmpMomentumX += fluidPDF[i, indices, j] * tmpEX[j] 326 | tmpMomentumY += fluidPDF[i, indices, j] * tmpEY[j] 327 | tmpRho += fluidPDF[i, indices, j] 328 | tmpMomentumX += 1./2. * forceX[i, indices] 329 | tmpMomentumY += 1./2. * forceY[i, indices] 330 | # tmpRho += fluidRho[i, indices] 331 | totalVX[indices] = tmpMomentumX / tmpRho 332 | totalVY[indices] = tmpMomentumY / tmpRho 333 | 334 | """ 335 | Calculate the equilibrium velocity in explicit scheme 336 | """ 337 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], float64[:], \ 338 | float64[:, :], float64[:, :], float64[:, :], float64[:, :, :], \ 339 | float64[:], float64[:])') 340 | def calEquilibriumVEFGPU(totalNodes, numFluids, xDim, tau, EX, EY, fluidRho, \ 341 | forceX, forceY, fluidPDF, eqVX, eqVY): 342 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 343 | by = cuda.blockIdx.y 344 | indices = by * xDim + bx * bDimX + tx 345 | tmpEX = cuda.shared.array(shape = (9,), dtype = float64) 346 | tmpEY = cuda.shared.array(shape = (9,), dtype = float64) 347 | for i in range(9): 348 | tmpEX[i] = EX[i] 349 | tmpEY[i] = EY[i] 350 | if (indices < totalNodes): 351 | tmpMomentumX = 0.; tmpMomentumY = 0.; tmpRhoT = 0. 352 | for i in range(numFluids): 353 | eachMX = 0.; eachMY = 0.; tmpRho = fluidRho[i, indices]; tmpTau = tau[i] 354 | for j in range(9): 355 | eachMX += fluidPDF[i, indices, j] * tmpEX[j] 356 | eachMY += fluidPDF[i, indices, j] * tmpEY[j] 357 | eachMX += 1./2. * forceX[i, indices] 358 | eachMY += 1./2. * forceY[i, indices] 359 | tmpMomentumX += eachMX / tmpTau 360 | tmpMomentumY += eachMY / tmpTau 361 | tmpRhoT = tmpRhoT + tmpRho / tmpTau 362 | eqVX[indices] = tmpMomentumX / tmpRhoT 363 | eqVY[indices] = tmpMomentumY / tmpRhoT 364 | 365 | 366 | """ 367 | Calculate the local pressure in the explicit scheme 368 | """ 369 | @cuda.jit('void(int64, int64, int64, float64[:, :], float64[:, :], float64[:, :], \ 370 | float64[:])') 371 | def calPressureExpGPU(totalNodes, numFluids, xDim, interCoeff, fluidRho, \ 372 | fluidPotential, fluidPressure): 373 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 374 | by = cuda.blockIdx.y 375 | indices = by * xDim + bx * bDimX + tx 376 | 377 | if (indices < totalNodes): 378 | tmpRho = 0.; tmpPressure = 0. 379 | for i in range(numFluids): 380 | tmpRho += fluidRho[i, indices] 381 | tmpPressure = 1./3. * tmpRho 382 | for i in range(numFluids - 1): 383 | for j in range(i+1, numFluids): 384 | tmpPressure += 6./2. * interCoeff[i, j] * fluidPotential[i, indices] * \ 385 | fluidPotential[j, indices] 386 | fluidPressure[indices] = tmpPressure 387 | 388 | """ 389 | Calculate the neighboring and the next neighboring nodes in isotropy = 8 390 | """ 391 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:, :], int64[:])') 392 | def fillNeighboringNodesISO8(totalNodes, nx, ny, xDim, fluidNodes, domainNewIndex, \ 393 | neighboringNodes): 394 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 395 | by = cuda.blockIdx.y 396 | # ty = cuda.threadIdx.y; by = cuda.blockIdx.y; bDimY = cuda.blockDim.y 397 | indices = by * xDim + bx * bDimX + tx 398 | if (indices < totalNodes): 399 | tmpStart = 24 * indices 400 | tmpLoc = fluidNodes[indices] 401 | i = int(tmpLoc / nx); j = tmpLoc % nx 402 | tmpF = j + 1 if j < nx - 1 else 0 403 | tmpB = j - 1 if j > 0 else (nx - 1) 404 | tmpU = i + 1 if i < ny - 1 else 0 405 | tmpL = i - 1 if i > 0 else (ny - 1) 406 | 407 | tmpF2 = j + 2 if (j < nx - 2) else (j - nx + 2) 408 | tmpB2 = j - 2 if (j > 1) else (nx - 2 + j) 409 | tmpU2 = i + 2 if (i < ny - 2) else (i - ny + 2) 410 | tmpL2 = i - 2 if (i > 1) else (ny - 2 + i) 411 | 412 | #Eastern node 413 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpF] 414 | #Northern node 415 | tmpStart += 1 416 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, j] 417 | #Western node 418 | tmpStart += 1 419 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpB] 420 | #Southern node 421 | tmpStart += 1 422 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, j] 423 | #Northeastern node 424 | tmpStart += 1 425 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpF] 426 | #Northwestern node 427 | tmpStart += 1 428 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpB] 429 | #Southwestern node 430 | tmpStart += 1 431 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpB] 432 | #southeastern node 433 | tmpStart += 1 434 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpF] 435 | #Eastern node 2 436 | tmpStart += 1 437 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpF2] 438 | #Northern node 2 439 | tmpStart += 1 440 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, j] 441 | #Western node 2 442 | tmpStart += 1 443 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpB2] 444 | #Southern node 2 445 | tmpStart += 1 446 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, j] 447 | #Northeastern node 2 448 | tmpStart += 1 449 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, tmpF2] 450 | #Northwestern node 2 451 | tmpStart += 1 452 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, tmpB2] 453 | #Southwestern node 2 454 | tmpStart += 1 455 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, tmpB2] 456 | #Southeastern node 2 457 | tmpStart += 1 458 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, tmpF2] 459 | #North1Eastern2 node 460 | tmpStart += 1 461 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpF2] 462 | #North2Eastern1 node 463 | tmpStart += 1 464 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, tmpF] 465 | #North2Western1 node 466 | tmpStart += 1 467 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, tmpB] 468 | #North1Western2 node 469 | tmpStart += 1 470 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpB2] 471 | #South1Western2 node 472 | tmpStart += 1 473 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpB2] 474 | #South2Western1 node 475 | tmpStart += 1 476 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, tmpB] 477 | #South2Eastern1 node 478 | tmpStart += 1 479 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, tmpF] 480 | #South1Eastern2 node 481 | tmpStart += 1 482 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpF2] 483 | 484 | """ 485 | Calculate the neighboring and the next neighboring nodes in isotropy = 10 486 | """ 487 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:, :], int64[:])') 488 | def fillNeighboringNodesISO10(totalNodes, nx, ny, xDim, fluidNodes, domainNewIndex, \ 489 | neighboringNodes): 490 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 491 | by = cuda.blockIdx.y 492 | # ty = cuda.threadIdx.y; by = cuda.blockIdx.y; bDimY = cuda.blockDim.y 493 | indices = by * xDim + bx * bDimX + tx 494 | if (indices < totalNodes): 495 | tmpStart = 36 * indices 496 | tmpLoc = fluidNodes[indices] 497 | i = int(tmpLoc / nx); j = tmpLoc % nx 498 | tmpF = j + 1 if j < nx - 1 else 0 499 | tmpB = j - 1 if j > 0 else (nx - 1) 500 | tmpU = i + 1 if i < ny - 1 else 0 501 | tmpL = i - 1 if i > 0 else (ny - 1) 502 | 503 | tmpF2 = j + 2 if (j < nx - 2) else (j - nx + 2) 504 | tmpB2 = j - 2 if (j > 1) else (nx - 2 + j) 505 | tmpU2 = i + 2 if (i < ny - 2) else (i - ny + 2) 506 | tmpL2 = i - 2 if (i > 1) else (ny - 2 + i) 507 | 508 | tmpF3 = j + 3 if (j < nx - 3) else (j - nx + 3) 509 | tmpB3 = j - 3 if (j > 2) else (nx - 3 + j) 510 | tmpU3 = i + 3 if (i < ny - 3) else (i - ny + 3) 511 | tmpL3 = i - 3 if (i > 2) else (ny - 3 + i) 512 | 513 | #Eastern node 514 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpF] 515 | #Northern node 516 | tmpStart += 1 517 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, j] 518 | #Western node 519 | tmpStart += 1 520 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpB] 521 | #Southern node 522 | tmpStart += 1 523 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, j] 524 | #Northeastern node 525 | tmpStart += 1 526 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpF] 527 | #Northwestern node 528 | tmpStart += 1 529 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpB] 530 | #Southwestern node 531 | tmpStart += 1 532 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpB] 533 | #southeastern node 534 | tmpStart += 1 535 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpF] 536 | #Eastern node 2 537 | tmpStart += 1 538 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpF2] 539 | #Northern node 2 540 | tmpStart += 1 541 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, j] 542 | #Western node 2 543 | tmpStart += 1 544 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpB2] 545 | #Southern node 2 546 | tmpStart += 1 547 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, j] 548 | #Northeastern node 2 549 | tmpStart += 1 550 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, tmpF2] 551 | #Northwestern node 2 552 | tmpStart += 1 553 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, tmpB2] 554 | #Southwestern node 2 555 | tmpStart += 1 556 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, tmpB2] 557 | #Southeastern node 2 558 | tmpStart += 1 559 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, tmpF2] 560 | #North1Eastern2 node 561 | tmpStart += 1 562 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpF2] 563 | #North2Eastern1 node 564 | tmpStart += 1 565 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, tmpF] 566 | #North2Western1 node 567 | tmpStart += 1 568 | neighboringNodes[tmpStart] = domainNewIndex[tmpU2, tmpB] 569 | #North1Western2 node 570 | tmpStart += 1 571 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpB2] 572 | #South1Western2 node 573 | tmpStart += 1 574 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpB2] 575 | #South2Western1 node 576 | tmpStart += 1 577 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, tmpB] 578 | #South2Eastern1 node 579 | tmpStart += 1 580 | neighboringNodes[tmpStart] = domainNewIndex[tmpL2, tmpF] 581 | #South1Eastern2 node 582 | tmpStart += 1 583 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpF2] 584 | #Eastern node 3 585 | tmpStart += 1 586 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpF3] 587 | #Northern node 3 588 | tmpStart += 1 589 | neighboringNodes[tmpStart] = domainNewIndex[tmpU3, j] 590 | #Western node 3 591 | tmpStart += 1 592 | neighboringNodes[tmpStart] = domainNewIndex[i, tmpB3] 593 | #Southern node 3 594 | tmpStart += 1 595 | neighboringNodes[tmpStart] = domainNewIndex[tmpL3, j] 596 | #North1eastern3 node 597 | tmpStart += 1 598 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpF3] 599 | #North3eastern1 node 600 | tmpStart += 1 601 | neighboringNodes[tmpStart] = domainNewIndex[tmpU3, tmpF] 602 | #North3western1 node 603 | tmpStart += 1 604 | neighboringNodes[tmpStart] = domainNewIndex[tmpU3, tmpB] 605 | #North1western3 node 606 | tmpStart += 1 607 | neighboringNodes[tmpStart] = domainNewIndex[tmpU, tmpB3] 608 | #South1western3 node 609 | tmpStart += 1 610 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpB3] 611 | #South3western1 node 612 | tmpStart += 1 613 | neighboringNodes[tmpStart] = domainNewIndex[tmpL3, tmpB] 614 | #South3eastern1 node 615 | tmpStart += 1 616 | neighboringNodes[tmpStart] = domainNewIndex[tmpL3, tmpF] 617 | #South1eastern3 node 618 | tmpStart += 1 619 | neighboringNodes[tmpStart] = domainNewIndex[tmpL, tmpF3] 620 | 621 | 622 | """ 623 | The explicit scheme for isotropy is 8 624 | """ 625 | @cuda.jit('void(int64, int64, int64, int64[:], int64[:], float64[:], float64[:, :], \ 626 | float64[:], float64[:, :], float64[:, :], float64[:, :])') 627 | def calExplicit8thOrderScheme(totalNodes, numFluids, xDim, fluidNodes, \ 628 | neighboringNodes, weightInter, interactionCoeff, \ 629 | interactionSolid, fluidPotential, forceX, forceY): 630 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 631 | by = cuda.blockIdx.y 632 | # ty = cuda.threadIdx.y; by = cuda.blockIdx.y; bDimY = cuda.blockDim.y 633 | indices = by * xDim + bx * bDimX + tx 634 | if (indices < totalNodes): 635 | for i in range(numFluids): 636 | forceX[i, indices] = 0.0; forceY[i, indices] = 0.0 637 | tmpStart = indices * 24 638 | tmpStart0 = tmpStart 639 | tmpStart1 = tmpStart + 1 640 | tmpStart2 = tmpStart + 2 641 | tmpStart3 = tmpStart + 3 642 | tmpStart4 = tmpStart + 4 643 | tmpStart5 = tmpStart + 5 644 | tmpStart6 = tmpStart + 6 645 | tmpStart7 = tmpStart + 7 646 | tmpStart8 = tmpStart + 8 647 | tmpStart9 = tmpStart + 9 648 | tmpStart10 = tmpStart + 10 649 | tmpStart11 = tmpStart + 11 650 | tmpStart12 = tmpStart + 12 651 | tmpStart13 = tmpStart + 13 652 | tmpStart14 = tmpStart + 14 653 | tmpStart15 = tmpStart + 15 654 | tmpStart16 = tmpStart + 16 655 | tmpStart17 = tmpStart + 17 656 | tmpStart18 = tmpStart + 18 657 | tmpStart19 = tmpStart + 19 658 | tmpStart20 = tmpStart + 20 659 | tmpStart21 = tmpStart + 21 660 | tmpStart22 = tmpStart + 22 661 | tmpStart23 = tmpStart + 23 662 | 663 | if (neighboringNodes[tmpStart0] != -1): 664 | tmpE = neighboringNodes[tmpStart0] 665 | for i in range(numFluids): 666 | for j in range(numFluids): 667 | forceX[i, indices] += -6.0 * weightInter[0] * interactionCoeff[i, j] * \ 668 | fluidPotential[i, indices] * (fluidPotential[j, tmpE] - \ 669 | fluidPotential[j, indices]) * (1.) 670 | elif (neighboringNodes[tmpStart0] == -1): 671 | for i in range(numFluids): 672 | forceX[i, indices] += -1./9. * interactionSolid[i] * \ 673 | fluidPotential[i, indices] * (1.) 674 | #Northern point 675 | if (neighboringNodes[tmpStart1] != -1): 676 | tmpN = neighboringNodes[tmpStart1] 677 | for i in range(numFluids): 678 | for j in range(numFluids): 679 | forceY[i, indices] += -6.0 * weightInter[1] * interactionCoeff[i, j] * \ 680 | fluidPotential[i, indices] * (fluidPotential[j, tmpN] - \ 681 | fluidPotential[j, indices])* (1.) 682 | elif (neighboringNodes[tmpStart1] == -1): 683 | for i in range(numFluids): 684 | forceY[i, indices] += -1./9. * interactionSolid[i] * \ 685 | fluidPotential[i, indices] * (1.) 686 | #Western Point 687 | if (neighboringNodes[tmpStart2] != -1): 688 | tmpW = neighboringNodes[tmpStart2] 689 | for i in range(numFluids): 690 | for j in range(numFluids): 691 | forceX[i, indices] += -6.0 * weightInter[2] * interactionCoeff[i, j] * \ 692 | fluidPotential[i, indices] * (fluidPotential[j, tmpW] - \ 693 | fluidPotential[j, indices]) * (-1.) 694 | elif(neighboringNodes[tmpStart2] == -1): 695 | for i in range(numFluids): 696 | forceX[i, indices] += -1./9. * interactionSolid[i] * \ 697 | fluidPotential[i, indices] * (-1.) 698 | #Southern point 699 | if (neighboringNodes[tmpStart3] != -1): 700 | tmpS = neighboringNodes[tmpStart3] 701 | for i in range(numFluids): 702 | for j in range(numFluids): 703 | forceY[i, indices] += -6.0 * weightInter[3] * interactionCoeff[i, j] * \ 704 | fluidPotential[i, indices] * (fluidPotential[j, tmpS] - \ 705 | fluidPotential[j, indices]) * (-1.) 706 | elif (neighboringNodes[tmpStart3] == -1): 707 | for i in range(numFluids): 708 | forceY[i, indices] += -1./9. * interactionSolid[i] * \ 709 | fluidPotential[i, indices] * (-1.) 710 | #Northeastern point 711 | if (neighboringNodes[tmpStart4] != -1): 712 | tmpNE = neighboringNodes[tmpStart4] 713 | for i in range(numFluids): 714 | for j in range(numFluids): 715 | forceX[i, indices] += -6.0 * weightInter[4] * interactionCoeff[i, j] * \ 716 | fluidPotential[i, indices] * (fluidPotential[j, tmpNE] - \ 717 | fluidPotential[j, indices]) * (1.) 718 | forceY[i, indices] += -6.0 * weightInter[4] * interactionCoeff[i, j] * \ 719 | fluidPotential[i, indices] * (fluidPotential[j, tmpNE] - \ 720 | fluidPotential[j, indices]) * (1.) 721 | elif(neighboringNodes[tmpStart4] == -1): 722 | for i in range(numFluids): 723 | forceX[i, indices] += -1./36. * interactionSolid[i] * \ 724 | fluidPotential[i, indices] * (1.) 725 | forceY[i, indices] += -1./36. * interactionSolid[i] * \ 726 | fluidPotential[i, indices] * (1.) 727 | #Northwestern point 728 | if (neighboringNodes[tmpStart5] != -1): 729 | tmpNW = neighboringNodes[tmpStart5] 730 | for i in range(numFluids): 731 | for j in range(numFluids): 732 | forceX[i, indices] += -6.0 * weightInter[5] * interactionCoeff[i, j] * \ 733 | fluidPotential[i, indices] * (fluidPotential[j, tmpNW] - \ 734 | fluidPotential[j, indices]) * (-1.) 735 | forceY[i, indices] += -6.0 * weightInter[5] * interactionCoeff[i, j] * \ 736 | fluidPotential[i, indices] * (fluidPotential[j, tmpNW] - \ 737 | fluidPotential[j, indices]) * (1.) 738 | elif (neighboringNodes[tmpStart5] == -1): 739 | for i in range(numFluids): 740 | forceX[i, indices] += -1./36. * interactionSolid[i] * \ 741 | fluidPotential[i, indices] * (-1.) 742 | forceY[i, indices] += -1./36. * interactionSolid[i] * \ 743 | fluidPotential[i, indices] * (1.) 744 | #Southwestern point 745 | if (neighboringNodes[tmpStart6] != -1): 746 | tmpSW = neighboringNodes[tmpStart6] 747 | for i in range(numFluids): 748 | for j in range(numFluids): 749 | forceX[i, indices] += -6.0 * weightInter[6] * interactionCoeff[i, j] * \ 750 | fluidPotential[i, indices] * (fluidPotential[j, tmpSW] - \ 751 | fluidPotential[j, indices]) * (-1.) 752 | forceY[i, indices] += -6.0 * weightInter[6] * interactionCoeff[i, j] * \ 753 | fluidPotential[i, indices] * (fluidPotential[j, tmpSW] - \ 754 | fluidPotential[j, indices]) * (-1.) 755 | elif (neighboringNodes[tmpStart6] == -1): 756 | for i in range(numFluids): 757 | forceX[i, indices] += -1./36. * interactionSolid[i] * \ 758 | fluidPotential[i, indices] * (-1.) 759 | forceY[i, indices] += -1./36. * interactionSolid[i] * \ 760 | fluidPotential[i, indices] * (-1.) 761 | #Southeastern point 762 | if (neighboringNodes[tmpStart7] != -1): 763 | tmpSE = neighboringNodes[tmpStart7] 764 | for i in range(numFluids): 765 | for j in range(numFluids): 766 | forceX[i, indices] += -6.0 * weightInter[7] * interactionCoeff[i, j] * \ 767 | fluidPotential[i, indices] * (fluidPotential[j, tmpSE] - \ 768 | fluidPotential[j, indices]) * (1.) 769 | forceY[i, indices] += -6.0 * weightInter[7] * interactionCoeff[i, j] * \ 770 | fluidPotential[i, indices] * (fluidPotential[j, tmpSE] - \ 771 | fluidPotential[j, indices]) * (-1.) 772 | elif (neighboringNodes[tmpStart7] == -1): 773 | for i in range(numFluids): 774 | forceX[i, indices] += -1./36. * interactionSolid[i] * \ 775 | fluidPotential[i, indices] * (1.) 776 | forceY[i, indices] += -1./36. * interactionSolid[i] * \ 777 | fluidPotential[i, indices] * (-1.) 778 | #Easter point 2 779 | if (neighboringNodes[tmpStart8] != -1 and neighboringNodes[tmpStart] != -1): 780 | tmpE2 = neighboringNodes[tmpStart8] 781 | for i in range(numFluids): 782 | for j in range(numFluids): 783 | forceX[i, indices] += -2. * 6.0 * weightInter[8] * interactionCoeff[i, j] * \ 784 | fluidPotential[i, indices] * (fluidPotential[j, tmpE2] - \ 785 | fluidPotential[j, indices]) * (1.) 786 | #Northern point 2 787 | if (neighboringNodes[tmpStart9] != -1 and neighboringNodes[tmpStart1] != -1): 788 | tmpN2 = neighboringNodes[tmpStart9] 789 | for i in range(numFluids): 790 | for j in range(numFluids): 791 | forceY[i, indices] += -2. * 6.0 * weightInter[9] * interactionCoeff[i, j] * \ 792 | fluidPotential[i, indices] * (fluidPotential[j, tmpN2] - \ 793 | fluidPotential[j, indices]) * (1.) 794 | #Western point 2 795 | if (neighboringNodes[tmpStart10] != -1 and neighboringNodes[tmpStart2] != -1): 796 | tmpW2 = neighboringNodes[tmpStart10] 797 | for i in range(numFluids): 798 | for j in range(numFluids): 799 | forceX[i, indices] += -2. * 6.0 * weightInter[10] * interactionCoeff[i, j] * \ 800 | fluidPotential[i, indices] * (fluidPotential[j, tmpW2] - \ 801 | fluidPotential[j, indices]) * (-1.) 802 | #Southern poitn 2 803 | if (neighboringNodes[tmpStart11] != -1 and neighboringNodes[tmpStart3] != -1): 804 | tmpS2 = neighboringNodes[tmpStart11] 805 | for i in range(numFluids): 806 | for j in range(numFluids): 807 | forceY[i, indices] += -2. * 6.0 * weightInter[11] * interactionCoeff[i, j] * \ 808 | fluidPotential[i, indices] * (fluidPotential[j, tmpS2] - \ 809 | fluidPotential[j, indices]) * (-1.) 810 | #Notheastern 2 811 | if (neighboringNodes[tmpStart12] != -1 and neighboringNodes[tmpStart4] != -1): 812 | tmpE2N2 = neighboringNodes[tmpStart12] 813 | for i in range(numFluids): 814 | for j in range(numFluids): 815 | forceX[i, indices] += -2. * 6.0 * weightInter[12] * interactionCoeff[i, j] * \ 816 | fluidPotential[i, indices] * (fluidPotential[j, tmpE2N2] - \ 817 | fluidPotential[j, indices])* (1.) 818 | forceY[i, indices] += -2. * 6.0 * weightInter[12] * interactionCoeff[i, j] * \ 819 | fluidPotential[i, indices] * (fluidPotential[j, tmpE2N2] - \ 820 | fluidPotential[j, indices])* (1.) 821 | #Northwestern 2 822 | if (neighboringNodes[tmpStart13] != -1 and neighboringNodes[tmpStart5] != -1): 823 | tmpW2N2 = neighboringNodes[tmpStart13] 824 | for i in range(numFluids): 825 | for j in range(numFluids): 826 | forceX[i, indices] += -2. * 6.0 * weightInter[13] * interactionCoeff[i, j] * \ 827 | fluidPotential[i, indices] * (fluidPotential[j, tmpW2N2] - \ 828 | fluidPotential[j, indices]) * (-1.) 829 | forceY[i, indices] += -2. * 6.0 * weightInter[13] * interactionCoeff[i, j] * \ 830 | fluidPotential[i, indices] * (fluidPotential[j, tmpW2N2] - \ 831 | fluidPotential[j, indices]) * (1.) 832 | #Southwestern 2 833 | if (neighboringNodes[tmpStart14] != -1 and neighboringNodes[tmpStart6] != -1): 834 | tmpW2S2 = neighboringNodes[tmpStart14] 835 | for i in range(numFluids): 836 | for j in range(numFluids): 837 | forceX[i, indices] += -2. * 6.0 * weightInter[14] * interactionCoeff[i, j] * \ 838 | fluidPotential[i, indices] * (fluidPotential[j, tmpW2S2] - \ 839 | fluidPotential[j, indices])* (-1.) 840 | forceY[i, indices] += -2. * 6.0 * weightInter[14] * interactionCoeff[i, j] * \ 841 | fluidPotential[i, indices] * (fluidPotential[j, tmpW2S2] - \ 842 | fluidPotential[j, indices]) * (-1.) 843 | #Southeastern 2 844 | if (neighboringNodes[tmpStart15] != -1 and neighboringNodes[tmpStart7] != -1): 845 | tmpE2S2 = neighboringNodes[tmpStart15] 846 | for i in range(numFluids): 847 | for j in range(numFluids): 848 | forceX[i, indices] += -2. * 6.0 * weightInter[15] * interactionCoeff[i, j] * \ 849 | fluidPotential[i, indices] * (fluidPotential[j, tmpE2S2] - \ 850 | fluidPotential[j, indices]) * (1.) 851 | forceY[i, indices] += -2. * 6.0 * weightInter[15] * interactionCoeff[i, j] * \ 852 | fluidPotential[i, indices] * (fluidPotential[j, tmpE2S2] - \ 853 | fluidPotential[j, indices]) * (-1.) 854 | #North1Eastern2 855 | if (neighboringNodes[tmpStart16] != -1 and (neighboringNodes[tmpStart] != -1 or \ 856 | neighboringNodes[tmpStart4] != -1)): 857 | tmpN1E2 = neighboringNodes[tmpStart16] 858 | for i in range(numFluids): 859 | for j in range(numFluids): 860 | forceX[i, indices] += -2. * 6.0 * weightInter[16] * interactionCoeff[i, j] * \ 861 | fluidPotential[i, indices] * (fluidPotential[j, tmpN1E2] - \ 862 | fluidPotential[j, indices]) * (1.) 863 | forceY[i, indices] += -6.0 * weightInter[16] * interactionCoeff[i, j] * \ 864 | fluidPotential[i, indices] * (fluidPotential[j, tmpN1E2] - \ 865 | fluidPotential[j, indices]) * (1.) 866 | #North2Eastern1 867 | if (neighboringNodes[tmpStart17] != -1 and (neighboringNodes[tmpStart1] != -1 or \ 868 | neighboringNodes[tmpStart4] != -1)): 869 | tmpN2E1 = neighboringNodes[tmpStart17] 870 | for i in range(numFluids): 871 | for j in range(numFluids): 872 | forceX[i, indices] += -6.0 * weightInter[17] * interactionCoeff[i, j] * \ 873 | fluidPotential[i, indices] * (fluidPotential[j, tmpN2E1] - \ 874 | fluidPotential[j, indices]) * (1.) 875 | forceY[i, indices] += -2. * 6.0 * weightInter[17] * interactionCoeff[i, j] * \ 876 | fluidPotential[i, indices] * (fluidPotential[j, tmpN2E1] - \ 877 | fluidPotential[j, indices]) * (1.) 878 | #North2Western1 879 | if (neighboringNodes[tmpStart18] != -1 and (neighboringNodes[tmpStart1] != -1 or \ 880 | neighboringNodes[tmpStart5] != -1)): 881 | tmpN2W1 = neighboringNodes[tmpStart18] 882 | for i in range(numFluids): 883 | for j in range(numFluids): 884 | forceX[i, indices] += -6.0 * weightInter[18] * interactionCoeff[i, j] * \ 885 | fluidPotential[i, indices] * (fluidPotential[j, tmpN2W1] - \ 886 | fluidPotential[j, indices]) * (-1.) 887 | forceY[i, indices] += -2. * 6.0 * weightInter[18] * interactionCoeff[i, j] * \ 888 | fluidPotential[i, indices] * (fluidPotential[j, tmpN2W1] - \ 889 | fluidPotential[j, indices]) * (1.) 890 | #North1Western2 891 | if (neighboringNodes[tmpStart19] != -1 and (neighboringNodes[tmpStart2] != -1 or \ 892 | neighboringNodes[tmpStart5] != -1)): 893 | tmpN1W2 = neighboringNodes[tmpStart19] 894 | for i in range(numFluids): 895 | for j in range(numFluids): 896 | forceX[i, indices] += -2. * 6.0 * weightInter[19] * interactionCoeff[i, j] * \ 897 | fluidPotential[i, indices] * (fluidPotential[j, tmpN1W2] - \ 898 | fluidPotential[j, indices]) * (-1.) 899 | forceY[i, indices] += -6.0 * weightInter[19] * interactionCoeff[i, j] * \ 900 | fluidPotential[i, indices] * (fluidPotential[j, tmpN1W2] - \ 901 | fluidPotential[j, indices]) * (1.) 902 | #South1Western2 903 | if (neighboringNodes[tmpStart20] != -1 and (neighboringNodes[tmpStart2] != -1 or \ 904 | neighboringNodes[tmpStart6] != -1)): 905 | tmpS1W2 = neighboringNodes[tmpStart20] 906 | for i in range(numFluids): 907 | for j in range(numFluids): 908 | forceX[i, indices] += -2. * 6.0 * weightInter[20] * interactionCoeff[i, j] * \ 909 | fluidPotential[i, indices] * (fluidPotential[j, tmpS1W2] - \ 910 | fluidPotential[j, indices]) * (-1.) 911 | forceY[i, indices] += -6.0 * weightInter[20] * interactionCoeff[i, j] * \ 912 | fluidPotential[i, indices] * (fluidPotential[j, tmpS1W2] - \ 913 | fluidPotential[j, indices]) * (-1.) 914 | #South2Western1 915 | if (neighboringNodes[tmpStart21] != -1 and (neighboringNodes[tmpStart3] != -1 or \ 916 | neighboringNodes[tmpStart6] != -1)): 917 | tmpS2W1 = neighboringNodes[tmpStart21] 918 | for i in range(numFluids): 919 | for j in range(numFluids): 920 | forceX[i, indices] += -6.0 * weightInter[21] * interactionCoeff[i, j] * \ 921 | fluidPotential[i, indices] * (fluidPotential[j, tmpS2W1] - \ 922 | fluidPotential[j, indices]) * (-1.) 923 | forceY[i, indices] += -2. * 6.0 * weightInter[21] * interactionCoeff[i, j] * \ 924 | fluidPotential[i, indices] * (fluidPotential[j, tmpS2W1] - \ 925 | fluidPotential[j, indices]) * (-1.) 926 | #South2Eastern1 927 | if (neighboringNodes[tmpStart22] != -1 and (neighboringNodes[tmpStart3] != -1 or \ 928 | neighboringNodes[tmpStart7] != -1)): 929 | tmpS2E1 = neighboringNodes[tmpStart22] 930 | for i in range(numFluids): 931 | for j in range(numFluids): 932 | forceX[i, indices] += -6.0 * weightInter[22] * interactionCoeff[i, j] * \ 933 | fluidPotential[i, indices] * (fluidPotential[j, tmpS2E1] - \ 934 | fluidPotential[j, indices]) * (1.) 935 | forceY[i, indices] += -2. * 6.0 * weightInter[22] * interactionCoeff[i, j] * \ 936 | fluidPotential[i, indices] * (fluidPotential[j, tmpS2E1] - \ 937 | fluidPotential[j, indices]) * (-1.) 938 | #South1Eastern2 939 | if (neighboringNodes[tmpStart23] != -1 and (neighboringNodes[tmpStart] != -1 or\ 940 | neighboringNodes[tmpStart7] != -1)): 941 | tmpS1E2 = neighboringNodes[tmpStart23] 942 | for i in range(numFluids): 943 | for j in range(numFluids): 944 | forceX[i, indices] += -2. * 6.0 * weightInter[23] * interactionCoeff[i, j] * \ 945 | fluidPotential[i, indices] * (fluidPotential[j, tmpS1E2] - \ 946 | fluidPotential[j, indices]) * (1.) 947 | forceY[i, indices] += -6.0 * weightInter[23] * interactionCoeff[i, j] * \ 948 | fluidPotential[i, indices] * (fluidPotential[j, tmpS1E2] - \ 949 | fluidPotential[j, indices]) * (-1.) 950 | cuda.syncthreads() 951 | 952 | """ 953 | The explicit scheme for isotropy = 10 954 | """ 955 | @cuda.jit('void(int64, int64, int64, int64[:], int64[:], float64[:], float64[:, :], \ 956 | float64[:], float64[:, :], float64[:, :], float64[:, :])') 957 | def calExplicit10thOrderScheme(totalNodes, numFluids, xDim, fluidNodes, \ 958 | neighboringNodes, weightInter, interactionCoeff, \ 959 | interactionSolid, fluidPotential, forceX, forceY): 960 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 961 | by = cuda.blockIdx.y 962 | indices = by * xDim + bx * bDimX + tx 963 | if (indices < totalNodes): 964 | for i in range(numFluids): 965 | forceX[i, indices] = 0.0; forceY[i, indices] = 0.0 966 | tmpStart = indices * 36 967 | tmpStart0 = tmpStart 968 | tmpStart1 = tmpStart + 1 969 | tmpStart2 = tmpStart + 2 970 | tmpStart3 = tmpStart + 3 971 | tmpStart4 = tmpStart + 4 972 | tmpStart5 = tmpStart + 5 973 | tmpStart6 = tmpStart + 6 974 | tmpStart7 = tmpStart + 7 975 | tmpStart8 = tmpStart + 8 976 | tmpStart9 = tmpStart + 9 977 | tmpStart10 = tmpStart + 10 978 | tmpStart11 = tmpStart + 11 979 | tmpStart12 = tmpStart + 12 980 | tmpStart13 = tmpStart + 13 981 | tmpStart14 = tmpStart + 14 982 | tmpStart15 = tmpStart + 15 983 | tmpStart16 = tmpStart + 16 984 | tmpStart17 = tmpStart + 17 985 | tmpStart18 = tmpStart + 18 986 | tmpStart19 = tmpStart + 19 987 | tmpStart20 = tmpStart + 20 988 | tmpStart21 = tmpStart + 21 989 | tmpStart22 = tmpStart + 22 990 | tmpStart23 = tmpStart + 23 991 | tmpStart24 = tmpStart + 24 992 | tmpStart25 = tmpStart + 25 993 | tmpStart26 = tmpStart + 26 994 | tmpStart27 = tmpStart + 27 995 | tmpStart28 = tmpStart + 28 996 | tmpStart29 = tmpStart + 29 997 | tmpStart30 = tmpStart + 30 998 | tmpStart31 = tmpStart + 31 999 | tmpStart32 = tmpStart + 32 1000 | tmpStart33 = tmpStart + 33 1001 | tmpStart34 = tmpStart + 34 1002 | tmpStart35 = tmpStart + 35 1003 | 1004 | if (neighboringNodes[tmpStart0] != -1): 1005 | tmpE = neighboringNodes[tmpStart0] 1006 | for i in range(numFluids): 1007 | for j in range(numFluids): 1008 | forceX[i, indices] += -6.0 * weightInter[0] * interactionCoeff[i, j] * \ 1009 | fluidPotential[i, indices] * fluidPotential[j, tmpE] * (1.) 1010 | elif (neighboringNodes[tmpStart0] == -1): 1011 | for i in range(numFluids): 1012 | forceX[i, indices] += -1./9. * interactionSolid[i] * \ 1013 | fluidPotential[i, indices] * (1.) 1014 | #Northern point 1015 | if (neighboringNodes[tmpStart1] != -1): 1016 | tmpN = neighboringNodes[tmpStart1] 1017 | for i in range(numFluids): 1018 | for j in range(numFluids): 1019 | forceY[i, indices] += -6.0 * weightInter[1] * interactionCoeff[i, j] * \ 1020 | fluidPotential[i, indices] * fluidPotential[j, tmpN] * (1.) 1021 | elif (neighboringNodes[tmpStart1] == -1): 1022 | for i in range(numFluids): 1023 | forceY[i, indices] += -1./9. * interactionSolid[i] * \ 1024 | fluidPotential[i, indices] * (1.) 1025 | #Western Point 1026 | if (neighboringNodes[tmpStart2] != -1): 1027 | tmpW = neighboringNodes[tmpStart2] 1028 | for i in range(numFluids): 1029 | for j in range(numFluids): 1030 | forceX[i, indices] += -6.0 * weightInter[2] * interactionCoeff[i, j] * \ 1031 | fluidPotential[i, indices] * fluidPotential[j, tmpW] * (-1.) 1032 | elif(neighboringNodes[tmpStart2] == -1): 1033 | for i in range(numFluids): 1034 | forceX[i, indices] += -1./9. * interactionSolid[i] * \ 1035 | fluidPotential[i, indices] * (-1.) 1036 | #Southern point 1037 | if (neighboringNodes[tmpStart3] != -1): 1038 | tmpS = neighboringNodes[tmpStart3] 1039 | for i in range(numFluids): 1040 | for j in range(numFluids): 1041 | forceY[i, indices] += -6.0 * weightInter[3] * interactionCoeff[i, j] * \ 1042 | fluidPotential[i, indices] * fluidPotential[j, tmpS] * (-1.) 1043 | elif (neighboringNodes[tmpStart3] == -1): 1044 | for i in range(numFluids): 1045 | forceY[i, indices] += -1./9. * interactionSolid[i] * \ 1046 | fluidPotential[i, indices] * (-1.) 1047 | #Northeastern point 1048 | if (neighboringNodes[tmpStart4] != -1): 1049 | tmpNE = neighboringNodes[tmpStart4] 1050 | for i in range(numFluids): 1051 | for j in range(numFluids): 1052 | forceX[i, indices] += -6.0 * weightInter[4] * interactionCoeff[i, j] * \ 1053 | fluidPotential[i, indices] * fluidPotential[j, tmpNE] * (1.) 1054 | forceY[i, indices] += -6.0 * weightInter[4] * interactionCoeff[i, j] * \ 1055 | fluidPotential[i, indices] * fluidPotential[j, tmpNE] * (1.) 1056 | elif(neighboringNodes[tmpStart4] == -1): 1057 | for i in range(numFluids): 1058 | forceX[i, indices] += -1./36. * interactionSolid[i] * \ 1059 | fluidPotential[i, indices] * (1.) 1060 | forceY[i, indices] += -1./36. * interactionSolid[i] * \ 1061 | fluidPotential[i, indices] * (1.) 1062 | #Northwestern point 1063 | if (neighboringNodes[tmpStart5] != -1): 1064 | tmpNW = neighboringNodes[tmpStart5] 1065 | for i in range(numFluids): 1066 | for j in range(numFluids): 1067 | forceX[i, indices] += -6.0 * weightInter[5] * interactionCoeff[i, j] * \ 1068 | fluidPotential[i, indices] * fluidPotential[j, tmpNW] * (-1.) 1069 | forceY[i, indices] += -6.0 * weightInter[5] * interactionCoeff[i, j] * \ 1070 | fluidPotential[i, indices] * fluidPotential[j, tmpNW] * (1.) 1071 | elif (neighboringNodes[tmpStart5] == -1): 1072 | for i in range(numFluids): 1073 | forceX[i, indices] += -1./36. * interactionSolid[i] * \ 1074 | fluidPotential[i, indices] * (-1.) 1075 | forceY[i, indices] += -1./36. * interactionSolid[i] * \ 1076 | fluidPotential[i, indices] * (1.) 1077 | #Southwestern point 1078 | if (neighboringNodes[tmpStart6] != -1): 1079 | tmpSW = neighboringNodes[tmpStart6] 1080 | for i in range(numFluids): 1081 | for j in range(numFluids): 1082 | forceX[i, indices] += -6.0 * weightInter[6] * interactionCoeff[i, j] * \ 1083 | fluidPotential[i, indices] * fluidPotential[j, tmpSW] * (-1.) 1084 | forceY[i, indices] += -6.0 * weightInter[6] * interactionCoeff[i, j] * \ 1085 | fluidPotential[i, indices] * fluidPotential[j, tmpSW] * (-1.) 1086 | elif (neighboringNodes[tmpStart6] == -1): 1087 | for i in range(numFluids): 1088 | forceX[i, indices] += -1./36. * interactionSolid[i] * \ 1089 | fluidPotential[i, indices] * (-1.) 1090 | forceY[i, indices] += -1./36. * interactionSolid[i] * \ 1091 | fluidPotential[i, indices] * (-1.) 1092 | #Southeastern point 1093 | if (neighboringNodes[tmpStart7] != -1): 1094 | tmpSE = neighboringNodes[tmpStart7] 1095 | for i in range(numFluids): 1096 | for j in range(numFluids): 1097 | forceX[i, indices] += -6.0 * weightInter[7] * interactionCoeff[i, j] * \ 1098 | fluidPotential[i, indices] * fluidPotential[j, tmpSE] * (1.) 1099 | forceY[i, indices] += -6.0 * weightInter[7] * interactionCoeff[i, j] * \ 1100 | fluidPotential[i, indices] * fluidPotential[j, tmpSE] * (-1.) 1101 | elif (neighboringNodes[tmpStart7] == -1): 1102 | for i in range(numFluids): 1103 | forceX[i, indices] += -1./36. * interactionSolid[i] * \ 1104 | fluidPotential[i, indices] * (1.) 1105 | forceY[i, indices] += -1./36. * interactionSolid[i] * \ 1106 | fluidPotential[i, indices] * (-1.) 1107 | #Easter point 2 1108 | if (neighboringNodes[tmpStart8] != -1 and neighboringNodes[tmpStart] != -1): 1109 | tmpE2 = neighboringNodes[tmpStart8] 1110 | for i in range(numFluids): 1111 | for j in range(numFluids): 1112 | forceX[i, indices] += -2. * 6.0 * weightInter[8] * interactionCoeff[i, j] * \ 1113 | fluidPotential[i, indices] * fluidPotential[j, tmpE2] * (1.) 1114 | #Northern point 2 1115 | if (neighboringNodes[tmpStart9] != -1 and neighboringNodes[tmpStart1] != -1): 1116 | tmpN2 = neighboringNodes[tmpStart9] 1117 | for i in range(numFluids): 1118 | for j in range(numFluids): 1119 | forceY[i, indices] += -2. * 6.0 * weightInter[9] * interactionCoeff[i, j] * \ 1120 | fluidPotential[i, indices] * fluidPotential[j, tmpN2] * (1.) 1121 | #Western point 2 1122 | if (neighboringNodes[tmpStart10] != -1 and neighboringNodes[tmpStart2] != -1): 1123 | tmpW2 = neighboringNodes[tmpStart10] 1124 | for i in range(numFluids): 1125 | for j in range(numFluids): 1126 | forceX[i, indices] += -2. * 6.0 * weightInter[10] * interactionCoeff[i, j] * \ 1127 | fluidPotential[i, indices] * fluidPotential[j, tmpW2] * (-1.) 1128 | #Southern poitn 2 1129 | if (neighboringNodes[tmpStart11] != -1 and neighboringNodes[tmpStart3] != -1): 1130 | tmpS2 = neighboringNodes[tmpStart11] 1131 | for i in range(numFluids): 1132 | for j in range(numFluids): 1133 | forceY[i, indices] += -2. * 6.0 * weightInter[11] * interactionCoeff[i, j] * \ 1134 | fluidPotential[i, indices] * fluidPotential[j, tmpS2] * (-1.) 1135 | #Notheastern 2 1136 | if (neighboringNodes[tmpStart12] != -1 and neighboringNodes[tmpStart4] != -1): 1137 | tmpE2N2 = neighboringNodes[tmpStart12] 1138 | for i in range(numFluids): 1139 | for j in range(numFluids): 1140 | forceX[i, indices] += -2. * 6.0 * weightInter[12] * interactionCoeff[i, j] * \ 1141 | fluidPotential[i, indices] * fluidPotential[j, tmpE2N2] * (1.) 1142 | forceY[i, indices] += -2. * 6.0 * weightInter[12] * interactionCoeff[i, j] * \ 1143 | fluidPotential[i, indices] * fluidPotential[j, tmpE2N2] * (1.) 1144 | #Northwestern 2 1145 | if (neighboringNodes[tmpStart13] != -1 and neighboringNodes[tmpStart5] != -1): 1146 | tmpW2N2 = neighboringNodes[tmpStart13] 1147 | for i in range(numFluids): 1148 | for j in range(numFluids): 1149 | forceX[i, indices] += -2. * 6.0 * weightInter[13] * interactionCoeff[i, j] * \ 1150 | fluidPotential[i, indices] * fluidPotential[j, tmpW2N2] * (-1.) 1151 | forceY[i, indices] += -2. * 6.0 * weightInter[13] * interactionCoeff[i, j] * \ 1152 | fluidPotential[i, indices] * fluidPotential[j, tmpW2N2] * (1.) 1153 | #Southwestern 2 1154 | if (neighboringNodes[tmpStart14] != -1 and neighboringNodes[tmpStart6] != -1): 1155 | tmpW2S2 = neighboringNodes[tmpStart14] 1156 | for i in range(numFluids): 1157 | for j in range(numFluids): 1158 | forceX[i, indices] += -2. * 6.0 * weightInter[14] * interactionCoeff[i, j] * \ 1159 | fluidPotential[i, indices] * fluidPotential[j, tmpW2S2] * (-1.) 1160 | forceY[i, indices] += -2. * 6.0 * weightInter[14] * interactionCoeff[i, j] * \ 1161 | fluidPotential[i, indices] * fluidPotential[j, tmpW2S2] * (-1.) 1162 | #Southeastern 2 1163 | if (neighboringNodes[tmpStart15] != -1 and neighboringNodes[tmpStart7] != -1): 1164 | tmpE2S2 = neighboringNodes[tmpStart15] 1165 | for i in range(numFluids): 1166 | for j in range(numFluids): 1167 | forceX[i, indices] += -2. * 6.0 * weightInter[15] * interactionCoeff[i, j] * \ 1168 | fluidPotential[i, indices] * fluidPotential[j, tmpE2S2] * (1.) 1169 | forceY[i, indices] += -2. * 6.0 * weightInter[15] * interactionCoeff[i, j] * \ 1170 | fluidPotential[i, indices] * fluidPotential[j, tmpE2S2] * (-1.) 1171 | #North1Eastern2 1172 | if (neighboringNodes[tmpStart16] != -1 and (neighboringNodes[tmpStart] != -1 or \ 1173 | neighboringNodes[tmpStart4] != -1)): 1174 | tmpN1E2 = neighboringNodes[tmpStart16] 1175 | for i in range(numFluids): 1176 | for j in range(numFluids): 1177 | forceX[i, indices] += -2. * 6.0 * weightInter[16] * interactionCoeff[i, j] * \ 1178 | fluidPotential[i, indices] * fluidPotential[j, tmpN1E2] * (1.) 1179 | forceY[i, indices] += -6.0 * weightInter[16] * interactionCoeff[i, j] * \ 1180 | fluidPotential[i, indices] * fluidPotential[j, tmpN1E2] * (1.) 1181 | #North2Eastern1 1182 | if (neighboringNodes[tmpStart17] != -1 and (neighboringNodes[tmpStart1] != -1 or \ 1183 | neighboringNodes[tmpStart4] != -1)): 1184 | tmpN2E1 = neighboringNodes[tmpStart17] 1185 | for i in range(numFluids): 1186 | for j in range(numFluids): 1187 | forceX[i, indices] += -6.0 * weightInter[17] * interactionCoeff[i, j] * \ 1188 | fluidPotential[i, indices] * fluidPotential[j, tmpN2E1] * (1.) 1189 | forceY[i, indices] += -2. * 6.0 * weightInter[17] * interactionCoeff[i, j] * \ 1190 | fluidPotential[i, indices] * fluidPotential[j, tmpN2E1] * (1.) 1191 | #North2Western1 1192 | if (neighboringNodes[tmpStart18] != -1 and (neighboringNodes[tmpStart1] != -1 or \ 1193 | neighboringNodes[tmpStart5] != -1)): 1194 | tmpN2W1 = neighboringNodes[tmpStart18] 1195 | for i in range(numFluids): 1196 | for j in range(numFluids): 1197 | forceX[i, indices] += -6.0 * weightInter[18] * interactionCoeff[i, j] * \ 1198 | fluidPotential[i, indices] * fluidPotential[j, tmpN2W1] * (-1.) 1199 | forceY[i, indices] += -2. * 6.0 * weightInter[18] * interactionCoeff[i, j] * \ 1200 | fluidPotential[i, indices] * fluidPotential[j, tmpN2W1] * (1.) 1201 | #North1Western2 1202 | if (neighboringNodes[tmpStart19] != -1 and (neighboringNodes[tmpStart2] != -1 or \ 1203 | neighboringNodes[tmpStart5] != -1)): 1204 | tmpN1W2 = neighboringNodes[tmpStart19] 1205 | for i in range(numFluids): 1206 | for j in range(numFluids): 1207 | forceX[i, indices] += -2. * 6.0 * weightInter[19] * interactionCoeff[i, j] * \ 1208 | fluidPotential[i, indices] * fluidPotential[j, tmpN1W2] * (-1.) 1209 | forceY[i, indices] += -6.0 * weightInter[19] * interactionCoeff[i, j] * \ 1210 | fluidPotential[i, indices] * fluidPotential[j, tmpN1W2] * (1.) 1211 | #South1Western2 1212 | if (neighboringNodes[tmpStart20] != -1 and (neighboringNodes[tmpStart2] != -1 or \ 1213 | neighboringNodes[tmpStart6] != -1)): 1214 | tmpS1W2 = neighboringNodes[tmpStart20] 1215 | for i in range(numFluids): 1216 | for j in range(numFluids): 1217 | forceX[i, indices] += -2. * 6.0 * weightInter[20] * interactionCoeff[i, j] * \ 1218 | fluidPotential[i, indices] * fluidPotential[j, tmpS1W2] * (-1.) 1219 | forceY[i, indices] += -6.0 * weightInter[20] * interactionCoeff[i, j] * \ 1220 | fluidPotential[i, indices] * fluidPotential[j, tmpS1W2] * (-1.) 1221 | #South2Western1 1222 | if (neighboringNodes[tmpStart21] != -1 and (neighboringNodes[tmpStart3] != -1 or \ 1223 | neighboringNodes[tmpStart6] != -1)): 1224 | tmpS2W1 = neighboringNodes[tmpStart21] 1225 | for i in range(numFluids): 1226 | for j in range(numFluids): 1227 | forceX[i, indices] += -6.0 * weightInter[21] * interactionCoeff[i, j] * \ 1228 | fluidPotential[i, indices] * fluidPotential[j, tmpS2W1] * (-1.) 1229 | forceY[i, indices] += -2. * 6.0 * weightInter[21] * interactionCoeff[i, j] * \ 1230 | fluidPotential[i, indices] * fluidPotential[j, tmpS2W1] * (-1.) 1231 | #South2Eastern1 1232 | if (neighboringNodes[tmpStart22] != -1 and (neighboringNodes[tmpStart3] != -1 or \ 1233 | neighboringNodes[tmpStart7] != -1)): 1234 | tmpS2E1 = neighboringNodes[tmpStart22] 1235 | for i in range(numFluids): 1236 | for j in range(numFluids): 1237 | forceX[i, indices] += -6.0 * weightInter[22] * interactionCoeff[i, j] * \ 1238 | fluidPotential[i, indices] * fluidPotential[j, tmpS2E1] * (1.) 1239 | forceY[i, indices] += -2. * 6.0 * weightInter[22] * interactionCoeff[i, j] * \ 1240 | fluidPotential[i, indices] * fluidPotential[j, tmpS2E1] * (-1.) 1241 | #South1Eastern2 1242 | if (neighboringNodes[tmpStart23] != -1 and (neighboringNodes[tmpStart] != -1 or\ 1243 | neighboringNodes[tmpStart7] != -1)): 1244 | tmpS1E2 = neighboringNodes[tmpStart23] 1245 | for i in range(numFluids): 1246 | for j in range(numFluids): 1247 | forceX[i, indices] += -2. * 6.0 * weightInter[23] * interactionCoeff[i, j] * \ 1248 | fluidPotential[i, indices] * fluidPotential[j, tmpS1E2] * (1.) 1249 | forceY[i, indices] += -6.0 * weightInter[23] * interactionCoeff[i, j] * \ 1250 | fluidPotential[i, indices] * fluidPotential[j, tmpS1E2] * (-1.) 1251 | 1252 | #Eastern 3 1253 | if ((neighboringNodes[tmpStart] != -1 and neighboringNodes[tmpStart8] != -1) and \ 1254 | neighboringNodes[tmpStart24] != -1): 1255 | tmpE3 = neighboringNodes[tmpStart24] 1256 | for i in range(numFluids): 1257 | for j in range(numFluids): 1258 | forceX[i, indices] += -3. * 6.0 * weightInter[24] * interactionCoeff[i, j] * \ 1259 | fluidPotential[i, indices] * fluidPotential[j, tmpE3] * (1.) 1260 | #Northern 3 1261 | if ((neighboringNodes[tmpStart1] != -1 and neighboringNodes[tmpStart9] != -1) and \ 1262 | neighboringNodes[tmpStart25] != -1): 1263 | tmpN3 = neighboringNodes[tmpStart25] 1264 | for i in range(numFluids): 1265 | for j in range(numFluids): 1266 | forceY[i, indices] += -3. * 6.0 * weightInter[25] * interactionCoeff[i, j] * \ 1267 | fluidPotential[i, indices] * fluidPotential[j, tmpN3] * (1.) 1268 | #Western 3 1269 | if ((neighboringNodes[tmpStart2] != -1 and neighboringNodes[tmpStart10] != -1) and \ 1270 | neighboringNodes[tmpStart26] != -1): 1271 | tmpW3 = neighboringNodes[tmpStart26] 1272 | for i in range(numFluids): 1273 | for j in range(numFluids): 1274 | forceX[i, indices] += -3. * 6.0 * weightInter[26] * interactionCoeff[i, j] * \ 1275 | fluidPotential[i, indices] * fluidPotential[j, tmpW3] * (-1.) 1276 | #Southern 3 1277 | if ((neighboringNodes[tmpStart3] != -1 and neighboringNodes[tmpStart11] != -1) and \ 1278 | neighboringNodes[tmpStart27] != -1): 1279 | tmpS3 = neighboringNodes[tmpStart27] 1280 | for i in range(numFluids): 1281 | for j in range(numFluids): 1282 | forceY[i, indices] += -3. * 6.0 * weightInter[27] * interactionCoeff[i, j] * \ 1283 | fluidPotential[i, indices] * fluidPotential[j, tmpS3] * (-1.) 1284 | #North1Eastern3 1285 | if (neighboringNodes[tmpStart28] != -1 and ((neighboringNodes[tmpStart4] != -1 \ 1286 | and neighboringNodes[tmpStart16] != -1) or (neighboringNodes[tmpStart] != -1 \ 1287 | and neighboringNodes[tmpStart8] != -1))): 1288 | tmpN1E3 = neighboringNodes[tmpStart28] 1289 | for i in range(numFluids): 1290 | for j in range(numFluids): 1291 | forceX[i, indices] += -3. * 6.0 * weightInter[28] * interactionCoeff[i, j] * \ 1292 | fluidPotential[i, indices] * fluidPotential[j, tmpN1E3] * (1.) 1293 | forceY[i, indices] += -6.0 * weightInter[28] * interactionCoeff[i, j] * \ 1294 | fluidPotential[i, indices] * fluidPotential[j, tmpN1E3] * (1.) 1295 | #North3Eastern1 1296 | if (neighboringNodes[tmpStart29] != -1 and ((neighboringNodes[tmpStart1] != -1 \ 1297 | and neighboringNodes[tmpStart9] != -1) or (neighboringNodes[tmpStart4] != -1 \ 1298 | and neighboringNodes[tmpStart17] != -1))): 1299 | tmpN3E1 = neighboringNodes[tmpStart29] 1300 | for i in range(numFluids): 1301 | for j in range(numFluids): 1302 | forceX[i, indices] += -6.0 * weightInter[29] * interactionCoeff[i, j] * \ 1303 | fluidPotential[i, indices] * fluidPotential[j, tmpN3E1] * (1.) 1304 | forceY[i, indices] += -3. * 6.0 * weightInter[29] * interactionCoeff[i, j] * \ 1305 | fluidPotential[i, indices] * fluidPotential[j, tmpN3E1] * (1.) 1306 | #North3Western1 1307 | if (neighboringNodes[tmpStart30] != -1 and ((neighboringNodes[tmpStart1] != -1 \ 1308 | and neighboringNodes[tmpStart9] != -1) or (neighboringNodes[tmpStart5] != -1 \ 1309 | and neighboringNodes[tmpStart18] != -1))): 1310 | tmpN3W1 = neighboringNodes[tmpStart30] 1311 | for i in range(numFluids): 1312 | for j in range(numFluids): 1313 | forceX[i, indices] += -6.0 * weightInter[30] * interactionCoeff[i, j] * \ 1314 | fluidPotential[i, indices] * fluidPotential[j, tmpN3W1] * (-1.) 1315 | forceY[i, indices] += -3. * 6.0 * weightInter[30] * interactionCoeff[i, j] * \ 1316 | fluidPotential[i, indices] * fluidPotential[j, tmpN3W1] * (1.) 1317 | #North1Western3 1318 | if (neighboringNodes[tmpStart31] != -1 and ((neighboringNodes[tmpStart2] != -1 \ 1319 | and neighboringNodes[tmpStart10] != -1) or (neighboringNodes[tmpStart5] != -1 \ 1320 | and neighboringNodes[tmpStart19] != -1))): 1321 | tmpN1W3 = neighboringNodes[tmpStart31] 1322 | for i in range(numFluids): 1323 | for j in range(numFluids): 1324 | forceX[i, indices] += -3. * 6.0 * weightInter[31] * interactionCoeff[i, j] * \ 1325 | fluidPotential[i, indices] * fluidPotential[j, tmpN1W3] * (-1.) 1326 | forceY[i, indices] += -6.0 * weightInter[31] * interactionCoeff[i, j] * \ 1327 | fluidPotential[i, indices] * fluidPotential[j, tmpN1W3] * (1.) 1328 | #South1Western3 1329 | if (neighboringNodes[tmpStart32] != -1 and ((neighboringNodes[tmpStart2] != -1 \ 1330 | and neighboringNodes[tmpStart10] != -1) or (neighboringNodes[tmpStart6] != -1 \ 1331 | and neighboringNodes[tmpStart20] != -1))): 1332 | tmpS1W3 = neighboringNodes[tmpStart32] 1333 | for i in range(numFluids): 1334 | for j in range(numFluids): 1335 | forceX[i, indices] += -3. * 6.0 * weightInter[32] * interactionCoeff[i, j] * \ 1336 | fluidPotential[i, indices] * fluidPotential[j, tmpS1W3] * (-1.) 1337 | forceY[i, indices] += -6.0 * weightInter[32] * interactionCoeff[i, j] * \ 1338 | fluidPotential[i, indices] * fluidPotential[j, tmpS1W3] * (-1.) 1339 | #South3Western1 1340 | if (neighboringNodes[tmpStart33] != -1 and ((neighboringNodes[tmpStart3] != -1 \ 1341 | and neighboringNodes[tmpStart11] != -1) or (neighboringNodes[tmpStart6] != -1 \ 1342 | and neighboringNodes[tmpStart21] != -1))): 1343 | tmpS3W1 = neighboringNodes[tmpStart33] 1344 | for i in range(numFluids): 1345 | for j in range(numFluids): 1346 | forceX[i, indices] += -6.0 * weightInter[33] * interactionCoeff[i, j] * \ 1347 | fluidPotential[i, indices] * fluidPotential[j, tmpS3W1] * (-1.) 1348 | forceY[i, indices] += -3. * 6.0 * weightInter[33] * interactionCoeff[i, j] * \ 1349 | fluidPotential[i, indices] * fluidPotential[j, tmpS3W1] * (-1.) 1350 | #South3Eastern1 1351 | if (neighboringNodes[tmpStart34] != -1 and ((neighboringNodes[tmpStart3] != -1 \ 1352 | and neighboringNodes[tmpStart11] != -1) or (neighboringNodes[tmpStart7] != -1 \ 1353 | and neighboringNodes[tmpStart22] != -1))): 1354 | tmpS3E1 = neighboringNodes[tmpStart34] 1355 | for i in range(numFluids): 1356 | for j in range(numFluids): 1357 | forceX[i, indices] += -6.0 * weightInter[34] * interactionCoeff[i, j] * \ 1358 | fluidPotential[i, indices] * fluidPotential[j, tmpS3E1] * (1.) 1359 | forceY[i, indices] += -3. * 6.0 * weightInter[34] * interactionCoeff[i, j] * \ 1360 | fluidPotential[i, indices] * fluidPotential[j, tmpS3E1] * (-1.) 1361 | #South1Eastern3 1362 | if (neighboringNodes[tmpStart35] != -1 and ((neighboringNodes[tmpStart] != -1 \ 1363 | and neighboringNodes[tmpStart8] != -1) or (neighboringNodes[tmpStart7] != -1 \ 1364 | and neighboringNodes[tmpStart23] != -1))): 1365 | tmpS1E3 = neighboringNodes[tmpStart35] 1366 | for i in range(numFluids): 1367 | for j in range(numFluids): 1368 | forceX[i, indices] += -3. * 6.0 * weightInter[35] * interactionCoeff[i, j] * \ 1369 | fluidPotential[i, indices] * fluidPotential[j, tmpS1E3] * (1.) 1370 | forceY[i, indices] += -6.0 * weightInter[35] * interactionCoeff[i, j] * \ 1371 | fluidPotential[i, indices] * fluidPotential[j, tmpS1E3] * (-1.) 1372 | cuda.syncthreads() 1373 | 1374 | """ 1375 | Convert original distribution f and f_eq to m and m_eq by collision matrix 1376 | """ 1377 | @cuda.jit('void(int64, int64, int64, float64[:, :, :], float64[:, :, :], float64[:, :, :], \ 1378 | float64[:, :, :])') 1379 | def transformPDFandEquil(totalNodes, numFluids, xDim, fluidPDF, fEq, collisionMatrix,\ 1380 | fluidPDFM): 1381 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 1382 | by = cuda.blockIdx.y 1383 | indices = by * xDim + bx * bDimX + tx 1384 | tmpFluidPDF = cuda.local.array(shape = 9, dtype = float64) 1385 | tmpfEq = cuda.local.array(shape = 9, dtype = float64) 1386 | if indices < totalNodes: 1387 | for i in range(numFluids): 1388 | for j in range(9): 1389 | tmpfPDF = 0.; tmpEq = 0. 1390 | for k in range(9): 1391 | tmpfPDF += collisionMatrix[i, j, k] * fluidPDF[i, indices, k] 1392 | tmpEq += collisionMatrix[i, j, k] * fEq[i, indices, k] 1393 | tmpFluidPDF[j] = tmpfPDF 1394 | tmpfEq[j] = tmpEq 1395 | for j in range(9): 1396 | fluidPDFM[i, indices, j] = tmpFluidPDF[j] 1397 | fEq[i, indices, j] = tmpfEq[j] 1398 | 1399 | """ 1400 | Convert force term to m_force by collision matrix 1401 | """ 1402 | @cuda.jit('void(int64, int64, int64, float64[:, :, :], float64[:, :, :], \ 1403 | float64[:, :,:])') 1404 | def transfromForceTerm(totalNodes, numFluids, xDim, fForce, collisionMatrix, \ 1405 | fForceM): 1406 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 1407 | by = cuda.blockIdx.y 1408 | indices = by * xDim + bx * bDimX + tx 1409 | tmpForceTerm = cuda.local.array(shape = 9, dtype = float64) 1410 | if indices < totalNodes: 1411 | for i in range(numFluids): 1412 | for j in range(9): 1413 | tmpF = 0. 1414 | for k in range(9): 1415 | tmpF += collisionMatrix[i, j, k] * fForce[i, indices, k] 1416 | tmpForceTerm[j] = tmpF 1417 | for j in range(9): 1418 | fForceM[i, indices, j] = tmpForceTerm[j] 1419 | 1420 | """ 1421 | Convert u_eq to MRT way for conserving momentum 1422 | """ 1423 | @cuda.jit('void(int64, int64, int64, float64[:], float64[:], \ 1424 | float64[:, :], float64[:, :], float64[:, :], float64[:, :, :], \ 1425 | float64[:], float64[:], float64[:])') 1426 | def transformEquilibriumVelocity(totalNodes, numFluids, xDim, EX, EY, fluidRho, \ 1427 | forceX, forceY, fluidPDF, conserveS, eqVX, eqVY): 1428 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 1429 | by = cuda.blockIdx.y 1430 | indices = by * xDim + bx * bDimX + tx 1431 | tmpEX = cuda.shared.array(shape = (9,), dtype = float64) 1432 | tmpEY = cuda.shared.array(shape = (9,), dtype = float64) 1433 | for i in range(9): 1434 | tmpEX[i] = EX[i] 1435 | tmpEY[i] = EY[i] 1436 | if (indices < totalNodes): 1437 | tmpMomentumX = 0.; tmpMomentumY = 0.; tmpRhoT = 0. 1438 | for i in range(numFluids): 1439 | eachMX = 0.; eachMY = 0.; tmpRho = fluidRho[i, indices] 1440 | for j in range(9): 1441 | eachMX += fluidPDF[i, indices, j] * tmpEX[j] 1442 | eachMY += fluidPDF[i, indices, j] * tmpEY[j] 1443 | eachMX += 1./2. * forceX[i, indices] 1444 | eachMY += 1./2. * forceY[i, indices] 1445 | tmpMomentumX += eachMX * conserveS[i] 1446 | tmpMomentumY += eachMY * conserveS[i] 1447 | tmpRhoT += tmpRho * conserveS[i] 1448 | eqVX[indices] = tmpMomentumX / tmpRhoT 1449 | eqVY[indices] = tmpMomentumY / tmpRhoT 1450 | 1451 | 1452 | """ 1453 | The last step of MRT transformation 1454 | """ 1455 | @cuda.jit('void(int64, int64, int64, float64[:, :, :], float64[:, :, :], \ 1456 | float64[:, :, :], float64[:, :, :], float64[:, :, :])') 1457 | def calAfterCollisionMRT(totalNodes, numFluids, xDim, fluidPDF, fForce, fEq, \ 1458 | fluidPDFM, fForceM): 1459 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 1460 | by = cuda.blockIdx.y 1461 | indices = by * xDim + bx * bDimX + tx 1462 | if indices < totalNodes: 1463 | for i in range(numFluids): 1464 | for j in range(9): 1465 | tmpCollision = 0. 1466 | tmpCollision = (fEq[i, indices, j] - fluidPDFM[i, indices, j] - \ 1467 | 1./2. * fForceM[i, indices, j]) 1468 | fluidPDF[i, indices, j] = fluidPDF[i, indices, j] + tmpCollision + \ 1469 | 1. * fForce[i, indices, j] 1470 | 1471 | """ 1472 | Calculate the outlet boundary with convective flow method. 1473 | """ 1474 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:], float64[:, :, :], \ 1475 | float64[:, :], float64[:, :, :], float64[:, :, :])') 1476 | def convectiveOutletGPUEFS(totalNodes, numFluids, nx, xDim, fluidNodes, neighboringNodes, \ 1477 | fluidPDFNew, fluidRho, fForce, fEq): 1478 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 1479 | by = cuda.blockIdx.y 1480 | indices = by * xDim + bx * bDimX + tx 1481 | #calculate the average velocity 1482 | tmpSumV = 0. 1483 | tmpStart = 3 * nx 1484 | 1485 | if (indices < totalNodes): 1486 | tmpIndex = fluidNodes[indices] 1487 | if (tmpIndex < 3 * nx and tmpIndex >= 2 * nx): 1488 | tmpIndices = neighboringNodes[8 * indices + 1] 1489 | for i in range(numFluids): 1490 | fluidRho[i, indices] = 0. 1491 | for j in range(9): 1492 | fluidPDFNew[i, indices, j] = fluidPDFNew[i, tmpIndices, j] 1493 | # (fluidPDFOld[i, indices, j] + \ 1494 | # averageV * fluidPDFNew[i, indices + nx, j]) / (1. + \ 1495 | # averageV) 1496 | fForce[i, indices, j] = fForce[i, tmpIndices, j] 1497 | fEq[i, indices, j] = fEq[i, tmpIndices, j] 1498 | fluidRho[i, indices] += fluidPDFNew[i, tmpIndices, j] 1499 | cuda.syncthreads() 1500 | 1501 | """ 1502 | Calculate the outlet boundary ghost nodes in second layer with convective flow method. 1503 | """ 1504 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:], float64[:, :, :], \ 1505 | float64[:, :], float64[:, :, :], float64[:, :, :])') 1506 | def convectiveOutletGhost2GPUEFS(totalNodes, numFluids, nx, xDim, \ 1507 | fluidNodes, neighboringNodes, fluidPDFNew, fluidRho, \ 1508 | fForce, fEq): 1509 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 1510 | by = cuda.blockIdx.y 1511 | indices = by * xDim + bx * bDimX + tx 1512 | #calculate the average velocity 1513 | tmpSumV = 0. 1514 | tmpStart = 3 * nx 1515 | 1516 | if (indices < totalNodes): 1517 | tmpIndex = fluidNodes[indices] 1518 | if (tmpIndex < 2 * nx and tmpIndex >= nx): 1519 | tmpIndices = neighboringNodes[8 * indices + 1] 1520 | for i in range(numFluids): 1521 | fluidRho[i, indices] = 0. 1522 | for j in range(9): 1523 | fluidPDFNew[i, indices, j] = fluidPDFNew[i, tmpIndices, j] 1524 | # (fluidPDFOld[i, indices, j] + \ 1525 | # averageV * fluidPDFNew[i, indices + nx, j]) / (1. + \ 1526 | # averageV) 1527 | fForce[i, indices, j] = fForce[i, tmpIndices, j] 1528 | fEq[i, indices, j] = fEq[i, tmpIndices, j] 1529 | fluidRho[i, indices] += fluidPDFNew[i, tmpIndices, j] 1530 | cuda.syncthreads() 1531 | 1532 | """ 1533 | Calculate the outlet boundary ghost nodes in first layer with convective flow method. 1534 | """ 1535 | @cuda.jit('void(int64, int64, int64, int64, int64[:], int64[:], float64[:, :, :], \ 1536 | float64[:, :], float64[:, :, :], float64[:, :, :])') 1537 | def convectiveOutletGhost3GPUEFS(totalNodes, numFluids, nx, xDim, \ 1538 | fluidNodes, neighboringNodes, fluidPDFNew, fluidRho, \ 1539 | fForce, fEq): 1540 | tx = cuda.threadIdx.x; bx = cuda.blockIdx.x; bDimX = cuda.blockDim.x 1541 | by = cuda.blockIdx.y 1542 | indices = by * xDim + bx * bDimX + tx 1543 | #calculate the average velocity 1544 | tmpSumV = 0. 1545 | tmpStart = 3 * nx 1546 | 1547 | if (indices < totalNodes): 1548 | tmpIndex = fluidNodes[indices] 1549 | if (tmpIndex < nx and tmpIndex >= 0): 1550 | tmpIndices = neighboringNodes[8 * indices + 1] 1551 | for i in range(numFluids): 1552 | fluidRho[i, indices] = 0. 1553 | for j in range(9): 1554 | fluidPDFNew[i, indices, j] = fluidPDFNew[i, tmpIndices, j] 1555 | # (fluidPDFOld[i, indices, j] + \ 1556 | # averageV * fluidPDFNew[i, indices + nx, j]) / (1. + \ 1557 | # averageV) 1558 | fForce[i, indices, j] = fForce[i, tmpIndices, j] 1559 | fEq[i, indices, j] = fEq[i, tmpIndices, j] 1560 | fluidRho[i, indices] += fluidPDFNew[i, tmpIndices, j] 1561 | cuda.syncthreads() 1562 | 1563 | -------------------------------------------------------------------------------- /ShanChen2D/SimpleD2Q9.py: -------------------------------------------------------------------------------- 1 | """ 2 | Class: BasicD2Q9 3 | Usage: includes basic algorithm (SRT & MRT) of LBM for fluid flow 4 | interactions.It can define 2D model with different boundary conditions and simple 5 | geometry. The computationale parts are accelerated using Anaconda. 6 | =============================================================================== 7 | author: Pei Li 8 | Email: pei.li@weizmann.ac.il 9 | """ 10 | import sys, os 11 | import configparser 12 | 13 | import numpy as np 14 | import scipy as sp 15 | import scipy.linalg as slin 16 | import matplotlib.pyplot as plt 17 | 18 | from numba import jit 19 | from numba import vectorize, cuda 20 | 21 | ##sys.path.append("..") 22 | ##from BoundaryCondition import BoundaryConditions as BC 23 | 24 | 25 | class BasicD2Q9: 26 | def __init__(self, pathIniFile): 27 | """ 28 | use configparser to read the .ini file 29 | """ 30 | self.path = pathIniFile 31 | config = configparser.ConfigParser() 32 | config.read(self.path + '/'+ 'basicsetup.ini') 33 | #read the grid number 34 | try: 35 | self.typeScheme = config['Scheme']['Type'] 36 | except KeyError: 37 | print('Could not have right scheme for LBM, please check .ini file') 38 | sys.exit('error') 39 | try: 40 | self.length = float(config['Geometry']['length']) 41 | self.width = float(config['Geometry']['width']) 42 | self.nx = int(config['Geometry']['nx']) 43 | self.ny = int(config['Geometry']['ny']) 44 | except KeyError: 45 | print('Could not give the right grid numbers, please check .ini file') 46 | sys.exit('error happens') 47 | #raise 48 | #read time and time step for simulation 49 | try: 50 | self.timeForSimulation = float(config['Time']['TimeLength']) 51 | self.timeStep = float(config['Time']['TimeStep']) 52 | except KeyError: 53 | print('Could not give the right time set up, please check .ini file') 54 | sys.exit('error happens') 55 | try: 56 | self.initialVXLB = float(config['InitialCondition']['VelocityXLB']) 57 | self.initialVYLB = float(config['InitialCondition']['VelocityYLB']) 58 | except KeyError: 59 | print('Could not have the intial velocity, please check .ini file') 60 | sys.exit('error happens') 61 | try: 62 | self.bodyForceG = float(config['BodyForce']['gValue']) 63 | except KeyError: 64 | print('Could not have the body force value, please check .ini file') 65 | sys.exit('error happens') 66 | try: 67 | self.xDomain = list(map(int, config.get('FlowDomain', 'xDomain').split(','))) 68 | self.yDomain = list(map(int, config.get('FlowDomain', 'yDomain').split(','))) 69 | except KeyError: 70 | print('Could not have the boundary position value, please check .ini file') 71 | sys.exit('error happens') 72 | self.deltaX = self.length / (self.nx - 1) 73 | self.deltaY = self.width / (self.ny - 1) 74 | #initialize coefficients in equilibrium function 75 | self.weightsCoeff = sp.empty(9) #D2Q9 algorithm 76 | self.weightsCoeff[0] = 4./ 9. 77 | self.weightsCoeff[1:5] = 1./ 9. 78 | self.weightsCoeff[5:] = 1./ 36. 79 | self.f1Eq = 3.; self.f2Eq = 9./2.; self.f3Eq = -3./2. 80 | #initialize microscopic velocities in each direction 81 | #self.microVelocity = sp.array([(c1, c2) for c1 in [0, -1, 1] \ 82 | # for c2 in [0, -1, 1]]) 83 | self.microVelocity = sp.empty([9, 2]) 84 | self.microVelocity[0] = [0., 0.] #center of the lattice 85 | self.microVelocity[1] = [1.0, 0.]; self.microVelocity[2] = [0., 1.0] 86 | self.microVelocity[3] = [-1., 0.]; self.microVelocity[4] = [0., -1.0] 87 | self.microVelocity[5] = [1., 1.,]; self.microVelocity[6] = [-1., 1.] 88 | self.microVelocity[7] = [-1., -1.]; self.microVelocity[8] = [1., -1.] 89 | self.velocityCoeff = 1.0 # (self.deltaX) / (self.deltaY) 90 | self.soundSpeed = 1.0 / sp.sqrt(3.) 91 | #initialize relaxation parameter 92 | #TODO check the calculation method for omega 93 | self.omega = 0.0 94 | self.tau = 1.0 #default value for numerical stablility 95 | #initialize macroscopic parameters in the domain (density, veclocity) 96 | self.rho = sp.ones([self.ny, self.nx]) 97 | self.velocityX = sp.empty([self.ny, self.nx]) 98 | self.velocityY = sp.empty([self.ny, self.nx]) 99 | #initialize distribution function of each direction in each lattice 100 | self.particleDisFunc = sp.ones([9, self.ny, self.nx]) 101 | #initialize the array for equilibrium function on each direction of 102 | #each lattice 103 | self.equilibriumDisFunc = sp.empty([9, self.ny, self.nx]) 104 | self.isWall = sp.empty([self.ny, self.nx], dtype = 'bool') 105 | self.isDomain = sp.empty([self.ny, self.nx], dtype = 'bool') 106 | #define the transformation matrix in MRT scheme 107 | self.transformationMatrix = sp.zeros([9, 9], dtype = 'float64') 108 | self.transformationMatrix[0, :] = 1.; self.transformationMatrix[1, 0] = -4. 109 | self.transformationMatrix[1, 1:5] = -1.; self.transformationMatrix[1, 5:] = 2. 110 | self.transformationMatrix[2, 0] = 4.; self.transformationMatrix[2, 1:5] = -2. 111 | self.transformationMatrix[2, 5:]= 1.; self.transformationMatrix[3, 1] = 1. 112 | self.transformationMatrix[3, 3] = -1.; self.transformationMatrix[3, 5] = 1. 113 | self.transformationMatrix[3, 6:8] = -1.; self.transformationMatrix[3, -1] = 1. 114 | self.transformationMatrix[4, 1] = -2.; self.transformationMatrix[4, 3] = 2.0 115 | self.transformationMatrix[4, 5] = 1.; self.transformationMatrix[4, 6:8] = -1. 116 | self.transformationMatrix[4, 8] = 1. 117 | self.transformationMatrix[5, 2] = 1.; self.transformationMatrix[5, 4] = -1 118 | self.transformationMatrix[5, 5:7] = 1.; self.transformationMatrix[5, 7:] = -1. 119 | self.transformationMatrix[6, 2] = -2.; self.transformationMatrix[6, 4] = 2. 120 | self.transformationMatrix[6, 5:7] = 1.; self.transformationMatrix[6, 7:] = -1. 121 | self.transformationMatrix[7, 1] = 1.; self.transformationMatrix[7, 2] = -1. 122 | self.transformationMatrix[7, 3] = 1.; self.transformationMatrix[7, 4] = -1. 123 | self.transformationMatrix[8, 5] = 1.; self.transformationMatrix[8, -3] = -1. 124 | self.transformationMatrix[8, -2] = 1.; self.transformationMatrix[8, -1] = -1. 125 | ## c = slin.inv(self.transformationMatrix) 126 | ## print(np.dot(self.transformationMatrix, slin.inv(self.transformationMatrix))) 127 | ## input() 128 | #define the relaxation rate in each direction (There are two options) 129 | self.relaxationS = sp.zeros(9, dtype = 'float64') 130 | self.relaxationS[1] = 1. / self.tau; self.relaxationS[2]= 1./self.tau 131 | self.relaxationS[7:] = 1./self.tau; 132 | self.relaxationS[4] = 8.* (2.-1./self.tau) / (8. - 1./self.tau) 133 | 134 | 135 | """ 136 | use perturbation function to give distribution function f_n the initial 137 | condition: 138 | """ 139 | @jit(target="cpu") 140 | def __initializeDomainCondition(self): 141 | """ 142 | Initialize the distribution function value in the domain 143 | """ 144 | #self.velocityX[:, 0] = 0.04 145 | for i in sp.arange(9): 146 | self.particleDisFunc[i, :, :] *= self.weightsCoeff[i] 147 | #self.equilibriumDisFunc = self.particleDisFunc 148 | self.velocityX[:, :] = self.initialVXLB 149 | self.velocityY[:, :] = self.initialVYLB 150 | 151 | @jit(target ="cpu") 152 | def __initializeSolidPosition(self): 153 | """ 154 | Define the solid phase position and domain size 155 | """ 156 | ## self.isWall[:, :] = False 157 | ## self.isWall[:, 0] = True; self.isWall[:, self.nx - 1] = True 158 | ## self.isDomain[:, :] = True 159 | ## self.isDomain[:, 0] = False; self.isDomain[:, self.nx - 1] = False 160 | self.isDomain[:, :] = True 161 | self.isDomain[self.yDomain[0], :] = False 162 | self.isDomain[self.yDomain[-1], :] = False 163 | self.isWall[:, :] = False 164 | self.isWall[self.yDomain[0], :] = True; self.isWall[self.yDomain[-1], :] = True 165 | 166 | @jit(target="cpu") 167 | def __calMacroscopicParameters(self, ): 168 | """ 169 | Update the density of each lattice and velocity by: 170 | rho = \sum_{n=0}^{9}particleDisFunc 171 | velocityX = 172 | """ 173 | self.rho[i, j] = sp.sum(self.particleDisFunc[:, i, j]) 174 | self.velocityX[i, j] = sp.sum(self.particleDisFunc[:, i, j] \ 175 | * self.microVelocity[:, 0]) / self.rho[i, j] 176 | self.velocityY[i, j] = sp.sum(self.particleDisFunc[:, i, j] \ 177 | * self.microVelocity[:, 1]) / self.rho[i, j] 178 | 179 | @jit(target="cpu" ) 180 | def __calEquilibriumDisFunc(self): 181 | """ 182 | Compute the equilibrium distribution function in each direction of each 183 | lattice 184 | """ 185 | coeff1 = 3.0; coeff2 = 9./2.; coeff3 = -3./2. 186 | for i in sp.arange(self.ny): 187 | for j in sp.arange(self.nx): 188 | velocityAtLattice = np.array([self.velocityX[i, j],\ 189 | self.velocityY[i, j] + self.bodyForceG]) 190 | for k in sp.arange(9): 191 | self.equilibriumDisFunc[k, i, j] = self.weightsCoeff[k] * \ 192 | self.rho[i, j] * (1.0 + coeff1 * (np.dot(self.microVelocity[k], \ 193 | velocityAtLattice)) + coeff2 * (sp.power(np.dot(self.microVelocity[k], \ 194 | velocityAtLattice), 2.0)) + coeff3 * np.dot(velocityAtLattice, \ 195 | velocityAtLattice)) 196 | 197 | @jit(target = "cpu") 198 | def calEquilibriumDisFuncLoc(self, macroDensity, macroVelocity): 199 | coeff1 = 3.0; coeff2 = 9./2.; coeff3 = -3./2.0 200 | tmpEquilibrium = np.ones(9, dtype = 'float64') 201 | for i in sp.arange(9): 202 | tmpEquilibrium[i] = self.weightsCoeff[i] * macroDensity * (1. + \ 203 | coeff1 * (np.dot(self.microVelocity[i], macroVelocity)) + \ 204 | coeff2 * (sp.power(np.dot(self.microVelocity[i], macroVelocity), \ 205 | 2.0)) + coeff3 * np.dot(macroVelocity, macroVelocity)) 206 | return tmpEquilibrium 207 | 208 | @jit(target="cpu") 209 | def __calCollisionProcess(self): 210 | """ 211 | Compute the collision step 212 | """ 213 | tempCollision = sp.empty([9, self.ny, self.nx]) 214 | for i in sp.arange(9): 215 | ## if (self.isDomain[i, j]): 216 | tempCollision[i, :, :] = self.particleDisFunc[i, :, :] - \ 217 | (self.particleDisFunc[i, :, :] - self.equilibriumDisFunc[i, :, :]) /\ 218 | self.tau 219 | return tempCollision 220 | 221 | @jit(target = "cpu") 222 | def __bounceBackBC(self, tempCollision): 223 | """ 224 | bounce-back boundary condition 225 | """ 226 | oppDirection = oppDirection = [0, 3, 4, 1, 2, 7, 8, 5, 6] 227 | for i in sp.arange(9): 228 | tempCollision[i, self.isWall] = self.particleDisFunc[oppDirection[i], \ 229 | self.isWall] 230 | return temCollision 231 | 232 | @jit(target="cpu") 233 | def __calStreamingProcess(self, tempParticleDisFunc): 234 | """ 235 | Streaming step for each lattice 236 | """ 237 | for i in sp.arange(9): 238 | self.particleDisFunc[i, :, :] = np.roll(np.roll(tempParticleDisFunc[i, \ 239 | :, :], self.microVelocity[i, 1], 240 | axis = 0), self.microVelocity[i, 0],\ 241 | axis = 1) 242 | 243 | @jit(target = "cpu") 244 | def __calMRTMoments(self): 245 | """ 246 | Transforming the distribution functions f to moments m 247 | """ 248 | tempMoments = sp.empty([9, self.ny, self.nx], dtype = 'float64') 249 | for i in sp.arange(self.ny): 250 | for j in sp.arange(self.nx): 251 | tempMoments[:, i, j] = np.dot(self.transformationMatrix, \ 252 | self.particleDisFunc[:, i, j]) 253 | return tempMoments 254 | 255 | @jit(target="cpu") 256 | def __calMRTMomentEquilbira(self): 257 | """ 258 | Transforming the equilibrium distribution to equilibria in the moment space 259 | """ 260 | tempMomentsEquilibria = sp.empty([9, self.ny, self.nx]) 261 | for i in sp.arange(self.ny): 262 | for j in sp.arange(self.nx): 263 | tempMomentsEquilibra[:, i, j] = np.dot(self.transformationMatrix, \ 264 | self.equilibriumDisFunc[:, i, j]) 265 | return tempMomentsEquilibra 266 | 267 | @jit(target="cpu") 268 | def __calMRTCollision(self, moments, equilibria): 269 | """ 270 | Calculate the collision in moment space 271 | """ 272 | tempMRTCollision = sp.empty([9, self.ny, self.nx]) 273 | tempRelaxationMatrix = sp.zeros([9, 9], dtype = 'float64') 274 | np.fill_diagonal(tempRelaxationMatrix, self.relaxationS) 275 | for i in sp.arange(9): 276 | tempMRTCollision[i, :, :] = moments[i, :, :] - np.dot(tempRelaxationMatrix, \ 277 | (moments[i, :, :] - equilibria[i, :, :])) 278 | return tempMRTCollision 279 | 280 | @jit(target="cpu") 281 | def __calPostParticleDisFunc(self, momentsCollision): 282 | """ 283 | Transforming the post-collision moments m' back to the post collision 284 | distribution function f' 285 | """ 286 | tempParticleDisFunc = sp.empty([9, self.ny, self.nx]) 287 | inverseTransformation = slin.inv(self.transformationMatrix) 288 | for i in sp.arange(self.ny): 289 | for j in sp.arange(self.nx): 290 | tempParticleDisFunc[:, i, j] = np.dot(inverseTransformation, \ 291 | momentsCollision[:, i, j]) 292 | return tempParticleDisFunc 293 | 294 | def plotVelocityProfile(self, yPosition): 295 | plt.figure() 296 | tempX = sp.arange(self.ny) 297 | print(tempX) 298 | plt.plot(self.velocityY[yPosition, :], 'bo', label = 'velocity profile') 299 | plt.legend() 300 | plt.show() 301 | 302 | def runModeling(self): 303 | #BounceBack = BC 304 | #test for single phase and periodic boundary condition 305 | nTimeSteps = int(self.timeForSimulation / self.timeStep) 306 | #tempCollision = sp.empty([self.ny, self.nx, 9]) 307 | #Initialize distribution function 308 | self.__initializeSolidPosition() 309 | self.__initializeDomainCondition() 310 | #self.__calMacroscopicParameters() 311 | #self.__calMacroscopicParameters() 312 | if (self.typeScheme == 'SRT'): 313 | for i in sp.arange(nTimeSteps): 314 | print('This is step %g' % i) 315 | self.__calMacroscopicParameters() 316 | #print(self.equilibriumDisFunc) 317 | self.__calEquilibriumDisFunc() 318 | tempParticleDisFunc = self.__calCollisionProcess() 319 | tempParticleDisFunc = self.__bounceBackBC(tempParticleDisFunc) 320 | self.__calStreamingProcess(tempParticleDisFunc) 321 | elif (self.typeScheme == 'MRT'): 322 | for i in sp.arange(nTimeSteps): 323 | print('This is step %g' % i) 324 | self.__calMacroscopicParameters() 325 | self.__calEquilibriumDisFunc() 326 | tempMoments = self.__calMRTMoments() 327 | tempEquilibria = self.__calMRTMomentEquilibria() 328 | tempMRTCollision = self.__calMRTCollision(tempMoments, tempEquilibria) 329 | tempParticleDisFunc = self.__calPostParticleDisFunc(tempMRTCollision) 330 | tempParticleDisFunc = self.__bounceBackBC(tempParticleDisFunc) 331 | self.__calStreamingProcess(tempParticleDisFunc) -------------------------------------------------------------------------------- /ShanChen2D/SimpleGeometry.py: -------------------------------------------------------------------------------- 1 | """ 2 | Define the simple geometry domain to test differernt phenomena and boundary 3 | conditions 4 | """ 5 | 6 | import os, sys 7 | 8 | import numpy as np 9 | import scipy as sp 10 | 11 | def defineGeometry(xDomain, yDomain): 12 | tmpVoid = np.ones([yDomain, xDomain], dtype = np.bool) 13 | tmpSolid = np.zeros([yDomain, xDomain], dtype = np.bool) 14 | # tmpVoid[0, :] = 0; tmpVoid[-1, :] = 0 15 | # tmpSolid[0, :] = 1; tmpSolid[-1, :] = 1 16 | # tmpVoid[:, 0] = 0; tmpVoid[:, -1] = 0 17 | # tmpSolid[:, 0] = 1; tmpSolid[:, -1] = 1 18 | tmpVoid[10:-10, 0] = 0; tmpVoid[10:-10, -1] = 0 19 | tmpSolid[10:-10, 0] = 1; tmpSolid[10:-10, -1] = 1 20 | # tmpVoid[10:-10, :16] = 0; tmpVoid[10:-10, 80:] = 0 21 | # tmpSolid[10:-10, :16] = 1; tmpSolid[10:-10, 80:] = 1 22 | # tmpVoid[108:148, 1:16] = 1; tmpVoid[108:148, 80:-1] = 1 23 | # tmpSolid[108:148, 1:16] = 0; tmpSolid[108:148, 80:-1] = 0 24 | 25 | # tmpVoid[-1, :] = 0; tmpSolid[-1, :] = 1 26 | # tmpVoid[0, :] = 0; tmpSolid[0, :] = 1 27 | return tmpVoid, tmpSolid -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | """ 2 | Main file for implementing LBM modeling. It will check whether there is existing 3 | dirctory for saving results, then create one. It will also check whether .ini 4 | files exists or not, because the file includes fluids properties, initial and 5 | boundary conditions. Then the simulation will run. 6 | =============================================================================== 7 | author: Pei Li 8 | Email: pei.li@weizmann.ac.il 9 | """ 10 | 11 | import os, sys, getpass 12 | import configparser 13 | 14 | from ShanChenD2Q9 import ShanChenD2Q9 15 | from Transport2D import Transport2D 16 | 17 | from ShanChenD3Q19 import ShanChenD3Q19 18 | 19 | from RKD2Q9 import RKColorGradientLBM 20 | from Transport2DRK import Transport2DRK 21 | 22 | from RKColorGradientD3Q19 import RKColorGradient3D 23 | 24 | #search and create LBMResults directory 25 | username = getpass.getuser() 26 | pathForResultDirectoryDensity = os.path.expanduser('~/LBMResults') 27 | pathForResultDirectoryVelocity = os.path.expanduser('~/LBMVelocity') 28 | pathForResultDirectionDensity3D = os.path.expanduser('~/LBMResults3D') 29 | 30 | if (os.path.exists(pathForResultDirectoryDensity) == False): 31 | os.mkdir('/home/' + username + '/LBMResults' ) 32 | if (os.path.exists(pathForResultDirectoryVelocity) == False): 33 | os.mkdir('/home/' + username + '/LBMVelocity') 34 | 35 | #search the directory for .ini file 36 | iniFilePath = 'IniFiles' 37 | if (os.path.isdir(iniFilePath) == False): 38 | sys.exit() 39 | 40 | modelDimension = input("Please choose 2D/3D model (enter 2D or 3D):") 41 | modelType = input("Please choose the type of the simulation (enter flow or transport): ") 42 | 43 | LBMType = input("Please choose ShanChen(SC) or Color Gradient(CG) methods for flow: ") 44 | 45 | if modelDimension == "2D": 46 | print("Run 2D simulation.") 47 | if (modelType == "flow" and LBMType == "SC"): 48 | flow2D = ShanChenD2Q9(iniFilePath) 49 | flow2D.runTypeSCmodel() 50 | elif (modelType == "flow" and LBMType == "CG"): 51 | flow2D = RKColorGradientLBM(iniFilePath) 52 | # flow2D.runRKColorGradient2D() 53 | flow2D.runModifiedRKColorGradient2D() 54 | elif (modelType == "transport" and LBMType == "SC"): 55 | flowType = input("Please choose the force scheme (OR: original or EF: explicit forcing): ") 56 | transport2D = Transport2D(iniFilePath) 57 | if (flowType == "OR"): 58 | #transport2D.runTransport2DStaticInterface() 59 | transport2D.runTransport2DMPMC() 60 | elif (flowType == "EF"): 61 | transport2D.runTransportMPMCEFS() 62 | #transport2D.runTransportCPU() 63 | elif (modelType == "transport" and LBMType == "CG"): 64 | transport2D = Transport2DRK(iniFilePath) 65 | transport2D.runTransport2DMPMCRK() 66 | 67 | elif (modelType == "transport" and LBMType == "No"): 68 | transport2D = Transport2D(iniFilePath) 69 | transport2D.testTransportMRTScheme() 70 | print("The chosen type does not exist in current version. Stop here.") 71 | sys.exit() 72 | elif modelDimension == "3D": 73 | if (modelType == "flow" and LBMType == "SC"): 74 | print("Run 3D simulation with SC.") 75 | MCMPLBM3D = ShanChenD3Q19(iniFilePath) 76 | # MCMPLBM3D.runOriginalSC3DGPU() 77 | MCMPLBM3D.runEFS4LBM3DGPU() 78 | elif (modelType == "flow" and LBMType == "CG"): 79 | print("Run 3D simulation with CG.") 80 | RKCGLBM3D = RKColorGradient3D(iniFilePath) 81 | RKCGLBM3D.runRKColorGradient3D() --------------------------------------------------------------------------------