Changes to package structure and config module. Added ability to choose E or H fields in snapshots.

这个提交包含在:
Craig Warren
2019-07-05 10:57:22 +01:00
父节点 4d061c4b1b
当前提交 abffb2e433
共有 33 个文件被更改,包括 2369 次插入2035 次删除

查看文件

@@ -1,4 +1,4 @@
# This is where the version number is set and read by setup.py and conf.py (for the docs)
__version__ = '3.1.5'
__version__ = '3.1.6b0'
codename = 'Big Smoke'

查看文件

@@ -20,10 +20,16 @@ import numpy as np
cimport numpy as np
ctypedef fused floattype_t:
np.float32_t
np.float64_t
ctypedef fused float_or_double:
float
double
ctypedef fused complextype_t:
np.complex64_t
np.complex128_t
ctypedef fused float_or_double_complex:
float complex
double complex
ctypedef fused real_or_complex:
float
double
float complex
double complex

查看文件

@@ -16,63 +16,64 @@
# You should have received a copy of the GNU General Public License
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
import os
import cython
import numpy as np
from scipy.constants import c
from scipy.constants import mu_0 as m0
from scipy.constants import epsilon_0 as e0
from gprMax.utilities import get_host_info
from .utilities import get_host_info
# Impedance of free space (Ohms)
z0 = np.sqrt(m0 / e0)
# Setting whether messages and progress bars are printed
messages = True
progressbars = messages
# General setting for the simulation
# inputfilepath: path to inputfile location
# outputfilepath: path to outputfile location
# messages: whether to print all messages as output to stdout or not
# progressbars: whether to show progress bars on stdoout or not
# mode: 2D TMx, 2D TMy, 2D TMz, or 3D
# cpu, cuda, opencl: solver type
general = {'inputfilepath': '', 'outputfilepath': '', 'messages': True,
'progressbars': True, 'mode': None, 'cpu': True, 'cuda': False, 'opencl': False}
# Store information about host machine
hostinfo = get_host_info()
# Store information about any GPUs as a list of GPU objects
gpus = None
# Copy snapshot data from GPU to CPU during simulation
# N.B. This will happen if the requested snapshots are too large to fit
# on the memory of the GPU. If True this will slow performance significantly
snapsgpu2cpu = False
# Store information for CUDA solver type
# gpus: information about any GPUs as a list of GPU objects
# snapsgpu2cpu: copy snapshot data from GPU to CPU during simulation
# N.B. This will happen if the requested snapshots are too large to fit
# on the memory of the GPU. If True this will slow performance significantly
cuda = {'gpus': None, 'snapsgpu2cpu': False}
# Numerical dispersion analysis parameters
# Threshold (dB) down from maximum power (0dB) of main frequency used
# to calculate highest frequency for numerical dispersion analysis
# Maximum allowable percentage physical phase-velocity phase error
# Minimum grid sampling of smallest wavelength for physical wave propagation
# highestfreqthres: threshold (dB) down from maximum power (0dB) of main frequency used
# to calculate highest frequency for numerical dispersion analysis
# maxnumericaldisp: maximum allowable percentage physical phase-velocity phase error
# mingridsampling: minimum grid sampling of smallest wavelength for physical wave propagation
numdispersion = {'highestfreqthres': 40, 'maxnumericaldisp': 2, 'mingridsampling': 3}
# Simulation mode - 2D TMx, 2D TMy, 2D TMz, or 3D
mode = None
# Materials
# maxpoles: Maximum number of dispersive material poles in a model
materials = {'maxpoles': 0, 'dispersivedtype': None, 'dispersiveCdtype': None}
# Data types
# Solid and ID arrays use 32-bit integers (0 to 4294967295)
# Rigid arrays use 8-bit integers (the smallest available type to store true/false)
# Fractal and dispersive coefficient arrays use complex numbers (complextype)
# Fractal and dispersive coefficient arrays use complex numbers (complex)
# which are represented as two floats
# Main field arrays use floats (floattype) and complex numbers (complextype)
# Precision of floattype and complextype: single or double
# Main field arrays use floats (float_or_double) and complex numbers (complex)
# Precision of float_or_double and complex: single or double for numpy and C (CUDA) arrays
precision = 'single'
if precision == 'single':
# For numpy arrays
floattype = np.float32
complextype = np.complex64
# For C (CUDA) arrays
cudafloattype = 'float'
cudacomplextype = 'pycuda::complex<float>'
dtypes = {'float_or_double': np.float32, 'complex': np.complex64,
'cython_float_or_double': cython.float, 'cython_complex': cython.floatcomplex,
'C_float_or_double': 'float', 'C_complex': 'pycuda::complex<float>'}
elif precision == 'double':
# For numpy arrays
floattype = np.float64
complextype = np.complex128
# For C (CUDA) arrays
cudafloattype = 'double'
cudacomplextype = 'pycuda::complex<double>'
dtypes = {'float_or_double': np.float64, 'complex': np.complex128,
'cython_float_or_double': cython.double, 'cython_complex': cython.doublecomplex,
'C_float_or_double': 'double', 'C_complex': 'pycuda::complex<double>'}

查看文件

@@ -18,7 +18,7 @@
from string import Template
kernels_template_fields = Template("""
kernel_template_fields = Template("""
#include <pycuda-complex.hpp>
@@ -33,11 +33,12 @@ kernels_template_fields = Template("""
__device__ __constant__ $REAL updatecoeffsE[$N_updatecoeffsE];
__device__ __constant__ $REAL updatecoeffsH[$N_updatecoeffsH];
/////////////////////////////////////////////////
// Electric field updates - standard materials //
/////////////////////////////////////////////////
__global__ void update_e(int NX, int NY, int NZ, const unsigned int* __restrict__ ID, $REAL *Ex, $REAL *Ey, $REAL *Ez, const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz) {
///////////////////////////////////////////////
// Electric field updates - normal materials //
///////////////////////////////////////////////
__global__ void update_electric(int NX, int NY, int NZ, const unsigned int* __restrict__ ID, $REAL *Ex, $REAL *Ey, $REAL *Ez, const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz) {
// This function updates electric field values.
//
@@ -77,11 +78,57 @@ __global__ void update_e(int NX, int NY, int NZ, const unsigned int* __restrict_
}
}
////////////////////////////
// Magnetic field updates //
////////////////////////////
__global__ void update_magnetic(int NX, int NY, int NZ, const unsigned int* __restrict__ ID, $REAL *Hx, $REAL *Hy, $REAL *Hz, const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez) {
// This function updates magnetic field values.
//
// Args:
// NX, NY, NZ: Number of cells of the model domain
// ID, E, H: Access to ID and field component arrays
// Obtain the linear index corresponding to the current thread
int idx = blockIdx.x * blockDim.x + threadIdx.x;
// Convert the linear index to subscripts for 3D field arrays
int i = idx / ($NY_FIELDS * $NZ_FIELDS);
int j = (idx % ($NY_FIELDS * $NZ_FIELDS)) / $NZ_FIELDS;
int k = (idx % ($NY_FIELDS * $NZ_FIELDS)) % $NZ_FIELDS;
// Convert the linear index to subscripts for 4D material ID array
int i_ID = (idx % ($NX_ID * $NY_ID * $NZ_ID)) / ($NY_ID * $NZ_ID);
int j_ID = ((idx % ($NX_ID * $NY_ID * $NZ_ID)) % ($NY_ID * $NZ_ID)) / $NZ_ID;
int k_ID = ((idx % ($NX_ID * $NY_ID * $NZ_ID)) % ($NY_ID * $NZ_ID)) % $NZ_ID;
// Hx component
if (NX != 1 && i > 0 && i < NX && j >= 0 && j < NY && k >= 0 && k < NZ) {
int materialHx = ID[INDEX4D_ID(3,i_ID,j_ID,k_ID)];
Hx[INDEX3D_FIELDS(i,j,k)] = updatecoeffsH[INDEX2D_MAT(materialHx,0)] * Hx[INDEX3D_FIELDS(i,j,k)] - updatecoeffsH[INDEX2D_MAT(materialHx,2)] * (Ez[INDEX3D_FIELDS(i,j+1,k)] - Ez[INDEX3D_FIELDS(i,j,k)]) + updatecoeffsH[INDEX2D_MAT(materialHx,3)] * (Ey[INDEX3D_FIELDS(i,j,k+1)] - Ey[INDEX3D_FIELDS(i,j,k)]);
}
// Hy component
if (NY != 1 && i >= 0 && i < NX && j > 0 && j < NY && k >= 0 && k < NZ) {
int materialHy = ID[INDEX4D_ID(4,i_ID,j_ID,k_ID)];
Hy[INDEX3D_FIELDS(i,j,k)] = updatecoeffsH[INDEX2D_MAT(materialHy,0)] * Hy[INDEX3D_FIELDS(i,j,k)] - updatecoeffsH[INDEX2D_MAT(materialHy,3)] * (Ex[INDEX3D_FIELDS(i,j,k+1)] - Ex[INDEX3D_FIELDS(i,j,k)]) + updatecoeffsH[INDEX2D_MAT(materialHy,1)] * (Ez[INDEX3D_FIELDS(i+1,j,k)] - Ez[INDEX3D_FIELDS(i,j,k)]);
}
// Hz component
if (NZ != 1 && i >= 0 && i < NX && j >= 0 && j < NY && k > 0 && k < NZ) {
int materialHz = ID[INDEX4D_ID(5,i_ID,j_ID,k_ID)];
Hz[INDEX3D_FIELDS(i,j,k)] = updatecoeffsH[INDEX2D_MAT(materialHz,0)] * Hz[INDEX3D_FIELDS(i,j,k)] - updatecoeffsH[INDEX2D_MAT(materialHz,1)] * (Ey[INDEX3D_FIELDS(i+1,j,k)] - Ey[INDEX3D_FIELDS(i,j,k)]) + updatecoeffsH[INDEX2D_MAT(materialHz,2)] * (Ex[INDEX3D_FIELDS(i,j+1,k)] - Ex[INDEX3D_FIELDS(i,j,k)]);
}
}
///////////////////////////////////////////////////
// Electric field updates - dispersive materials //
///////////////////////////////////////////////////
__global__ void update_e_dispersive_A(int NX, int NY, int NZ, int MAXPOLES, const $COMPLEX* __restrict__ updatecoeffsdispersive, $COMPLEX *Tx, $COMPLEX *Ty, $COMPLEX *Tz, const unsigned int* __restrict__ ID, $REAL *Ex, $REAL *Ey, $REAL *Ez, const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz) {
__global__ void update_electric_dispersive_A(int NX, int NY, int NZ, int MAXPOLES, const $REAL_OR_COMPLEX* __restrict__ updatecoeffsdispersive, $REAL_OR_COMPLEX *Tx, $REAL_OR_COMPLEX *Ty, $REAL_OR_COMPLEX *Tz, const unsigned int* __restrict__ ID, $REAL *Ex, $REAL *Ey, $REAL *Ez, const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz) {
// This function is part A of updates to electric field values when dispersive materials (with multiple poles) are present.
//
@@ -142,7 +189,7 @@ __global__ void update_e_dispersive_A(int NX, int NY, int NZ, int MAXPOLES, cons
}
}
__global__ void update_e_dispersive_B(int NX, int NY, int NZ, int MAXPOLES, const $COMPLEX* __restrict__ updatecoeffsdispersive, $COMPLEX *Tx, $COMPLEX *Ty, $COMPLEX *Tz, const unsigned int* __restrict__ ID, const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez) {
__global__ void update_electric_dispersive_B(int NX, int NY, int NZ, int MAXPOLES, const $REAL_OR_COMPLEX* __restrict__ updatecoeffsdispersive, $REAL_OR_COMPLEX *Tx, $REAL_OR_COMPLEX *Ty, $REAL_OR_COMPLEX *Tz, const unsigned int* __restrict__ ID, const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez) {
// This function is part B which updates the dispersive field arrays when dispersive materials (with multiple poles) are present.
//
@@ -194,49 +241,4 @@ __global__ void update_e_dispersive_B(int NX, int NY, int NZ, int MAXPOLES, cons
}
}
////////////////////////////
// Magnetic field updates //
////////////////////////////
__global__ void update_h(int NX, int NY, int NZ, const unsigned int* __restrict__ ID, $REAL *Hx, $REAL *Hy, $REAL *Hz, const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez) {
// This function updates magnetic field values.
//
// Args:
// NX, NY, NZ: Number of cells of the model domain
// ID, E, H: Access to ID and field component arrays
// Obtain the linear index corresponding to the current thread
int idx = blockIdx.x * blockDim.x + threadIdx.x;
// Convert the linear index to subscripts for 3D field arrays
int i = idx / ($NY_FIELDS * $NZ_FIELDS);
int j = (idx % ($NY_FIELDS * $NZ_FIELDS)) / $NZ_FIELDS;
int k = (idx % ($NY_FIELDS * $NZ_FIELDS)) % $NZ_FIELDS;
// Convert the linear index to subscripts for 4D material ID array
int i_ID = (idx % ($NX_ID * $NY_ID * $NZ_ID)) / ($NY_ID * $NZ_ID);
int j_ID = ((idx % ($NX_ID * $NY_ID * $NZ_ID)) % ($NY_ID * $NZ_ID)) / $NZ_ID;
int k_ID = ((idx % ($NX_ID * $NY_ID * $NZ_ID)) % ($NY_ID * $NZ_ID)) % $NZ_ID;
// Hx component
if (NX != 1 && i > 0 && i < NX && j >= 0 && j < NY && k >= 0 && k < NZ) {
int materialHx = ID[INDEX4D_ID(3,i_ID,j_ID,k_ID)];
Hx[INDEX3D_FIELDS(i,j,k)] = updatecoeffsH[INDEX2D_MAT(materialHx,0)] * Hx[INDEX3D_FIELDS(i,j,k)] - updatecoeffsH[INDEX2D_MAT(materialHx,2)] * (Ez[INDEX3D_FIELDS(i,j+1,k)] - Ez[INDEX3D_FIELDS(i,j,k)]) + updatecoeffsH[INDEX2D_MAT(materialHx,3)] * (Ey[INDEX3D_FIELDS(i,j,k+1)] - Ey[INDEX3D_FIELDS(i,j,k)]);
}
// Hy component
if (NY != 1 && i >= 0 && i < NX && j > 0 && j < NY && k >= 0 && k < NZ) {
int materialHy = ID[INDEX4D_ID(4,i_ID,j_ID,k_ID)];
Hy[INDEX3D_FIELDS(i,j,k)] = updatecoeffsH[INDEX2D_MAT(materialHy,0)] * Hy[INDEX3D_FIELDS(i,j,k)] - updatecoeffsH[INDEX2D_MAT(materialHy,3)] * (Ex[INDEX3D_FIELDS(i,j,k+1)] - Ex[INDEX3D_FIELDS(i,j,k)]) + updatecoeffsH[INDEX2D_MAT(materialHy,1)] * (Ez[INDEX3D_FIELDS(i+1,j,k)] - Ez[INDEX3D_FIELDS(i,j,k)]);
}
// Hz component
if (NZ != 1 && i >= 0 && i < NX && j >= 0 && j < NY && k > 0 && k < NZ) {
int materialHz = ID[INDEX4D_ID(5,i_ID,j_ID,k_ID)];
Hz[INDEX3D_FIELDS(i,j,k)] = updatecoeffsH[INDEX2D_MAT(materialHz,0)] * Hz[INDEX3D_FIELDS(i,j,k)] - updatecoeffsH[INDEX2D_MAT(materialHz,1)] * (Ey[INDEX3D_FIELDS(i+1,j,k)] - Ey[INDEX3D_FIELDS(i,j,k)]) + updatecoeffsH[INDEX2D_MAT(materialHz,2)] * (Ex[INDEX3D_FIELDS(i,j+1,k)] - Ex[INDEX3D_FIELDS(i,j,k)]);
}
}
""")

查看文件

@@ -18,7 +18,7 @@
from string import Template
kernels_template_sources = Template("""
kernel_template_sources = Template("""
// Macros for converting subscripts to linear index:
#define INDEX2D_MAT(m, n) (m)*($NY_MATCOEFFS)+(n)

查看文件

@@ -1,412 +0,0 @@
# Copyright (C) 2015-2019: The University of Edinburgh
# Authors: Craig Warren and Antonis Giannopoulos
#
# This file is part of gprMax.
#
# gprMax is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gprMax is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
import numpy as np
cimport numpy as np
from cython.parallel import prange
from gprMax.config cimport floattype_t
from gprMax.config cimport complextype_t
###############################################
# Electric field updates - standard materials #
###############################################
cpdef void update_electric(
int nx,
int ny,
int nz,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz
):
"""This function updates the electric field components.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
updatecoeffs, ID, E, H (memoryviews): Access to update coeffients, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int materialEx, materialEy, materialEz
# 2D - Ex component
if nx == 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
materialEx = ID[0, i, j, k]
Ex[i, j, k] = updatecoeffsE[materialEx, 0] * Ex[i, j, k] + updatecoeffsE[materialEx, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[materialEx, 3] * (Hy[i, j, k] - Hy[i, j, k - 1])
# 2D - Ey component
elif ny == 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
materialEy = ID[1, i, j, k]
Ey[i, j, k] = updatecoeffsE[materialEy, 0] * Ey[i, j, k] + updatecoeffsE[materialEy, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[materialEy, 1] * (Hz[i, j, k] - Hz[i - 1, j, k])
# 2D - Ez component
elif nz == 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
materialEz = ID[2, i, j, k]
Ez[i, j, k] = updatecoeffsE[materialEz, 0] * Ez[i, j, k] + updatecoeffsE[materialEz, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[materialEz, 2] * (Hx[i, j, k] - Hx[i, j - 1, k])
# 3D
else:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
materialEx = ID[0, i, j, k]
materialEy = ID[1, i, j, k]
materialEz = ID[2, i, j, k]
Ex[i, j, k] = updatecoeffsE[materialEx, 0] * Ex[i, j, k] + updatecoeffsE[materialEx, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[materialEx, 3] * (Hy[i, j, k] - Hy[i, j, k - 1])
Ey[i, j, k] = updatecoeffsE[materialEy, 0] * Ey[i, j, k] + updatecoeffsE[materialEy, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[materialEy, 1] * (Hz[i, j, k] - Hz[i - 1, j, k])
Ez[i, j, k] = updatecoeffsE[materialEz, 0] * Ez[i, j, k] + updatecoeffsE[materialEz, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[materialEz, 2] * (Hx[i, j, k] - Hx[i, j - 1, k])
# Ex components at i = 0
for j in prange(1, ny, nogil=True, schedule='static', num_threads=nthreads):
for k in range(1, nz):
materialEx = ID[0, 0, j, k]
Ex[0, j, k] = updatecoeffsE[materialEx, 0] * Ex[0, j, k] + updatecoeffsE[materialEx, 2] * (Hz[0, j, k] - Hz[0, j - 1, k]) - updatecoeffsE[materialEx, 3] * (Hy[0, j, k] - Hy[0, j, k - 1])
# Ey components at j = 0
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for k in range(1, nz):
materialEy = ID[1, i, 0, k]
Ey[i, 0, k] = updatecoeffsE[materialEy, 0] * Ey[i, 0, k] + updatecoeffsE[materialEy, 3] * (Hx[i, 0, k] - Hx[i, 0, k - 1]) - updatecoeffsE[materialEy, 1] * (Hz[i, 0, k] - Hz[i - 1, 0, k])
# Ez components at k = 0
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
materialEz = ID[2, i, j, 0]
Ez[i, j, 0] = updatecoeffsE[materialEz, 0] * Ez[i, j, 0] + updatecoeffsE[materialEz, 1] * (Hy[i, j, 0] - Hy[i - 1, j, 0]) - updatecoeffsE[materialEz, 2] * (Hx[i, j, 0] - Hx[i, j - 1, 0])
#################################################
# Electric field updates - dispersive materials #
#################################################
cpdef void update_electric_dispersive_multipole_A(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
floattype_t[:, ::1] updatecoeffsE,
complextype_t[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
complextype_t[:, :, :, ::1] Tx,
complextype_t[:, :, :, ::1] Ty,
complextype_t[:, :, :, ::1] Tz,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz
):
"""This function updates the electric field components when dispersive materials (with multiple poles) are present.
Args:
nx, ny, nz (int): Grid size in cells
maxpoles (int): Maximum number of poles
nthreads (int): Number of threads to use
updatecoeffs, T, ID, E, H (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k, pole
cdef int material
cdef float phi = 0
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
phi = 0
for pole in range(maxpoles):
phi = phi + updatecoeffsdispersive[material, pole * 3].real * Tx[pole, i, j, k].real
Tx[pole, i, j, k] = updatecoeffsdispersive[material, 1 + (pole * 3)] * Tx[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)] * Ex[i, j, k]
Ex[i, j, k] = updatecoeffsE[material, 0] * Ex[i, j, k] + updatecoeffsE[material, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[material, 3] * (Hy[i, j, k] - Hy[i, j, k - 1]) - updatecoeffsE[material, 4] * phi
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
phi = 0
for pole in range(maxpoles):
phi = phi + updatecoeffsdispersive[material, pole * 3].real * Ty[pole, i, j, k].real
Ty[pole, i, j, k] = updatecoeffsdispersive[material, 1 + (pole * 3)] * Ty[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)] * Ey[i, j, k]
Ey[i, j, k] = updatecoeffsE[material, 0] * Ey[i, j, k] + updatecoeffsE[material, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[material, 1] * (Hz[i, j, k] - Hz[i - 1, j, k]) - updatecoeffsE[material, 4] * phi
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
phi = 0
for pole in range(maxpoles):
phi = phi + updatecoeffsdispersive[material, pole * 3].real * Tz[pole, i, j, k].real
Tz[pole, i, j, k] = updatecoeffsdispersive[material, 1 + (pole * 3)] * Tz[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)] * Ez[i, j, k]
Ez[i, j, k] = updatecoeffsE[material, 0] * Ez[i, j, k] + updatecoeffsE[material, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[material, 2] * (Hx[i, j, k] - Hx[i, j - 1, k]) - updatecoeffsE[material, 4] * phi
cpdef void update_electric_dispersive_multipole_B(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
complextype_t[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
complextype_t[:, :, :, ::1] Tx,
complextype_t[:, :, :, ::1] Ty,
complextype_t[:, :, :, ::1] Tz,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez
):
"""This function updates a temporary dispersive material array when disperisive materials (with multiple poles) are present.
Args:
nx, ny, nz (int): Grid size in cells
maxpoles (int): Maximum number of poles
nthreads (int): Number of threads to use
updatecoeffs, T, ID, E (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k, pole
cdef int material
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
for pole in range(maxpoles):
Tx[pole, i, j, k] = Tx[pole, i, j, k] - updatecoeffsdispersive[material, 2 + (pole * 3)] * Ex[i, j, k]
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
for pole in range(maxpoles):
Ty[pole, i, j, k] = Ty[pole, i, j, k] - updatecoeffsdispersive[material, 2 + (pole * 3)] * Ey[i, j, k]
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
for pole in range(maxpoles):
Tz[pole, i, j, k] = Tz[pole, i, j, k] - updatecoeffsdispersive[material, 2 + (pole * 3)] * Ez[i, j, k]
cpdef void update_electric_dispersive_1pole_A(
int nx,
int ny,
int nz,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
complextype_t[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
complextype_t[:, :, :, ::1] Tx,
complextype_t[:, :, :, ::1] Ty,
complextype_t[:, :, :, ::1] Tz,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz
):
"""This function updates the electric field components when dispersive materials (with 1 pole) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
updatecoeffs, T, ID, E, H (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int material
cdef float phi = 0
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
phi = updatecoeffsdispersive[material, 0].real * Tx[0, i, j, k].real
Tx[0, i, j, k] = updatecoeffsdispersive[material, 1] * Tx[0, i, j, k] + updatecoeffsdispersive[material, 2] * Ex[i, j, k]
Ex[i, j, k] = updatecoeffsE[material, 0] * Ex[i, j, k] + updatecoeffsE[material, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[material, 3] * (Hy[i, j, k] - Hy[i, j, k - 1]) - updatecoeffsE[material, 4] * phi
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
phi = updatecoeffsdispersive[material, 0].real * Ty[0, i, j, k].real
Ty[0, i, j, k] = updatecoeffsdispersive[material, 1] * Ty[0, i, j, k] + updatecoeffsdispersive[material, 2] * Ey[i, j, k]
Ey[i, j, k] = updatecoeffsE[material, 0] * Ey[i, j, k] + updatecoeffsE[material, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[material, 1] * (Hz[i, j, k] - Hz[i - 1, j, k]) - updatecoeffsE[material, 4] * phi
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
phi = updatecoeffsdispersive[material, 0].real * Tz[0, i, j, k].real
Tz[0, i, j, k] = updatecoeffsdispersive[material, 1] * Tz[0, i, j, k] + updatecoeffsdispersive[material, 2] * Ez[i, j, k]
Ez[i, j, k] = updatecoeffsE[material, 0] * Ez[i, j, k] + updatecoeffsE[material, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[material, 2] * (Hx[i, j, k] - Hx[i, j - 1, k]) - updatecoeffsE[material, 4] * phi
cpdef void update_electric_dispersive_1pole_B(
int nx,
int ny,
int nz,
int nthreads,
complextype_t[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
complextype_t[:, :, :, ::1] Tx,
complextype_t[:, :, :, ::1] Ty,
complextype_t[:, :, :, ::1] Tz,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez
):
"""This function updates a temporary dispersive material array when disperisive materials (with 1 pole) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
updatecoeffs, T, ID, E (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int material
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
Tx[0, i, j, k] = Tx[0, i, j, k] - updatecoeffsdispersive[material, 2] * Ex[i, j, k]
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
Ty[0, i, j, k] = Ty[0, i, j, k] - updatecoeffsdispersive[material, 2] * Ey[i, j, k]
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
Tz[0, i, j, k] = Tz[0, i, j, k] - updatecoeffsdispersive[material, 2] * Ez[i, j, k]
##########################
# Magnetic field updates #
##########################
cpdef void update_magnetic(
int nx,
int ny,
int nz,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz
):
"""This function updates the magnetic field components.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
updatecoeffs, ID, E, H (memoryviews): Access to update coeffients, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int materialHx, materialHy, materialHz
# 2D
if nx == 1 or ny == 1 or nz == 1:
# Hx component
if ny == 1 or nz == 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(0, nz):
materialHx = ID[3, i, j, k]
Hx[i, j, k] = updatecoeffsH[materialHx, 0] * Hx[i, j, k] - updatecoeffsH[materialHx, 2] * (Ez[i, j + 1, k] - Ez[i, j, k]) + updatecoeffsH[materialHx, 3] * (Ey[i, j, k + 1] - Ey[i, j, k])
# Hy component
if nx == 1 or nz == 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
materialHy = ID[4, i, j, k]
Hy[i, j, k] = updatecoeffsH[materialHy, 0] * Hy[i, j, k] - updatecoeffsH[materialHy, 3] * (Ex[i, j, k + 1] - Ex[i, j, k]) + updatecoeffsH[materialHy, 1] * (Ez[i + 1, j, k] - Ez[i, j, k])
# Hz component
if nx == 1 or ny == 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
materialHz = ID[5, i, j, k]
Hz[i, j, k] = updatecoeffsH[materialHz, 0] * Hz[i, j, k] - updatecoeffsH[materialHz, 1] * (Ey[i + 1, j, k] - Ey[i, j, k]) + updatecoeffsH[materialHz, 2] * (Ex[i, j + 1, k] - Ex[i, j, k])
# 3D
else:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(0, nz):
materialHx = ID[3, i + 1, j, k]
materialHy = ID[4, i, j + 1, k]
materialHz = ID[5, i, j, k + 1]
Hx[i + 1, j, k] = updatecoeffsH[materialHx, 0] * Hx[i + 1, j, k] - updatecoeffsH[materialHx, 2] * (Ez[i + 1, j + 1, k] - Ez[i + 1, j, k]) + updatecoeffsH[materialHx, 3] * (Ey[i + 1, j, k + 1] - Ey[i + 1, j, k])
Hy[i, j + 1, k] = updatecoeffsH[materialHy, 0] * Hy[i, j + 1, k] - updatecoeffsH[materialHy, 3] * (Ex[i, j + 1, k + 1] - Ex[i, j + 1, k]) + updatecoeffsH[materialHy, 1] * (Ez[i + 1, j + 1, k] - Ez[i, j + 1, k])
Hz[i, j, k + 1] = updatecoeffsH[materialHz, 0] * Hz[i, j, k + 1] - updatecoeffsH[materialHz, 1] * (Ey[i + 1, j, k + 1] - Ey[i, j, k + 1]) + updatecoeffsH[materialHz, 2] * (Ex[i, j + 1, k + 1] - Ex[i, j, k + 1])

查看文件

@@ -0,0 +1,514 @@
# Copyright (C) 2015-2019: The University of Edinburgh
# Authors: Craig Warren and Antonis Giannopoulos
#
# This file is part of gprMax.
#
# gprMax is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gprMax is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
import numpy as np
cimport numpy as np
from cython.parallel import prange
from gprMax.config cimport float_or_double
from gprMax.config cimport real_or_complex
cdef double mycreal(double complex dc) nogil:
cdef double complex* dcptr = &dc
return (<double *>dcptr)[0]
#########################################################
# Electric field updates - dispersive materials - Debye #
#########################################################
cpdef void update_electric_dispersive_debye_multipole_A(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
float_or_double[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
float_or_double[:, :, :, ::1] Tx,
float_or_double[:, :, :, ::1] Ty,
float_or_double[:, :, :, ::1] Tz,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz
):
"""This function updates the electric field components when dispersive materials (with multiple poles) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
maxpoles (int): Maximum number of poles
updatecoeffs, T, ID, E, H (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k, pole
cdef int material
cdef float phi = 0
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
phi = 0
for pole in range(maxpoles):
phi = phi + updatecoeffsdispersive[material, pole * 3] * Tx[pole, i, j, k]
Tx[pole, i, j, k] = updatecoeffsdispersive[material, 1 + (pole * 3)] * Tx[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)] * Ex[i, j, k]
Ex[i, j, k] = updatecoeffsE[material, 0] * Ex[i, j, k] + updatecoeffsE[material, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[material, 3] * (Hy[i, j, k] - Hy[i, j, k - 1]) - updatecoeffsE[material, 4] * phi
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
phi = 0
for pole in range(maxpoles):
phi = phi + updatecoeffsdispersive[material, pole * 3] * Ty[pole, i, j, k]
Ty[pole, i, j, k] = updatecoeffsdispersive[material, 1 + (pole * 3)] * Ty[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)] * Ey[i, j, k]
Ey[i, j, k] = updatecoeffsE[material, 0] * Ey[i, j, k] + updatecoeffsE[material, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[material, 1] * (Hz[i, j, k] - Hz[i - 1, j, k]) - updatecoeffsE[material, 4] * phi
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
phi = 0
for pole in range(maxpoles):
phi = phi + updatecoeffsdispersive[material, pole * 3] * Tz[pole, i, j, k]
Tz[pole, i, j, k] = updatecoeffsdispersive[material, 1 + (pole * 3)] * Tz[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)] * Ez[i, j, k]
Ez[i, j, k] = updatecoeffsE[material, 0] * Ez[i, j, k] + updatecoeffsE[material, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[material, 2] * (Hx[i, j, k] - Hx[i, j - 1, k]) - updatecoeffsE[material, 4] * phi
cpdef void update_electric_dispersive_debye_multipole_B(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
float_or_double[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
float_or_double[:, :, :, ::1] Tx,
float_or_double[:, :, :, ::1] Ty,
float_or_double[:, :, :, ::1] Tz,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez
):
"""This function updates a temporary dispersive material array when disperisive materials (with multiple poles) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
maxpoles (int): Maximum number of poles
updatecoeffs, T, ID, E (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k, pole
cdef int material
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
for pole in range(maxpoles):
Tx[pole, i, j, k] = Tx[pole, i, j, k] - updatecoeffsdispersive[material, 2 + (pole * 3)] * Ex[i, j, k]
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
for pole in range(maxpoles):
Ty[pole, i, j, k] = Ty[pole, i, j, k] - updatecoeffsdispersive[material, 2 + (pole * 3)] * Ey[i, j, k]
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
for pole in range(maxpoles):
Tz[pole, i, j, k] = Tz[pole, i, j, k] - updatecoeffsdispersive[material, 2 + (pole * 3)] * Ez[i, j, k]
cpdef void update_electric_dispersive_debye_1pole_A(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
float_or_double[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
float_or_double[:, :, :, ::1] Tx,
float_or_double[:, :, :, ::1] Ty,
float_or_double[:, :, :, ::1] Tz,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz
):
"""This function updates the electric field components when dispersive materials (with 1 pole) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
maxpoles (int): Maximum number of poles
updatecoeffs, T, ID, E, H (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int material
cdef float phi = 0
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
phi = updatecoeffsdispersive[material, 0] * Tx[0, i, j, k]
Tx[0, i, j, k] = updatecoeffsdispersive[material, 1] * Tx[0, i, j, k] + updatecoeffsdispersive[material, 2] * Ex[i, j, k]
Ex[i, j, k] = updatecoeffsE[material, 0] * Ex[i, j, k] + updatecoeffsE[material, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[material, 3] * (Hy[i, j, k] - Hy[i, j, k - 1]) - updatecoeffsE[material, 4] * phi
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
phi = updatecoeffsdispersive[material, 0] * Ty[0, i, j, k]
Ty[0, i, j, k] = updatecoeffsdispersive[material, 1] * Ty[0, i, j, k] + updatecoeffsdispersive[material, 2] * Ey[i, j, k]
Ey[i, j, k] = updatecoeffsE[material, 0] * Ey[i, j, k] + updatecoeffsE[material, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[material, 1] * (Hz[i, j, k] - Hz[i - 1, j, k]) - updatecoeffsE[material, 4] * phi
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
phi = updatecoeffsdispersive[material, 0] * Tz[0, i, j, k]
Tz[0, i, j, k] = updatecoeffsdispersive[material, 1] * Tz[0, i, j, k] + updatecoeffsdispersive[material, 2] * Ez[i, j, k]
Ez[i, j, k] = updatecoeffsE[material, 0] * Ez[i, j, k] + updatecoeffsE[material, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[material, 2] * (Hx[i, j, k] - Hx[i, j - 1, k]) - updatecoeffsE[material, 4] * phi
cpdef void update_electric_dispersive_debye_1pole_B(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
float_or_double[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
float_or_double[:, :, :, ::1] Tx,
float_or_double[:, :, :, ::1] Ty,
float_or_double[:, :, :, ::1] Tz,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez
):
"""This function updates a temporary dispersive material array when disperisive materials (with 1 pole) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
maxpoles (int): Maximum number of poles
updatecoeffs, T, ID, E (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int material
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
Tx[0, i, j, k] = Tx[0, i, j, k] - updatecoeffsdispersive[material, 2] * Ex[i, j, k]
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
Ty[0, i, j, k] = Ty[0, i, j, k] - updatecoeffsdispersive[material, 2] * Ey[i, j, k]
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
Tz[0, i, j, k] = Tz[0, i, j, k] - updatecoeffsdispersive[material, 2] * Ez[i, j, k]
#################################################################
# Electric field updates - dispersive materials - Drude, Lorenz #
#################################################################
cpdef void update_electric_dispersive_multipole_A(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
float_or_double[:, ::1] updatecoeffsE,
real_or_complex[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
real_or_complex[:, :, :, ::1] Tx,
real_or_complex[:, :, :, ::1] Ty,
real_or_complex[:, :, :, ::1] Tz,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz
):
"""This function updates the electric field components when dispersive materials (with multiple poles) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
maxpoles (int): Maximum number of poles
updatecoeffs, T, ID, E, H (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k, pole
cdef int material
cdef float phi
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
phi = 0
for pole in range(maxpoles):
phi = phi + mycreal(updatecoeffsdispersive[material, pole * 3]) * mycreal(Tx[pole, i, j, k])
Tx[pole, i, j, k] = updatecoeffsdispersive[material, 1 + (pole * 3)] * Tx[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)] * Ex[i, j, k]
Ex[i, j, k] = updatecoeffsE[material, 0] * Ex[i, j, k] + updatecoeffsE[material, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[material, 3] * (Hy[i, j, k] - Hy[i, j, k - 1]) - updatecoeffsE[material, 4] * phi
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
phi = 0
for pole in range(maxpoles):
phi = phi + mycreal(updatecoeffsdispersive[material, pole * 3]) * mycreal(Ty[pole, i, j, k])
Ty[pole, i, j, k] = updatecoeffsdispersive[material, 1 + (pole * 3)] * Ty[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)] * Ey[i, j, k]
Ey[i, j, k] = updatecoeffsE[material, 0] * Ey[i, j, k] + updatecoeffsE[material, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[material, 1] * (Hz[i, j, k] - Hz[i - 1, j, k]) - updatecoeffsE[material, 4] * phi
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
phi = 0
for pole in range(maxpoles):
phi = phi + mycreal(updatecoeffsdispersive[material, pole * 3]) * mycreal(Tz[pole, i, j, k])
Tz[pole, i, j, k] = updatecoeffsdispersive[material, 1 + (pole * 3)] * Tz[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)] * Ez[i, j, k]
Ez[i, j, k] = updatecoeffsE[material, 0] * Ez[i, j, k] + updatecoeffsE[material, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[material, 2] * (Hx[i, j, k] - Hx[i, j - 1, k]) - updatecoeffsE[material, 4] * phi
cpdef void update_electric_dispersive_multipole_B(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
real_or_complex[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
real_or_complex[:, :, :, ::1] Tx,
real_or_complex[:, :, :, ::1] Ty,
real_or_complex[:, :, :, ::1] Tz,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez
):
"""This function updates a temporary dispersive material array when disperisive materials (with multiple poles) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
maxpoles (int): Maximum number of poles
updatecoeffs, T, ID, E (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k, pole
cdef int material
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
for pole in range(maxpoles):
Tx[pole, i, j, k] = Tx[pole, i, j, k] - updatecoeffsdispersive[material, 2 + (pole * 3)] * Ex[i, j, k]
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
for pole in range(maxpoles):
Ty[pole, i, j, k] = Ty[pole, i, j, k] - updatecoeffsdispersive[material, 2 + (pole * 3)] * Ey[i, j, k]
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
for pole in range(maxpoles):
Tz[pole, i, j, k] = Tz[pole, i, j, k] - updatecoeffsdispersive[material, 2 + (pole * 3)] * Ez[i, j, k]
cpdef void update_electric_dispersive_1pole_A(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
float_or_double[:, ::1] updatecoeffsE,
real_or_complex[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
real_or_complex[:, :, :, ::1] Tx,
real_or_complex[:, :, :, ::1] Ty,
real_or_complex[:, :, :, ::1] Tz,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz
):
"""This function updates the electric field components when dispersive materials (with 1 pole) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
maxpoles (int): Maximum number of poles
updatecoeffs, T, ID, E, H (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int material
cdef float phi = 0
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
phi = mycreal(updatecoeffsdispersive[material, 0]) * mycreal(Tx[0, i, j, k])
Tx[0, i, j, k] = updatecoeffsdispersive[material, 1] * Tx[0, i, j, k] + updatecoeffsdispersive[material, 2] * Ex[i, j, k]
Ex[i, j, k] = updatecoeffsE[material, 0] * Ex[i, j, k] + updatecoeffsE[material, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[material, 3] * (Hy[i, j, k] - Hy[i, j, k - 1]) - updatecoeffsE[material, 4] * phi
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
phi = mycreal(updatecoeffsdispersive[material, 0]) * mycreal(Ty[0, i, j, k])
Ty[0, i, j, k] = updatecoeffsdispersive[material, 1] * Ty[0, i, j, k] + updatecoeffsdispersive[material, 2] * Ey[i, j, k]
Ey[i, j, k] = updatecoeffsE[material, 0] * Ey[i, j, k] + updatecoeffsE[material, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[material, 1] * (Hz[i, j, k] - Hz[i - 1, j, k]) - updatecoeffsE[material, 4] * phi
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
phi = mycreal(updatecoeffsdispersive[material, 0]) * mycreal(Tz[0, i, j, k])
Tz[0, i, j, k] = updatecoeffsdispersive[material, 1] * Tz[0, i, j, k] + updatecoeffsdispersive[material, 2] * Ez[i, j, k]
Ez[i, j, k] = updatecoeffsE[material, 0] * Ez[i, j, k] + updatecoeffsE[material, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[material, 2] * (Hx[i, j, k] - Hx[i, j - 1, k]) - updatecoeffsE[material, 4] * phi
cpdef void update_electric_dispersive_1pole_B(
int nx,
int ny,
int nz,
int nthreads,
int maxpoles,
real_or_complex[:, ::1] updatecoeffsdispersive,
np.uint32_t[:, :, :, ::1] ID,
real_or_complex[:, :, :, ::1] Tx,
real_or_complex[:, :, :, ::1] Ty,
real_or_complex[:, :, :, ::1] Tz,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez
):
"""This function updates a temporary dispersive material array when disperisive materials (with 1 pole) are present.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
maxpoles (int): Maximum number of poles
updatecoeffs, T, ID, E (memoryviews): Access to update coeffients, temporary, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int material
# Ex component
if ny != 1 or nz != 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
material = ID[0, i, j, k]
Tx[0, i, j, k] = Tx[0, i, j, k] - updatecoeffsdispersive[material, 2] * Ex[i, j, k]
# Ey component
if nx != 1 or nz != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
material = ID[1, i, j, k]
Ty[0, i, j, k] = Ty[0, i, j, k] - updatecoeffsdispersive[material, 2] * Ey[i, j, k]
# Ez component
if nx != 1 or ny != 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
material = ID[2, i, j, k]
Tz[0, i, j, k] = Tz[0, i, j, k] - updatecoeffsdispersive[material, 2] * Ez[i, j, k]

查看文件

@@ -0,0 +1,172 @@
cdef float phi# Copyright (C) 2015-2019: The University of Edinburgh
# Authors: Craig Warren and Antonis Giannopoulos
#
# This file is part of gprMax.
#
# gprMax is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gprMax is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
import numpy as np
cimport numpy as np
from cython.parallel import prange
from gprMax.config cimport float_or_double
###############################################
# Electric field updates - standard materials #
###############################################
cpdef void update_electric(
int nx,
int ny,
int nz,
int nthreads,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz
):
"""This function updates the electric field components.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
updatecoeffs, ID, E, H (memoryviews): Access to update coeffients, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int materialEx, materialEy, materialEz
# 2D - Ex component
if nx == 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
materialEx = ID[0, i, j, k]
Ex[i, j, k] = updatecoeffsE[materialEx, 0] * Ex[i, j, k] + updatecoeffsE[materialEx, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[materialEx, 3] * (Hy[i, j, k] - Hy[i, j, k - 1])
# 2D - Ey component
elif ny == 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
materialEy = ID[1, i, j, k]
Ey[i, j, k] = updatecoeffsE[materialEy, 0] * Ey[i, j, k] + updatecoeffsE[materialEy, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[materialEy, 1] * (Hz[i, j, k] - Hz[i - 1, j, k])
# 2D - Ez component
elif nz == 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
materialEz = ID[2, i, j, k]
Ez[i, j, k] = updatecoeffsE[materialEz, 0] * Ez[i, j, k] + updatecoeffsE[materialEz, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[materialEz, 2] * (Hx[i, j, k] - Hx[i, j - 1, k])
# 3D
else:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(1, nz):
materialEx = ID[0, i, j, k]
materialEy = ID[1, i, j, k]
materialEz = ID[2, i, j, k]
Ex[i, j, k] = updatecoeffsE[materialEx, 0] * Ex[i, j, k] + updatecoeffsE[materialEx, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[materialEx, 3] * (Hy[i, j, k] - Hy[i, j, k - 1])
Ey[i, j, k] = updatecoeffsE[materialEy, 0] * Ey[i, j, k] + updatecoeffsE[materialEy, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[materialEy, 1] * (Hz[i, j, k] - Hz[i - 1, j, k])
Ez[i, j, k] = updatecoeffsE[materialEz, 0] * Ez[i, j, k] + updatecoeffsE[materialEz, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[materialEz, 2] * (Hx[i, j, k] - Hx[i, j - 1, k])
# Ex components at i = 0
for j in prange(1, ny, nogil=True, schedule='static', num_threads=nthreads):
for k in range(1, nz):
materialEx = ID[0, 0, j, k]
Ex[0, j, k] = updatecoeffsE[materialEx, 0] * Ex[0, j, k] + updatecoeffsE[materialEx, 2] * (Hz[0, j, k] - Hz[0, j - 1, k]) - updatecoeffsE[materialEx, 3] * (Hy[0, j, k] - Hy[0, j, k - 1])
# Ey components at j = 0
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for k in range(1, nz):
materialEy = ID[1, i, 0, k]
Ey[i, 0, k] = updatecoeffsE[materialEy, 0] * Ey[i, 0, k] + updatecoeffsE[materialEy, 3] * (Hx[i, 0, k] - Hx[i, 0, k - 1]) - updatecoeffsE[materialEy, 1] * (Hz[i, 0, k] - Hz[i - 1, 0, k])
# Ez components at k = 0
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
materialEz = ID[2, i, j, 0]
Ez[i, j, 0] = updatecoeffsE[materialEz, 0] * Ez[i, j, 0] + updatecoeffsE[materialEz, 1] * (Hy[i, j, 0] - Hy[i - 1, j, 0]) - updatecoeffsE[materialEz, 2] * (Hx[i, j, 0] - Hx[i, j - 1, 0])
##########################
# Magnetic field updates #
##########################
cpdef void update_magnetic(
int nx,
int ny,
int nz,
int nthreads,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz
):
"""This function updates the magnetic field components.
Args:
nx, ny, nz (int): Grid size in cells
nthreads (int): Number of threads to use
updatecoeffs, ID, E, H (memoryviews): Access to update coeffients, ID and field component arrays
"""
cdef Py_ssize_t i, j, k
cdef int materialHx, materialHy, materialHz
# 2D
if nx == 1 or ny == 1 or nz == 1:
# Hx component
if ny == 1 or nz == 1:
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(0, nz):
materialHx = ID[3, i, j, k]
Hx[i, j, k] = updatecoeffsH[materialHx, 0] * Hx[i, j, k] - updatecoeffsH[materialHx, 2] * (Ez[i, j + 1, k] - Ez[i, j, k]) + updatecoeffsH[materialHx, 3] * (Ey[i, j, k + 1] - Ey[i, j, k])
# Hy component
if nx == 1 or nz == 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(1, ny):
for k in range(0, nz):
materialHy = ID[4, i, j, k]
Hy[i, j, k] = updatecoeffsH[materialHy, 0] * Hy[i, j, k] - updatecoeffsH[materialHy, 3] * (Ex[i, j, k + 1] - Ex[i, j, k]) + updatecoeffsH[materialHy, 1] * (Ez[i + 1, j, k] - Ez[i, j, k])
# Hz component
if nx == 1 or ny == 1:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(1, nz):
materialHz = ID[5, i, j, k]
Hz[i, j, k] = updatecoeffsH[materialHz, 0] * Hz[i, j, k] - updatecoeffsH[materialHz, 1] * (Ey[i + 1, j, k] - Ey[i, j, k]) + updatecoeffsH[materialHz, 2] * (Ex[i, j + 1, k] - Ex[i, j, k])
# 3D
else:
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
for j in range(0, ny):
for k in range(0, nz):
materialHx = ID[3, i + 1, j, k]
materialHy = ID[4, i, j + 1, k]
materialHz = ID[5, i, j, k + 1]
Hx[i + 1, j, k] = updatecoeffsH[materialHx, 0] * Hx[i + 1, j, k] - updatecoeffsH[materialHx, 2] * (Ez[i + 1, j + 1, k] - Ez[i + 1, j, k]) + updatecoeffsH[materialHx, 3] * (Ey[i + 1, j, k + 1] - Ey[i + 1, j, k])
Hy[i, j + 1, k] = updatecoeffsH[materialHy, 0] * Hy[i, j + 1, k] - updatecoeffsH[materialHy, 3] * (Ex[i, j + 1, k + 1] - Ex[i, j + 1, k]) + updatecoeffsH[materialHy, 1] * (Ez[i + 1, j + 1, k] - Ez[i, j + 1, k])
Hz[i, j, k + 1] = updatecoeffsH[materialHz, 0] * Hz[i, j, k + 1] - updatecoeffsH[materialHz, 1] * (Ey[i + 1, j, k + 1] - Ey[i, j, k + 1]) + updatecoeffsH[materialHz, 2] * (Ex[i, j + 1, k + 1] - Ex[i, j, k + 1])

查看文件

@@ -20,12 +20,12 @@ import numpy as np
cimport numpy as np
from cython.parallel import prange
from gprMax.config cimport complextype_t
from gprMax.config cimport float_or_double_complex
cpdef void generate_fractal2D(int nx, int ny, int nthreads, int b, np.float64_t[:] weighting, np.float64_t[:] v1, np.complex128_t[:, ::1] A, complextype_t[:, ::1] fractalsurface):
cpdef void generate_fractal2D(int nx, int ny, int nthreads, int b, np.float64_t[:] weighting, np.float64_t[:] v1, np.complex128_t[:, ::1] A, float_or_double_complex[:, ::1] fractalsurface):
"""This function generates a fractal surface for a 2D array.
Args:
nx, ny (int): Fractal surface size in cells
nthreads (int): Number of threads to use
@@ -55,7 +55,7 @@ cpdef void generate_fractal2D(int nx, int ny, int nthreads, int b, np.float64_t[
fractalsurface[i, j] = A[i, j] * 1 / (rr**b)
cpdef void generate_fractal3D(int nx, int ny, int nz, int nthreads, int b, np.float64_t[:] weighting, np.float64_t[:] v1, np.complex128_t[:, :, ::1] A, complextype_t[:, :, ::1] fractalvolume):
cpdef void generate_fractal3D(int nx, int ny, int nz, int nthreads, int b, np.float64_t[:] weighting, np.float64_t[:] v1, np.complex128_t[:, :, ::1] A, float_or_double_complex[:, :, ::1] fractalvolume):
"""This function generates a fractal volume for a 3D array.
Args:

查看文件

@@ -20,7 +20,7 @@ import numpy as np
cimport numpy as np
from cython.parallel import prange
from gprMax.config cimport floattype_t
from gprMax.config cimport float_or_double
cpdef void order1_xminus(
@@ -31,20 +31,20 @@ cpdef void order1_xminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ey and Ez field components for the xminus slab.
@@ -59,7 +59,7 @@ cpdef void order1_xminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEy, materialEz
cdef floattype_t dx, dHy, dHz, RA01, RB0, RE0, RF0
cdef float_or_double dx, dHy, dHz, RA01, RB0, RE0, RF0
dx = d
nx = xf - xs
ny = yf - ys
@@ -94,20 +94,20 @@ cpdef void order2_xminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ey and Ez field components for the xminus slab.
@@ -122,7 +122,7 @@ cpdef void order2_xminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEy, materialEz
cdef floattype_t dx, dHy, dHz, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
cdef float_or_double dx, dHy, dHz, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
dx = d
nx = xf - xs
ny = yf - ys
@@ -165,20 +165,20 @@ cpdef void order1_xplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ey and Ez field components for the xplus slab.
@@ -193,7 +193,7 @@ cpdef void order1_xplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEy, materialEz
cdef floattype_t dx, dHy, dHz, RA01, RB0, RE0, RF0
cdef float_or_double dx, dHy, dHz, RA01, RB0, RE0, RF0
dx = d
nx = xf - xs
ny = yf - ys
@@ -228,20 +228,20 @@ cpdef void order2_xplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ey and Ez field components for the xplus slab.
@@ -256,7 +256,7 @@ cpdef void order2_xplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEy, materialEz
cdef floattype_t dx, dHy, dHz, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
cdef float_or_double dx, dHy, dHz, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
dx = d
nx = xf - xs
ny = yf - ys
@@ -299,20 +299,20 @@ cpdef void order1_yminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ez field components for the yminus slab.
@@ -327,7 +327,7 @@ cpdef void order1_yminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEz
cdef floattype_t dy, dHx, dHz, RA01, RB0, RE0, RF0
cdef float_or_double dy, dHx, dHz, RA01, RB0, RE0, RF0
dy = d
nx = xf - xs
ny = yf - ys
@@ -362,20 +362,20 @@ cpdef void order2_yminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ez field components for the yminus slab.
@@ -390,7 +390,7 @@ cpdef void order2_yminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEz
cdef floattype_t dy, dHx, dHz, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
cdef float_or_double dy, dHx, dHz, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
dy = d
nx = xf - xs
ny = yf - ys
@@ -433,20 +433,20 @@ cpdef void order1_yplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ez field components for the yplus slab.
@@ -461,7 +461,7 @@ cpdef void order1_yplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEz
cdef floattype_t dy, dHx, dHz, RA01, RB0, RE0, RF0
cdef float_or_double dy, dHx, dHz, RA01, RB0, RE0, RF0
dy = d
nx = xf - xs
ny = yf - ys
@@ -496,20 +496,20 @@ cpdef void order2_yplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ez field components for the yplus slab.
@@ -524,7 +524,7 @@ cpdef void order2_yplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEz
cdef floattype_t dy, dHx, dHz, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
cdef float_or_double dy, dHx, dHz, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
dy = d
nx = xf - xs
ny = yf - ys
@@ -567,20 +567,20 @@ cpdef void order1_zminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ey field components for the zminus slab.
@@ -595,7 +595,7 @@ cpdef void order1_zminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEy
cdef floattype_t dz, dHx, dHy, RA01, RB0, RE0, RF0
cdef float_or_double dz, dHx, dHy, RA01, RB0, RE0, RF0
dz = d
nx = xf - xs
ny = yf - ys
@@ -630,20 +630,20 @@ cpdef void order2_zminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ey field components for the zminus slab.
@@ -658,7 +658,7 @@ cpdef void order2_zminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEy
cdef floattype_t dz, dHx, dHy, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
cdef float_or_double dz, dHx, dHy, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
dz = d
nx = xf - xs
ny = yf - ys
@@ -701,20 +701,20 @@ cpdef void order1_zplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ey field components for the zplus slab.
@@ -729,7 +729,7 @@ cpdef void order1_zplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEy
cdef floattype_t dz, dHx, dHy, RA01, RB0, RE0, RF0
cdef float_or_double dz, dHx, dHy, RA01, RB0, RE0, RF0
dz = d
nx = xf - xs
ny = yf - ys
@@ -764,20 +764,20 @@ cpdef void order2_zplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ey field components for the zplus slab.
@@ -792,7 +792,7 @@ cpdef void order2_zplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEy
cdef floattype_t dz, dHx, dHy, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
cdef float_or_double dz, dHx, dHy, RA0, RB0, RE0, RF0, RA1, RB1, RE1, RF1, RA01
dz = d
nx = xf - xs
ny = yf - ys

查看文件

@@ -1,4 +1,4 @@
cdef floattype_t# Copyright (C) 2015-2019: The University of Edinburgh
cdef float_or_double# Copyright (C) 2015-2019: The University of Edinburgh
# Authors: Craig Warren and Antonis Giannopoulos
#
# This file is part of gprMax.
@@ -20,7 +20,7 @@ import numpy as np
cimport numpy as np
from cython.parallel import prange
from gprMax.config cimport floattype_t
from gprMax.config cimport float_or_double
cpdef void order1_xminus(
@@ -31,20 +31,20 @@ cpdef void order1_xminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ey and Ez field components for the xminus slab.
@@ -59,7 +59,7 @@ cpdef void order1_xminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEy, materialEz
cdef floattype_t dx, dHy, dHz, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dx, dHy, dHz, IRA, IRA1, RB0, RC0, RE0, RF0
dx = d
nx = xf - xs
ny = yf - ys
@@ -96,20 +96,20 @@ cpdef void order2_xminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ey and Ez field components for the xminus slab.
@@ -124,7 +124,7 @@ cpdef void order2_xminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEy, materialEz
cdef floattype_t dx, dHy, dHz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dx, dHy, dHz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dx = d
nx = xf - xs
ny = yf - ys
@@ -170,20 +170,20 @@ cpdef void order1_xplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ey and Ez field components for the xplus slab.
@@ -198,7 +198,7 @@ cpdef void order1_xplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEy, materialEz
cdef floattype_t dx, dHy, dHz, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dx, dHy, dHz, IRA, IRA1, RB0, RC0, RE0, RF0
dx = d
nx = xf - xs
ny = yf - ys
@@ -235,20 +235,20 @@ cpdef void order2_xplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ey and Ez field components for the xplus slab.
@@ -263,7 +263,7 @@ cpdef void order2_xplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEy, materialEz
cdef floattype_t dx, dHy, dHz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dx, dHy, dHz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dx = d
nx = xf - xs
ny = yf - ys
@@ -309,20 +309,20 @@ cpdef void order1_yminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ez field components for the yminus slab.
@@ -337,7 +337,7 @@ cpdef void order1_yminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEz
cdef floattype_t dy, dHx, dHz, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dy, dHx, dHz, IRA, IRA1, RB0, RC0, RE0, RF0
dy = d
nx = xf - xs
ny = yf - ys
@@ -374,20 +374,20 @@ cpdef void order2_yminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ez field components for the yminus slab.
@@ -402,7 +402,7 @@ cpdef void order2_yminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEz
cdef floattype_t dy, dHx, dHz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dy, dHx, dHz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dy = d
nx = xf - xs
ny = yf - ys
@@ -448,20 +448,20 @@ cpdef void order1_yplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ez field components for the yplus slab.
@@ -476,7 +476,7 @@ cpdef void order1_yplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEz
cdef floattype_t dy, dHx, dHz, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dy, dHx, dHz, IRA, IRA1, RB0, RC0, RE0, RF0
dy = d
nx = xf - xs
ny = yf - ys
@@ -513,20 +513,20 @@ cpdef void order2_yplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ez field components for the yplus slab.
@@ -541,7 +541,7 @@ cpdef void order2_yplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEz
cdef floattype_t dy, dHx, dHz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dy, dHx, dHz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dy = d
nx = xf - xs
ny = yf - ys
@@ -587,20 +587,20 @@ cpdef void order1_zminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ey field components for the zminus slab.
@@ -615,7 +615,7 @@ cpdef void order1_zminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEy
cdef floattype_t dz, dHx, dHy, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dz, dHx, dHy, IRA, IRA1, RB0, RC0, RE0, RF0
dz = d
nx = xf - xs
ny = yf - ys
@@ -652,20 +652,20 @@ cpdef void order2_zminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ey field components for the zminus slab.
@@ -680,7 +680,7 @@ cpdef void order2_zminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEy
cdef floattype_t dz, dHx, dHy, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dz, dHx, dHy, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dz = d
nx = xf - xs
ny = yf - ys
@@ -726,20 +726,20 @@ cpdef void order1_zplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ey field components for the zplus slab.
@@ -754,7 +754,7 @@ cpdef void order1_zplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEy
cdef floattype_t dz, dHx, dHy, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dz, dHx, dHy, IRA, IRA1, RB0, RC0, RE0, RF0
dz = d
nx = xf - xs
ny = yf - ys
@@ -791,20 +791,20 @@ cpdef void order2_zplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsE,
float_or_double[:, ::1] updatecoeffsE,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Ex and Ey field components for the zplus slab.
@@ -819,7 +819,7 @@ cpdef void order2_zplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialEx, materialEy
cdef floattype_t dz, dHx, dHy, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dz, dHx, dHy, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dz = d
nx = xf - xs
ny = yf - ys

查看文件

@@ -20,7 +20,7 @@ import numpy as np
cimport numpy as np
from cython.parallel import prange
from gprMax.config cimport floattype_t
from gprMax.config cimport float_or_double
cpdef void order1_xminus(
@@ -31,20 +31,20 @@ cpdef void order1_xminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hy and Hz field components for the xminus slab.
@@ -59,7 +59,7 @@ cpdef void order1_xminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHy, materialHz
cdef floattype_t dx, dEy, dEz, RA01, RB0, RE0, RF0
cdef float_or_double dx, dEy, dEz, RA01, RB0, RE0, RF0
dx = d
nx = xf - xs
ny = yf - ys
@@ -94,20 +94,20 @@ cpdef void order2_xminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hy and Hz field components for the xminus slab.
@@ -122,7 +122,7 @@ cpdef void order2_xminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHy, materialHz
cdef floattype_t dx, dEy, dEz, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
cdef float_or_double dx, dEy, dEz, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
dx = d
nx = xf - xs
ny = yf - ys
@@ -165,20 +165,20 @@ cpdef void order1_xplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hy and Hz field components for the xplus slab.
@@ -193,7 +193,7 @@ cpdef void order1_xplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHy, materialHz
cdef floattype_t dx, dEy, dEz, RA01, RB0, RE0, RF0
cdef float_or_double dx, dEy, dEz, RA01, RB0, RE0, RF0
dx = d
nx = xf - xs
ny = yf - ys
@@ -228,20 +228,20 @@ cpdef void order2_xplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hy and Hz field components for the xplus slab.
@@ -256,7 +256,7 @@ cpdef void order2_xplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHy, materialHz
cdef floattype_t dx, dEy, dEz, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
cdef float_or_double dx, dEy, dEz, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
dx = d
nx = xf - xs
ny = yf - ys
@@ -299,20 +299,20 @@ cpdef void order1_yminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hz field components for the yminus slab.
@@ -327,7 +327,7 @@ cpdef void order1_yminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHz
cdef floattype_t dy, dEx, dEz, RA01, RB0, RE0, RF0
cdef float_or_double dy, dEx, dEz, RA01, RB0, RE0, RF0
dy = d
nx = xf - xs
ny = yf - ys
@@ -362,20 +362,20 @@ cpdef void order2_yminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hz field components for the yminus slab.
@@ -390,7 +390,7 @@ cpdef void order2_yminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHz
cdef floattype_t dy, dEx, dEz, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
cdef float_or_double dy, dEx, dEz, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
dy = d
nx = xf - xs
ny = yf - ys
@@ -433,20 +433,20 @@ cpdef void order1_yplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hz field components for the yplus slab.
@@ -461,7 +461,7 @@ cpdef void order1_yplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHz
cdef floattype_t dy, dEx, dEz, RA01, RB0, RE0, RF0
cdef float_or_double dy, dEx, dEz, RA01, RB0, RE0, RF0
dy = d
nx = xf - xs
ny = yf - ys
@@ -496,20 +496,20 @@ cpdef void order2_yplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hz field components for the yplus slab.
@@ -524,7 +524,7 @@ cpdef void order2_yplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHz
cdef floattype_t dy, dEx, dEz, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
cdef float_or_double dy, dEx, dEz, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
dy = d
nx = xf - xs
ny = yf - ys
@@ -567,20 +567,20 @@ cpdef void order1_zminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hy field components for the zminus slab.
@@ -595,7 +595,7 @@ cpdef void order1_zminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHy
cdef floattype_t dz, dEx, dEy, RA01, RB0, RE0, RF0
cdef float_or_double dz, dEx, dEy, RA01, RB0, RE0, RF0
dz = d
nx = xf - xs
ny = yf - ys
@@ -630,20 +630,20 @@ cpdef void order2_zminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hy field components for the zminus slab.
@@ -658,7 +658,7 @@ cpdef void order2_zminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHy
cdef floattype_t dz, dEx, dEy, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
cdef float_or_double dz, dEx, dEy, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
dz = d
nx = xf - xs
ny = yf - ys
@@ -701,20 +701,20 @@ cpdef void order1_zplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hy field components for the zplus slab.
@@ -729,7 +729,7 @@ cpdef void order1_zplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHy
cdef floattype_t dz, dEx, dEy, RA01, RB0, RE0, RF0
cdef float_or_double dz, dEx, dEy, RA01, RB0, RE0, RF0
dz = d
nx = xf - xs
ny = yf - ys
@@ -764,20 +764,20 @@ cpdef void order2_zplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hy field components for the zplus slab.
@@ -792,7 +792,7 @@ cpdef void order2_zplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHy
cdef floattype_t dz, dEx, dEy, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
cdef float_or_double dz, dEx, dEy, RA0, RA01, RB0, RE0, RF0, RA1, RB1, RE1, RF1
dz = d
nx = xf - xs
ny = yf - ys

查看文件

@@ -20,7 +20,7 @@ import numpy as np
cimport numpy as np
from cython.parallel import prange
from gprMax.config cimport floattype_t
from gprMax.config cimport float_or_double
cpdef void order1_xminus(
@@ -31,20 +31,20 @@ cpdef void order1_xminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hy and Hz field components for the xminus slab.
@@ -59,7 +59,7 @@ cpdef void order1_xminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHy, materialHz
cdef floattype_t dx, dEy, dEz, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dx, dEy, dEz, IRA, IRA1, RB0, RC0, RE0, RF0
dx = d
nx = xf - xs
ny = yf - ys
@@ -96,20 +96,20 @@ cpdef void order2_xminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hy and Hz field components for the xminus slab.
@@ -124,7 +124,7 @@ cpdef void order2_xminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHy, materialHz
cdef floattype_t dx, dEy, dEz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dx, dEy, dEz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dx = d
nx = xf - xs
ny = yf - ys
@@ -170,20 +170,20 @@ cpdef void order1_xplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hy and Hz field components for the xplus slab.
@@ -198,7 +198,7 @@ cpdef void order1_xplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHy, materialHz
cdef floattype_t dx, dEy, dEz, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dx, dEy, dEz, IRA, IRA1, RB0, RC0, RE0, RF0
dx = d
nx = xf - xs
ny = yf - ys
@@ -235,20 +235,20 @@ cpdef void order2_xplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hy and Hz field components for the xplus slab.
@@ -263,7 +263,7 @@ cpdef void order2_xplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHy, materialHz
cdef floattype_t dx, dEy, dEz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dx, dEy, dEz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dx = d
nx = xf - xs
ny = yf - ys
@@ -309,20 +309,20 @@ cpdef void order1_yminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hz field components for the yminus slab.
@@ -337,7 +337,7 @@ cpdef void order1_yminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHz
cdef floattype_t dy, dEx, dEz, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dy, dEx, dEz, IRA, IRA1, RB0, RC0, RE0, RF0
dy = d
nx = xf - xs
ny = yf - ys
@@ -374,20 +374,20 @@ cpdef void order2_yminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hz field components for the yminus slab.
@@ -402,7 +402,7 @@ cpdef void order2_yminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHz
cdef floattype_t dy, dEx, dEz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dy, dEx, dEz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dy = d
nx = xf - xs
ny = yf - ys
@@ -448,20 +448,20 @@ cpdef void order1_yplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hz field components for the yplus slab.
@@ -476,7 +476,7 @@ cpdef void order1_yplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHz
cdef floattype_t dy, dEx, dEz, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dy, dEx, dEz, IRA, IRA1, RB0, RC0, RE0, RF0
dy = d
nx = xf - xs
ny = yf - ys
@@ -513,20 +513,20 @@ cpdef void order2_yplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hz field components for the yplus slab.
@@ -541,7 +541,7 @@ cpdef void order2_yplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHz
cdef floattype_t dy, dEx, dEz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dy, dEx, dEz, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dy = d
nx = xf - xs
ny = yf - ys
@@ -587,20 +587,20 @@ cpdef void order1_zminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hy field components for the zminus slab.
@@ -615,7 +615,7 @@ cpdef void order1_zminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHy
cdef floattype_t dz, dEx, dEy, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dz, dEx, dEy, IRA, IRA1, RB0, RC0, RE0, RF0
dz = d
nx = xf - xs
ny = yf - ys
@@ -652,20 +652,20 @@ cpdef void order2_zminus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hy field components for the zminus slab.
@@ -680,7 +680,7 @@ cpdef void order2_zminus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHy
cdef floattype_t dz, dEx, dEy, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dz, dEx, dEy, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dz = d
nx = xf - xs
ny = yf - ys
@@ -726,20 +726,20 @@ cpdef void order1_zplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hy field components for the zplus slab.
@@ -754,7 +754,7 @@ cpdef void order1_zplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHy
cdef floattype_t dz, dEx, dEy, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double dz, dEx, dEy, IRA, IRA1, RB0, RC0, RE0, RF0
dz = d
nx = xf - xs
ny = yf - ys
@@ -791,20 +791,20 @@ cpdef void order2_zplus(
int zs,
int zf,
int nthreads,
floattype_t[:, ::1] updatecoeffsH,
float_or_double[:, ::1] updatecoeffsH,
np.uint32_t[:, :, :, ::1] ID,
floattype_t[:, :, ::1] Ex,
floattype_t[:, :, ::1] Ey,
floattype_t[:, :, ::1] Ez,
floattype_t[:, :, ::1] Hx,
floattype_t[:, :, ::1] Hy,
floattype_t[:, :, ::1] Hz,
floattype_t[:, :, :, ::1] Phi1,
floattype_t[:, :, :, ::1] Phi2,
floattype_t[:, ::1] RA,
floattype_t[:, ::1] RB,
floattype_t[:, ::1] RE,
floattype_t[:, ::1] RF,
float_or_double[:, :, ::1] Ex,
float_or_double[:, :, ::1] Ey,
float_or_double[:, :, ::1] Ez,
float_or_double[:, :, ::1] Hx,
float_or_double[:, :, ::1] Hy,
float_or_double[:, :, ::1] Hz,
float_or_double[:, :, :, ::1] Phi1,
float_or_double[:, :, :, ::1] Phi2,
float_or_double[:, ::1] RA,
float_or_double[:, ::1] RB,
float_or_double[:, ::1] RE,
float_or_double[:, ::1] RF,
float d
):
"""This function updates the Hx and Hy field components for the zplus slab.
@@ -819,7 +819,7 @@ cpdef void order2_zplus(
cdef Py_ssize_t i, j, k, ii, jj, kk
cdef int nx, ny, nz, materialHx, materialHy
cdef floattype_t dz, dEx, dEy, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
cdef float_or_double dz, dEx, dEy, IRA, IRA1, RB0, RC0, RE0, RF0, RB1, RC1, RE1, RF1, Psi1, Psi2
dz = d
nx = xf - xs
ny = yf - ys

查看文件

@@ -18,35 +18,35 @@
cimport numpy as np
from gprMax.config cimport floattype_t
from gprMax.config cimport float_or_double
cpdef void calculate_snapshot_fields(
int nx,
int ny,
int nz,
floattype_t[:, :, ::1] sliceEx,
floattype_t[:, :, ::1] sliceEy,
floattype_t[:, :, ::1] sliceEz,
floattype_t[:, :, ::1] sliceHx,
floattype_t[:, :, ::1] sliceHy,
floattype_t[:, :, ::1] sliceHz,
floattype_t[:, :, ::1] snapEx,
floattype_t[:, :, ::1] snapEy,
floattype_t[:, :, ::1] snapEz,
floattype_t[:, :, ::1] snapHx,
floattype_t[:, :, ::1] snapHy,
floattype_t[:, :, ::1] snapHz
float_or_double[:, :, ::1] sliceEx,
float_or_double[:, :, ::1] sliceEy,
float_or_double[:, :, ::1] sliceEz,
float_or_double[:, :, ::1] sliceHx,
float_or_double[:, :, ::1] sliceHy,
float_or_double[:, :, ::1] sliceHz,
float_or_double[:, :, ::1] snapEx,
float_or_double[:, :, ::1] snapEy,
float_or_double[:, :, ::1] snapEz,
float_or_double[:, :, ::1] snapHx,
float_or_double[:, :, ::1] snapHy,
float_or_double[:, :, ::1] snapHz
):
"""This function calculates electric and magnetic values at points from
averaging values in cells
averaging values in cells.
Args:
nx, ny, nz (int): Size of snapshot array
sliceEx, sliceEy, sliceEz,
sliceHx, sliceHy, sliceHz (memoryview): Access to slices of field arrays
snapEx, snapEy, snapEz, snapHx,
snapHy, snapHz (memoryview): Access to snapshot arrays
snapEx, snapEy, snapEz,
snapHx, snapHy, snapHz (memoryview): Access to snapshot arrays
"""
cdef Py_ssize_t i, j, k
@@ -54,9 +54,8 @@ cpdef void calculate_snapshot_fields(
for i in range(nx):
for j in range(ny):
for k in range(nz):
# The electric field component value at a point comes from
# average of the 4 electric field component values in that cell
# The electric field component value at a point comes from the
# average of the 4 electric field component values in that cell.
snapEx[i, j, k] = (sliceEx[i, j, k] + sliceEx[i, j + 1, k] +
sliceEx[i, j, k + 1] + sliceEx[i, j + 1, k + 1]) / 4
snapEy[i, j, k] = (sliceEy[i, j, k] + sliceEy[i + 1, j, k] +
@@ -64,8 +63,9 @@ cpdef void calculate_snapshot_fields(
snapEz[i, j, k] = (sliceEz[i, j, k] + sliceEz[i + 1, j, k] +
sliceEz[i, j + 1, k] + sliceEz[i + 1, j + 1, k]) / 4
# The magnetic field component value at a point comes from average
# of 2 magnetic field component values in that cell and the following cell
# The magnetic field component value at a point comes from
# average of 2 magnetic field component values in that cell and
# the neighbouring cell.
snapHx[i, j, k] = (sliceHx[i, j, k] + sliceHx[i + 1, j, k]) / 2
snapHy[i, j, k] = (sliceHy[i, j, k] + sliceHy[i, j + 1, k]) / 2
snapHz[i, j, k] = (sliceHz[i, j, k] + sliceHz[i, j, k + 1]) / 2

查看文件

@@ -37,7 +37,9 @@ class GeneralError(ValueError):
class CmdInputError(ValueError):
"""Handles errors in user specified commands. Subclasses the ValueError class."""
"""Handles errors in user specified commands. Subclasses the ValueError
class.
"""
def __init__(self, message, *args):

查看文件

@@ -20,7 +20,7 @@ from string import Template
import h5py
from gprMax._version import __version__
from ._version import __version__
def store_outputs(iteration, Ex, Ey, Ez, Hx, Hy, Hz, G):
@@ -28,8 +28,10 @@ def store_outputs(iteration, Ex, Ey, Ez, Hx, Hy, Hz, G):
Args:
iteration (int): Current iteration number.
Ex, Ey, Ez, Hx, Hy, Hz (memory view): Current electric and magnetic field values.
G (class): Grid class instance - holds essential parameters describing the model.
Ex, Ey, Ez, Hx, Hy, Hz (memory view): Current electric and magnetic
field values.
G (class): Grid class instance - holds essential parameters describing
the model.
"""
for rx in G.rxs:
@@ -41,7 +43,8 @@ def store_outputs(iteration, Ex, Ey, Ez, Hx, Hy, Hz, G):
# Store current component
else:
func = globals()[output]
rx.outputs[output][iteration] = func(rx.xcoord, rx.ycoord, rx.zcoord, Hx, Hy, Hz, G)
rx.outputs[output][iteration] = func(rx.xcoord, rx.ycoord, rx.zcoord,
Hx, Hy, Hz, G)
for tl in G.transmissionlines:
tl.Vtotal[iteration] = tl.voltage[tl.antpos]
@@ -94,8 +97,10 @@ def write_hdf5_outputfile(outputfile, Ex, Ey, Ez, Hx, Hy, Hz, G):
Args:
outputfile (str): Name of the output file.
Ex, Ey, Ez, Hx, Hy, Hz (memory view): Current electric and magnetic field values.
G (class): Grid class instance - holds essential parameters describing the model.
Ex, Ey, Ez, Hx, Hy, Hz (memory view): Current electric and magnetic
field values.
G (class): Grid class instance - holds essential parameters describing
the model.
"""
f = h5py.File(outputfile, 'w')

查看文件

@@ -19,12 +19,10 @@
import numpy as np
from scipy import fftpack
from gprMax.config import floattype
from gprMax.config import complextype
from gprMax.config import hostinfo
from gprMax.cython.fractals_generate import generate_fractal2D
from gprMax.cython.fractals_generate import generate_fractal3D
from gprMax.utilities import round_value
import gprMax.config as config
from .cython.fractals_generate import generate_fractal2D
from .cython.fractals_generate import generate_fractal3D
from .utilities import round_value
np.seterr(divide='raise')
@@ -37,9 +35,11 @@ class FractalSurface(object):
def __init__(self, xs, xf, ys, yf, zs, zf, dimension):
"""
Args:
xs, xf, ys, yf, zs, zf (float): Extent of the fractal surface (one pair of
coordinates must be equal to correctly define a surface).
dimension (float): Fractal dimension that controls the fractal distribution.
xs, xf, ys, yf, zs, zf (float): Extent of the fractal surface
(one pair of coordinates must be
equal to correctly define a surface).
dimension (float): Fractal dimension that controls the fractal
distribution.
"""
self.ID = None
@@ -66,7 +66,8 @@ class FractalSurface(object):
"""Generate a 2D array with a fractal distribution.
Args:
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
"""
if self.xs == self.xf:
@@ -76,10 +77,11 @@ class FractalSurface(object):
elif self.zs == self.zf:
surfacedims = (self.nx, self.ny)
self.fractalsurface = np.zeros(surfacedims, dtype=complextype)
self.fractalsurface = np.zeros(surfacedims, dtype=config.dtypes['complex'])
# Positional vector at centre of array, scaled by weighting
v1 = np.array([self.weighting[0] * (surfacedims[0]) / 2, self.weighting[1] * (surfacedims[1]) / 2])
v1 = np.array([self.weighting[0] * (surfacedims[0]) / 2, self.weighting[1]
* (surfacedims[1]) / 2])
# 2D array of random numbers to be convolved with the fractal function
R = np.random.RandomState(self.seed)
@@ -91,7 +93,8 @@ class FractalSurface(object):
A = fftpack.fftshift(A)
# Generate fractal
generate_fractal2D(surfacedims[0], surfacedims[1], hostinfo['ompthreads'], self.b, self.weighting, v1, A, self.fractalsurface)
generate_fractal2D(surfacedims[0], surfacedims[1], config.hostinfo['ompthreads'],
self.b, self.weighting, v1, A, self.fractalsurface)
# Shift the zero frequency component to start of the array
self.fractalsurface = fftpack.ifftshift(self.fractalsurface)
@@ -101,8 +104,10 @@ class FractalSurface(object):
fractalmin = np.amin(self.fractalsurface)
fractalmax = np.amax(self.fractalsurface)
fractalrange = fractalmax - fractalmin
self.fractalsurface = self.fractalsurface * ((self.fractalrange[1] - self.fractalrange[0]) / fractalrange) \
+ self.fractalrange[0] - ((self.fractalrange[1] - self.fractalrange[0]) / fractalrange) * fractalmin
self.fractalsurface = (self.fractalsurface * ((self.fractalrange[1]
- self.fractalrange[0]) / fractalrange)
+ self.fractalrange[0] - ((self.fractalrange[1]
- self.fractalrange[0]) / fractalrange) * fractalmin)
class FractalVolume(object):
@@ -112,7 +117,8 @@ class FractalVolume(object):
"""
Args:
xs, xf, ys, yf, zs, zf (float): Extent of the fractal volume.
dimension (float): Fractal dimension that controls the fractal distribution.
dimension (float): Fractal dimension that controls the fractal
distribution.
"""
self.ID = None
@@ -139,7 +145,8 @@ class FractalVolume(object):
"""Generate a 3D volume with a fractal distribution.
Args:
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
"""
# Scale filter according to size of fractal volume
@@ -158,10 +165,11 @@ class FractalVolume(object):
# Adjust weighting to account for filter scaling
self.weighting = np.multiply(self.weighting, filterscaling)
self.fractalvolume = np.zeros((self.nx, self.ny, self.nz), dtype=complextype)
self.fractalvolume = np.zeros((self.nx, self.ny, self.nz), dtype=config.dtypes['complex'])
# Positional vector at centre of array, scaled by weighting
v1 = np.array([self.weighting[0] * self.nx / 2, self.weighting[1] * self.ny / 2, self.weighting[2] * self.nz / 2])
v1 = np.array([self.weighting[0] * self.nx / 2, self.weighting[1]
* self.ny / 2, self.weighting[2] * self.nz / 2])
# 3D array of random numbers to be convolved with the fractal function
R = np.random.RandomState(self.seed)
@@ -173,7 +181,8 @@ class FractalVolume(object):
A = fftpack.fftshift(A)
# Generate fractal
generate_fractal3D(self.nx, self.ny, self.nz, hostinfo['ompthreads'], self.b, self.weighting, v1, A, self.fractalvolume)
generate_fractal3D(self.nx, self.ny, self.nz, config.hostinfo['ompthreads'],
self.b, self.weighting, v1, A, self.fractalvolume)
# Shift the zero frequency component to the start of the array
self.fractalvolume = fftpack.ifftshift(self.fractalvolume)
@@ -186,9 +195,10 @@ class FractalVolume(object):
self.fractalvolume[:, j, k] = np.digitize(self.fractalvolume[:, j, k], bins, right=True)
def generate_volume_mask(self):
"""Generate a 3D volume to use as a mask for adding rough surfaces,
water and grass/roots. Zero signifies the mask is not set, one
signifies the mask is set.
"""
Generate a 3D volume to use as a mask for adding rough surfaces, water and grass/roots.
Zero signifies the mask is not set, one signifies the mask is set."""
self.mask = np.zeros((self.nx, self.ny, self.nz), dtype=np.int8)
maskxs = self.originalxs - self.xs
@@ -210,7 +220,8 @@ class Grass(object):
"""
self.numblades = numblades
self.geometryparams = np.zeros((self.numblades, 6), dtype=floattype)
self.geometryparams = np.zeros((self.numblades, 6),
dtype=config.dtypes['float_or_double'])
self.seed = None
# Randomly defined parameters that will be used to calculate geometry
@@ -238,8 +249,10 @@ class Grass(object):
x, y (float): x and y coordinates of grass blade.
"""
x = self.geometryparams[blade, 2] * (height / self.geometryparams[blade, 0]) * (height / self.geometryparams[blade, 0])
y = self.geometryparams[blade, 3] * (height / self.geometryparams[blade, 1]) * (height / self.geometryparams[blade, 1])
x = (self.geometryparams[blade, 2] * (height / self.geometryparams[blade, 0])
* (height / self.geometryparams[blade, 0]))
y = (self.geometryparams[blade, 3] * (height / self.geometryparams[blade, 1])
* (height / self.geometryparams[blade, 1]))
x = round_value(x)
y = round_value(y)

查看文件

@@ -23,10 +23,12 @@ import h5py
import numpy as np
from struct import pack
from gprMax._version import __version__
from gprMax.cython.geometry_outputs import define_normal_geometry
from gprMax.cython.geometry_outputs import define_fine_geometry
from gprMax.utilities import round_value
import gprMax.config as config
from ._version import __version__
from .cython.geometry_outputs import define_normal_geometry
from .cython.geometry_outputs import define_fine_geometry
from .utilities import round_value
class GeometryView(object):
@@ -104,16 +106,15 @@ class GeometryView(object):
+ np.dtype(np.uint32).itemsize * vtk_cell_offsets
+ np.dtype(np.uint32).itemsize * 4)
def set_filename(self, appendmodelnumber, G):
def set_filename(self, appendmodelnumber):
"""
Construct filename from user-supplied name and model run number.
Args:
appendmodelnumber (str): Text to append to filename.
G (class): Grid class instance - holds essential parameters describing the model.
"""
self.filename = os.path.abspath(os.path.join(G.inputdirectory, self.basefilename + appendmodelnumber))
self.filename = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(config.general['inputfilepath'])), self.basefilename + appendmodelnumber))
self.filename += self.fileext
def write_vtk(self, G, pbar):

查看文件

@@ -28,22 +28,17 @@ from enum import Enum
import h5py
import numpy as np
from gprMax._version import __version__
from gprMax._version import codename
from ._version import __version__
from ._version import codename
import gprMax.config as config
from gprMax.config import c
from gprMax.config import e0
from gprMax.config import m0
from gprMax.config import z0
from gprMax.config import hostinfo
from gprMax.exceptions import GeneralError
from gprMax.model_build_run import run_model
from gprMax.utilities import detect_check_gpus
from gprMax.utilities import get_terminal_width
from gprMax.utilities import human_size
from gprMax.utilities import logo
from gprMax.utilities import open_path_file
from gprMax.utilities import timer
from .exceptions import GeneralError
from .model_build_run import run_model
from .utilities import detect_check_gpus
from .utilities import get_terminal_width
from .utilities import human_size
from .utilities import logo
from .utilities import open_path_file
from .utilities import timer
def main():
"""This is the main function for gprMax."""
@@ -116,24 +111,24 @@ def run_main(args):
logo(__version__ + ' (' + codename + ')')
# Print information about host machine
hyperthreading = ', {} cores with HT'.format(hostinfo['logicalcores']) if hostinfo['hyperthreading'] else ''
print('\nHost: {} | {} | {} x {} ({} cores{}) | {} RAM | {}'.format(hostinfo['hostname'],
hostinfo['machineID'], hostinfo['sockets'], hostinfo['cpuID'], hostinfo['physicalcores'],
hyperthreading, human_size(hostinfo['ram'], a_kilobyte_is_1024_bytes=True), hostinfo['osversion']))
hyperthreading = ', {} cores with HT'.format(config.hostinfo['logicalcores']) if config.hostinfo['hyperthreading'] else ''
print('\nHost: {} | {} | {} x {} ({} cores{}) | {} RAM | {}'.format(config.hostinfo['hostname'],
config.hostinfo['machineID'], config.hostinfo['sockets'], config.hostinfo['cpuID'], config.hostinfo['physicalcores'],
hyperthreading, human_size(config.hostinfo['ram'], a_kilobyte_is_1024_bytes=True), config.hostinfo['osversion']))
# Get information/setup any Nvidia GPU(s)
if args.gpu is not None:
# Flatten a list of lists
if any(isinstance(element, list) for element in args.gpu):
args.gpu = [val for sublist in args.gpu for val in sublist]
config.gpus, allgpustext = detect_check_gpus(args.gpu)
config.cuda['gpus'], allgpustext = detect_check_gpus(args.gpu)
print('GPU(s): {}'.format(' | '.join(allgpustext)))
# Process input file
with open_path_file(args.inputfile) as inputfile:
# Create a separate namespace that users can access in any Python code blocks in the input file
usernamespace = {'c': c, 'e0': e0, 'm0': m0, 'z0': z0, 'number_model_runs': args.n, 'inputfile': os.path.abspath(inputfile.name)}
usernamespace = {'c': config.c, 'e0': config.e0, 'm0': config.m0, 'z0': config.z0, 'number_model_runs': args.n, 'inputfile': os.path.abspath(inputfile.name)}
#######################################
# Process for benchmarking simulation #
@@ -167,8 +162,8 @@ def run_main(args):
else:
if args.task and args.restart:
raise GeneralError('Job array and restart modes cannot be used together')
if config.gpus:
config.gpus = config.gpus[0]
if config.cuda['gpus']:
config.cuda['gpus'] = config.cuda['gpus'][0]
run_std_sim(args, inputfile, usernamespace)
@@ -201,7 +196,7 @@ def run_std_sim(args, inputfile, usernamespace):
for currentmodelrun in range(modelstart, modelend):
run_model(args, currentmodelrun, modelend - 1, numbermodelruns, inputfile, usernamespace)
tsimend = timer()
simcompletestr = '\n=== Simulation on {} completed in [HH:MM:SS]: {}'.format(hostinfo['hostname'], datetime.timedelta(seconds=tsimend - tsimstart))
simcompletestr = '\n=== Simulation on {} completed in [HH:MM:SS]: {}'.format(config.hostinfo['hostname'], datetime.timedelta(seconds=tsimend - tsimstart))
print('{} {}\n'.format(simcompletestr, '=' * (get_terminal_width() - 1 - len(simcompletestr))))
@@ -219,8 +214,8 @@ def run_benchmark_sim(args, inputfile, usernamespace):
"""
# Store information about host machine
hyperthreading = ', {} cores with HT'.format(hostinfo['logicalcores']) if hostinfo['hyperthreading'] else ''
machineIDlong = '{}; {} x {} ({} cores{}); {} RAM; {}'.format(hostinfo['machineID'], hostinfo['sockets'], hostinfo['cpuID'], hostinfo['physicalcores'], hyperthreading, human_size(hostinfo['ram'], a_kilobyte_is_1024_bytes=True), hostinfo['osversion'])
hyperthreading = ', {} cores with HT'.format(config.hostinfo['logicalcores']) if config.hostinfo['hyperthreading'] else ''
machineIDlong = '{}; {} x {} ({} cores{}); {} RAM; {}'.format(config.hostinfo['machineID'], config.hostinfo['sockets'], config.hostinfo['cpuID'], config.hostinfo['physicalcores'], hyperthreading, human_size(config.hostinfo['ram'], a_kilobyte_is_1024_bytes=True), config.hostinfo['osversion'])
# Initialise arrays to hold CPU thread info and times, and GPU info and times
cputhreads = np.array([], dtype=np.int32)
@@ -232,8 +227,8 @@ def run_benchmark_sim(args, inputfile, usernamespace):
if args.gpu is None:
# Number of CPU threads to benchmark - start from single thread and double threads until maximum number of physical cores
threads = 1
maxthreads = hostinfo['physicalcores']
maxthreadspersocket = hostinfo['physicalcores'] / hostinfo['sockets']
maxthreads = config.hostinfo['physicalcores']
maxthreadspersocket = config.hostinfo['physicalcores'] / config.hostinfo['sockets']
while threads < maxthreadspersocket:
cputhreads = np.append(cputhreads, int(threads))
threads *= 2
@@ -271,7 +266,7 @@ def run_benchmark_sim(args, inputfile, usernamespace):
# Run GPU benchmark
else:
args.gpu = gpus[(currentmodelrun - 1)]
os.environ['OMP_NUM_THREADS'] = str(hostinfo['physicalcores'])
os.environ['OMP_NUM_THREADS'] = str(config.hostinfo['physicalcores'])
gputimes[(currentmodelrun - 1)] = run_model(args, currentmodelrun, modelend - 1, numbermodelruns, inputfile, usernamespace)
# Get model size (in cells) and number of iterations

查看文件

@@ -26,17 +26,11 @@ import numpy as np
np.seterr(invalid='raise')
import gprMax.config as config
from gprMax.config import c
from gprMax.config import floattype
from gprMax.config import complextype
from gprMax.config import numdispersion
from gprMax.config import hostinfo
from gprMax.exceptions import GeneralError
from gprMax.materials import Material
from gprMax.pml import PML
from gprMax.utilities import fft_power
from gprMax.utilities import human_size
from gprMax.utilities import round_value
from .exceptions import GeneralError
from .pml import PML
from .utilities import fft_power
from .utilities import human_size
from .utilities import round_value
class Grid(object):
@@ -87,9 +81,6 @@ class FDTDGrid(Grid):
"""
def __init__(self):
self.inputfilename = ''
self.inputdirectory = ''
self.outputdirectory = ''
self.title = ''
self.memoryusage = 0
@@ -144,24 +135,24 @@ class FDTDGrid(Grid):
def initialise_field_arrays(self):
"""Initialise arrays for the electric and magnetic field components."""
self.Ex = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=floattype)
self.Ey = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=floattype)
self.Ez = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=floattype)
self.Hx = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=floattype)
self.Hy = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=floattype)
self.Hz = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=floattype)
self.Ex = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.dtypes['float_or_double'])
self.Ey = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.dtypes['float_or_double'])
self.Ez = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.dtypes['float_or_double'])
self.Hx = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.dtypes['float_or_double'])
self.Hy = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.dtypes['float_or_double'])
self.Hz = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.dtypes['float_or_double'])
def initialise_std_update_coeff_arrays(self):
"""Initialise arrays for storing update coefficients."""
self.updatecoeffsE = np.zeros((len(self.materials), 5), dtype=floattype)
self.updatecoeffsH = np.zeros((len(self.materials), 5), dtype=floattype)
self.updatecoeffsE = np.zeros((len(self.materials), 5), dtype=config.dtypes['float_or_double'])
self.updatecoeffsH = np.zeros((len(self.materials), 5), dtype=config.dtypes['float_or_double'])
def initialise_dispersive_arrays(self):
def initialise_dispersive_arrays(self, dtype):
"""Initialise arrays for storing coefficients when there are dispersive materials present."""
self.Tx = np.zeros((Material.maxpoles, self.nx + 1, self.ny + 1, self.nz + 1), dtype=complextype)
self.Ty = np.zeros((Material.maxpoles, self.nx + 1, self.ny + 1, self.nz + 1), dtype=complextype)
self.Tz = np.zeros((Material.maxpoles, self.nx + 1, self.ny + 1, self.nz + 1), dtype=complextype)
self.updatecoeffsdispersive = np.zeros((len(self.materials), 3 * Material.maxpoles), dtype=complextype)
self.Tx = np.zeros((config.materials['maxpoles'], self.nx + 1, self.ny + 1, self.nz + 1), dtype=dtype)
self.Ty = np.zeros((config.materials['maxpoles'], self.nx + 1, self.ny + 1, self.nz + 1), dtype=dtype)
self.Tz = np.zeros((config.materials['maxpoles'], self.nx + 1, self.ny + 1, self.nz + 1), dtype=dtype)
self.updatecoeffsdispersive = np.zeros((len(self.materials), 3 * config.materials['maxpoles']), dtype=dtype)
def memory_estimate_basic(self):
"""Estimate the amount of memory (RAM) required to run a model."""
@@ -174,7 +165,7 @@ class FDTDGrid(Grid):
rigidarrays = (12 + 6) * self.nx * self.ny * self.nz * np.dtype(np.int8).itemsize
# 6 x field arrays + 6 x ID arrays
fieldarrays = (6 + 6) * (self.nx + 1) * (self.ny + 1) * (self.nz + 1) * np.dtype(floattype).itemsize
fieldarrays = (6 + 6) * (self.nx + 1) * (self.ny + 1) * (self.nz + 1) * np.dtype(config.dtypes['float_or_double']).itemsize
# PML arrays
pmlarrays = 0
@@ -206,21 +197,21 @@ class FDTDGrid(Grid):
"""
# Check if model can be built and/or run on host
if self.memoryusage > hostinfo['ram']:
raise GeneralError('Memory (RAM) required ~{} exceeds {} detected!\n'.format(human_size(self.memoryusage), human_size(hostinfo['ram'], a_kilobyte_is_1024_bytes=True)))
if self.memoryusage > config.hostinfo['ram']:
raise GeneralError('Memory (RAM) required ~{} exceeds {} detected!\n'.format(human_size(self.memoryusage), human_size(config.hostinfo['ram'], a_kilobyte_is_1024_bytes=True)))
# Check if model can be run on specified GPU if required
if config.gpus is not None:
if self.memoryusage - snapsmemsize > config.gpus.totalmem:
raise GeneralError('Memory (RAM) required ~{} exceeds {} detected on specified {} - {} GPU!\n'.format(human_size(self.memoryusage), human_size(config.gpus.totalmem, a_kilobyte_is_1024_bytes=True), config.gpus.deviceID, config.gpus.name))
if config.cuda['gpus'] is not None:
if self.memoryusage - snapsmemsize > config.cuda['gpus'].totalmem:
raise GeneralError('Memory (RAM) required ~{} exceeds {} detected on specified {} - {} GPU!\n'.format(human_size(self.memoryusage), human_size(config.cuda['gpus'].totalmem, a_kilobyte_is_1024_bytes=True), config.cuda['gpus'].deviceID, config.cuda['gpus'].name))
# If the required memory without the snapshots will fit on the GPU then transfer and store snaphots on host
if snapsmemsize != 0 and self.memoryusage - snapsmemsize < config.gpus.totalmem:
config.snapsgpu2cpu = True
if snapsmemsize != 0 and self.memoryusage - snapsmemsize < config.cuda['gpus'].totalmem:
config.cuda['snapsgpu2cpu'] = True
def gpu_set_blocks_per_grid(self):
"""Set the blocks per grid size used for updating the electric and magnetic field arrays on a GPU."""
config.gpus.bpg = (int(np.ceil(((self.nx + 1) * (self.ny + 1) * (self.nz + 1)) / config.gpus.tpb[0])), 1, 1)
config.cuda['gpus'].bpg = (int(np.ceil(((self.nx + 1) * (self.ny + 1) * (self.nz + 1)) / config.cuda['gpus'].tpb[0])), 1, 1)
def gpu_initialise_arrays(self):
"""Initialise standard field arrays on GPU."""
@@ -298,7 +289,7 @@ def dispersion_analysis(G):
# Set maximum frequency to a threshold drop from maximum power, ignoring DC value
try:
freqthres = np.where(power[freqmaxpower:] < -numdispersion['highestfreqthres'])[0][0] + freqmaxpower
freqthres = np.where(power[freqmaxpower:] < -config.numdispersion['highestfreqthres'])[0][0] + freqmaxpower
results['maxfreq'].append(freqs[freqthres])
except ValueError:
results['error'] = 'unable to calculate maximum power from waveform, most likely due to undersampling.'
@@ -324,7 +315,7 @@ def dispersion_analysis(G):
er = x.er
# If there are dispersive materials calculate the complex relative permittivity
# at maximum frequency and take the real part
if x.poles > 0:
if x.__class__.__name__ is 'DispersiveMaterial':
er = x.calculate_er(results['maxfreq'])
er = er.real
if er > maxer:
@@ -333,7 +324,7 @@ def dispersion_analysis(G):
results['material'] = next(x for x in G.materials if x.ID == matmaxer)
# Minimum velocity
minvelocity = c / np.sqrt(maxer)
minvelocity = config.c / np.sqrt(maxer)
# Minimum wavelength
minwavelength = minvelocity / results['maxfreq']
@@ -350,18 +341,18 @@ def dispersion_analysis(G):
delta = max(G.dx, G.dy)
# Courant stability factor
S = (c * G.dt) / delta
S = (config.c * G.dt) / delta
# Grid sampling density
results['N'] = minwavelength / delta
# Check grid sampling will result in physical wave propagation
if int(np.floor(results['N'])) >= numdispersion['mingridsampling']:
if int(np.floor(results['N'])) >= config.numdispersion['mingridsampling']:
# Numerical phase velocity
vp = np.pi / (results['N'] * np.arcsin((1 / S) * np.sin((np.pi * S) / results['N'])))
# Physical phase velocity error (percentage)
results['deltavp'] = (((vp * c) - c) / c) * 100
results['deltavp'] = (((vp * config.c) - config.c) / config.c) * 100
# Store rounded down value of grid sampling density
results['N'] = int(np.floor(results['N']))
@@ -369,21 +360,6 @@ def dispersion_analysis(G):
return results
def get_other_directions(direction):
"""Return the two other directions from x, y, z given a single direction
Args:
direction (str): Component x, y or z
Returns:
(tuple): Two directions from x, y, z
"""
directions = {'x': ('y', 'z'), 'y': ('x', 'z'), 'z': ('x', 'y')}
return directions[direction]
def Ix(x, y, z, Hx, Hy, Hz, G):
"""Calculates the x-component of current at a grid position.

查看文件

@@ -20,7 +20,7 @@ import os
import sys
from io import StringIO
from gprMax.exceptions import CmdInputError
from .exceptions import CmdInputError
def process_python_include_code(inputfile, usernamespace):
@@ -151,7 +151,7 @@ def process_include_files(hashcmds, inputfile):
return processedincludecmds
def write_processed_file(processedlines, appendmodelnumber, G):
def write_processed_file(processedlines, appendmodelnumber):
"""
Writes an input file after any Python code and include commands
in the original input file have been processed.
@@ -160,10 +160,9 @@ def write_processed_file(processedlines, appendmodelnumber, G):
processedlines (list): Input commands after after processing any
Python code and include commands.
appendmodelnumber (str): Text to append to filename.
G (class): Grid class instance - holds essential parameters describing the model.
"""
processedfile = os.path.join(G.inputdirectory, os.path.splitext(G.inputfilename)[0] + appendmodelnumber + '_processed.in')
processedfile = os.path.join(outputfilepath, os.path.splitext(inputfilepath)[0] + appendmodelnumber + '_processed.in')
with open(processedfile, 'w') as f:
for item in processedlines:

查看文件

@@ -23,31 +23,30 @@ import h5py
import numpy as np
from tqdm import tqdm
from gprMax.config import floattype
from gprMax.config import messages
from gprMax.config import progressbars
from gprMax.input_cmds_file import check_cmd_names
from gprMax.input_cmds_multiuse import process_multicmds
from gprMax.exceptions import CmdInputError
from gprMax.fractals import FractalSurface
from gprMax.fractals import FractalVolume
from gprMax.fractals import Grass
from gprMax.cython.geometry_primitives import build_edge_x
from gprMax.cython.geometry_primitives import build_edge_y
from gprMax.cython.geometry_primitives import build_edge_z
from gprMax.cython.geometry_primitives import build_face_yz
from gprMax.cython.geometry_primitives import build_face_xz
from gprMax.cython.geometry_primitives import build_face_xy
from gprMax.cython.geometry_primitives import build_triangle
from gprMax.cython.geometry_primitives import build_box
from gprMax.cython.geometry_primitives import build_cylinder
from gprMax.cython.geometry_primitives import build_cylindrical_sector
from gprMax.cython.geometry_primitives import build_sphere
from gprMax.cython.geometry_primitives import build_voxels_from_array
from gprMax.cython.geometry_primitives import build_voxels_from_array_mask
from gprMax.materials import Material
from gprMax.utilities import round_value
from gprMax.utilities import get_terminal_width
import gprMax.config as config
from .input_cmds_file import check_cmd_names
from .input_cmds_multiuse import process_multicmds
from .exceptions import CmdInputError
from .fractals import FractalSurface
from .fractals import FractalVolume
from .fractals import Grass
from .cython.geometry_primitives import build_edge_x
from .cython.geometry_primitives import build_edge_y
from .cython.geometry_primitives import build_edge_z
from .cython.geometry_primitives import build_face_yz
from .cython.geometry_primitives import build_face_xz
from .cython.geometry_primitives import build_face_xy
from .cython.geometry_primitives import build_triangle
from .cython.geometry_primitives import build_box
from .cython.geometry_primitives import build_cylinder
from .cython.geometry_primitives import build_cylindrical_sector
from .cython.geometry_primitives import build_sphere
from .cython.geometry_primitives import build_voxels_from_array
from .cython.geometry_primitives import build_voxels_from_array_mask
from .materials import Material
from .utilities import round_value
from .utilities import get_terminal_width
def process_geometrycmds(geometry, G):
@@ -63,9 +62,9 @@ def process_geometrycmds(geometry, G):
# Disable progress bar if on Windows as it does not update properly
# when messages are printed for geometry
if sys.platform == 'win32':
progressbarsgeo = False
progressbarsgeo = True
else:
progressbarsgeo = not progressbars
progressbarsgeo = not config.general['progressbars']
for object in tqdm(geometry, desc='Processing geometry related cmds', unit='cmds', ncols=get_terminal_width() - 1, file=sys.stdout, disable=progressbarsgeo):
tmp = object.split()
@@ -137,12 +136,12 @@ def process_geometrycmds(geometry, G):
G.rigidE[:, xs:xs + rigidE.shape[1], ys:ys + rigidE.shape[2], zs:zs + rigidE.shape[3]] = rigidE
G.rigidH[:, xs:xs + rigidH.shape[1], ys:ys + rigidH.shape[2], zs:zs + rigidH.shape[3]] = rigidH
G.ID[:, xs:xs + ID.shape[1], ys:ys + ID.shape[2], zs:zs + ID.shape[3]] = ID + numexistmaterials
if messages:
if config.general['messages']:
tqdm.write('Geometry objects from file {} inserted at {:g}m, {:g}m, {:g}m, with corresponding materials file {}.'.format(geofile, xs * G.dx, ys * G.dy, zs * G.dz, matfile))
except KeyError:
averaging = False
build_voxels_from_array(xs, ys, zs, numexistmaterials, averaging, data, G.solid, G.rigidE, G.rigidH, G.ID)
if messages:
if config.general['messages']:
tqdm.write('Geometry objects from file (voxels only) {} inserted at {:g}m, {:g}m, {:g}m, with corresponding materials file {}.'.format(geofile, xs * G.dx, ys * G.dy, zs * G.dz, matfile))
elif tmp[0] == '#edge:':
@@ -201,7 +200,7 @@ def process_geometrycmds(geometry, G):
for k in range(zs, zf):
build_edge_z(xs, ys, k, material.numID, G.rigidE, G.rigidH, G.ID)
if messages:
if config.general['messages']:
tqdm.write('Edge from {:g}m, {:g}m, {:g}m, to {:g}m, {:g}m, {:g}m of material {} created.'.format(xs * G.dx, ys * G.dy, zs * G.dz, xf * G.dx, yf * G.dy, zf * G.dz, tmp[7]))
elif tmp[0] == '#plate:':
@@ -309,7 +308,7 @@ def process_geometrycmds(geometry, G):
for j in range(ys, yf):
build_face_xy(i, j, zs, numIDx, numIDy, G.rigidE, G.rigidH, G.ID)
if messages:
if config.general['messages']:
tqdm.write('Plate from {:g}m, {:g}m, {:g}m, to {:g}m, {:g}m, {:g}m of material(s) {} created.'.format(xs * G.dx, ys * G.dy, zs * G.dz, xf * G.dx, yf * G.dy, zf * G.dz, ', '.join(materialsrequested)))
elif tmp[0] == '#triangle:':
@@ -422,7 +421,7 @@ def process_geometrycmds(geometry, G):
build_triangle(x1, y1, z1, x2, y2, z2, x3, y3, z3, normal, thickness, G.dx, G.dy, G.dz, numID, numIDx, numIDy, numIDz, averaging, G.solid, G.rigidE, G.rigidH, G.ID)
if messages:
if config.general['messages']:
if thickness > 0:
if averaging:
dielectricsmoothing = 'on'
@@ -517,7 +516,7 @@ def process_geometrycmds(geometry, G):
build_box(xs, xf, ys, yf, zs, zf, numID, numIDx, numIDy, numIDz, averaging, G.solid, G.rigidE, G.rigidH, G.ID)
if messages:
if config.general['messages']:
if averaging:
dielectricsmoothing = 'on'
else:
@@ -598,7 +597,7 @@ def process_geometrycmds(geometry, G):
build_cylinder(x1, y1, z1, x2, y2, z2, r, G.dx, G.dy, G.dz, numID, numIDx, numIDy, numIDz, averaging, G.solid, G.rigidE, G.rigidH, G.ID)
if messages:
if config.general['messages']:
if averaging:
dielectricsmoothing = 'on'
else:
@@ -719,7 +718,7 @@ def process_geometrycmds(geometry, G):
build_cylindrical_sector(ctr1, ctr2, level, sectorstartangle, sectorangle, r, normal, thickness, G.dx, G.dy, G.dz, numID, numIDx, numIDy, numIDz, averaging, G.solid, G.rigidE, G.rigidH, G.ID)
if messages:
if config.general['messages']:
if thickness > 0:
if averaging:
dielectricsmoothing = 'on'
@@ -798,7 +797,7 @@ def process_geometrycmds(geometry, G):
build_sphere(xc, yc, zc, r, G.dx, G.dy, G.dz, numID, numIDx, numIDy, numIDz, averaging, G.solid, G.rigidE, G.rigidH, G.ID)
if messages:
if config.general['messages']:
if averaging:
dielectricsmoothing = 'on'
else:
@@ -879,7 +878,7 @@ def process_geometrycmds(geometry, G):
volume.weighting = np.array([float(tmp[8]), float(tmp[9]), float(tmp[10])])
volume.averaging = averagefractalbox
if messages:
if config.general['messages']:
if volume.averaging:
dielectricsmoothing = 'on'
else:
@@ -1002,7 +1001,7 @@ def process_geometrycmds(geometry, G):
surface.generate_fractal_surface(G)
volume.fractalsurfaces.append(surface)
if messages:
if config.general['messages']:
tqdm.write('Fractal surface from {:g}m, {:g}m, {:g}m, to {:g}m, {:g}m, {:g}m with fractal dimension {:g}, fractal weightings {:g}, {:g}, fractal seeding {}, and range {:g}m to {:g}m, added to {}.'.format(xs * G.dx, ys * G.dy, zs * G.dz, xf * G.dx, yf * G.dy, zf * G.dz, surface.dimension, surface.weighting[0], surface.weighting[1], surface.seed, float(tmp[10]), float(tmp[11]), surface.operatingonID))
if tmp[0] == '#add_surface_water:':
@@ -1110,7 +1109,7 @@ def process_geometrycmds(geometry, G):
if testwater:
raise CmdInputError("'" + ' '.join(tmp) + "'" + ' requires the time step for the model to be less than the relaxation time required to model water.')
if messages:
if config.general['messages']:
tqdm.write('Water on surface from {:g}m, {:g}m, {:g}m, to {:g}m, {:g}m, {:g}m with depth {:g}m, added to {}.'.format(xs * G.dx, ys * G.dy, zs * G.dz, xf * G.dx, yf * G.dy, zf * G.dz, filldepth, surface.operatingonID))
if tmp[0] == '#add_grass:':
@@ -1260,7 +1259,7 @@ def process_geometrycmds(geometry, G):
volume.fractalsurfaces.append(surface)
if messages:
if config.general['messages']:
tqdm.write('{} blades of grass on surface from {:g}m, {:g}m, {:g}m, to {:g}m, {:g}m, {:g}m with fractal dimension {:g}, fractal seeding {}, and range {:g}m to {:g}m, added to {}.'.format(numblades, xs * G.dx, ys * G.dy, zs * G.dz, xf * G.dx, yf * G.dy, zf * G.dz, surface.dimension, surface.seed, float(tmp[8]), float(tmp[9]), surface.operatingonID))
# Process any modifications to the original fractal box then generate it
@@ -1301,7 +1300,7 @@ def process_geometrycmds(geometry, G):
# If there is only 1 bin then a normal material is being used, otherwise a mixing model
if volume.nbins == 1:
volume.fractalvolume = np.ones((volume.nx, volume.ny, volume.nz), dtype=floattype)
volume.fractalvolume = np.ones((volume.nx, volume.ny, volume.nz), dtype=config.dtypes['float_or_double'])
materialnumID = next(x.numID for x in G.materials if x.ID == volume.operatingonID)
volume.fractalvolume *= materialnumID
else:

查看文件

@@ -20,30 +20,27 @@ from colorama import init
from colorama import Fore
from colorama import Style
init()
from copy import deepcopy
import numpy as np
from tqdm import tqdm
import gprMax.config as config
from gprMax.config import z0
from gprMax.config import floattype
from gprMax.config import gpus
from gprMax.config import messages
from gprMax.exceptions import CmdInputError
from gprMax.geometry_outputs import GeometryView
from gprMax.geometry_outputs import GeometryObjects
from gprMax.materials import Material
from gprMax.materials import PeplinskiSoil
from gprMax.pml import CFSParameter
from gprMax.pml import CFS
from gprMax.receivers import Rx
from gprMax.snapshots import Snapshot
from gprMax.sources import VoltageSource
from gprMax.sources import HertzianDipole
from gprMax.sources import MagneticDipole
from gprMax.sources import TransmissionLine
from gprMax.utilities import round_value
from gprMax.waveforms import Waveform
from .exceptions import CmdInputError
from .geometry_outputs import GeometryView
from .geometry_outputs import GeometryObjects
from .materials import DispersiveMaterial
from .materials import Material
from .materials import PeplinskiSoil
from .pml import CFSParameter
from .pml import CFS
from .receivers import Rx
from .snapshots import Snapshot
from .sources import VoltageSource
from .sources import HertzianDipole
from .sources import MagneticDipole
from .sources import TransmissionLine
from .utilities import round_value
from .waveforms import Waveform
def process_multicmds(multicmds, G):
@@ -84,7 +81,7 @@ def process_multicmds(multicmds, G):
w.amp = float(tmp[1])
w.freq = float(tmp[2])
if messages:
if config.general['messages']:
print('Waveform {} of type {} with maximum amplitude scaling {:g}, frequency {:g}Hz created.'.format(w.ID, w.type, w.amp, w.freq))
G.waveforms.append(w)
@@ -155,7 +152,7 @@ def process_multicmds(multicmds, G):
v.calculate_waveform_values(G)
if messages:
if config.general['messages']:
print('Voltage source with polarity {} at {:g}m, {:g}m, {:g}m, resistance {:.1f} Ohms,'.format(v.polarisation, v.xcoord * G.dx, v.ycoord * G.dy, v.zcoord * G.dz, v.resistance) + startstop + 'using waveform {} created.'.format(v.waveformID))
G.voltagesources.append(v)
@@ -233,7 +230,7 @@ def process_multicmds(multicmds, G):
h.calculate_waveform_values(G)
if messages:
if config.general['messages']:
if '2D' in config.mode:
print('Hertzian dipole is a line source in 2D with polarity {} at {:g}m, {:g}m, {:g}m,'.format(h.polarisation, h.xcoord * G.dx, h.ycoord * G.dy, h.zcoord * G.dz) + startstop + 'using waveform {} created.'.format(h.waveformID))
else:
@@ -305,7 +302,7 @@ def process_multicmds(multicmds, G):
m.calculate_waveform_values(G)
if messages:
if config.general['messages']:
print('Magnetic dipole with polarity {} at {:g}m, {:g}m, {:g}m,'.format(m.polarisation, m.xcoord * G.dx, m.ycoord * G.dy, m.zcoord * G.dz) + startstop + 'using waveform {} created.'.format(m.waveformID))
G.magneticdipoles.append(m)
@@ -341,7 +338,7 @@ def process_multicmds(multicmds, G):
check_coordinates(xcoord, ycoord, zcoord)
if xcoord < G.pmlthickness['x0'] or xcoord > G.nx - G.pmlthickness['xmax'] or ycoord < G.pmlthickness['y0'] or ycoord > G.ny - G.pmlthickness['ymax'] or zcoord < G.pmlthickness['z0'] or zcoord > G.nz - G.pmlthickness['zmax']:
print(Fore.RED + "WARNING: '" + cmdname + ': ' + ' '.join(tmp) + "'" + ' sources and receivers should not normally be positioned within the PML.' + Style.RESET_ALL)
if resistance <= 0 or resistance >= z0:
if resistance <= 0 or resistance >= config.z0:
raise CmdInputError("'" + cmdname + ': ' + ' '.join(tmp) + "'" + ' requires a resistance greater than zero and less than the impedance of free space, i.e. 376.73 Ohms')
# Check if there is a waveformID in the waveforms list
@@ -381,7 +378,7 @@ def process_multicmds(multicmds, G):
t.calculate_waveform_values(G)
t.calculate_incident_V_I(G)
if messages:
if config.general['messages']:
print('Transmission line with polarity {} at {:g}m, {:g}m, {:g}m, resistance {:.1f} Ohms,'.format(t.polarisation, t.xcoord * G.dx, t.ycoord * G.dy, t.zcoord * G.dz, t.resistance) + startstop + 'using waveform {} created.'.format(t.waveformID))
G.transmissionlines.append(t)
@@ -413,23 +410,30 @@ def process_multicmds(multicmds, G):
# If no ID or outputs are specified, use default
if len(tmp) == 3:
r.ID = r.__class__.__name__ + '(' + str(r.xcoord) + ',' + str(r.ycoord) + ',' + str(r.zcoord) + ')'
for key in Rx.defaultoutputs:
r.outputs[key] = np.zeros(G.iterations, dtype=floattype)
r.outputs[key] = np.zeros(G.iterations, dtype=config.dtypes['float_or_double'])
else:
r.ID = tmp[3]
# Get allowable outputs
if gpus is not None:
if config.cuda['gpus'] is not None:
allowableoutputs = Rx.gpu_allowableoutputs
else:
allowableoutputs = Rx.allowableoutputs
# Check and add field output names
for field in tmp[4::]:
# Check, sort and add field output names
fieldnames = tmp[4::]
fieldnames = sorted(fieldnames, key=lambda x: allowableoutputs.index(x))
for field in fieldnames:
if field in allowableoutputs:
r.outputs[field] = np.zeros(G.iterations, dtype=floattype)
r.outputs[field] = np.zeros(G.iterations, dtype=config.dtypes['float_or_double'])
else:
raise CmdInputError("'" + cmdname + ': ' + ' '.join(tmp) + "'" + ' contains an output type that is not allowable. Allowable outputs in current context are {}'.format(allowableoutputs))
if messages:
# Keep track of maximum number of field outputs on a receiver
if len(r.outputs) > Rx.maxnumoutputs:
Rx.maxnumoutputs = len(r.outputs)
if config.general['messages']:
print('Receiver at {:g}m, {:g}m, {:g}m with output component(s) {} created.'.format(r.xcoord * G.dx, r.ycoord * G.dy, r.zcoord * G.dz, ', '.join(r.outputs)))
G.rxs.append(r)
@@ -479,7 +483,7 @@ def process_multicmds(multicmds, G):
else:
raise CmdInputError("'" + cmdname + ': ' + ' '.join(tmp) + "'" + ' the step size should not be less than the spatial discretisation')
if messages:
if config.general['messages']:
print('Receiver array {:g}m, {:g}m, {:g}m, to {:g}m, {:g}m, {:g}m with steps {:g}m, {:g}m, {:g}m'.format(xs * G.dx, ys * G.dy, zs * G.dz, xf * G.dx, yf * G.dy, zf * G.dz, dx * G.dx, dy * G.dy, dz * G.dz))
for x in range(xs, xf + 1, dx):
@@ -494,8 +498,8 @@ def process_multicmds(multicmds, G):
r.zcoordorigin = z
r.ID = r.__class__.__name__ + '(' + str(x) + ',' + str(y) + ',' + str(z) + ')'
for key in Rx.defaultoutputs:
r.outputs[key] = np.zeros(G.iterations, dtype=floattype)
if messages:
r.outputs[key] = np.zeros(G.iterations, dtype=config.dtypes['float_or_double'])
if config.general['messages']:
print(' Receiver at {:g}m, {:g}m, {:g}m with output component(s) {} created.'.format(r.xcoord * G.dx, r.ycoord * G.dy, r.zcoord * G.dz, ', '.join(r.outputs)))
G.rxs.append(r)
@@ -544,7 +548,7 @@ def process_multicmds(multicmds, G):
s = Snapshot(xs, ys, zs, xf, yf, zf, dx, dy, dz, time, tmp[10])
if messages:
if config.general['messages']:
print('Snapshot from {:g}m, {:g}m, {:g}m, to {:g}m, {:g}m, {:g}m, discretisation {:g}m, {:g}m, {:g}m, at {:g} secs with filename {} created.'.format(xs * G.dx, ys * G.dy, zs * G.dz, xf * G.dx, yf * G.dy, zf * G.dz, dx * G.dx, dy * G.dy, dz * G.dz, s.time * G.dt, s.basefilename))
G.snapshots.append(s)
@@ -582,7 +586,7 @@ def process_multicmds(multicmds, G):
if m.se == float('inf'):
m.averagable = False
if messages:
if config.general['messages']:
tqdm.write('Material {} with eps_r={:g}, sigma={:g} S/m; mu_r={:g}, sigma*={:g} Ohm/m created.'.format(m.ID, m.er, m.se, m.mr, m.sm))
# Append the new material object to the materials list
@@ -608,21 +612,25 @@ def process_multicmds(multicmds, G):
raise CmdInputError("'" + cmdname + ': ' + ' '.join(tmp) + "'" + ' material(s) {} do not exist'.format(notfound))
for material in materials:
material.type = 'debye'
material.poles = poles
material.averagable = False
dispersivemat = DispersiveMaterial(material.numID, material.ID)
dispersivemat.type = 'debye'
dispersivemat.poles = poles
dispersivemat.averagable = False
for pole in range(1, 2 * poles, 2):
# N.B Not checking if relaxation times are greater than time-step
if float(tmp[pole]) > 0:
material.deltaer.append(float(tmp[pole]))
material.tau.append(float(tmp[pole + 1]))
dispersivemat.deltaer.append(float(tmp[pole]))
dispersivemat.tau.append(float(tmp[pole + 1]))
else:
raise CmdInputError("'" + cmdname + ': ' + ' '.join(tmp) + "'" + ' requires positive values for the permittivity difference.')
if material.poles > Material.maxpoles:
Material.maxpoles = material.poles
if dispersivemat.poles > config.materials['maxpoles']:
config.materials['maxpoles'] = dispersivemat.poles
if messages:
tqdm.write('Debye disperion added to {} with delta_eps_r={}, and tau={} secs created.'.format(material.ID, ', '.join('%4.2f' % deltaer for deltaer in material.deltaer), ', '.join('%4.3e' % tau for tau in material.tau)))
# Replace original (non-dispersive) material with new dispersive instance
G.materials[material.numID] = dispersivemat
if config.general['messages']:
tqdm.write('Debye disperion added to {} with delta_eps_r={}, and tau={} secs created.'.format(dispersivemat.ID, ', '.join('%4.2f' % deltaer for deltaer in dispersivemat.deltaer), ', '.join('%4.3e' % tau for tau in dispersivemat.tau)))
cmdname = '#add_dispersion_lorentz'
if multicmds[cmdname] is not None:
@@ -654,10 +662,10 @@ def process_multicmds(multicmds, G):
material.alpha.append(float(tmp[pole + 2]))
else:
raise CmdInputError("'" + cmdname + ': ' + ' '.join(tmp) + "'" + ' requires positive values for the permittivity difference and frequencies, and associated times that are greater than the time step for the model.')
if material.poles > Material.maxpoles:
Material.maxpoles = material.poles
if material.poles > config.materials['maxpoles']:
config.materials['maxpoles'] = material.poles
if messages:
if config.general['messages']:
tqdm.write('Lorentz disperion added to {} with delta_eps_r={}, omega={} secs, and gamma={} created.'.format(material.ID, ', '.join('%4.2f' % deltaer for deltaer in material.deltaer), ', '.join('%4.3e' % tau for tau in material.tau), ', '.join('%4.3e' % alpha for alpha in material.alpha)))
cmdname = '#add_dispersion_drude'
@@ -689,10 +697,10 @@ def process_multicmds(multicmds, G):
material.alpha.append(float(tmp[pole + 1]))
else:
raise CmdInputError("'" + cmdname + ': ' + ' '.join(tmp) + "'" + ' requires positive values for the frequencies, and associated times that are greater than the time step for the model.')
if material.poles > Material.maxpoles:
Material.maxpoles = material.poles
if material.poles > config.materials['maxpoles']:
config.materials['maxpoles'] = material.poles
if messages:
if config.general['messages']:
tqdm.write('Drude disperion added to {} with omega={} secs, and gamma={} secs created.'.format(material.ID, ', '.join('%4.3e' % tau for tau in material.tau), ', '.join('%4.3e' % alpha for alpha in material.alpha)))
cmdname = '#soil_peplinski'
@@ -719,7 +727,7 @@ def process_multicmds(multicmds, G):
# Create a new instance of the Material class material (start index after pec & free_space)
s = PeplinskiSoil(tmp[6], float(tmp[0]), float(tmp[1]), float(tmp[2]), float(tmp[3]), (float(tmp[4]), float(tmp[5])))
if messages:
if config.general['messages']:
print('Mixing model (Peplinski) used to create {} with sand fraction {:g}, clay fraction {:g}, bulk density {:g}g/cm3, sand particle density {:g}g/cm3, and water volumetric fraction {:g} to {:g} created.'.format(s.ID, s.S, s.C, s.rb, s.rs, s.mu[0], s.mu[1]))
# Append the new material object to the materials list
@@ -769,7 +777,7 @@ def process_multicmds(multicmds, G):
g = GeometryView(xs, ys, zs, xf, yf, zf, dx, dy, dz, tmp[9], fileext)
if messages:
if config.general['messages']:
print('Geometry view from {:g}m, {:g}m, {:g}m, to {:g}m, {:g}m, {:g}m, discretisation {:g}m, {:g}m, {:g}m, with filename base {} created.'.format(xs * G.dx, ys * G.dy, zs * G.dz, xf * G.dx, yf * G.dy, zf * G.dz, dx * G.dx, dy * G.dy, dz * G.dz, g.basefilename))
# Append the new GeometryView object to the geometry views list
@@ -799,7 +807,7 @@ def process_multicmds(multicmds, G):
g = GeometryObjects(xs, ys, zs, xf, yf, zf, tmp[6])
if messages:
if config.general['messages']:
print('Geometry objects in the volume from {:g}m, {:g}m, {:g}m, to {:g}m, {:g}m, {:g}m, will be written to {}, with materials written to {}'.format(xs * G.dx, ys * G.dy, zs * G.dz, xf * G.dx, yf * G.dy, zf * G.dz, g.filename, g.materialsfilename))
# Append the new GeometryView object to the geometry objects to write list
@@ -849,7 +857,7 @@ def process_multicmds(multicmds, G):
cfs.kappa = cfskappa
cfs.sigma = cfssigma
if messages:
if config.general['messages']:
print('PML CFS parameters: alpha (scaling: {}, scaling direction: {}, min: {:g}, max: {:g}), kappa (scaling: {}, scaling direction: {}, min: {:g}, max: {:g}), sigma (scaling: {}, scaling direction: {}, min: {:g}, max: {}) created.'.format(cfsalpha.scalingprofile, cfsalpha.scalingdirection, cfsalpha.min, cfsalpha.max, cfskappa.scalingprofile, cfskappa.scalingdirection, cfskappa.min, cfskappa.max, cfssigma.scalingprofile, cfssigma.scalingdirection, cfssigma.min, cfssigma.max))
G.cfs.append(cfs)

查看文件

@@ -29,16 +29,12 @@ import numpy as np
from scipy import interpolate
import gprMax.config as config
from gprMax.config import c
from gprMax.config import floattype
from gprMax.config import gpus as gpu
from gprMax.config import hostinfo
from gprMax.exceptions import CmdInputError
from gprMax.exceptions import GeneralError
from gprMax.pml import PML
from gprMax.utilities import human_size
from gprMax.utilities import round_value
from gprMax.waveforms import Waveform
from .exceptions import CmdInputError
from .exceptions import GeneralError
from .pml import PML
from .utilities import human_size
from .utilities import round_value
from .waveforms import Waveform
def process_singlecmds(singlecmds, G):
@@ -57,9 +53,9 @@ def process_singlecmds(singlecmds, G):
if len(tmp) != 1:
raise CmdInputError(cmd + ' requires exactly one parameter')
if singlecmds[cmd].lower() == 'y':
config.messages = True
config.general['messages'] = True
elif singlecmds[cmd].lower() == 'n':
config.messages = False
config.general['messages'] = False
else:
raise CmdInputError(cmd + ' requires input values of either y or n')
@@ -73,7 +69,7 @@ def process_singlecmds(singlecmds, G):
# os.environ['OMP_DISPLAY_ENV'] = 'TRUE' # Prints OMP version and environment variables (useful for debug)
# Catch bug with Windows Subsystem for Linux (https://github.com/Microsoft/BashOnWindows/issues/785)
if 'Microsoft' in hostinfo['osversion']:
if 'Microsoft' in config.hostinfo['osversion']:
os.environ['KMP_AFFINITY'] = 'disabled'
del os.environ['OMP_PLACES']
del os.environ['OMP_PROC_BIND']
@@ -90,28 +86,28 @@ def process_singlecmds(singlecmds, G):
config.hostinfo['ompthreads'] = int(os.environ.get('OMP_NUM_THREADS'))
else:
# Set number of threads to number of physical CPU cores
config.hostinfo['ompthreads'] = hostinfo['physicalcores']
config.hostinfo['ompthreads'] = config.hostinfo['physicalcores']
os.environ['OMP_NUM_THREADS'] = str(config.hostinfo['ompthreads'])
if config.messages:
if config.general['messages']:
print('CPU (OpenMP) threads: {}'.format(config.hostinfo['ompthreads']))
if config.hostinfo['ompthreads'] > hostinfo['physicalcores']:
print(Fore.RED + 'WARNING: You have specified more threads ({}) than available physical CPU cores ({}). This may lead to degraded performance.'.format(config.hostinfo['ompthreads'], hostinfo['physicalcores']) + Style.RESET_ALL)
if config.hostinfo['ompthreads'] > config.hostinfo['physicalcores']:
print(Fore.RED + 'WARNING: You have specified more threads ({}) than available physical CPU cores ({}). This may lead to degraded performance.'.format(config.hostinfo['ompthreads'], config.hostinfo['physicalcores']) + Style.RESET_ALL)
# Print information about any GPU in use
if config.messages:
if gpu is not None:
print('GPU: {} - {}'.format(gpu.deviceID, gpu.name))
if config.general['messages']:
if config.cuda['gpus'] is not None:
print('GPU: {} - {}'.format(config.cuda['gpus'].deviceID, config.cuda['gpus'].name))
# Print information about precision of main field values
if config.messages:
print('Output data type: {}\n'.format(np.dtype(floattype).name))
if config.general['messages']:
print('Output data type: {}\n'.format(np.dtype(config.dtypes['float_or_double']).name))
# Title
cmd = '#title'
if singlecmds[cmd] is not None:
G.title = singlecmds[cmd]
if config.messages:
if config.general['messages']:
print('Model title: {}'.format(G.title))
# Spatial discretisation
@@ -128,7 +124,7 @@ def process_singlecmds(singlecmds, G):
G.dx = tmp[0]
G.dy = tmp[1]
G.dz = tmp[2]
if config.messages:
if config.general['messages']:
print('Spatial discretisation: {:g} x {:g} x {:g}m'.format(G.dx, G.dy, G.dz))
# Domain
@@ -141,34 +137,34 @@ def process_singlecmds(singlecmds, G):
G.nz = round_value(tmp[2] / G.dz)
if G.nx == 0 or G.ny == 0 or G.nz == 0:
raise CmdInputError(cmd + ' requires at least one cell in every dimension')
if config.messages:
if config.general['messages']:
print('Domain size: {:g} x {:g} x {:g}m ({:d} x {:d} x {:d} = {:g} cells)'.format(tmp[0], tmp[1], tmp[2], G.nx, G.ny, G.nz, (G.nx * G.ny * G.nz)))
# Time step CFL limit (either 2D or 3D); switch off appropriate PMLs for 2D
if G.nx == 1:
G.dt = 1 / (c * np.sqrt((1 / G.dy) * (1 / G.dy) + (1 / G.dz) * (1 / G.dz)))
G.dt = 1 / (config.c * np.sqrt((1 / G.dy) * (1 / G.dy) + (1 / G.dz) * (1 / G.dz)))
config.mode = '2D TMx'
G.pmlthickness['x0'] = 0
G.pmlthickness['xmax'] = 0
elif G.ny == 1:
G.dt = 1 / (c * np.sqrt((1 / G.dx) * (1 / G.dx) + (1 / G.dz) * (1 / G.dz)))
G.dt = 1 / (config.c * np.sqrt((1 / G.dx) * (1 / G.dx) + (1 / G.dz) * (1 / G.dz)))
config.mode = '2D TMy'
G.pmlthickness['y0'] = 0
G.pmlthickness['ymax'] = 0
elif G.nz == 1:
G.dt = 1 / (c * np.sqrt((1 / G.dx) * (1 / G.dx) + (1 / G.dy) * (1 / G.dy)))
G.dt = 1 / (config.c * np.sqrt((1 / G.dx) * (1 / G.dx) + (1 / G.dy) * (1 / G.dy)))
config.mode = '2D TMz'
G.pmlthickness['z0'] = 0
G.pmlthickness['zmax'] = 0
else:
G.dt = 1 / (c * np.sqrt((1 / G.dx) * (1 / G.dx) + (1 / G.dy) * (1 / G.dy) + (1 / G.dz) * (1 / G.dz)))
G.dt = 1 / (config.c * np.sqrt((1 / G.dx) * (1 / G.dx) + (1 / G.dy) * (1 / G.dy) + (1 / G.dz) * (1 / G.dz)))
config.mode = '3D'
# Round down time step to nearest float with precision one less than hardware maximum.
# Avoids inadvertently exceeding the CFL due to binary representation of floating point number.
G.dt = round_value(G.dt, decimalplaces=d.getcontext().prec - 1)
if config.messages:
if config.general['messages']:
print('Mode: {}'.format(config.mode))
print('Time step (at CFL limit): {:g} secs'.format(G.dt))
@@ -181,7 +177,7 @@ def process_singlecmds(singlecmds, G):
if tmp[0] <= 0 or tmp[0] > 1:
raise CmdInputError(cmd + ' requires the value of the time step stability factor to be between zero and one')
G.dt = G.dt * tmp[0]
if config.messages:
if config.general['messages']:
print('Time step (modified): {:g} secs'.format(G.dt))
# Time window
@@ -206,7 +202,7 @@ def process_singlecmds(singlecmds, G):
G.iterations = int(np.ceil(tmp / G.dt)) + 1
else:
raise CmdInputError(cmd + ' must have a value greater than zero')
if config.messages:
if config.general['messages']:
print('Time window: {:g} secs ({} iterations)'.format(G.timewindow, G.iterations))
# PML cells
@@ -248,7 +244,7 @@ def process_singlecmds(singlecmds, G):
G.srcsteps[0] = round_value(float(tmp[0]) / G.dx)
G.srcsteps[1] = round_value(float(tmp[1]) / G.dy)
G.srcsteps[2] = round_value(float(tmp[2]) / G.dz)
if config.messages:
if config.general['messages']:
print('Simple sources will step {:g}m, {:g}m, {:g}m for each model run.'.format(G.srcsteps[0] * G.dx, G.srcsteps[1] * G.dy, G.srcsteps[2] * G.dz))
# rx_steps
@@ -260,7 +256,7 @@ def process_singlecmds(singlecmds, G):
G.rxsteps[0] = round_value(float(tmp[0]) / G.dx)
G.rxsteps[1] = round_value(float(tmp[1]) / G.dy)
G.rxsteps[2] = round_value(float(tmp[2]) / G.dz)
if config.messages:
if config.general['messages']:
print('All receivers will step {:g}m, {:g}m, {:g}m for each model run.'.format(G.rxsteps[0] * G.dx, G.rxsteps[1] * G.dy, G.rxsteps[2] * G.dz))
# Excitation file for user-defined source waveforms
@@ -284,7 +280,7 @@ def process_singlecmds(singlecmds, G):
if not os.path.isfile(excitationfile):
excitationfile = os.path.abspath(os.path.join(G.inputdirectory, excitationfile))
if config.messages:
if config.general['messages']:
print('\nExcitation file: {}'.format(excitationfile))
# Get waveform names
@@ -292,7 +288,7 @@ def process_singlecmds(singlecmds, G):
waveformIDs = f.readline().split()
# Read all waveform values into an array
waveformvalues = np.loadtxt(excitationfile, skiprows=1, dtype=floattype)
waveformvalues = np.loadtxt(excitationfile, skiprows=1, dtype=config.dtypes['float_or_double'])
# Time array (if specified) for interpolation, otherwise use simulation time
if waveformIDs[0].lower() == 'time':
@@ -326,7 +322,7 @@ def process_singlecmds(singlecmds, G):
# Interpolate waveform values
w.userfunc = interpolate.interp1d(waveformtime, singlewaveformvalues, **kwargs)
if config.messages:
if config.general['messages']:
print('User waveform {} created using {} and, if required, interpolation parameters (kind: {}, fill value: {}).'.format(w.ID, timestr, kwargs['kind'], kwargs['fill_value']))
G.waveforms.append(w)
@@ -334,5 +330,7 @@ def process_singlecmds(singlecmds, G):
# Set the output directory
cmd = '#output_dir'
if singlecmds[cmd] is not None:
outputdir = singlecmds[cmd]
G.outputdirectory = outputdir
config.outputfilepath = singlecmds[cmd]
if config.general['messages']:
print('Output directory: {}'.format(config.outputfilepath))

查看文件

@@ -18,28 +18,13 @@
import numpy as np
from gprMax.config import e0
from gprMax.config import m0
from gprMax.config import complextype
import gprMax.config as config
class Material(object):
"""Materials, their properties and update coefficients."""
# Maximum number of dispersive material poles in a model
maxpoles = 0
# Properties of water from: http://dx.doi.org/10.1109/TGRS.2006.873208
waterer = 80.1
watereri = 4.9
waterdeltaer = waterer - watereri
watertau = 9.231e-12
# Properties of grass from: http://dx.doi.org/10.1007/BF00902994
grasser = 18.5087
grasseri = 12.7174
grassdeltaer = grasser - grasseri
grasstau = 1.0793e-11
"""Super-class to describe generic, non-dispersive materials,
their properties and update coefficients.
"""
def __init__(self, numID, ID):
"""
@@ -60,21 +45,16 @@ class Material(object):
self.mr = 1.0
self.sm = 0.0
# Parameters for dispersive materials
self.poles = 0
self.deltaer = []
self.tau = []
self.alpha = []
def calculate_update_coeffsH(self, G):
"""Calculates the magnetic update coefficients of the material.
Args:
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
"""
HA = (m0 * self.mr / G.dt) + 0.5 * self.sm
HB = (m0 * self.mr / G.dt) - 0.5 * self.sm
HA = (config.m0 * self.mr / G.dt) + 0.5 * self.sm
HB = (config.m0 * self.mr / G.dt) - 0.5 * self.sm
self.DA = HB / HA
self.DBx = (1 / G.dx) * 1 / HA
self.DBy = (1 / G.dy) * 1 / HA
@@ -86,48 +66,11 @@ class Material(object):
Args:
G (class): Grid class instance - holds essential parameters
describing the model.
describing the model.
"""
# The implementation of the dispersive material modelling comes from the
# derivation in: http://dx.doi.org/10.1109/TAP.2014.2308549
if self.maxpoles > 0:
self.w = np.zeros(self.maxpoles, dtype=complextype)
self.q = np.zeros(self.maxpoles, dtype=complextype)
self.zt = np.zeros(self.maxpoles, dtype=complextype)
self.zt2 = np.zeros(self.maxpoles, dtype=complextype)
self.eqt = np.zeros(self.maxpoles, dtype=complextype)
self.eqt2 = np.zeros(self.maxpoles, dtype=complextype)
for x in range(self.poles):
if 'debye' in self.type:
self.w[x] = self.deltaer[x] / self.tau[x]
self.q[x] = -1 / self.tau[x]
elif 'lorentz' in self.type:
# tau for Lorentz materials are pole frequencies
# alpha for Lorentz materials are the damping coefficients
wp2 = (2 * np.pi * self.tau[x])**2
self.w[x] = -1j * ((wp2 * self.deltaer[x]) / np.sqrt(wp2 - self.alpha[x]**2))
self.q[x] = -self.alpha[x] + (1j * np.sqrt(wp2 - self.alpha[x]**2))
elif 'drude' in self.type:
# tau for Drude materials are pole frequencies
# alpha for Drude materials are the inverse of relaxation times
wp2 = (2 * np.pi * self.tau[x])**2
self.se += wp2 / self.alpha[x]
self.w[x] = - (wp2 / self.alpha[x])
self.q[x] = - self.alpha[x]
self.eqt[x] = np.exp(self.q[x] * G.dt)
self.eqt2[x] = np.exp(self.q[x] * (G.dt / 2))
self.zt[x] = (self.w[x] / self.q[x]) * (1 - self.eqt[x]) / G.dt
self.zt2[x] = (self.w[x] / self.q[x]) * (1 - self.eqt2[x])
EA = (e0 * self.er / G.dt) + 0.5 * self.se - (e0 / G.dt) * np.sum(self.zt2.real)
EB = (e0 * self.er / G.dt) - 0.5 * self.se - (e0 / G.dt) * np.sum(self.zt2.real)
else:
EA = (e0 * self.er / G.dt) + 0.5 * self.se
EB = (e0 * self.er / G.dt) - 0.5 * self.se
EA = (config.e0 * self.er / G.dt) + 0.5 * self.se
EB = (config.e0 * self.er / G.dt) - 0.5 * self.se
if self.ID == 'pec' or self.se == float('inf'):
self.CA = 0
@@ -143,11 +86,100 @@ class Material(object):
self.srce = 1 / EA
def calculate_er(self, freq):
"""
Calculates the complex relative permittivity of the material at a specific frequency.
"""Calculates the complex relative permittivity of the material at a
specific frequency.
Args:
freq (float): Frequency used to calculate complex relative permittivity.
freq (float): Frequency used to calculate complex relative
permittivity.
Returns:
er (float): Complex relative permittivity.
"""
return self.er
class DispersiveMaterial(Material):
"""Class to describe materials with frequency dependent properties, e.g.
Debye, Drude, Lorenz
"""
# Properties of water from: http://dx.doi.org/10.1109/TGRS.2006.873208
waterer = 80.1
watereri = 4.9
waterdeltaer = waterer - watereri
watertau = 9.231e-12
# Properties of grass from: http://dx.doi.org/10.1007/BF00902994
grasser = 18.5087
grasseri = 12.7174
grassdeltaer = grasser - grasseri
grasstau = 1.0793e-11
def __init__(self, numID, ID):
super().__init__(numID, ID)
self.poles = 0
self.deltaer = []
self.tau = []
self.alpha = []
def calculate_update_coeffsE(self, G):
"""Calculates the electric update coefficients of the material.
Args:
G (class): Grid class instance - holds essential parameters
describing the model.
"""
# The implementation of the dispersive material modelling comes from the
# derivation in: http://dx.doi.org/10.1109/TAP.2014.2308549
self.w = np.zeros(config.materials['maxpoles'], dtype=config.materials['dispersivedtype'])
self.q = np.zeros(config.materials['maxpoles'], dtype=config.materials['dispersivedtype'])
self.zt = np.zeros(config.materials['maxpoles'], dtype=config.materials['dispersivedtype'])
self.zt2 = np.zeros(config.materials['maxpoles'], dtype=config.materials['dispersivedtype'])
self.eqt = np.zeros(config.materials['maxpoles'], dtype=config.materials['dispersivedtype'])
self.eqt2 = np.zeros(config.materials['maxpoles'], dtype=config.materials['dispersivedtype'])
for x in range(self.poles):
if 'debye' in self.type:
self.w[x] = self.deltaer[x] / self.tau[x]
self.q[x] = -1 / self.tau[x]
elif 'lorentz' in self.type:
# tau for Lorentz materials are pole frequencies
# alpha for Lorentz materials are the damping coefficients
wp2 = (2 * np.pi * self.tau[x])**2
self.w[x] = -1j * ((wp2 * self.deltaer[x]) / np.sqrt(wp2 - self.alpha[x]**2))
self.q[x] = -self.alpha[x] + (1j * np.sqrt(wp2 - self.alpha[x]**2))
elif 'drude' in self.type:
# tau for Drude materials are pole frequencies
# alpha for Drude materials are the inverse of relaxation times
wp2 = (2 * np.pi * self.tau[x])**2
self.se += wp2 / self.alpha[x]
self.w[x] = - (wp2 / self.alpha[x])
self.q[x] = - self.alpha[x]
self.eqt[x] = np.exp(self.q[x] * G.dt)
self.eqt2[x] = np.exp(self.q[x] * (G.dt / 2))
self.zt[x] = (self.w[x] / self.q[x]) * (1 - self.eqt[x]) / G.dt
self.zt2[x] = (self.w[x] / self.q[x]) * (1 - self.eqt2[x])
EA = (config.e0 * self.er / G.dt) + 0.5 * self.se - (config.e0 / G.dt) * np.sum(self.zt2.real)
EB = (config.e0 * self.er / G.dt) - 0.5 * self.se - (config.e0 / G.dt) * np.sum(self.zt2.real)
self.CA = EB / EA
self.CBx = (1 / G.dx) * 1 / EA
self.CBy = (1 / G.dy) * 1 / EA
self.CBz = (1 / G.dz) * 1 / EA
self.srce = 1 / EA
def calculate_er(self, freq):
"""Calculates the complex relative permittivity of the material at a
specific frequency.
Args:
freq (float): Frequency used to calculate complex relative
permittivity.
Returns:
er (float): Complex relative permittivity.
@@ -156,55 +188,60 @@ class Material(object):
# Permittivity at infinite frequency if the material is dispersive
er = self.er
if self.poles > 0:
w = 2 * np.pi * freq
er += self.se / (w * e0)
if 'debye' in self.type:
for pole in range(self.poles):
er += self.deltaer[pole] / (1 + 1j * w * self.tau[pole])
elif 'lorentz' in self.type:
for pole in range(self.poles):
er += (self.deltaer[pole] * self.tau[pole]**2) / (self.tau[pole]**2 + 2j * w * self.alpha[pole] - w**2)
elif 'drude' in self.type:
ersum = 0
for pole in range(self.poles):
ersum += self.tau[pole]**2 / (w**2 - 1j * w * self.alpha[pole])
er -= ersum
w = 2 * np.pi * freq
er += self.se / (w * config.e0)
if 'debye' in self.type:
for pole in range(self.poles):
er += self.deltaer[pole] / (1 + 1j * w * self.tau[pole])
elif 'lorentz' in self.type:
for pole in range(self.poles):
er += ((self.deltaer[pole] * self.tau[pole]**2)
/ (self.tau[pole]**2 + 2j * w * self.alpha[pole] - w**2))
elif 'drude' in self.type:
ersum = 0
for pole in range(self.poles):
ersum += self.tau[pole]**2 / (w**2 - 1j * w * self.alpha[pole])
er -= ersum
return er
def process_materials(G):
"""
Process complete list of materials - calculate update coefficients,
store in arrays, and build text list of materials/properties
"""Process complete list of materials - calculate update coefficients,
store in arrays, and build text list of materials/properties
Args:
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
Returns:
materialsdata (list): List of material IDs, names, and properties to print a table.
materialsdata (list): List of material IDs, names, and properties to
print a table.
"""
if Material.maxpoles == 0:
materialsdata = [['\nID', '\nName', '\nType', '\neps_r', 'sigma\n[S/m]', '\nmu_r', 'sigma*\n[Ohm/m]', 'Dielectric\nsmoothable']]
if config.materials['maxpoles'] == 0:
materialsdata = [['\nID', '\nName', '\nType', '\neps_r', 'sigma\n[S/m]',
'\nmu_r', 'sigma*\n[Ohm/m]', 'Dielectric\nsmoothable']]
else:
materialsdata = [['\nID', '\nName', '\nType', '\neps_r', 'sigma\n[S/m]', 'Delta\neps_r', 'tau\n[s]', 'omega\n[Hz]', 'delta\n[Hz]', 'gamma\n[Hz]', '\nmu_r', 'sigma*\n[Ohm/m]', 'Dielectric\nsmoothable']]
materialsdata = [['\nID', '\nName', '\nType', '\neps_r', 'sigma\n[S/m]',
'Delta\neps_r', 'tau\n[s]', 'omega\n[Hz]', 'delta\n[Hz]',
'gamma\n[Hz]', '\nmu_r', 'sigma*\n[Ohm/m]', 'Dielectric\nsmoothable']]
for material in G.materials:
# Calculate update coefficients for material
# Calculate update coefficients for specific material
material.calculate_update_coeffsE(G)
material.calculate_update_coeffsH(G)
# Store all update coefficients together
# Add update coefficients to overall storage for all materials
G.updatecoeffsE[material.numID, :] = material.CA, material.CBx, material.CBy, material.CBz, material.srce
G.updatecoeffsH[material.numID, :] = material.DA, material.DBx, material.DBy, material.DBz, material.srcm
# Store coefficients for any dispersive materials
if Material.maxpoles > 0:
# Add update coefficients to overall storage for dispersive materials
if hasattr(material, 'poles'):
z = 0
for pole in range(Material.maxpoles):
G.updatecoeffsdispersive[material.numID, z:z + 3] = e0 * material.eqt2[pole], material.eqt[pole], material.zt[pole]
for pole in range(config.materials['maxpoles']):
G.updatecoeffsdispersive[material.numID, z:z + 3] = (config.e0
* material.eqt2[pole], material.eqt[pole], material.zt[pole])
z += 3
# Construct information on material properties for printing table
@@ -214,7 +251,7 @@ def process_materials(G):
materialtext.append(material.type)
materialtext.append('{:g}'.format(material.er))
materialtext.append('{:g}'.format(material.se))
if Material.maxpoles > 0:
if config.materials['maxpoles'] > 0:
if 'debye' in material.type:
materialtext.append('\n'.join('{:g}'.format(deltaer) for deltaer in material.deltaer))
materialtext.append('\n'.join('{:g}'.format(tau) for tau in material.tau))
@@ -242,9 +279,8 @@ def process_materials(G):
class PeplinskiSoil(object):
"""
Soil objects that are characterised according to a mixing
model by Peplinski (http://dx.doi.org/10.1109/36.387598).
"""Soil objects that are characterised according to a mixing model
by Peplinski (http://dx.doi.org/10.1109/36.387598).
"""
def __init__(self, ID, sandfraction, clayfraction, bulkdensity, sandpartdensity, watervolfraction):
@@ -254,8 +290,10 @@ class PeplinskiSoil(object):
sandfraction (float): Sand fraction of the soil.
clayfraction (float): Clay fraction of the soil.
bulkdensity (float): Bulk density of the soil (g/cm3).
sandpartdensity (float): Density of the sand particles in the soil (g/cm3).
watervolfraction (float): Two numbers that specify a range for the volumetric water fraction of the soil.
sandpartdensity (float): Density of the sand particles in the
soil (g/cm3).
watervolfraction (float): Two numbers that specify a range for the
volumetric water fraction of the soil.
"""
self.ID = ID
@@ -267,9 +305,9 @@ class PeplinskiSoil(object):
self.startmaterialnum = 0
def calculate_debye_properties(self, nbins, G):
"""
Calculates the real and imaginery part of a Debye model for the soil as
well as a conductivity. It uses an approximation to a semi-empirical model (http://dx.doi.org/10.1109/36.387598).
"""Calculates the real and imaginery part of a Debye model for the soil
as well as a conductivity. It uses an approximation to a semi-empirical
model (http://dx.doi.org/10.1109/36.387598).
Args:
nbins (int): Number of bins to use to create the different materials.
@@ -279,7 +317,8 @@ class PeplinskiSoil(object):
# Debye model properties of water
f = 1.3e9
w = 2 * np.pi * f
erealw = Material.watereri + ((Material.waterdeltaer) / (1 + (w * Material.watertau)**2))
erealw = DispersiveMaterial.watereri + ((DispersiveMaterial.waterdeltaer)
/ (1 + (w * DispersiveMaterial.watertau)**2))
a = 0.65 # Experimentally derived constant
es = (1.01 + 0.44 * self.rs)**2 - 0.062 #  Relative permittivity of sand particles
@@ -300,12 +339,13 @@ class PeplinskiSoil(object):
muiter = np.nditer(mumaterials, flags=['c_index'])
while not muiter.finished:
# Real part for frequencies in the range 1.4GHz to 18GHz
er = (1 + (self.rb / self.rs) * ((es**a) - 1) + (muiter[0]**b1 * erealw**a) - muiter[0]) ** (1 / a)
er = (1 + (self.rb / self.rs) * ((es**a) - 1) + (muiter[0]**b1 * erealw**a)
- muiter[0]) ** (1 / a)
# Real part for frequencies in the range 0.3GHz to 1.3GHz (linear correction to 1.4-18GHz value)
er = 1.15 * er - 0.68
# Permittivity at infinite frequency
eri = er - (muiter[0]**(b2 / a) * Material.waterdeltaer)
eri = er - (muiter[0]**(b2 / a) * DispersiveMaterial.waterdeltaer)
# Effective conductivity
sig = muiter[0]**(b2 / a) * ((sigf * (self.rs - self.rb)) / (self.rs * muiter[0]))
@@ -319,16 +359,16 @@ class PeplinskiSoil(object):
else:
self.startmaterialnum = len(G.materials)
if not material:
m = Material(len(G.materials), requiredID)
m = DispersiveMaterial(len(G.materials), requiredID)
m.type = 'debye'
m.averagable = False
m.poles = 1
if m.poles > Material.maxpoles:
Material.maxpoles = m.poles
if m.poles > config.materials['maxpoles']:
config.materials['maxpoles'] = m.poles
m.er = eri
m.se = sig
m.deltaer.append(er - eri)
m.tau.append(Material.watertau)
m.tau.append(DispersiveMaterial.watertau)
G.materials.append(m)
muiter.iternext()

查看文件

@@ -32,58 +32,49 @@ from terminaltables import SingleTable
from tqdm import tqdm
import gprMax.config as config
from gprMax.config import floattype
from gprMax.config import complextype
from gprMax.config import cudafloattype
from gprMax.config import cudacomplextype
from gprMax.config import numdispersion
from gprMax.config import hostinfo
from gprMax.config import messages
from gprMax.config import progressbars
from gprMax.config import snapsgpu2cpu
from gprMax.exceptions import GeneralError
from gprMax.fields_outputs import store_outputs
from gprMax.fields_outputs import kernel_template_store_outputs
from gprMax.fields_outputs import write_hdf5_outputfile
from gprMax.cython.fields_updates import update_electric
from gprMax.cython.fields_updates import update_magnetic
from gprMax.cython.fields_updates import update_electric_dispersive_multipole_A
from gprMax.cython.fields_updates import update_electric_dispersive_multipole_B
from gprMax.cython.fields_updates import update_electric_dispersive_1pole_A
from gprMax.cython.fields_updates import update_electric_dispersive_1pole_B
from gprMax.cuda.fields_updates import kernels_template_fields
from gprMax.grid import FDTDGrid
from gprMax.grid import dispersion_analysis
from gprMax.input_cmds_geometry import process_geometrycmds
from gprMax.input_cmds_file import process_python_include_code
from gprMax.input_cmds_file import write_processed_file
from gprMax.input_cmds_file import check_cmd_names
from gprMax.input_cmds_singleuse import process_singlecmds
from gprMax.input_cmds_multiuse import process_multicmds
from gprMax.materials import Material
from gprMax.materials import process_materials
from gprMax.pml import CFS
from gprMax.pml import PML
from gprMax.pml import build_pmls
from gprMax.receivers import gpu_initialise_rx_arrays
from gprMax.receivers import gpu_get_rx_array
from gprMax.snapshots import Snapshot
from gprMax.snapshots import gpu_initialise_snapshot_array
from gprMax.snapshots import gpu_get_snapshot_array
from gprMax.cuda.snapshots import kernel_template_store_snapshot
from gprMax.sources import gpu_initialise_src_arrays
from gprMax.cuda.source_updates import kernels_template_sources
from gprMax.utilities import get_terminal_width
from gprMax.utilities import human_size
from gprMax.utilities import open_path_file
from gprMax.utilities import round32
from gprMax.utilities import timer
from gprMax.cython.yee_cell_build import build_electric_components
from gprMax.cython.yee_cell_build import build_magnetic_components
from .cuda.fields_updates import kernel_template_fields
from .cuda.source_updates import kernel_template_sources
from .cython.fields_updates_normal import update_electric
from .cython.fields_updates_normal import update_magnetic
from .cython.fields_updates_dispersive import update_electric_dispersive_1pole_A
from .cython.fields_updates_dispersive import update_electric_dispersive_1pole_B
from .cython.fields_updates_dispersive import update_electric_dispersive_multipole_A
from .cython.fields_updates_dispersive import update_electric_dispersive_multipole_B
from .cython.fields_updates_dispersive import update_electric_dispersive_debye_1pole_A
from .cython.fields_updates_dispersive import update_electric_dispersive_debye_1pole_B
from .cython.fields_updates_dispersive import update_electric_dispersive_debye_multipole_A
from .cython.fields_updates_dispersive import update_electric_dispersive_debye_multipole_B
from .cython.yee_cell_build import build_electric_components
from .cython.yee_cell_build import build_magnetic_components
from .exceptions import GeneralError
from .fields_outputs import store_outputs
from .fields_outputs import kernel_template_store_outputs
from .fields_outputs import write_hdf5_outputfile
from .grid import FDTDGrid
from .grid import dispersion_analysis
from .input_cmds_geometry import process_geometrycmds
from .input_cmds_file import process_python_include_code
from .input_cmds_file import write_processed_file
from .input_cmds_file import check_cmd_names
from .input_cmds_singleuse import process_singlecmds
from .input_cmds_multiuse import process_multicmds
from .materials import Material
from .materials import process_materials
from .pml import CFS
from .pml import PML
from .pml import build_pmls
from .receivers import gpu_initialise_rx_arrays
from .receivers import gpu_get_rx_array
from .receivers import Rx
from .snapshots import Snapshot
from .snapshots import gpu_initialise_snapshot_array
from .snapshots import gpu_get_snapshot_array
from .sources import gpu_initialise_src_arrays
from .utilities import get_terminal_width
from .utilities import human_size
from .utilities import open_path_file
from .utilities import round32
from .utilities import timer
def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usernamespace):
@@ -117,10 +108,10 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
# Initialise an instance of the FDTDGrid class
G = FDTDGrid()
G.inputfilename = os.path.split(inputfile.name)[1]
G.inputdirectory = os.path.dirname(os.path.abspath(inputfile.name))
config.inputfilepath = os.path.realpath(inputfile.name)
config.outputfilepath = os.path.dirname(os.path.abspath(config.inputfilepath))
inputfilestr = '\n--- Model {}/{}, input file: {}'.format(currentmodelrun, modelend, inputfile.name)
if messages:
if config.general['messages']:
print(Fore.GREEN + '{} {}\n'.format(inputfilestr, '-' * (get_terminal_width() - 1 - len(inputfilestr))) + Style.RESET_ALL)
# Add the current model run to namespace that can be accessed by
@@ -135,12 +126,12 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
for key, value in sorted(usernamespace.items()):
if key != '__builtins__':
uservars += '{}: {}, '.format(key, value)
if messages:
if config.general['messages']:
print('Constants/variables used/available for Python scripting: {{{}}}\n'.format(uservars[:-2]))
# Write a file containing the input commands after Python or include file commands have been processed
if args.write_processed:
write_processed_file(processedlines, appendmodelnumber, G)
write_processed_file(processedlines, appendmodelnumber)
# Check validity of command names and that essential commands are present
singlecmds, multicmds, geometry = check_cmd_names(processedlines)
@@ -157,18 +148,17 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
# Process parameters for commands that can only occur once in the model
process_singlecmds(singlecmds, G)
from gprMax.config import mode
# Process parameters for commands that can occur multiple times in the model
if messages: print()
if config.general['messages']: print()
process_multicmds(multicmds, G)
# Estimate and check memory (RAM) usage
G.memory_estimate_basic()
G.memory_check()
if messages:
if config.general['messages']:
memGPU = ''
if config.gpus:
if config.cuda['gpus']:
memGPU = ' host + ~{} GPU'.format(human_size(G.memoryusage))
print('\nMemory (RAM) required: ~{}{}\n'.format(human_size(G.memoryusage), memGPU))
@@ -184,16 +174,16 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
process_geometrycmds(geometry, G)
# Build the PMLs and calculate initial coefficients
if messages: print()
if config.general['messages']: print()
if all(value == 0 for value in G.pmlthickness.values()):
if messages:
if config.general['messages']:
print('PML: switched off')
pass # If all the PMLs are switched off don't need to build anything
else:
# Set default CFS parameters for PML if not given
if not G.cfs:
G.cfs = [CFS()]
if messages:
if config.general['messages']:
if all(value == G.pmlthickness['x0'] for value in G.pmlthickness.values()):
pmlinfo = str(G.pmlthickness['x0'])
else:
@@ -202,14 +192,14 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
pmlinfo += '{}: {}, '.format(key, value)
pmlinfo = pmlinfo[:-2] + ' cells'
print('PML: formulation: {}, order: {}, thickness: {}'.format(G.pmlformulation, len(G.cfs), pmlinfo))
pbar = tqdm(total=sum(1 for value in G.pmlthickness.values() if value > 0), desc='Building PML boundaries', ncols=get_terminal_width() - 1, file=sys.stdout, disable=not progressbars)
pbar = tqdm(total=sum(1 for value in G.pmlthickness.values() if value > 0), desc='Building PML boundaries', ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.general['progressbars'])
build_pmls(G, pbar)
pbar.close()
# Build the model, i.e. set the material properties (ID) for every edge
# of every Yee cell
if messages: print()
pbar = tqdm(total=2, desc='Building main grid', ncols=get_terminal_width() - 1, file=sys.stdout, disable=not progressbars)
if config.general['messages']: print()
pbar = tqdm(total=2, desc='Building main grid', ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.general['progressbars'])
build_electric_components(G.solid, G.rigidE, G.ID, G)
pbar.update()
build_magnetic_components(G.solid, G.rigidH, G.ID, G)
@@ -218,19 +208,19 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
# Add PEC boundaries to invariant direction in 2D modes
# N.B. 2D modes are a single cell slice of 3D grid
if '2D TMx' in mode:
if '2D TMx' in config.mode:
# Ey & Ez components
G.ID[1, 0, :, :] = 0
G.ID[1, 1, :, :] = 0
G.ID[2, 0, :, :] = 0
G.ID[2, 1, :, :] = 0
elif '2D TMy' in mode:
elif '2D TMy' in config.mode:
# Ex & Ez components
G.ID[0, :, 0, :] = 0
G.ID[0, :, 1, :] = 0
G.ID[2, :, 0, :] = 0
G.ID[2, :, 1, :] = 0
elif '2D TMz' in mode:
elif '2D TMz' in config.mode:
# Ex & Ey components
G.ID[0, :, :, 0] = 0
G.ID[0, :, :, 1] = 0
@@ -245,16 +235,23 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
# Initialise arrays of update coefficients to pass to update functions
G.initialise_std_update_coeff_arrays()
# Initialise arrays of update coefficients and temporary values if
# there are any dispersive materials
if Material.maxpoles != 0:
# Set datatype for dispersive arrays if there are any dispersive materials.
if config.materials['maxpoles'] != 0:
drudelorentz = any([m for m in G.materials if 'drude' in m.type or 'lorentz' in m.type])
if drudelorentz:
config.materials['dispersivedtype'] = config.dtypes['complex']
config.materials['dispersiveCdtype'] = config.dtypes['C_complex']
else:
config.materials['dispersivedtype'] = config.dtypes['float_or_double']
config.materials['dispersiveCdtype'] = config.dtypes['C_float_or_double']
# Update estimated memory (RAM) usage
G.memoryusage += int(3 * Material.maxpoles * (G.nx + 1) * (G.ny + 1) * (G.nz + 1) * np.dtype(complextype).itemsize)
G.memoryusage += int(3 * config.materials['maxpoles'] * (G.nx + 1) * (G.ny + 1) * (G.nz + 1) * np.dtype(config.materials['dispersivedtype']).itemsize)
G.memory_check()
if messages:
if config.general['messages']:
print('\nMemory (RAM) required - updated (dispersive): ~{}\n'.format(human_size(G.memoryusage)))
G.initialise_dispersive_arrays()
G.initialise_dispersive_arrays(config.materials['dispersivedtype'])
# Check there is sufficient memory to store any snapshots
if G.snapshots:
@@ -264,13 +261,13 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
snapsmemsize += (2 * snap.datasizefield)
G.memoryusage += int(snapsmemsize)
G.memory_check(snapsmemsize=int(snapsmemsize))
if messages:
if config.general['messages']:
print('\nMemory (RAM) required - updated (snapshots): ~{}\n'.format(human_size(G.memoryusage)))
# Process complete list of materials - calculate update coefficients,
# store in arrays, and build text list of materials/properties
materialsdata = process_materials(G)
if messages:
if config.general['messages']:
print('\nMaterials:')
materialstable = SingleTable(materialsdata)
materialstable.outer_border = False
@@ -279,19 +276,19 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
# Check to see if numerical dispersion might be a problem
results = dispersion_analysis(G)
if results['error'] and messages:
if results['error'] and config.general['messages']:
print(Fore.RED + "\nWARNING: Numerical dispersion analysis not carried out as {}".format(results['error']) + Style.RESET_ALL)
elif results['N'] < numdispersion['mingridsampling']:
elif results['N'] < config.numdispersion['mingridsampling']:
raise GeneralError("Non-physical wave propagation: Material '{}' has wavelength sampled by {} cells, less than required minimum for physical wave propagation. Maximum significant frequency estimated as {:g}Hz".format(results['material'].ID, results['N'], results['maxfreq']))
elif results['deltavp'] and np.abs(results['deltavp']) > numdispersion['maxnumericaldisp'] and messages:
elif results['deltavp'] and np.abs(results['deltavp']) > config.numdispersion['maxnumericaldisp'] and config.general['messages']:
print(Fore.RED + "\nWARNING: Potentially significant numerical dispersion. Estimated largest physical phase-velocity error is {:.2f}% in material '{}' whose wavelength sampled by {} cells. Maximum significant frequency estimated as {:g}Hz".format(results['deltavp'], results['material'].ID, results['N'], results['maxfreq']) + Style.RESET_ALL)
elif results['deltavp'] and messages:
elif results['deltavp'] and config.general['messages']:
print("\nNumerical dispersion analysis: estimated largest physical phase-velocity error is {:.2f}% in material '{}' whose wavelength sampled by {} cells. Maximum significant frequency estimated as {:g}Hz".format(results['deltavp'], results['material'].ID, results['N'], results['maxfreq']))
# If geometry information to be reused between model runs
else:
inputfilestr = '\n--- Model {}/{}, input file (not re-processed, i.e. geometry fixed): {}'.format(currentmodelrun, modelend, inputfile.name)
if messages:
if config.general['messages']:
print(Fore.GREEN + '{} {}\n'.format(inputfilestr, '-' * (get_terminal_width() - 1 - len(inputfilestr))) + Style.RESET_ALL)
# Clear arrays for field components
@@ -320,20 +317,18 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
receiver.zcoord = receiver.zcoordorigin + (currentmodelrun - 1) * G.rxsteps[2]
# Write files for any geometry views and geometry object outputs
if not (G.geometryviews or G.geometryobjectswrite) and args.geometry_only and messages:
if not (G.geometryviews or G.geometryobjectswrite) and args.geometry_only and config.general['messages']:
print(Fore.RED + '\nWARNING: No geometry views or geometry objects to output found.' + Style.RESET_ALL)
if G.geometryviews:
if messages: print()
for i, geometryview in enumerate(G.geometryviews):
geometryview.set_filename(appendmodelnumber, G)
pbar = tqdm(total=geometryview.datawritesize, unit='byte', unit_scale=True, desc='Writing geometry view file {}/{}, {}'.format(i + 1, len(G.geometryviews), os.path.split(geometryview.filename)[1]), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not progressbars)
geometryview.write_vtk(G, pbar)
pbar.close()
if G.geometryobjectswrite:
for i, geometryobject in enumerate(G.geometryobjectswrite):
pbar = tqdm(total=geometryobject.datawritesize, unit='byte', unit_scale=True, desc='Writing geometry object file {}/{}, {}'.format(i + 1, len(G.geometryobjectswrite), os.path.split(geometryobject.filename)[1]), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not progressbars)
geometryobject.write_hdf5(G, pbar)
pbar.close()
if config.general['messages']: print()
for i, geometryview in enumerate(G.geometryviews):
geometryview.set_filename(appendmodelnumber)
pbar = tqdm(total=geometryview.datawritesize, unit='byte', unit_scale=True, desc='Writing geometry view file {}/{}, {}'.format(i + 1, len(G.geometryviews), os.path.split(geometryview.filename)[1]), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.general['progressbars'])
geometryview.write_vtk(G, pbar)
pbar.close()
for i, geometryobject in enumerate(G.geometryobjectswrite):
pbar = tqdm(total=geometryobject.datawritesize, unit='byte', unit_scale=True, desc='Writing geometry object file {}/{}, {}'.format(i + 1, len(G.geometryobjectswrite), os.path.split(geometryobject.filename)[1]), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.general['progressbars'])
geometryobject.write_hdf5(G, pbar)
pbar.close()
# If only writing geometry information
if args.geometry_only:
@@ -341,29 +336,17 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
# Run simulation
else:
# Output filename
inputdirectory, inputfilename = os.path.split(os.path.join(G.inputdirectory, G.inputfilename))
if G.outputdirectory is None:
outputdir = inputdirectory
else:
outputdir = G.outputdirectory
# Save current directory
curdir = os.getcwd()
os.chdir(inputdirectory)
outputdir = os.path.abspath(outputdir)
if not os.path.isdir(outputdir):
os.mkdir(outputdir)
if messages:
print('\nCreated output directory: {}'.format(outputdir))
# Restore current directory
os.chdir(curdir)
basename, ext = os.path.splitext(inputfilename)
outputfile = os.path.join(outputdir, basename + appendmodelnumber + '.out')
if messages:
# Check and set output directory and filename
if not os.path.isdir(config.outputfilepath):
os.mkdir(config.outputfilepath)
if config.general['messages']:
print('\nCreated output directory: {}'.format(config.outputfilepath))
outputfile = os.path.join(config.outputfilepath, os.path.splitext(os.path.split(config.inputfilepath)[1])[0] + appendmodelnumber + '.out')
if config.general['messages']:
print('\nOutput file: {}\n'.format(outputfile))
# Main FDTD solving functions for either CPU or GPU
if config.gpus is None:
if config.cuda['gpus'] is None:
tsolve = solve_cpu(currentmodelrun, modelend, G)
else:
tsolve, memsolve = solve_gpu(currentmodelrun, modelend, G)
@@ -374,21 +357,21 @@ def run_model(args, currentmodelrun, modelend, numbermodelruns, inputfile, usern
# Write any snapshots to file
if G.snapshots:
# Create directory and construct filename from user-supplied name and model run number
snapshotdir = os.path.join(G.inputdirectory, os.path.splitext(G.inputfilename)[0] + '_snaps' + appendmodelnumber)
snapshotdir = os.path.splitext(config.inputfilepath)[0] + '_snaps' + appendmodelnumber
if not os.path.exists(snapshotdir):
os.mkdir(snapshotdir)
if messages: print()
if config.general['messages']: print()
for i, snap in enumerate(G.snapshots):
snap.filename = os.path.abspath(os.path.join(snapshotdir, snap.basefilename + '.vti'))
pbar = tqdm(total=snap.vtkdatawritesize, leave=True, unit='byte', unit_scale=True, desc='Writing snapshot file {} of {}, {}'.format(i + 1, len(G.snapshots), os.path.split(snap.filename)[1]), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not progressbars)
pbar = tqdm(total=snap.vtkdatawritesize, leave=True, unit='byte', unit_scale=True, desc='Writing snapshot file {} of {}, {}'.format(i + 1, len(G.snapshots), os.path.split(snap.filename)[1]), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.general['progressbars'])
snap.write_vtk_imagedata(pbar, G)
pbar.close()
if messages: print()
if config.general['messages']: print()
if messages:
if config.general['messages']:
memGPU = ''
if config.gpus:
if config.cuda['gpus']:
memGPU = ' host + ~{} GPU'.format(human_size(memsolve))
print('\nMemory (RAM) used: ~{}{}'.format(human_size(p.memory_full_info().uss), memGPU))
print('Solving time [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=tsolve)))
@@ -415,9 +398,26 @@ def solve_cpu(currentmodelrun, modelend, G):
tsolve (float): Time taken to execute solving (seconds)
"""
# Set update functions if there are dispersive materials
if config.materials['maxpoles'] != 0:
if config.materials['dispersivedtype'] == config.dtypes['complex']:
if config.materials['maxpoles'] == 1:
update_electric_dispersive_A = update_electric_dispersive_1pole_A
update_electric_dispersive_B = update_electric_dispersive_1pole_B
elif config.materials['maxpoles'] > 1:
update_electric_dispersive_A = update_electric_dispersive_multipole_A
update_electric_dispersive_B = update_electric_dispersive_multipole_B
elif config.materials['dispersivedtype'] == config.dtypes['float_or_double']:
if config.materials['maxpoles'] == 2:
update_electric_dispersive_A = update_electric_dispersive_debye_1pole_A
update_electric_dispersive_B = update_electric_dispersive_debye_1pole_B
elif config.materials['maxpoles'] == 1:
update_electric_dispersive_A = update_electric_dispersive_debye_multipole_A
update_electric_dispersive_B = update_electric_dispersive_debye_multipole_B
tsolvestart = timer()
for iteration in tqdm(range(G.iterations), desc='Running simulation, model ' + str(currentmodelrun) + '/' + str(modelend), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not progressbars):
for iteration in tqdm(range(G.iterations), desc='Running simulation, model ' + str(currentmodelrun) + '/' + str(modelend), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.general['progressbars']):
# Store field component values for every receiver and transmission line
store_outputs(iteration, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, G)
@@ -427,7 +427,7 @@ def solve_cpu(currentmodelrun, modelend, G):
snap.store(G)
# Update magnetic field components
update_magnetic(G.nx, G.ny, G.nz, hostinfo['ompthreads'], G.updatecoeffsH, G.ID, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
update_magnetic(G.nx, G.ny, G.nz, config.hostinfo['ompthreads'], G.updatecoeffsH, G.ID, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
# Update magnetic field components with the PML correction
for pml in G.pmls:
@@ -439,14 +439,12 @@ def solve_cpu(currentmodelrun, modelend, G):
# Update electric field components
# All materials are non-dispersive so do standard update
if Material.maxpoles == 0:
update_electric(G.nx, G.ny, G.nz, hostinfo['ompthreads'], G.updatecoeffsE, G.ID, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
if config.materials['maxpoles'] == 0:
update_electric(G.nx, G.ny, G.nz, config.hostinfo['ompthreads'], G.updatecoeffsE, G.ID, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
# If there are any dispersive materials do 1st part of dispersive update
# (it is split into two parts as it requires present and updated electric field values).
elif Material.maxpoles == 1:
update_electric_dispersive_1pole_A(G.nx, G.ny, G.nz, hostinfo['ompthreads'], G.updatecoeffsE, G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
elif Material.maxpoles > 1:
update_electric_dispersive_multipole_A(G.nx, G.ny, G.nz, hostinfo['ompthreads'], Material.maxpoles, G.updatecoeffsE, G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
else:
update_electric_dispersive_A(G.nx, G.ny, G.nz, config.hostinfo['ompthreads'], config.materials['maxpoles'], G.updatecoeffsE, G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
# Update electric field components with the PML correction
for pml in G.pmls:
@@ -460,10 +458,8 @@ def solve_cpu(currentmodelrun, modelend, G):
# (it is split into two parts as it requires present and updated electric
# field values). Therefore it can only be completely updated after the
# electric field has been updated by the PML and source updates.
if Material.maxpoles == 1:
update_electric_dispersive_1pole_B(G.nx, G.ny, G.nz, hostinfo['ompthreads'], G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez)
elif Material.maxpoles > 1:
update_electric_dispersive_multipole_B(G.nx, G.ny, G.nz, hostinfo['ompthreads'], Material.maxpoles, G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez)
if config.materials['maxpoles'] != 0:
update_electric_dispersive_B(G.nx, G.ny, G.nz, config.hostinfo['ompthreads'], config.materials['maxpoles'], G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez)
tsolve = timer() - tsolvestart
@@ -494,32 +490,30 @@ def solve_gpu(currentmodelrun, modelend, G):
compiler_opts = None
# Create device handle and context on specifc GPU device (and make it current context)
dev = drv.Device(config.gpus.deviceID)
dev = drv.Device(config.cuda['gpus'].deviceID)
ctx = dev.make_context()
# Electric and magnetic field updates - prepare kernels, and get kernel functions
if Material.maxpoles > 0:
kernels_fields = SourceModule(kernels_template_fields.substitute(REAL=cudafloattype, COMPLEX=cudacomplextype, N_updatecoeffsE=G.updatecoeffsE.size, N_updatecoeffsH=G.updatecoeffsH.size, NY_MATCOEFFS=G.updatecoeffsE.shape[1], NY_MATDISPCOEFFS=G.updatecoeffsdispersive.shape[1], NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3], NX_T=G.Tx.shape[1], NY_T=G.Tx.shape[2], NZ_T=G.Tx.shape[3]), options=compiler_opts)
else: # Set to one any substitutions for dispersive materials
kernels_fields = SourceModule(kernels_template_fields.substitute(REAL=cudafloattype, COMPLEX=cudacomplextype, N_updatecoeffsE=G.updatecoeffsE.size, N_updatecoeffsH=G.updatecoeffsH.size, NY_MATCOEFFS=G.updatecoeffsE.shape[1], NY_MATDISPCOEFFS=1, NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3], NX_T=1, NY_T=1, NZ_T=1), options=compiler_opts)
# Electric and magnetic field updates - prepare kernels, get kernel functions, and initialise arrays on GPU
if config.materials['maxpoles'] == 0:
kernels_fields = SourceModule(kernels_template_fields.substitute(REAL=config.dtypes['C_float_or_double'], REAL_OR_COMPLEX=config.dtypes['C_complex'], N_updatecoeffsE=G.updatecoeffsE.size, N_updatecoeffsH=G.updatecoeffsH.size, NY_MATCOEFFS=G.updatecoeffsE.shape[1], NY_MATDISPCOEFFS=1, NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3], NX_T=1, NY_T=1, NZ_T=1), options=compiler_opts)
else: # # If there are any dispersive materials (updates are split into two parts as they require present and updated electric field values).
kernels_fields = SourceModule(kernels_template_fields.substitute(REAL=config.dtypes['C_float_or_double'], REAL_OR_COMPLEX=config.dtypes['C_complex'], N_updatecoeffsE=G.updatecoeffsE.size, N_updatecoeffsH=G.updatecoeffsH.size, NY_MATCOEFFS=G.updatecoeffsE.shape[1], NY_MATDISPCOEFFS=G.updatecoeffsdispersive.shape[1], NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3], NX_T=G.Tx.shape[1], NY_T=G.Tx.shape[2], NZ_T=G.Tx.shape[3]), options=compiler_opts)
update_e_dispersive_A_gpu = kernels_fields.get_function("update_e_dispersive_A")
update_e_dispersive_B_gpu = kernels_fields.get_function("update_e_dispersive_B")
G.gpu_initialise_dispersive_arrays()
update_e_gpu = kernels_fields.get_function("update_e")
update_h_gpu = kernels_fields.get_function("update_h")
# Copy material coefficient arrays to constant memory of GPU (must be <64KB) for fields kernels
updatecoeffsE = kernels_fields.get_global('updatecoeffsE')[0]
updatecoeffsH = kernels_fields.get_global('updatecoeffsH')[0]
if G.updatecoeffsE.nbytes + G.updatecoeffsH.nbytes > config.gpus.constmem:
raise GeneralError('Too many materials in the model to fit onto constant memory of size {} on {} - {} GPU'.format(human_size(config.gpus.constmem), config.gpus.deviceID, config.gpus.name))
if G.updatecoeffsE.nbytes + G.updatecoeffsH.nbytes > config.cuda['gpus'].constmem:
raise GeneralError('Too many materials in the model to fit onto constant memory of size {} on {} - {} GPU'.format(human_size(config.cuda['gpus'].constmem), config.cuda['gpus'].deviceID, config.cuda['gpus'].name))
else:
drv.memcpy_htod(updatecoeffsE, G.updatecoeffsE)
drv.memcpy_htod(updatecoeffsH, G.updatecoeffsH)
# Electric and magnetic field updates - dispersive materials - get kernel functions and initialise array on GPU
if Material.maxpoles > 0: # If there are any dispersive materials (updates are split into two parts as they require present and updated electric field values).
update_e_dispersive_A_gpu = kernels_fields.get_function("update_e_dispersive_A")
update_e_dispersive_B_gpu = kernels_fields.get_function("update_e_dispersive_B")
G.gpu_initialise_dispersive_arrays()
# Electric and magnetic field updates - set blocks per grid and initialise field arrays on GPU
G.gpu_set_blocks_per_grid()
G.gpu_initialise_arrays()
@@ -527,12 +521,10 @@ def solve_gpu(currentmodelrun, modelend, G):
# PML updates
if G.pmls:
# Prepare kernels
pmlmodulelectric = 'gprMax.pml_updates.pml_updates_electric_' + G.pmlformulation + '_gpu'
kernelelectricfunc = getattr(import_module(pmlmodulelectric), 'kernels_template_pml_electric_' + G.pmlformulation)
pmlmodulemagnetic = 'gprMax.pml_updates.pml_updates_magnetic_' + G.pmlformulation + '_gpu'
kernelmagneticfunc = getattr(import_module(pmlmodulemagnetic), 'kernels_template_pml_magnetic_' + G.pmlformulation)
kernels_pml_electric = SourceModule(kernelelectricfunc.substitute(REAL=cudafloattype, N_updatecoeffsE=G.updatecoeffsE.size, NY_MATCOEFFS=G.updatecoeffsE.shape[1], NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3]), options=compiler_opts)
kernels_pml_magnetic = SourceModule(kernelmagneticfunc.substitute(REAL=cudafloattype, N_updatecoeffsH=G.updatecoeffsH.size, NY_MATCOEFFS=G.updatecoeffsH.shape[1], NX_FIELDS=G.Hx.shape[0], NY_FIELDS=G.Hx.shape[1], NZ_FIELDS=G.Hx.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3]), options=compiler_opts)
kernelelectricfunc = getattr(import_module('gprMax.cuda.pml_updates_electric_' + G.pmlformulation), 'kernels_template_pml_electric_' + G.pmlformulation)
kernelmagneticfunc = getattr(import_module('gprMax.cuda.pml_updates_magnetic_' + G.pmlformulation), 'kernels_template_pml_magnetic_' + G.pmlformulation)
kernels_pml_electric = SourceModule(kernelelectricfunc.substitute(REAL=config.dtypes['C_float_or_double'], N_updatecoeffsE=G.updatecoeffsE.size, NY_MATCOEFFS=G.updatecoeffsE.shape[1], NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3]), options=compiler_opts)
kernels_pml_magnetic = SourceModule(kernelmagneticfunc.substitute(REAL=config.dtypes['C_float_or_double'], N_updatecoeffsH=G.updatecoeffsH.size, NY_MATCOEFFS=G.updatecoeffsH.shape[1], NX_FIELDS=G.Hx.shape[0], NY_FIELDS=G.Hx.shape[1], NZ_FIELDS=G.Hx.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3]), options=compiler_opts)
# Copy material coefficient arrays to constant memory of GPU (must be <64KB) for PML kernels
updatecoeffsE = kernels_pml_electric.get_global('updatecoeffsE')[0]
updatecoeffsH = kernels_pml_magnetic.get_global('updatecoeffsH')[0]
@@ -549,12 +541,13 @@ def solve_gpu(currentmodelrun, modelend, G):
# Initialise arrays on GPU
rxcoords_gpu, rxs_gpu = gpu_initialise_rx_arrays(G)
# Prepare kernel and get kernel function
kernel_store_outputs = SourceModule(kernel_template_store_outputs.substitute(REAL=cudafloattype, NY_RXCOORDS=3, NX_RXS=6, NY_RXS=G.iterations, NZ_RXS=len(G.rxs), NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2]), options=compiler_opts)
kernel_store_outputs = SourceModule(kernel_template_store_outputs.substitute(REAL=config.dtypes['C_float_or_double'], NY_RXCOORDS=3, NX_RXS=len(Rx.gpu_allowableoutputs), NY_RXS=G.iterations, NZ_RXS=len(G.rxs), NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2]), options=compiler_opts)
store_outputs_gpu = kernel_store_outputs.get_function("store_outputs")
# Sources - initialise arrays on GPU, prepare kernel and get kernel functions
if G.voltagesources + G.hertziandipoles + G.magneticdipoles:
kernels_sources = SourceModule(kernels_template_sources.substitute(REAL=cudafloattype, N_updatecoeffsE=G.updatecoeffsE.size, N_updatecoeffsH=G.updatecoeffsH.size, NY_MATCOEFFS=G.updatecoeffsE.shape[1], NY_SRCINFO=4, NY_SRCWAVES=G.iterations, NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3]), options=compiler_opts)
kernels_sources = SourceModule(kernels_template_sources.substitute(REAL=config.dtypes['C_float_or_double'], N_updatecoeffsE=G.updatecoeffsE.size, N_updatecoeffsH=G.updatecoeffsH.size, NY_MATCOEFFS=G.updatecoeffsE.shape[1], NY_SRCINFO=4, NY_SRCWAVES=G.iterations, NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2], NX_ID=G.ID.shape[1], NY_ID=G.ID.shape[2], NZ_ID=G.ID.shape[3]), options=compiler_opts)
# Copy material coefficient arrays to constant memory of GPU (must be <64KB) for source kernels
updatecoeffsE = kernels_sources.get_global('updatecoeffsE')[0]
updatecoeffsH = kernels_sources.get_global('updatecoeffsH')[0]
@@ -575,7 +568,7 @@ def solve_gpu(currentmodelrun, modelend, G):
# Initialise arrays on GPU
snapEx_gpu, snapEy_gpu, snapEz_gpu, snapHx_gpu, snapHy_gpu, snapHz_gpu = gpu_initialise_snapshot_array(G)
# Prepare kernel and get kernel function
kernel_store_snapshot = SourceModule(kernel_template_store_snapshot.substitute(REAL=cudafloattype, NX_SNAPS=Snapshot.nx_max, NY_SNAPS=Snapshot.ny_max, NZ_SNAPS=Snapshot.nz_max, NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2]), options=compiler_opts)
kernel_store_snapshot = SourceModule(kernel_template_store_snapshot.substitute(REAL=config.dtypes['C_float_or_double'], NX_SNAPS=Snapshot.nx_max, NY_SNAPS=Snapshot.ny_max, NZ_SNAPS=Snapshot.nz_max, NX_FIELDS=G.Ex.shape[0], NY_FIELDS=G.Ex.shape[1], NZ_FIELDS=G.Ex.shape[2]), options=compiler_opts)
store_snapshot_gpu = kernel_store_snapshot.get_function("store_snapshot")
# Iteration loop timer
@@ -583,7 +576,7 @@ def solve_gpu(currentmodelrun, modelend, G):
iterend = drv.Event()
iterstart.record()
for iteration in tqdm(range(G.iterations), desc='Running simulation, model ' + str(currentmodelrun) + '/' + str(modelend), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not progressbars):
for iteration in tqdm(range(G.iterations), desc='Running simulation, model ' + str(currentmodelrun) + '/' + str(modelend), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.general['progressbars']):
# Get GPU memory usage on final iteration
if iteration == G.iterations - 1:
@@ -600,7 +593,7 @@ def solve_gpu(currentmodelrun, modelend, G):
# Store any snapshots
for i, snap in enumerate(G.snapshots):
if snap.time == iteration + 1:
if not snapsgpu2cpu:
if not config.cuda['snapsgpu2cpu']:
store_snapshot_gpu(np.int32(i), np.int32(snap.xs),
np.int32(snap.xf), np.int32(snap.ys),
np.int32(snap.yf), np.int32(snap.zs),
@@ -629,7 +622,7 @@ def solve_gpu(currentmodelrun, modelend, G):
update_h_gpu(np.int32(G.nx), np.int32(G.ny), np.int32(G.nz),
G.ID_gpu.gpudata, G.Hx_gpu.gpudata, G.Hy_gpu.gpudata,
G.Hz_gpu.gpudata, G.Ex_gpu.gpudata, G.Ey_gpu.gpudata,
G.Ez_gpu.gpudata, block=config.gpus.tpb, grid=config.gpus.bpg)
G.Ez_gpu.gpudata, block=config.cuda['gpus'].tpb, grid=config.cuda['gpus'].bpg)
# Update magnetic field components with the PML correction
for pml in G.pmls:
@@ -638,7 +631,7 @@ def solve_gpu(currentmodelrun, modelend, G):
# Update magnetic field components for magetic dipole sources
if G.magneticdipoles:
update_magnetic_dipole_gpu(np.int32(len(G.magneticdipoles)), np.int32(iteration),
floattype(G.dx), floattype(G.dy), floattype(G.dz),
config.dtypes['float_or_double'](G.dx), config.dtypes['float_or_double'](G.dy), config.dtypes['float_or_double'](G.dz),
srcinfo1_magnetic_gpu.gpudata, srcinfo2_magnetic_gpu.gpudata,
srcwaves_magnetic_gpu.gpudata, G.ID_gpu.gpudata,
G.Hx_gpu.gpudata, G.Hy_gpu.gpudata, G.Hz_gpu.gpudata,
@@ -646,20 +639,20 @@ def solve_gpu(currentmodelrun, modelend, G):
# Update electric field components
# If all materials are non-dispersive do standard update
if Material.maxpoles == 0:
if config.materials['maxpoles'] == 0:
update_e_gpu(np.int32(G.nx), np.int32(G.ny), np.int32(G.nz), G.ID_gpu.gpudata,
G.Ex_gpu.gpudata, G.Ey_gpu.gpudata, G.Ez_gpu.gpudata,
G.Hx_gpu.gpudata, G.Hy_gpu.gpudata, G.Hz_gpu.gpudata,
block=config.gpus.tpb, grid=config.gpus.bpg)
block=config.cuda['gpus'].tpb, grid=config.cuda['gpus'].bpg)
# If there are any dispersive materials do 1st part of dispersive update
# (it is split into two parts as it requires present and updated electric field values).
else:
update_e_dispersive_A_gpu(np.int32(G.nx), np.int32(G.ny), np.int32(G.nz),
np.int32(Material.maxpoles), G.updatecoeffsdispersive_gpu.gpudata,
np.int32(config.materials['maxpoles']), G.updatecoeffsdispersive_gpu.gpudata,
G.Tx_gpu.gpudata, G.Ty_gpu.gpudata, G.Tz_gpu.gpudata, G.ID_gpu.gpudata,
G.Ex_gpu.gpudata, G.Ey_gpu.gpudata, G.Ez_gpu.gpudata,
G.Hx_gpu.gpudata, G.Hy_gpu.gpudata, G.Hz_gpu.gpudata,
block=config.gpus.tpb, grid=config.gpus.bpg)
block=config.cuda['gpus'].tpb, grid=config.cuda['gpus'].bpg)
# Update electric field components with the PML correction
for pml in G.pmls:
@@ -668,7 +661,7 @@ def solve_gpu(currentmodelrun, modelend, G):
# Update electric field components for voltage sources
if G.voltagesources:
update_voltage_source_gpu(np.int32(len(G.voltagesources)), np.int32(iteration),
floattype(G.dx), floattype(G.dy), floattype(G.dz),
config.dtypes['float_or_double'](G.dx), config.dtypes['float_or_double'](G.dy), config.dtypes['float_or_double'](G.dz),
srcinfo1_voltage_gpu.gpudata, srcinfo2_voltage_gpu.gpudata,
srcwaves_voltage_gpu.gpudata, G.ID_gpu.gpudata,
G.Ex_gpu.gpudata, G.Ey_gpu.gpudata, G.Ez_gpu.gpudata,
@@ -677,26 +670,26 @@ def solve_gpu(currentmodelrun, modelend, G):
# Update electric field components for Hertzian dipole sources (update any Hertzian dipole sources last)
if G.hertziandipoles:
update_hertzian_dipole_gpu(np.int32(len(G.hertziandipoles)), np.int32(iteration),
floattype(G.dx), floattype(G.dy), floattype(G.dz),
config.dtypes['float_or_double'](G.dx), config.dtypes['float_or_double'](G.dy), config.dtypes['float_or_double'](G.dz),
srcinfo1_hertzian_gpu.gpudata, srcinfo2_hertzian_gpu.gpudata,
srcwaves_hertzian_gpu.gpudata, G.ID_gpu.gpudata,
G.Ex_gpu.gpudata, G.Ey_gpu.gpudata, G.Ez_gpu.gpudata,
block=(1, 1, 1), grid=(round32(len(G.hertziandipoles)), 1, 1))
# If there are any dispersive materials do 2nd part of dispersive update (it is split into two parts as it requires present and updated electric field values). Therefore it can only be completely updated after the electric field has been updated by the PML and source updates.
if Material.maxpoles > 0:
if config.materials['maxpoles'] > 0:
update_e_dispersive_B_gpu(np.int32(G.nx), np.int32(G.ny), np.int32(G.nz),
np.int32(Material.maxpoles), G.updatecoeffsdispersive_gpu.gpudata,
np.int32(config.materials['maxpoles']), G.updatecoeffsdispersive_gpu.gpudata,
G.Tx_gpu.gpudata, G.Ty_gpu.gpudata, G.Tz_gpu.gpudata, G.ID_gpu.gpudata,
G.Ex_gpu.gpudata, G.Ey_gpu.gpudata, G.Ez_gpu.gpudata,
block=config.gpus.tpb, grid=config.gpus.bpg)
block=config.cuda['gpus'].tpb, grid=config.cuda['gpus'].bpg)
# Copy output from receivers array back to correct receiver objects
if G.rxs:
gpu_get_rx_array(rxs_gpu.get(), rxcoords_gpu.get(), G)
# Copy data from any snapshots back to correct snapshot objects
if G.snapshots and not snapsgpu2cpu:
if G.snapshots and not config.cuda['snapsgpu2cpu']:
for i, snap in enumerate(G.snapshots):
gpu_get_snapshot_array(snapEx_gpu.get(), snapEy_gpu.get(), snapEz_gpu.get(),
snapHx_gpu.get(), snapHy_gpu.get(), snapHz_gpu.get(), i, snap)

查看文件

@@ -22,21 +22,18 @@ import numpy as np
from tqdm import tqdm
import gprMax.config as config
from gprMax.config import e0
from gprMax.config import z0
from gprMax.config import floattype
from gprMax.config import hostinfo
from gprMax.exceptions import GeneralError
class CFSParameter(object):
"""Individual CFS parameter (e.g. alpha, kappa, or sigma)."""
# Allowable scaling profiles and directions
scalingprofiles = {'constant': 0, 'linear': 1, 'quadratic': 2, 'cubic': 3, 'quartic': 4, 'quintic': 5, 'sextic': 6, 'septic': 7, 'octic': 8}
scalingprofiles = {'constant': 0, 'linear': 1, 'quadratic': 2, 'cubic': 3,
'quartic': 4, 'quintic': 5, 'sextic': 6, 'septic': 7, 'octic': 8}
scalingdirections = ['forward', 'reverse']
def __init__(self, ID=None, scaling='polynomial', scalingprofile=None, scalingdirection='forward', min=0, max=0):
def __init__(self, ID=None, scaling='polynomial', scalingprofile=None,
scalingdirection='forward', min=0, max=0):
"""
Args:
ID (str): Identifier for CFS parameter, can be: 'alpha', 'kappa' or 'sigma'.
@@ -71,60 +68,73 @@ class CFS(object):
self.sigma = CFSParameter(ID='sigma', scalingprofile='quartic', min=0, max=None)
def calculate_sigmamax(self, d, er, mr, G):
"""Calculates an optimum value for sigma max based on underlying material properties.
"""Calculates an optimum value for sigma max based on underlying
material properties.
Args:
d (float): dx, dy, or dz in direction of PML.
er (float): Average permittivity of underlying material.
mr (float): Average permeability of underlying material.
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
"""
# Calculation of the maximum value of sigma from http://dx.doi.org/10.1109/8.546249
m = CFSParameter.scalingprofiles[self.sigma.scalingprofile]
self.sigma.max = (0.8 * (m + 1)) / (z0 * d * np.sqrt(er * mr))
self.sigma.max = (0.8 * (m + 1)) / (config.z0 * d * np.sqrt(er * mr))
def scaling_polynomial(self, order, Evalues, Hvalues):
"""Applies the polynomial to be used for the scaling profile for electric and magnetic PML updates.
"""Applies the polynomial to be used for the scaling profile for
electric and magnetic PML updates.
Args:
order (int): Order of polynomial for scaling profile.
Evalues (float): numpy array holding scaling profile values for electric PML update.
Hvalues (float): numpy array holding scaling profile values for magnetic PML update.
Evalues (float): numpy array holding scaling profile values for
electric PML update.
Hvalues (float): numpy array holding scaling profile values for
magnetic PML update.
Returns:
Evalues (float): numpy array holding scaling profile values for electric PML update.
Hvalues (float): numpy array holding scaling profile values for magnetic PML update.
Evalues (float): numpy array holding scaling profile values for
electric PML update.
Hvalues (float): numpy array holding scaling profile values for
magnetic PML update.
"""
tmp = (np.linspace(0, (len(Evalues) - 1) + 0.5, num=2 * len(Evalues)) / (len(Evalues) - 1)) ** order
tmp = (np.linspace(0, (len(Evalues) - 1) + 0.5, num=2 * len(Evalues))
/ (len(Evalues) - 1)) ** order
Evalues = tmp[0:-1:2]
Hvalues = tmp[1::2]
return Evalues, Hvalues
def calculate_values(self, thickness, parameter):
"""Calculates values for electric and magnetic PML updates based on profile type and minimum and maximum values.
"""Calculates values for electric and magnetic PML updates based on
profile type and minimum and maximum values.
Args:
thickness (int): Thickness of PML in cells.
parameter (CFSParameter): Instance of CFSParameter
Returns:
Evalues (float): numpy array holding profile value for electric PML update.
Hvalues (float): numpy array holding profile value for magnetic PML update.
Evalues (float): numpy array holding profile value for electric
PML update.
Hvalues (float): numpy array holding profile value for magnetic
PML update.
"""
# Extra cell of thickness added to allow correct scaling of electric and magnetic values
Evalues = np.zeros(thickness + 1, dtype=floattype)
Hvalues = np.zeros(thickness + 1, dtype=floattype)
Evalues = np.zeros(thickness + 1, dtype=config.dtypes['float_or_double'])
Hvalues = np.zeros(thickness + 1, dtype=config.dtypes['float_or_double'])
if parameter.scalingprofile == 'constant':
Evalues += parameter.max
Hvalues += parameter.max
elif parameter.scaling == 'polynomial':
Evalues, Hvalues = self.scaling_polynomial(CFSParameter.scalingprofiles[parameter.scalingprofile], Evalues, Hvalues)
Evalues, Hvalues = self.scaling_polynomial(
CFSParameter.scalingprofiles[parameter.scalingprofile],
Evalues, Hvalues)
if parameter.ID == 'alpha':
Evalues = Evalues * (self.alpha.max - self.alpha.min) + self.alpha.min
Hvalues = Hvalues * (self.alpha.max - self.alpha.min) + self.alpha.min
@@ -167,7 +177,8 @@ class PML(object):
def __init__(self, G, ID=None, direction=None, xs=0, xf=0, ys=0, yf=0, zs=0, zf=0):
"""
Args:
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
ID (str): Identifier for PML slab.
direction (str): Direction of increasing absorption.
xs, xf, ys, yf, zs, zf (float): Extent of the PML slab.
@@ -204,20 +215,32 @@ class PML(object):
"""Initialise arrays to store fields in PML."""
if self.direction[0] == 'x':
self.EPhi1 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz + 1), dtype=floattype)
self.EPhi2 = np.zeros((len(self.CFS), self.nx + 1, self.ny + 1, self.nz), dtype=floattype)
self.HPhi1 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz), dtype=floattype)
self.HPhi2 = np.zeros((len(self.CFS), self.nx, self.ny, self.nz + 1), dtype=floattype)
self.EPhi1 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz + 1),
dtype=config.dtypes['float_or_double'])
self.EPhi2 = np.zeros((len(self.CFS), self.nx + 1, self.ny + 1, self.nz),
dtype=config.dtypes['float_or_double'])
self.HPhi1 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz),
dtype=config.dtypes['float_or_double'])
self.HPhi2 = np.zeros((len(self.CFS), self.nx, self.ny, self.nz + 1),
dtype=config.dtypes['float_or_double'])
elif self.direction[0] == 'y':
self.EPhi1 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz + 1), dtype=floattype)
self.EPhi2 = np.zeros((len(self.CFS), self.nx + 1, self.ny + 1, self.nz), dtype=floattype)
self.HPhi1 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz), dtype=floattype)
self.HPhi2 = np.zeros((len(self.CFS), self.nx, self.ny, self.nz + 1), dtype=floattype)
self.EPhi1 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz + 1),
dtype=config.dtypes['float_or_double'])
self.EPhi2 = np.zeros((len(self.CFS), self.nx + 1, self.ny + 1, self.nz),
dtype=config.dtypes['float_or_double'])
self.HPhi1 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz),
dtype=config.dtypes['float_or_double'])
self.HPhi2 = np.zeros((len(self.CFS), self.nx, self.ny, self.nz + 1),
dtype=config.dtypes['float_or_double'])
elif self.direction[0] == 'z':
self.EPhi1 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz + 1), dtype=floattype)
self.EPhi2 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz + 1), dtype=floattype)
self.HPhi1 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz), dtype=floattype)
self.HPhi2 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz), dtype=floattype)
self.EPhi1 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz + 1),
dtype=config.dtypes['float_or_double'])
self.EPhi2 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz + 1),
dtype=config.dtypes['float_or_double'])
self.HPhi1 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz),
dtype=config.dtypes['float_or_double'])
self.HPhi2 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz),
dtype=config.dtypes['float_or_double'])
def calculate_update_coeffs(self, er, mr, G):
"""Calculates electric and magnetic update coefficients for the PML.
@@ -225,17 +248,26 @@ class PML(object):
Args:
er (float): Average permittivity of underlying material
mr (float): Average permeability of underlying material
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
"""
self.ERA = np.zeros((len(self.CFS), self.thickness), dtype=floattype)
self.ERB = np.zeros((len(self.CFS), self.thickness), dtype=floattype)
self.ERE = np.zeros((len(self.CFS), self.thickness), dtype=floattype)
self.ERF = np.zeros((len(self.CFS), self.thickness), dtype=floattype)
self.HRA = np.zeros((len(self.CFS), self.thickness), dtype=floattype)
self.HRB = np.zeros((len(self.CFS), self.thickness), dtype=floattype)
self.HRE = np.zeros((len(self.CFS), self.thickness), dtype=floattype)
self.HRF = np.zeros((len(self.CFS), self.thickness), dtype=floattype)
self.ERA = np.zeros((len(self.CFS), self.thickness),
dtype=config.dtypes['float_or_double'])
self.ERB = np.zeros((len(self.CFS), self.thickness),
dtype=config.dtypes['float_or_double'])
self.ERE = np.zeros((len(self.CFS), self.thickness),
dtype=config.dtypes['float_or_double'])
self.ERF = np.zeros((len(self.CFS), self.thickness),
dtype=config.dtypes['float_or_double'])
self.HRA = np.zeros((len(self.CFS), self.thickness),
dtype=config.dtypes['float_or_double'])
self.HRB = np.zeros((len(self.CFS), self.thickness),
dtype=config.dtypes['float_or_double'])
self.HRE = np.zeros((len(self.CFS), self.thickness),
dtype=config.dtypes['float_or_double'])
self.HRF = np.zeros((len(self.CFS), self.thickness),
dtype=config.dtypes['float_or_double'])
for x, cfs in enumerate(self.CFS):
if not cfs.sigma.max:
@@ -247,31 +279,33 @@ class PML(object):
# Define different parameters depending on PML formulation
if G.pmlformulation == 'HORIPML':
# HORIPML electric update coefficients
tmp = (2 * e0 * Ekappa) + G.dt * (Ealpha * Ekappa + Esigma)
self.ERA[x, :] = (2 * e0 + G.dt * Ealpha) / tmp
self.ERB[x, :] = (2 * e0 * Ekappa) / tmp
self.ERE[x, :] = ((2 * e0 * Ekappa) - G.dt * (Ealpha * Ekappa + Esigma)) / tmp
tmp = (2 * config.e0 * Ekappa) + G.dt * (Ealpha * Ekappa + Esigma)
self.ERA[x, :] = (2 * config.e0 + G.dt * Ealpha) / tmp
self.ERB[x, :] = (2 * config.e0 * Ekappa) / tmp
self.ERE[x, :] = ((2 * config.e0 * Ekappa) - G.dt
* (Ealpha * Ekappa + Esigma)) / tmp
self.ERF[x, :] = (2 * Esigma * G.dt) / (Ekappa * tmp)
# HORIPML magnetic update coefficients
tmp = (2 * e0 * Hkappa) + G.dt * (Halpha * Hkappa + Hsigma)
self.HRA[x, :] = (2 * e0 + G.dt * Halpha) / tmp
self.HRB[x, :] = (2 * e0 * Hkappa) / tmp
self.HRE[x, :] = ((2 * e0 * Hkappa) - G.dt * (Halpha * Hkappa + Hsigma)) / tmp
tmp = (2 * config.e0 * Hkappa) + G.dt * (Halpha * Hkappa + Hsigma)
self.HRA[x, :] = (2 * config.e0 + G.dt * Halpha) / tmp
self.HRB[x, :] = (2 * config.e0 * Hkappa) / tmp
self.HRE[x, :] = ((2 * config.e0 * Hkappa) - G.dt
* (Halpha * Hkappa + Hsigma)) / tmp
self.HRF[x, :] = (2 * Hsigma * G.dt) / (Hkappa * tmp)
elif G.pmlformulation == 'MRIPML':
tmp = 2 * e0 + G.dt * Ealpha
tmp = 2 * config.e0 + G.dt * Ealpha
self.ERA[x, :] = Ekappa + (G.dt * Esigma) / tmp
self.ERB[x, :] = (2 * e0) / tmp
self.ERE[x, :] = ((2 * e0) - G.dt * Ealpha) / tmp
self.ERB[x, :] = (2 * config.e0) / tmp
self.ERE[x, :] = ((2 * config.e0) - G.dt * Ealpha) / tmp
self.ERF[x, :] = (2 * Esigma * G.dt) / tmp
# MRIPML magnetic update coefficients
tmp = 2 * e0 + G.dt * Halpha
tmp = 2 * config.e0 + G.dt * Halpha
self.HRA[x, :] = Hkappa + (G.dt * Hsigma) / tmp
self.HRB[x, :] = (2 * e0) / tmp
self.HRE[x, :] = ((2 * e0) - G.dt * Halpha) / tmp
self.HRB[x, :] = (2 * config.e0) / tmp
self.HRE[x, :] = ((2 * config.e0) - G.dt * Halpha) / tmp
self.HRF[x, :] = (2 * Hsigma * G.dt) / tmp
def update_electric(self, G):
@@ -283,7 +317,10 @@ class PML(object):
pmlmodule = 'gprMax.cython.pml_updates_electric_' + G.pmlformulation
func = getattr(import_module(pmlmodule), 'order' + str(len(self.CFS)) + '_' + self.direction)
func(self.xs, self.xf, self.ys, self.yf, self.zs, self.zf, hostinfo['ompthreads'], G.updatecoeffsE, G.ID, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, self.EPhi1, self.EPhi2, self.ERA, self.ERB, self.ERE, self.ERF, self.d)
func(self.xs, self.xf, self.ys, self.yf, self.zs, self.zf,
config.hostinfo['ompthreads'], G.updatecoeffsE, G.ID,
G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, self.EPhi1, self.EPhi2,
self.ERA, self.ERB, self.ERE, self.ERF, self.d)
def update_magnetic(self, G):
"""This functions updates magnetic field components with the PML correction.
@@ -294,7 +331,10 @@ class PML(object):
pmlmodule = 'gprMax.cython.pml_updates_magnetic_' + G.pmlformulation
func = getattr(import_module(pmlmodule), 'order' + str(len(self.CFS)) + '_' + self.direction)
func(self.xs, self.xf, self.ys, self.yf, self.zs, self.zf, hostinfo['ompthreads'], G.updatecoeffsH, G.ID, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, self.HPhi1, self.HPhi2, self.HRA, self.HRB, self.HRE, self.HRF, self.d)
func(self.xs, self.xf, self.ys, self.yf, self.zs, self.zf,
config.hostinfo['ompthreads'], G.updatecoeffsH, G.ID,
G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, self.HPhi1, self.HPhi2,
self.HRA, self.HRB, self.HRE, self.HRF, self.d)
def gpu_set_blocks_per_grid(self, G):
"""Set the blocks per grid size used for updating the PML field arrays on a GPU.
@@ -303,7 +343,10 @@ class PML(object):
G (class): Grid class instance - holds essential parameters describing the model.
"""
config.gpus.bpg = (int(np.ceil(((self.EPhi1.shape[1] + 1) * (self.EPhi1.shape[2] + 1) * (self.EPhi1.shape[3] + 1)) / config.gpus.tpb[0])), 1, 1)
config.cuda['gpus'].bpg = (int(np.ceil(((self.EPhi1.shape[1] + 1)
* (self.EPhi1.shape[2] + 1)
* (self.EPhi1.shape[3] + 1))
/ config.cuda['gpus'].tpb[0])), 1, 1)
def gpu_initialise_arrays(self):
"""Initialise PML field and coefficient arrays on GPU."""
@@ -327,42 +370,76 @@ class PML(object):
"""Get update functions from PML kernels.
Args:
kernelselectric: PyCuda SourceModule containing PML kernels for electric updates.
kernelsmagnetic: PyCuda SourceModule containing PML kernels for magnetic updates.
kernelselectric: PyCuda SourceModule containing PML kernels for
electric updates.
kernelsmagnetic: PyCuda SourceModule containing PML kernels for
magnetic updates.
"""
from pycuda.compiler import SourceModule
self.update_electric_gpu = kernelselectric.get_function('order' + str(len(self.CFS)) + '_' + self.direction)
self.update_magnetic_gpu = kernelsmagnetic.get_function('order' + str(len(self.CFS)) + '_' + self.direction)
self.update_electric = kernelselectric.get_function('order' + str(len(self.CFS))
+ '_' + self.direction)
self.update_magnetic = kernelsmagnetic.get_function('order' + str(len(self.CFS))
+ '_' + self.direction)
def gpu_update_electric(self, G):
"""This functions updates electric field components with the PML correction on the GPU.
"""This functions updates electric field components with the PML
correction on the GPU.
Args:
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
"""
self.update_electric_gpu(np.int32(self.xs), np.int32(self.xf), np.int32(self.ys), np.int32(self.yf), np.int32(self.zs), np.int32(self.zf), np.int32(self.EPhi1.shape[1]), np.int32(self.EPhi1.shape[2]), np.int32(self.EPhi1.shape[3]), np.int32(self.EPhi2.shape[1]), np.int32(self.EPhi2.shape[2]), np.int32(self.EPhi2.shape[3]), np.int32(self.thickness), G.ID_gpu.gpudata, G.Ex_gpu.gpudata, G.Ey_gpu.gpudata, G.Ez_gpu.gpudata, G.Hx_gpu.gpudata, G.Hy_gpu.gpudata, G.Hz_gpu.gpudata, self.EPhi1_gpu.gpudata, self.EPhi2_gpu.gpudata, self.ERA_gpu.gpudata, self.ERB_gpu.gpudata, self.ERE_gpu.gpudata, self.ERF_gpu.gpudata, floattype(self.d), block=config.gpus.tpb, grid=config.gpus.bpg)
self.update_electric(np.int32(self.xs), np.int32(self.xf),
np.int32(self.ys), np.int32(self.yf),
np.int32(self.zs), np.int32(self.zf),
np.int32(self.EPhi1.shape[1]), np.int32(self.EPhi1.shape[2]),
np.int32(self.EPhi1.shape[3]), np.int32(self.EPhi2.shape[1]),
np.int32(self.EPhi2.shape[2]), np.int32(self.EPhi2.shape[3]),
np.int32(self.thickness), G.ID_gpu.gpudata,
G.Ex_gpu.gpudata, G.Ey_gpu.gpudata, G.Ez_gpu.gpudata,
G.Hx_gpu.gpudata, G.Hy_gpu.gpudata, G.Hz_gpu.gpudata,
self.EPhi1_gpu.gpudata, self.EPhi2_gpu.gpudata,
self.ERA_gpu.gpudata, self.ERB_gpu.gpudata,
self.ERE_gpu.gpudata, self.ERF_gpu.gpudata,
config.dtypes['float_or_double'](self.d),
block=config.cuda['gpus'].tpb, grid=config.cuda['gpus'].bpg)
def gpu_update_magnetic(self, G):
"""This functions updates magnetic field components with the PML correction on the GPU.
"""This functions updates magnetic field components with the PML
correction on the GPU.
Args:
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
"""
self.update_magnetic_gpu(np.int32(self.xs), np.int32(self.xf), np.int32(self.ys), np.int32(self.yf), np.int32(self.zs), np.int32(self.zf), np.int32(self.HPhi1.shape[1]), np.int32(self.HPhi1.shape[2]), np.int32(self.HPhi1.shape[3]), np.int32(self.HPhi2.shape[1]), np.int32(self.HPhi2.shape[2]), np.int32(self.HPhi2.shape[3]), np.int32(self.thickness), G.ID_gpu.gpudata, G.Ex_gpu.gpudata, G.Ey_gpu.gpudata, G.Ez_gpu.gpudata, G.Hx_gpu.gpudata, G.Hy_gpu.gpudata, G.Hz_gpu.gpudata, self.HPhi1_gpu.gpudata, self.HPhi2_gpu.gpudata, self.HRA_gpu.gpudata, self.HRB_gpu.gpudata, self.HRE_gpu.gpudata, self.HRF_gpu.gpudata, floattype(self.d), block=config.gpus.tpb, grid=config.gpus.bpg)
self.update_magnetic(np.int32(self.xs), np.int32(self.xf),
np.int32(self.ys), np.int32(self.yf),
np.int32(self.zs), np.int32(self.zf),
np.int32(self.HPhi1.shape[1]), np.int32(self.HPhi1.shape[2]),
np.int32(self.HPhi1.shape[3]), np.int32(self.HPhi2.shape[1]),
np.int32(self.HPhi2.shape[2]), np.int32(self.HPhi2.shape[3]),
np.int32(self.thickness), G.ID_gpu.gpudata,
G.Ex_gpu.gpudata, G.Ey_gpu.gpudata, G.Ez_gpu.gpudata,
G.Hx_gpu.gpudata, G.Hy_gpu.gpudata, G.Hz_gpu.gpudata,
self.HPhi1_gpu.gpudata, self.HPhi2_gpu.gpudata,
self.HRA_gpu.gpudata, self.HRB_gpu.gpudata,
self.HRE_gpu.gpudata, self.HRF_gpu.gpudata,
config.dtypes['float_or_double'](self.d),
block=config.cuda['gpus'].tpb, grid=config.cuda['gpus'].bpg)
def build_pmls(G, pbar):
"""
This function builds instances of the PML and calculates the initial
"""This function builds instances of the PML and calculates the initial
parameters and coefficients including setting profile
(based on underlying material er and mr from solid array).
Args:
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
pbar (class): Progress bar class instance.
"""

查看文件

@@ -20,7 +20,7 @@ from collections import OrderedDict
import numpy as np
from gprMax.config import floattype
import gprMax.config as config
class Rx(object):
@@ -29,6 +29,7 @@ class Rx(object):
allowableoutputs = ['Ex', 'Ey', 'Ez', 'Hx', 'Hy', 'Hz', 'Ix', 'Iy', 'Iz']
gpu_allowableoutputs = allowableoutputs[:-3]
defaultoutputs = allowableoutputs[:-3]
maxnumoutputs = 0
def __init__(self):
@@ -43,10 +44,12 @@ class Rx(object):
def gpu_initialise_rx_arrays(G):
"""Initialise arrays on GPU for receiver coordinates and to store field components for receivers.
"""Initialise arrays on GPU for receiver coordinates and to store field
components for receivers.
Args:
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
"""
import pycuda.gpuarray as gpuarray
@@ -58,8 +61,10 @@ def gpu_initialise_rx_arrays(G):
rxcoords[i, 1] = rx.ycoord
rxcoords[i, 2] = rx.zcoord
# Array to store field components for receivers on GPU - rows are field components; columns are iterations; pages are receivers
rxs = np.zeros((len(Rx.gpu_allowableoutputs), G.iterations, len(G.rxs)), dtype=floattype)
# Array to store field components for receivers on GPU - rows are field components;
# columns are iterations; pages are receivers
rxs = np.zeros((Rx.maxnumoutputs, G.iterations, len(G.rxs)),
dtype=config.dtypes['float_or_double'])
# Copy arrays to GPU
rxcoords_gpu = gpuarray.to_gpu(rxcoords)
@@ -72,17 +77,17 @@ def gpu_get_rx_array(rxs_gpu, rxcoords_gpu, G):
"""Copy output from receivers array used on GPU back to receiver objects.
Args:
rxs_gpu (float): numpy array of receiver data from GPU - rows are field components; columns are iterations; pages are receivers.
rxs_gpu (float): numpy array of receiver data from GPU - rows are field
components; columns are iterations; pages are receivers.
rxcoords_gpu (float): numpy array of receiver coordinates from GPU.
G (class): Grid class instance - holds essential parameters describing the model.
G (class): Grid class instance - holds essential parameters
describing the model.
"""
for rx in G.rxs:
for rxgpu in range(len(G.rxs)):
if rx.xcoord == rxcoords_gpu[rxgpu, 0] and rx.ycoord == rxcoords_gpu[rxgpu, 1] and rx.zcoord == rxcoords_gpu[rxgpu, 2]:
rx.outputs['Ex'] = rxs_gpu[0, :, rxgpu]
rx.outputs['Ey'] = rxs_gpu[1, :, rxgpu]
rx.outputs['Ez'] = rxs_gpu[2, :, rxgpu]
rx.outputs['Hx'] = rxs_gpu[3, :, rxgpu]
rx.outputs['Hy'] = rxs_gpu[4, :, rxgpu]
rx.outputs['Hz'] = rxs_gpu[5, :, rxgpu]
if rx.xcoord == rxcoords_gpu[rxgpu, 0] and \
rx.ycoord == rxcoords_gpu[rxgpu, 1] and \
rx.zcoord == rxcoords_gpu[rxgpu, 2]:
for k, v in rx.outputs.items():
v = rxs_gpu[Rx.gpu_allowableoutputs.index(k), :, rxgpu]

查看文件

@@ -22,10 +22,9 @@ from struct import pack
import numpy as np
from gprMax.config import floattype
from gprMax.config import snapsgpu2cpu
from gprMax.cython.snapshots import calculate_snapshot_fields
from gprMax.utilities import round_value
import gprMax.config as config
from .cython.snapshots import calculate_snapshot_fields
from .utilities import round_value
class Snapshot(object):
@@ -48,14 +47,15 @@ class Snapshot(object):
byteorder = 'BigEndian'
# Set format text and string depending on float type
if np.dtype(floattype).name == 'float32':
if config.dtypes['float_or_double'] == np.float32:
floatname = 'Float32'
floatstring = 'f'
elif np.dtype(floattype).name == 'float64':
elif config.dtypes['float_or_double'] == np.float64:
floatname = 'Float64'
floatstring = 'd'
def __init__(self, xs=None, ys=None, zs=None, xf=None, yf=None, zf=None, dx=None, dy=None, dz=None, time=None, filename=None):
def __init__(self, xs=None, ys=None, zs=None, xf=None, yf=None, zf=None,
dx=None, dy=None, dz=None, time=None, filename=None):
"""
Args:
xs, xf, ys, yf, zs, zf (int): Extent of the volume in cells.
@@ -64,6 +64,7 @@ class Snapshot(object):
filename (str): Filename to save to.
"""
self.fieldoutputs = {'electric': True, 'magnetic': True}
self.xs = xs
self.ys = ys
self.zs = zs
@@ -80,8 +81,13 @@ class Snapshot(object):
self.sy = slice(self.ys, self.yf + self.dy, self.dy)
self.sz = slice(self.zs, self.zf + self.dz, self.dz)
self.ncells = self.nx * self.ny * self.nz
self.datasizefield = 3 * np.dtype(floattype).itemsize * self.ncells
self.vtkdatawritesize = 2 * self.datasizefield + 2 * np.dtype(np.uint32).itemsize
self.datasizefield = (3 * np.dtype(config.dtypes['float_or_double']).itemsize
* self.ncells)
self.vtkdatawritesize = ((self.fieldoutputs['electric']
+ self.fieldoutputs['magnetic']) * self.datasizefield
+ (self.fieldoutputs['electric']
+ self.fieldoutputs['magnetic'])
* np.dtype(np.uint32).itemsize)
self.time = time
self.basefilename = filename
@@ -101,12 +107,12 @@ class Snapshot(object):
Hzslice = np.ascontiguousarray(G.Hz[self.sx, self.sy, self.sz])
# Create arrays to hold the field data for snapshot
Exsnap = np.zeros((self.nx, self.ny, self.nz), dtype=floattype)
Eysnap = np.zeros((self.nx, self.ny, self.nz), dtype=floattype)
Ezsnap = np.zeros((self.nx, self.ny, self.nz), dtype=floattype)
Hxsnap = np.zeros((self.nx, self.ny, self.nz), dtype=floattype)
Hysnap = np.zeros((self.nx, self.ny, self.nz), dtype=floattype)
Hzsnap = np.zeros((self.nx, self.ny, self.nz), dtype=floattype)
Exsnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.dtypes['float_or_double'])
Eysnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.dtypes['float_or_double'])
Ezsnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.dtypes['float_or_double'])
Hxsnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.dtypes['float_or_double'])
Hysnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.dtypes['float_or_double'])
Hzsnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.dtypes['float_or_double'])
# Calculate field values at points (comes from averaging field components in cells)
calculate_snapshot_fields(
@@ -140,29 +146,53 @@ class Snapshot(object):
G (class): Grid class instance - holds essential parameters describing the model.
"""
hfield_offset = 3 * np.dtype(floattype).itemsize * self.ncells + np.dtype(np.uint32).itemsize
hfield_offset = (3 * np.dtype(config.dtypes['float_or_double']).itemsize
* self.ncells + np.dtype(np.uint32).itemsize)
self.filehandle = open(self.filename, 'wb')
self.filehandle.write('<?xml version="1.0"?>\n'.encode('utf-8'))
self.filehandle.write('<VTKFile type="ImageData" version="1.0" byte_order="{}">\n'.format(Snapshot.byteorder).encode('utf-8'))
self.filehandle.write('<ImageData WholeExtent="{} {} {} {} {} {}" Origin="0 0 0" Spacing="{:.3} {:.3} {:.3}">\n'.format(self.xs, round_value(self.xf / self.dx), self.ys, round_value(self.yf / self.dy), self.zs, round_value(self.zf / self.dz), self.dx * G.dx, self.dy * G.dy, self.dz * G.dz).encode('utf-8'))
self.filehandle.write('<Piece Extent="{} {} {} {} {} {}">\n'.format(self.xs, round_value(self.xf / self.dx), self.ys, round_value(self.yf / self.dy), self.zs, round_value(self.zf / self.dz)).encode('utf-8'))
self.filehandle.write('<CellData Vectors="E-field H-field">\n'.encode('utf-8'))
self.filehandle.write('<DataArray type="{}" Name="E-field" NumberOfComponents="3" format="appended" offset="0" />\n'.format(Snapshot.floatname).encode('utf-8'))
self.filehandle.write('<DataArray type="{}" Name="H-field" NumberOfComponents="3" format="appended" offset="{}" />\n'.format(Snapshot.floatname, hfield_offset).encode('utf-8'))
self.filehandle.write('<VTKFile type="ImageData" version="1.0" byte_order="{}">\n'
.format(Snapshot.byteorder).encode('utf-8'))
self.filehandle.write('<ImageData WholeExtent="{} {} {} {} {} {}" Origin="0 0 0" Spacing="{:.3} {:.3} {:.3}">\n'
.format(self.xs, round_value(self.xf / self.dx),
self.ys, round_value(self.yf / self.dy), self.zs,
round_value(self.zf / self.dz), self.dx * G.dx,
self.dy * G.dy, self.dz * G.dz).encode('utf-8'))
self.filehandle.write('<Piece Extent="{} {} {} {} {} {}">\n'
.format(self.xs, round_value(self.xf / self.dx),
self.ys, round_value(self.yf / self.dy),
self.zs, round_value(self.zf / self.dz)).encode('utf-8'))
if self.fieldoutputs['electric'] and self.fieldoutputs['magnetic']:
self.filehandle.write('<CellData Vectors="E-field H-field">\n'.encode('utf-8'))
self.filehandle.write('<DataArray type="{}" Name="E-field" NumberOfComponents="3" format="appended" offset="0" />\n'
.format(Snapshot.floatname).encode('utf-8'))
self.filehandle.write('<DataArray type="{}" Name="H-field" NumberOfComponents="3" format="appended" offset="{}" />\n'
.format(Snapshot.floatname, hfield_offset).encode('utf-8'))
elif self.fieldoutputs['electric']:
self.filehandle.write('<CellData Vectors="E-field">\n'.encode('utf-8'))
self.filehandle.write('<DataArray type="{}" Name="E-field" NumberOfComponents="3" format="appended" offset="0" />\n'
.format(Snapshot.floatname).encode('utf-8'))
elif self.fieldoutputs['magnetic']:
self.filehandle.write('<CellData Vectors="H-field">\n'.encode('utf-8'))
self.filehandle.write('<DataArray type="{}" Name="H-field" NumberOfComponents="3" format="appended" offset="0" />\n'
.format(Snapshot.floatname).encode('utf-8'))
self.filehandle.write('</CellData>\n</Piece>\n</ImageData>\n<AppendedData encoding="raw">\n_'.encode('utf-8'))
# Write number of bytes of appended data as UInt32
self.filehandle.write(pack('I', self.datasizefield))
pbar.update(n=4)
self.electric.tofile(self.filehandle)
pbar.update(n=self.datasizefield)
if self.fieldoutputs['electric']:
# Write number of bytes of appended data as UInt32
self.filehandle.write(pack('I', self.datasizefield))
pbar.update(n=4)
self.electric.tofile(self.filehandle)
pbar.update(n=self.datasizefield)
# Write number of bytes of appended data as UInt32
self.filehandle.write(pack('I', self.datasizefield))
pbar.update(n=4)
self.magnetic.tofile(self.filehandle)
pbar.update(n=self.datasizefield)
if self.fieldoutputs['magnetic']:
# Write number of bytes of appended data as UInt32
self.filehandle.write(pack('I', self.datasizefield))
pbar.update(n=4)
self.magnetic.tofile(self.filehandle)
pbar.update(n=self.datasizefield)
self.filehandle.write('\n</AppendedData>\n</VTKFile>'.encode('utf-8'))
self.filehandle.close()
@@ -192,14 +222,22 @@ def gpu_initialise_snapshot_array(G):
# GPU - blocks per grid - according to largest requested snapshot
Snapshot.bpg = (int(np.ceil(((Snapshot.nx_max) * (Snapshot.ny_max) * (Snapshot.nz_max)) / Snapshot.tpb[0])), 1, 1)
# 4D arrays to store snapshots on GPU, e.g. snapEx(time, x, y, z)
numsnaps = 1 if snapsgpu2cpu else len(G.snapshots)
snapEx = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
snapEy = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
snapEz = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
snapHx = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
snapHy = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
snapHz = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=floattype)
# 4D arrays to store snapshots on GPU, e.g. snapEx(time, x, y, z);
# if snapshots are not being stored on the GPU during the simulation then
# they are copied back to the host after each iteration, hence numsnaps = 1
numsnaps = 1 if config.cuda['snapsgpu2cpu'] else len(G.snapshots)
snapEx = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.dtypes['float_or_double'])
snapEy = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.dtypes['float_or_double'])
snapEz = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.dtypes['float_or_double'])
snapHx = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.dtypes['float_or_double'])
snapHy = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.dtypes['float_or_double'])
snapHz = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.dtypes['float_or_double'])
# Copy arrays to GPU
snapEx_gpu = gpuarray.to_gpu(snapEx)
@@ -222,8 +260,8 @@ def gpu_get_snapshot_array(snapEx_gpu, snapEy_gpu, snapEz_gpu, snapHx_gpu, snapH
"""
snap.electric = np.stack((snapEx_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf],
snapEy_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf],
snapEz_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf])).reshape(-1, order='F')
snapEy_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf],
snapEz_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf])).reshape(-1, order='F')
snap.magnetic = np.stack((snapHx_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf],
snapHy_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf],
snapHz_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf])).reshape(-1, order='F')
snapHy_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf],
snapHz_gpu[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf])).reshape(-1, order='F')

查看文件

@@ -20,12 +20,11 @@ from copy import deepcopy
import numpy as np
from gprMax.config import c
from gprMax.config import floattype
from gprMax.grid import Ix
from gprMax.grid import Iy
from gprMax.grid import Iz
from gprMax.utilities import round_value
import gprMax.config as config
from .grid import Ix
from .grid import Iy
from .grid import Iz
from .utilities import round_value
class Source(object):
@@ -52,10 +51,10 @@ class Source(object):
"""
# Waveform values for electric sources - calculated half a timestep later
self.waveformvaluesJ = np.zeros((G.iterations), dtype=floattype)
self.waveformvaluesJ = np.zeros((G.iterations), dtype=config.dtypes['float_or_double'])
# Waveform values for magnetic sources
self.waveformvaluesM = np.zeros((G.iterations), dtype=floattype)
self.waveformvaluesM = np.zeros((G.iterations), dtype=config.dtypes['float_or_double'])
waveform = next(x for x in G.waveforms if x.ID == self.waveformID)
@@ -72,7 +71,8 @@ class VoltageSource(Source):
"""
A voltage source can be a hard source if it's resistance is zero, i.e. the
time variation of the specified electric field component is prescribed.
If it's resistance is non-zero it behaves as a resistive voltage source."""
If it's resistance is non-zero it behaves as a resistive voltage source.
"""
def __init__(self):
super().__init__()
@@ -114,8 +114,7 @@ class VoltageSource(Source):
Ez[i, j, k] = -1 * self.waveformvaluesJ[iteration] / G.dz
def create_material(self, G):
"""
Create a new material at the voltage source location that adds the
"""Create a new material at the voltage source location that adds the
voltage source conductivity to the underlying parameters.
Args:
@@ -231,8 +230,8 @@ def gpu_initialise_src_arrays(sources, G):
import pycuda.gpuarray as gpuarray
srcinfo1 = np.zeros((len(sources), 4), dtype=np.int32)
srcinfo2 = np.zeros((len(sources)), dtype=floattype)
srcwaves = np.zeros((len(sources), G.iterations), dtype=floattype)
srcinfo2 = np.zeros((len(sources)), dtype=config.dtypes['float_or_double'])
srcwaves = np.zeros((len(sources), G.iterations), dtype=config.dtypes['float_or_double'])
for i, src in enumerate(sources):
srcinfo1[i, 0] = src.xcoord
srcinfo1[i, 1] = src.ycoord
@@ -262,9 +261,8 @@ def gpu_initialise_src_arrays(sources, G):
class TransmissionLine(Source):
"""
A transmission line source is a one-dimensional transmission
line which is attached virtually to a grid cell.
"""A transmission line source is a one-dimensional transmission line
which is attached virtually to a grid cell.
"""
def __init__(self, G):
@@ -282,7 +280,7 @@ class TransmissionLine(Source):
# Spatial step of transmission line (N.B if the magic time step is
# used it results in instabilities for certain impedances)
self.dl = np.sqrt(3) * c * G.dt
self.dl = np.sqrt(3) * config.c * G.dt
# Number of cells in the transmission line (initially a long line to
# calculate incident voltage and current); consider putting ABCs/PML at end
@@ -294,16 +292,15 @@ class TransmissionLine(Source):
# Cell position of where line connects to antenna/main grid
self.antpos = 10
self.voltage = np.zeros(self.nl, dtype=floattype)
self.current = np.zeros(self.nl, dtype=floattype)
self.Vinc = np.zeros(G.iterations, dtype=floattype)
self.Iinc = np.zeros(G.iterations, dtype=floattype)
self.Vtotal = np.zeros(G.iterations, dtype=floattype)
self.Itotal = np.zeros(G.iterations, dtype=floattype)
self.voltage = np.zeros(self.nl, dtype=config.dtypes['float_or_double'])
self.current = np.zeros(self.nl, dtype=config.dtypes['float_or_double'])
self.Vinc = np.zeros(G.iterations, dtype=config.dtypes['float_or_double'])
self.Iinc = np.zeros(G.iterations, dtype=config.dtypes['float_or_double'])
self.Vtotal = np.zeros(G.iterations, dtype=config.dtypes['float_or_double'])
self.Itotal = np.zeros(G.iterations, dtype=config.dtypes['float_or_double'])
def calculate_incident_V_I(self, G):
"""
Calculates the incident voltage and current with a long length
"""Calculates the incident voltage and current with a long length
transmission line not connected to the main grid from: http://dx.doi.org/10.1002/mop.10415
Args:
@@ -326,7 +323,7 @@ class TransmissionLine(Source):
G (class): Grid class instance - holds essential parameters describing the model.
"""
h = (c * G.dt - self.dl) / (c * G.dt + self.dl)
h = (config.c * G.dt - self.dl) / (config.c * G.dt + self.dl)
self.voltage[0] = h * (self.voltage[1] - self.abcv0) + self.abcv1
self.abcv0 = self.voltage[0]
@@ -341,10 +338,10 @@ class TransmissionLine(Source):
"""
# Update all the voltage values along the line
self.voltage[1:self.nl] -= self.resistance * (c * G.dt / self.dl) * (self.current[1:self.nl] - self.current[0:self.nl - 1])
self.voltage[1:self.nl] -= self.resistance * (config.c * G.dt / self.dl) * (self.current[1:self.nl] - self.current[0:self.nl - 1])
# Update the voltage at the position of the one-way injector excitation
self.voltage[self.srcpos] += (c * G.dt / self.dl) * self.waveformvaluesJ[iteration]
self.voltage[self.srcpos] += (config.c * G.dt / self.dl) * self.waveformvaluesJ[iteration]
# Update ABC before updating current
self.update_abc(G)
@@ -358,10 +355,10 @@ class TransmissionLine(Source):
"""
# Update all the current values along the line
self.current[0:self.nl - 1] -= (1 / self.resistance) * (c * G.dt / self.dl) * (self.voltage[1:self.nl] - self.voltage[0:self.nl - 1])
self.current[0:self.nl - 1] -= (1 / self.resistance) * (config.c * G.dt / self.dl) * (self.voltage[1:self.nl] - self.voltage[0:self.nl - 1])
# Update the current one cell before the position of the one-way injector excitation
self.current[self.srcpos - 1] += (1 / self.resistance) * (c * G.dt / self.dl) * self.waveformvaluesM[iteration]
self.current[self.srcpos - 1] += (1 / self.resistance) * (config.c * G.dt / self.dl) * self.waveformvaluesM[iteration]
def update_electric(self, iteration, updatecoeffsE, ID, Ex, Ey, Ez, G):
"""Updates electric field value in the main grid from voltage value in the transmission line.
@@ -416,95 +413,3 @@ class TransmissionLine(Source):
self.current[self.antpos] = Iz(i, j, k, G.Hx, G.Hy, G.Hz, G)
self.update_current(iteration, G)
class PlaneWave(Source):
"""A plane wave source. It uses a total-field/scattered-field (TF/SF) formulation."""
def __init__(self, G):
"""
Args:
G (class): Grid class instance - holds essential parameters describing the model.
"""
super(Source, self).__init__()
# Coordinates defining Huygen's surface
self.xs = 0
self.xf = 0
self.ys = 0
self.yf = 0
self.zs = 0
self.zf = 0
# Spherical coordinates defining incident unit wavevector (k)
self.theta = 0 # 0 <= theta <= 180
self.phi = 0 # 0 <= phi <= 360
# Angle that incident electric field makes with k cross z
self.psi = 0 # 0 <= psi <= 360
def calculate_origin(self, G):
"""Calculate origin of TF/SF interface with incident wavefront."""
if self.theta >= 0 and self.theta <= 90:
if self.phi >= 0 and self.phi <= 90:
self.xcoordorigin = 0
self.ycoordorigin = 0
self.zcoordorigin = 0
elif self.phi > 90 and self.phi <= 180:
self.xcoordorigin = G.nx
self.ycoordorigin = 0
self.zcoordorigin = 0
elif self.phi > 180 and self.phi <= 270:
self.xcoordorigin = G.nx
self.ycoordorigin = G.ny
self.zcoordorigin = 0
elif self.phi > 270 and self.phi <= 360:
self.xcoordorigin = 0
self.ycoordorigin = G.ny
self.zcoordorigin = 0
elif self.theta > 90 and self.theta <= 180:
if self.phi >= 0 and self.phi <= 90:
self.xcoordorigin = 0
self.ycoordorigin = 0
self.zcoordorigin = G.nz
elif self.phi > 90 and self.phi <= 180:
self.xcoordorigin = G.nx
self.ycoordorigin = 0
self.zcoordorigin = G.nz
elif self.phi > 180 and self.phi <= 270:
self.xcoordorigin = G.nx
self.ycoordorigin = G.ny
self.zcoordorigin = G.nz
elif self.phi > 270 and self.phi <= 360:
self.xcoordorigin = 0
self.ycoordorigin = G.ny
self.zcoordorigin = G.nz
def calculate_vector_components(self):
"""Calculate components of incident fields."""
self.theta = np.deg2rad(self.theta)
self.phi = np.deg2rad(self.phi)
self.psi = np.deg2rad(self.psi)
# Components of incident unit wavevector
self.kx = np.sin(self.theta) * np.cos(self.phi)
self.ky = np.sin(self.theta) * np.sin(self.phi)
self.kz = np.cos(self.theta)
# Components of incident field vectors
self.Exinc = np.cos(self.psi) * np.sin(self.phi) - np.sin(self.psi) * np.cos(self.theta) * np.cos(self.phi)
self.Eyinc = -np.cos(self.psi) * np.cos(self.phi) - np.sin(self.psi) * np.cos(self.theta) * np.sin(self.phi)
self.Ezinc = np.sin(self.psi) * np.sin(self.theta)
self.Hxinc = np.sin(self.psi) * np.sin(self.phi) + np.cos(self.psi) * np.cos(self.theta) * np.cos(self.phi)
self.Hyinc = -np.sin(self.psi) * np.cos(self.phi) + np.cos(self.psi) * np.cos(self.theta) * np.sin(self.phi)
self.Hzinc = -np.cos(self.psi) * np.sin(self.theta)

查看文件

@@ -27,15 +27,15 @@ import subprocess
from shutil import get_terminal_size
import sys
import textwrap
from time import perf_counter
from colorama import init
from colorama import Fore
from colorama import Style
init()
import numpy as np
from time import process_time
from gprMax.exceptions import GeneralError
from .exceptions import GeneralError
def get_terminal_width():
@@ -86,8 +86,7 @@ def logo(version):
@contextmanager
def open_path_file(path_or_file):
"""
Accepts either a path as a string or a file object and returns a file
"""Accepts either a path as a string or a file object and returns a file
object (http://stackoverflow.com/a/6783680).
Args:
@@ -140,7 +139,7 @@ def round32(value):
def fft_power(waveform, dt):
"""Calculate a FFT of the given waveform of amplitude values;
converted to decibels and shifted so that maximum power is 0dB
converted to decibels and shifted so that maximum power is 0dB
Args:
waveform (ndarray): time domain waveform
@@ -417,4 +416,4 @@ def detect_check_gpus(deviceIDs):
def timer():
"""Function to return the current process wide time in fractional seconds."""
return process_time()
return perf_counter()

查看文件

@@ -18,8 +18,6 @@
import numpy as np
from gprMax.utilities import round_value
class Waveform(object):
"""Definitions of waveform shapes that can be used with sources."""

查看文件

@@ -40,22 +40,22 @@ from tests.analytical_solutions import hertzian_dipole_fs
"""
basepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'models_')
# basepath += 'basic'
basepath += 'basic'
# basepath += 'advanced'
basepath += 'pmls'
# basepath += 'pmls'
# List of available basic test models
# testmodels = ['hertzian_dipole_fs_analytical', '2D_ExHyHz', '2D_EyHxHz', '2D_EzHxHy', 'cylinder_Ascan_2D', 'hertzian_dipole_fs', 'hertzian_dipole_hs', 'hertzian_dipole_dispersive', 'magnetic_dipole_fs', 'pmls']
testmodels = ['hertzian_dipole_fs_analytical', '2D_ExHyHz', '2D_EyHxHz', '2D_EzHxHy', 'cylinder_Ascan_2D', 'hertzian_dipole_fs', 'hertzian_dipole_hs', 'hertzian_dipole_dispersive', 'magnetic_dipole_fs']
# List of available advanced test models
# testmodels = ['antenna_GSSI_1500_fs', 'antenna_MALA_1200_fs']
# List of available PML models
testmodels = ['pml_x0', 'pml_y0', 'pml_z0', 'pml_xmax', 'pml_ymax', 'pml_zmax', 'pml_3D_pec_plate']
# testmodels = ['pml_x0', 'pml_y0', 'pml_z0', 'pml_xmax', 'pml_ymax', 'pml_zmax', 'pml_3D_pec_plate']
# Select a specific model if desired
# testmodels = testmodels[:-1]
testmodels = [testmodels[6]]
# testmodels = [testmodels[6]]
testresults = dict.fromkeys(testmodels)
path = '/rxs/rx1/'
@@ -68,7 +68,7 @@ for i, model in enumerate(testmodels):
# Run model
inputfile = os.path.join(basepath, model + os.path.sep + model + '.in')
api(inputfile, gpu=[None])
api(inputfile, gpu=None)
# Special case for analytical comparison
if model == 'hertzian_dipole_fs_analytical':
@@ -80,12 +80,12 @@ for i, model in enumerate(testmodels):
outputstest = list(filetest[path].keys())
# Arrays for storing time
floattype = filetest[path + outputstest[0]].dtype
float_or_double = filetest[path + outputstest[0]].dtype
timetest = np.linspace(0, (filetest.attrs['Iterations'] - 1) * filetest.attrs['dt'], num=filetest.attrs['Iterations']) / 1e-9
timeref = timetest
# Arrays for storing field data
datatest = np.zeros((filetest.attrs['Iterations'], len(outputstest)), dtype=floattype)
datatest = np.zeros((filetest.attrs['Iterations'], len(outputstest)), dtype=float_or_double)
for ID, name in enumerate(outputstest):
datatest[:, ID] = filetest[path + str(name)][:]
if np.any(np.isnan(datatest[:, ID])):
@@ -117,18 +117,18 @@ for i, model in enumerate(testmodels):
# Check that type of float used to store fields matches
if filetest[path + outputstest[0]].dtype != fileref[path + outputsref[0]].dtype:
print(Fore.RED + 'WARNING: Type of floating point number in test model ({}) does not match type in reference solution ({})\n'.format(filetest[path + outputstest[0]].dtype, fileref[path + outputsref[0]].dtype) + Style.RESET_ALL)
floattyperef = fileref[path + outputsref[0]].dtype
floattypetest = filetest[path + outputstest[0]].dtype
float_or_doubleref = fileref[path + outputsref[0]].dtype
float_or_doubletest = filetest[path + outputstest[0]].dtype
# Arrays for storing time
timeref = np.zeros((fileref.attrs['Iterations']), dtype=floattyperef)
timeref = np.zeros((fileref.attrs['Iterations']), dtype=float_or_doubleref)
timeref = np.linspace(0, (fileref.attrs['Iterations'] - 1) * fileref.attrs['dt'], num=fileref.attrs['Iterations']) / 1e-9
timetest = np.zeros((filetest.attrs['Iterations']), dtype=floattypetest)
timetest = np.zeros((filetest.attrs['Iterations']), dtype=float_or_doubletest)
timetest = np.linspace(0, (filetest.attrs['Iterations'] - 1) * filetest.attrs['dt'], num=filetest.attrs['Iterations']) / 1e-9
# Arrays for storing field data
dataref = np.zeros((fileref.attrs['Iterations'], len(outputsref)), dtype=floattyperef)
datatest = np.zeros((filetest.attrs['Iterations'], len(outputstest)), dtype=floattypetest)
dataref = np.zeros((fileref.attrs['Iterations'], len(outputsref)), dtype=float_or_doubleref)
datatest = np.zeros((filetest.attrs['Iterations'], len(outputstest)), dtype=float_or_doubletest)
for ID, name in enumerate(outputsref):
dataref[:, ID] = fileref[path + str(name)][:]
datatest[:, ID] = filetest[path + str(name)][:]