├── make.sh ├── .gitattributes ├── images ├── cuda_fdtd.png ├── fdtd_eqn1.png └── fdtd_eqn2.png ├── CMakeLists.txt ├── src ├── cfdtd_wrapper.cu └── cuda_fdtd.h ├── README.md └── .save.vim /make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd build 4 | make 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-vendored 2 | *.cu linguist-vendored=false 3 | -------------------------------------------------------------------------------- /images/cuda_fdtd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jwhite510/CUDA-FDTD-simulation/HEAD/images/cuda_fdtd.png -------------------------------------------------------------------------------- /images/fdtd_eqn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jwhite510/CUDA-FDTD-simulation/HEAD/images/fdtd_eqn1.png -------------------------------------------------------------------------------- /images/fdtd_eqn2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jwhite510/CUDA-FDTD-simulation/HEAD/images/fdtd_eqn2.png -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(cfdtd) 3 | 4 | add_definitions("-std=c++11 -O3 -ffast-math") 5 | 6 | set(CMAKE_BUILD_TYPE Debug) 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 8 | 9 | set(CUDA_HOST_COMPILER "g++-6") 10 | find_package(CUDA REQUIRED) 11 | 12 | cuda_add_library(cfdtd_wrapper SHARED src/cfdtd_wrapper.cu) 13 | -------------------------------------------------------------------------------- /src/cfdtd_wrapper.cu: -------------------------------------------------------------------------------- 1 | // #include"cfdtd.h" 2 | #include"cuda_fdtd.h" 3 | #include 4 | 5 | 6 | using namespace std; 7 | extern "C"{ 8 | void* FDTD_new(int N_x,int N_y,int N_z, 9 | double dx,double dt,double omega,double tau, 10 | double*Ex,double*Ey,double*Ez, 11 | double*Hx,double*Hy,double*Hz, 12 | double*Jx,double*Jy,double*Jz 13 | ) 14 | { 15 | 16 | // FDTD*m = new FDTD(s_0,s_1,s_2,arr1hostd,arr2hostd); 17 | FDTD*m = new FDTD(N_x,N_y,N_z, 18 | dx,dt,omega,tau, 19 | Ex,Ey,Ez, 20 | Hx,Hy,Hz, 21 | Jx,Jy,Jz 22 | ); 23 | return (void*)m; 24 | } 25 | void FDTD_run(void*p,int N){ 26 | FDTD*m=(FDTD*)p; 27 | m->run(N); 28 | } 29 | void FDTD_delete(void*p){ 30 | FDTD*m=(FDTD*)p; 31 | delete m; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CUDA-FDTD-simulation 2 | 3 | Finite Difference Time Domain Simulation written in CUDA, with python Bindings. 4 | All of the CUDA Tensors for the Electric and Magnetic fields are exposed as numpy arrays 5 | in python. 6 | 7 | CUDA is used to calculate each point of the computational grid in parallel on a GPU. 8 | 9 | The FDTD uses a discretized form of Maxwell's equations to simulate propagation of a source through vacuum or a material described by a complex refractive index n(x,y,z). 10 | ## Maxwell's Equations discretized to 3D space 11 | 12 | 13 | The computational process is extremely demanding because the computational grid must be resolved on the order of the wavelength of the EM waves being simulated. 14 | 15 | 16 | ``` 17 | import matplotlib.pyplot as plt 18 | import numpy as np 19 | from Cfdtd import FDTD 20 | 21 | if __name__=="__main__": 22 | N_x=200 23 | N_y=200 24 | N_z=200 25 | dx=50e-9 26 | c=2.998e8 27 | dt=dx/(2*c) 28 | freq=500e12; 29 | omega =2*np.pi*freq; 30 | tau=10*dt 31 | 32 | fdtd = FDTD(N_x,N_y,N_z,dx,dt,omega,tau) 33 | 34 | time_span=15e-15; 35 | tmax_steps=int(time_span/dt); 36 | 37 | # define source term 38 | _x=np.arange(N_x).reshape(-1,1,1) 39 | _y=np.arange(N_y).reshape(1,-1,1) 40 | _z=np.arange(N_z).reshape(1,1,-1) 41 | fdtd.J.z[:,:,:]=np.exp(-(_x-100)**2 / 5)*np.exp(-(_y-100)**2 / 5)*np.exp(-(_z-100)**2 / 5) 42 | fdtd.J.z[:,:,:]+=np.exp(-(_x-75)**2 / 5)*np.exp(-(_y-75)**2 / 5)*np.exp(-(_z-100)**2 / 5) 43 | 44 | 45 | plt.figure(1) 46 | for n in range(0,tmax_steps): 47 | 48 | fdtd.timestep(5) # run 5 timesteps 49 | 50 | plt.gca().cla() 51 | # show the x component of the magnetic field 52 | plt.imshow(fdtd.H.x[:,:,100]) 53 | plt.pause(0.01) 54 | 55 | 56 | fdtd.delete() 57 | ``` 58 | -------------------------------------------------------------------------------- /src/cuda_fdtd.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std::chrono; 6 | using namespace std; 7 | 8 | struct Parameters{ 9 | double Hc; 10 | double Jc; 11 | double Ec; 12 | double t; 13 | double tau; // duration of excitation 14 | double omega; // frequency of excitation 15 | double dt; // frequency of excitation 16 | }; 17 | 18 | struct array3d{ 19 | int size_0; 20 | int size_1; 21 | int size_2; 22 | int length; 23 | double* h_data; 24 | double* d_data; 25 | void CopyToHost(){ 26 | cudaMemcpy(h_data,d_data,length*sizeof(double),cudaMemcpyDeviceToHost); 27 | } 28 | void CopyToDevice(){ 29 | cudaMemcpy(d_data,h_data,length*sizeof(double),cudaMemcpyHostToDevice); 30 | } 31 | void show(){ 32 | for(int _i0=0; _i0 < size_0; _i0++){ 33 | // printing slice 34 | for(int _i1=0; _i1 < size_1; _i1++){ 35 | for(int _i2=0; _i2 < size_2; _i2++){ 36 | cout<0 && j>0 && k>0){ 144 | if(i0 && j>0 && k>0){ 195 | if(i " << N << endl; 263 | // run N times 264 | for(int i=0; i < N; i++){ 265 | auto start=high_resolution_clock::now(); 266 | timestepE<<>>(E,H,J,params); 267 | timestepH<<>>(E,H,J,params); 268 | params.t+=params.dt; 269 | auto stop=high_resolution_clock::now(); 270 | auto duration=duration_cast(stop-start); 271 | // cout << "duration [ms] => " << duration.count() << endl; 272 | } 273 | 274 | // cout << "numBlocks => " << numBlocks << endl; 275 | // add<<>>(arr1, arr2); 276 | E.CopyToHost(); 277 | H.CopyToHost(); 278 | J.CopyToHost(); 279 | 280 | // Wait for GPU to finish before accessing on host 281 | // cout<<"arr1:"<:p") 4 | silent only 5 | cd ~/Projects/ftdt 6 | if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' 7 | let s:wipebuf = bufnr('%') 8 | endif 9 | set shortmess=aoO 10 | badd +46 term://.//7997:/bin/bash 11 | badd +1 CMakeLists.txt 12 | badd +24 ~/Projects/fdtdt_simulation/src/fdtd.h 13 | badd +11 ~/Projects/fdtdt_simulation/src/fdtdwrapper.cu 14 | badd +19 build/test.py 15 | badd +17 build/Cfdtd.py 16 | badd +1 src/cfdtd_wrapper.h 17 | badd +1 src/cfdtd_wrapper.cpp 18 | badd +319 term://.//3069:/bin/bash 19 | badd +1 ~/Projects/fdtdt_simulation/src 20 | badd +1 ~/Projects/fdtdt_simulation/CMakeLists.txt 21 | badd +54 term://.//8452:/bin/bash 22 | badd +92 src/cfdtd.cpp 23 | badd +40 src/cfdtd.h 24 | badd +60 src/cuda_fdtd.h 25 | badd +1 make.sh 26 | badd +22 src/cfdtd_wrapper.cu 27 | badd +116 term://.//12536:/bin/bash 28 | badd +1 .save.vim 29 | badd +574 term://.//12846:/bin/bash 30 | badd +814 term://.//15836:/bin/bash 31 | badd +300 term://.//19637:/bin/bash 32 | badd +292 term://.//22828:/bin/bash 33 | badd +1213 term://.//23280:/bin/bash 34 | badd +1 term://.//3144:/bin/bash 35 | badd +1 term://.//3136:/bin/bash 36 | argglobal 37 | %argdel 38 | $argadd ./ 39 | set stal=2 40 | edit build/test.py 41 | set splitbelow splitright 42 | wincmd _ | wincmd | 43 | split 44 | 1wincmd k 45 | wincmd w 46 | wincmd _ | wincmd | 47 | vsplit 48 | wincmd _ | wincmd | 49 | vsplit 50 | 2wincmd h 51 | wincmd w 52 | wincmd w 53 | set nosplitbelow 54 | set nosplitright 55 | wincmd t 56 | set winminheight=0 57 | set winheight=1 58 | set winminwidth=0 59 | set winwidth=1 60 | exe '1resize ' . ((&lines * 7 + 24) / 49) 61 | exe '2resize ' . ((&lines * 38 + 24) / 49) 62 | exe 'vert 2resize ' . ((&columns * 70 + 106) / 212) 63 | exe '3resize ' . ((&lines * 38 + 24) / 49) 64 | exe 'vert 3resize ' . ((&columns * 70 + 106) / 212) 65 | exe '4resize ' . ((&lines * 38 + 24) / 49) 66 | exe 'vert 4resize ' . ((&columns * 70 + 106) / 212) 67 | argglobal 68 | if bufexists("term://.//3069:/bin/bash") | buffer term://.//3069:/bin/bash | else | edit term://.//3069:/bin/bash | endif 69 | setlocal fdm=manual 70 | setlocal fde=0 71 | setlocal fmr={{{,}}} 72 | setlocal fdi=# 73 | setlocal fdl=0 74 | setlocal fml=1 75 | setlocal fdn=20 76 | setlocal fen 77 | let s:l = 3086 - ((6 * winheight(0) + 3) / 7) 78 | if s:l < 1 | let s:l = 1 | endif 79 | exe s:l 80 | normal! zt 81 | 3086 82 | normal! 043| 83 | lcd ~/Projects/ftdt 84 | wincmd w 85 | argglobal 86 | setlocal fdm=manual 87 | setlocal fde=0 88 | setlocal fmr={{{,}}} 89 | setlocal fdi= 90 | setlocal fdl=2 91 | setlocal fml=1 92 | setlocal fdn=20 93 | setlocal fen 94 | silent! normal! zE 95 | 28,38fold 96 | 7,38fold 97 | 7 98 | normal! zo 99 | let s:l = 32 - ((26 * winheight(0) + 19) / 38) 100 | if s:l < 1 | let s:l = 1 | endif 101 | exe s:l 102 | normal! zt 103 | 32 104 | normal! 09| 105 | lcd ~/Projects/ftdt 106 | wincmd w 107 | argglobal 108 | if bufexists("~/Projects/ftdt/src/cuda_fdtd.h") | buffer ~/Projects/ftdt/src/cuda_fdtd.h | else | edit ~/Projects/ftdt/src/cuda_fdtd.h | endif 109 | setlocal fdm=indent 110 | setlocal fde=0 111 | setlocal fmr={{{,}}} 112 | setlocal fdi=# 113 | setlocal fdl=5 114 | setlocal fml=1 115 | setlocal fdn=20 116 | setlocal nofen 117 | let s:l = 146 - ((21 * winheight(0) + 19) / 38) 118 | if s:l < 1 | let s:l = 1 | endif 119 | exe s:l 120 | normal! zt 121 | 146 122 | normal! 09| 123 | lcd ~/Projects/ftdt 124 | wincmd w 125 | argglobal 126 | if bufexists("~/Projects/ftdt/src/cuda_fdtd.h") | buffer ~/Projects/ftdt/src/cuda_fdtd.h | else | edit ~/Projects/ftdt/src/cuda_fdtd.h | endif 127 | setlocal fdm=indent 128 | setlocal fde=0 129 | setlocal fmr={{{,}}} 130 | setlocal fdi=# 131 | setlocal fdl=5 132 | setlocal fml=1 133 | setlocal fdn=20 134 | setlocal nofen 135 | let s:l = 188 - ((11 * winheight(0) + 19) / 38) 136 | if s:l < 1 | let s:l = 1 | endif 137 | exe s:l 138 | normal! zt 139 | 188 140 | normal! 058| 141 | lcd ~/Projects/ftdt 142 | wincmd w 143 | 2wincmd w 144 | exe '1resize ' . ((&lines * 7 + 24) / 49) 145 | exe '2resize ' . ((&lines * 38 + 24) / 49) 146 | exe 'vert 2resize ' . ((&columns * 70 + 106) / 212) 147 | exe '3resize ' . ((&lines * 38 + 24) / 49) 148 | exe 'vert 3resize ' . ((&columns * 70 + 106) / 212) 149 | exe '4resize ' . ((&lines * 38 + 24) / 49) 150 | exe 'vert 4resize ' . ((&columns * 70 + 106) / 212) 151 | tabnew 152 | set splitbelow splitright 153 | set nosplitbelow 154 | set nosplitright 155 | wincmd t 156 | set winminheight=0 157 | set winheight=1 158 | set winminwidth=0 159 | set winwidth=1 160 | argglobal 161 | if bufexists("term://.//3136:/bin/bash") | buffer term://.//3136:/bin/bash | else | edit term://.//3136:/bin/bash | endif 162 | setlocal fdm=manual 163 | setlocal fde=0 164 | setlocal fmr={{{,}}} 165 | setlocal fdi=# 166 | setlocal fdl=0 167 | setlocal fml=1 168 | setlocal fdn=20 169 | setlocal fen 170 | let s:l = 46 - ((45 * winheight(0) + 23) / 46) 171 | if s:l < 1 | let s:l = 1 | endif 172 | exe s:l 173 | normal! zt 174 | 46 175 | normal! 0 176 | lcd ~/Projects/ftdt 177 | tabnew 178 | set splitbelow splitright 179 | set nosplitbelow 180 | set nosplitright 181 | wincmd t 182 | set winminheight=0 183 | set winheight=1 184 | set winminwidth=0 185 | set winwidth=1 186 | argglobal 187 | if bufexists("term://.//3144:/bin/bash") | buffer term://.//3144:/bin/bash | else | edit term://.//3144:/bin/bash | endif 188 | setlocal fdm=manual 189 | setlocal fde=0 190 | setlocal fmr={{{,}}} 191 | setlocal fdi=# 192 | setlocal fdl=0 193 | setlocal fml=1 194 | setlocal fdn=20 195 | setlocal fen 196 | let s:l = 46 - ((45 * winheight(0) + 23) / 46) 197 | if s:l < 1 | let s:l = 1 | endif 198 | exe s:l 199 | normal! zt 200 | 46 201 | normal! 0 202 | lcd ~/Projects/ftdt 203 | tabedit ~/Projects/ftdt/src/cuda_fdtd.h 204 | set splitbelow splitright 205 | wincmd _ | wincmd | 206 | vsplit 207 | 1wincmd h 208 | wincmd w 209 | set nosplitbelow 210 | set nosplitright 211 | wincmd t 212 | set winminheight=0 213 | set winheight=1 214 | set winminwidth=0 215 | set winwidth=1 216 | exe 'vert 1resize ' . ((&columns * 106 + 106) / 212) 217 | exe 'vert 2resize ' . ((&columns * 105 + 106) / 212) 218 | argglobal 219 | setlocal fdm=indent 220 | setlocal fde=0 221 | setlocal fmr={{{,}}} 222 | setlocal fdi=# 223 | setlocal fdl=5 224 | setlocal fml=1 225 | setlocal fdn=20 226 | setlocal fen 227 | let s:l = 190 - ((8 * winheight(0) + 23) / 46) 228 | if s:l < 1 | let s:l = 1 | endif 229 | exe s:l 230 | normal! zt 231 | 190 232 | normal! 0 233 | lcd ~/Projects/ftdt 234 | wincmd w 235 | argglobal 236 | if bufexists("~/Projects/ftdt/src/cfdtd_wrapper.cu") | buffer ~/Projects/ftdt/src/cfdtd_wrapper.cu | else | edit ~/Projects/ftdt/src/cfdtd_wrapper.cu | endif 237 | setlocal fdm=indent 238 | setlocal fde=0 239 | setlocal fmr={{{,}}} 240 | setlocal fdi=# 241 | setlocal fdl=4 242 | setlocal fml=1 243 | setlocal fdn=20 244 | setlocal fen 245 | 8 246 | normal! zo 247 | 16 248 | normal! zo 249 | 18 250 | normal! zo 251 | let s:l = 18 - ((17 * winheight(0) + 23) / 46) 252 | if s:l < 1 | let s:l = 1 | endif 253 | exe s:l 254 | normal! zt 255 | 18 256 | normal! 011| 257 | lcd ~/Projects/ftdt 258 | wincmd w 259 | exe 'vert 1resize ' . ((&columns * 106 + 106) / 212) 260 | exe 'vert 2resize ' . ((&columns * 105 + 106) / 212) 261 | tabedit ~/Projects/ftdt/build/test.py 262 | set splitbelow splitright 263 | wincmd _ | wincmd | 264 | vsplit 265 | 1wincmd h 266 | wincmd w 267 | set nosplitbelow 268 | set nosplitright 269 | wincmd t 270 | set winminheight=0 271 | set winheight=1 272 | set winminwidth=0 273 | set winwidth=1 274 | exe 'vert 1resize ' . ((&columns * 106 + 106) / 212) 275 | exe 'vert 2resize ' . ((&columns * 105 + 106) / 212) 276 | argglobal 277 | setlocal fdm=indent 278 | setlocal fde=0 279 | setlocal fmr={{{,}}} 280 | setlocal fdi= 281 | setlocal fdl=2 282 | setlocal fml=1 283 | setlocal fdn=20 284 | setlocal fen 285 | 7 286 | normal! zo 287 | let s:l = 28 - ((27 * winheight(0) + 23) / 46) 288 | if s:l < 1 | let s:l = 1 | endif 289 | exe s:l 290 | normal! zt 291 | 28 292 | normal! 09| 293 | lcd ~/Projects/ftdt 294 | wincmd w 295 | argglobal 296 | if bufexists("~/Projects/ftdt/build/Cfdtd.py") | buffer ~/Projects/ftdt/build/Cfdtd.py | else | edit ~/Projects/ftdt/build/Cfdtd.py | endif 297 | setlocal fdm=manual 298 | setlocal fde=0 299 | setlocal fmr={{{,}}} 300 | setlocal fdi=# 301 | setlocal fdl=0 302 | setlocal fml=1 303 | setlocal fdn=20 304 | setlocal fen 305 | silent! normal! zE 306 | let s:l = 22 - ((21 * winheight(0) + 23) / 46) 307 | if s:l < 1 | let s:l = 1 | endif 308 | exe s:l 309 | normal! zt 310 | 22 311 | normal! 017| 312 | lcd ~/Projects/ftdt 313 | wincmd w 314 | exe 'vert 1resize ' . ((&columns * 106 + 106) / 212) 315 | exe 'vert 2resize ' . ((&columns * 105 + 106) / 212) 316 | tabedit ~/Projects/ftdt/src/cuda_fdtd.h 317 | set splitbelow splitright 318 | wincmd _ | wincmd | 319 | vsplit 320 | wincmd _ | wincmd | 321 | vsplit 322 | 2wincmd h 323 | wincmd w 324 | wincmd w 325 | set nosplitbelow 326 | set nosplitright 327 | wincmd t 328 | set winminheight=0 329 | set winheight=1 330 | set winminwidth=0 331 | set winwidth=1 332 | exe 'vert 1resize ' . ((&columns * 70 + 106) / 212) 333 | exe 'vert 2resize ' . ((&columns * 70 + 106) / 212) 334 | exe 'vert 3resize ' . ((&columns * 70 + 106) / 212) 335 | argglobal 336 | setlocal fdm=indent 337 | setlocal fde=0 338 | setlocal fmr={{{,}}} 339 | setlocal fdi=# 340 | setlocal fdl=5 341 | setlocal fml=1 342 | setlocal fdn=20 343 | setlocal fen 344 | let s:l = 190 - ((5 * winheight(0) + 23) / 46) 345 | if s:l < 1 | let s:l = 1 | endif 346 | exe s:l 347 | normal! zt 348 | 190 349 | normal! 0 350 | lcd ~/Projects/ftdt 351 | wincmd w 352 | argglobal 353 | if bufexists("~/Projects/ftdt/src/cuda_fdtd.h") | buffer ~/Projects/ftdt/src/cuda_fdtd.h | else | edit ~/Projects/ftdt/src/cuda_fdtd.h | endif 354 | setlocal fdm=indent 355 | setlocal fde=0 356 | setlocal fmr={{{,}}} 357 | setlocal fdi=# 358 | setlocal fdl=5 359 | setlocal fml=1 360 | setlocal fdn=20 361 | setlocal fen 362 | let s:l = 118 - ((25 * winheight(0) + 23) / 46) 363 | if s:l < 1 | let s:l = 1 | endif 364 | exe s:l 365 | normal! zt 366 | 118 367 | normal! 05| 368 | lcd ~/Projects/ftdt 369 | wincmd w 370 | argglobal 371 | if bufexists("~/Projects/ftdt/src/cuda_fdtd.h") | buffer ~/Projects/ftdt/src/cuda_fdtd.h | else | edit ~/Projects/ftdt/src/cuda_fdtd.h | endif 372 | setlocal fdm=indent 373 | setlocal fde=0 374 | setlocal fmr={{{,}}} 375 | setlocal fdi=# 376 | setlocal fdl=5 377 | setlocal fml=1 378 | setlocal fdn=20 379 | setlocal fen 380 | 15 381 | normal! zo 382 | 28 383 | normal! zo 384 | 29 385 | normal! zo 386 | 40 387 | normal! zo 388 | 57 389 | normal! zo 390 | 109 391 | normal! zo 392 | 113 393 | normal! zo 394 | 128 395 | normal! zo 396 | 132 397 | normal! zo 398 | 137 399 | normal! zo 400 | 179 401 | normal! zo 402 | 183 403 | normal! zo 404 | 188 405 | normal! zo 406 | let s:l = 36 - ((22 * winheight(0) + 23) / 46) 407 | if s:l < 1 | let s:l = 1 | endif 408 | exe s:l 409 | normal! zt 410 | 36 411 | normal! 0 412 | lcd ~/Projects/ftdt 413 | wincmd w 414 | exe 'vert 1resize ' . ((&columns * 70 + 106) / 212) 415 | exe 'vert 2resize ' . ((&columns * 70 + 106) / 212) 416 | exe 'vert 3resize ' . ((&columns * 70 + 106) / 212) 417 | tabnext 1 418 | set stal=1 419 | if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' 420 | silent exe 'bwipe ' . s:wipebuf 421 | endif 422 | unlet! s:wipebuf 423 | set winheight=1 winwidth=20 winminheight=1 winminwidth=1 shortmess=filnxtToOFc 424 | let s:sx = expand(":p:r")."x.vim" 425 | if file_readable(s:sx) 426 | exe "source " . fnameescape(s:sx) 427 | endif 428 | let &so = s:so_save | let &siso = s:siso_save 429 | doautoall SessionLoadPost 430 | unlet SessionLoad 431 | " vim: set ft=vim : 432 | --------------------------------------------------------------------------------