Added a pre-commit config file and reformatted all the files accordingly by using it.

这个提交包含在:
Sai-Suraj-27
2023-06-26 16:09:39 +05:30
父节点 c71e87e34f
当前提交 f9dd7f2420
共有 155 个文件被更改,包括 11383 次插入8802 次删除

2
.gitattributes vendored
查看文件

@@ -1 +1 @@
tools/Jupyter_notebooks/* linguist-vendored
tools/Jupyter_notebooks/* linguist-vendored

2
.github/FUNDING.yml vendored
查看文件

@@ -10,4 +10,4 @@ liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

14
.pre-commit-config.yaml 普通文件
查看文件

@@ -0,0 +1,14 @@
# See https://pre-commit.com for more information
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
args: ["--line-length", "120"] # Adjust the max line length value as needed.

查看文件

@@ -18,4 +18,4 @@ sphinx:
configuration: docs/source/conf.py
formats:
- pdf
- pdf

查看文件

@@ -24,4 +24,3 @@ dependencies:
- terminaltables
- tqdm
- git+https://github.com/craig-warren/PyEVTK.git

查看文件

@@ -8,7 +8,7 @@ The most computationally intensive parts of gprMax, which are the FDTD solver lo
1. `OpenMP <http://openmp.org>`_ which supports multi-platform shared memory multiprocessing.
2. `NVIDIA CUDA <https://developer.nvidia.com/cuda-toolkit>`_ for NVIDIA GPUs.
3. `OpenCL <https://www.khronos.org/api/opencl>`_ for a wider range of CPU and GPU hardware.
3. `OpenCL <https://www.khronos.org/api/opencl>`_ for a wider range of CPU and GPU hardware.
Additionally, the Message Passing Interface (MPI) can be utilised to implement a simple task farm that can be used to distribute a series of models as independent tasks. This can be useful in many GPR simulations where a B-scan (composed of multiple A-scans) is required. Each A-scan can be task-farmed as an independent model, and within each model, OpenMP or CUDA can still be used for parallelism. This creates mixed mode OpenMP/MPI or CUDA/MPI environments.
@@ -74,7 +74,7 @@ Run one of the test models:
.. note::
* If you want to select a specific GPU card on your system, you can specify an integer after the ``-gpu`` flag. The integer should be the NVIDIA CUDA device ID for a specific GPU card. If it is not specified it defaults to device ID 0.
* If you want to select a specific GPU card on your system, you can specify an integer after the ``-gpu`` flag. The integer should be the NVIDIA CUDA device ID for a specific GPU card. If it is not specified it defaults to device ID 0.
* You can use the ``get_host_spec.py`` module (in ``toolboxes/Utilities``) to help you understand what hardware (CPU/GPU) you have and how gprMax can use it.
@@ -108,7 +108,7 @@ Run one of the test models:
CUDA/MPI
========
Message Passing Interface (MPI) has been utilised to implement a simple task farm that can be used to distribute a series of models as independent tasks. This is described in more detail in the :ref:`HPC <hpc>` section. MPI can be combined with the GPU functionality to allow a series of models to be distributed to multiple GPUs on the same machine (node).
Message Passing Interface (MPI) has been utilised to implement a simple task farm that can be used to distribute a series of models as independent tasks. This is described in more detail in the :ref:`HPC <hpc>` section. MPI can be combined with the GPU functionality to allow a series of models to be distributed to multiple GPUs on the same machine (node).
Example
-------

查看文件

@@ -50,4 +50,3 @@ Results
Input impedance (resistive and reactive) of a bowtie antenna in free space using FDTD (gprMax) and MoM (MATLAB) models.
The results from the FDTD and MoM modelling techniques are in very good agreement. The biggest mismatch occurs in the resistive part of the input impedance at frequencies above 3GHz.

查看文件

@@ -9,30 +9,26 @@
import re
import time
project = 'gprMax'
project = "gprMax"
copyright = f'2015-{time.strftime("%Y")}, The University of Edinburgh, United Kingdom. Authors: Craig Warren, Antonis Giannopoulos, and John Hartley'
author = 'Craig Warren, Antonis Giannopoulos, and John Hartley'
with open('../../gprMax/_version.py', 'r') as fd:
version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]',
fd.read(), re.MULTILINE).group(1)
author = "Craig Warren, Antonis Giannopoulos, and John Hartley"
with open("../../gprMax/_version.py", "r") as fd:
version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', fd.read(), re.MULTILINE).group(1)
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = ['sphinx.ext.mathjax',
'sphinx.ext.autodoc',
'sphinx.ext.napoleon']
extensions = ["sphinx.ext.mathjax", "sphinx.ext.autodoc", "sphinx.ext.napoleon"]
# Figure numbering
numfig = True
templates_path = ['_templates']
templates_path = ["_templates"]
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
html_theme = "sphinx_rtd_theme"
html_static_path = ["_static"]

查看文件

@@ -63,9 +63,9 @@ This example is a basic demonstration of how to use subgrids. The geometry is 3D
:language: python
:linenos:
Much of the functionality demonstrated in this example is standard use of our :ref:`Python API <input-api>`, so mainly the parts that relate to the subgrid will be described here. Lines 20-25 specify the spatial discretisation of the course main grid (5mm) and fine subgrid (1mm). Lines 56-60 specify the centres and radius of the cylinder and coordinates of a bounding box which will be used to set the domain of the subgrid.
Much of the functionality demonstrated in this example is standard use of our :ref:`Python API <input-api>`, so mainly the parts that relate to the subgrid will be described here. Lines 20-25 specify the spatial discretisation of the course main grid (5mm) and fine subgrid (1mm). Lines 56-60 specify the centres and radius of the cylinder and coordinates of a bounding box which will be used to set the domain of the subgrid.
The subgrid object is created on line 63 (providing its extent, the ratio of the spatial resolution, and a string identifier) and then added to the main scene on line 64. Any objects that are to be placed within the subgrid can be added to the subgrid scene (through the variable ``subgrid``) in the same way as the main grid/scene.
The subgrid object is created on line 63 (providing its extent, the ratio of the spatial resolution, and a string identifier) and then added to the main scene on line 64. Any objects that are to be placed within the subgrid can be added to the subgrid scene (through the variable ``subgrid``) in the same way as the main grid/scene.
In lines 67-71 the material used to represent water is created and added to the subgrid. The function ``calculate_water_properties()`` is used to help define the properties of water which is represented as a dispersive material using a single pole Debye model.
@@ -122,14 +122,4 @@ The performance of each PML can be compared with a reference solution using the
:language: python
:linenos:
In lines 43-122 a dictionary with different PML formulations and parameters is created.
In lines 43-122 a dictionary with different PML formulations and parameters is created.

查看文件

@@ -9,7 +9,7 @@ This section highlights some of the key features of gprMax that are useful for G
Python API
==========
There is now a **Python API**, which includes all the functionality of the input file (hash) commands as well as several more advanced features. It allows users to access to gprMax functions directly from Python by importing the gprMax module. This method is recommended for those who prefer to use Python or need access to specific API-only advanced features, and is described in the :ref:`Python API <input-api>` section. There are several advantages to using the Python API:
There is now a **Python API**, which includes all the functionality of the input file (hash) commands as well as several more advanced features. It allows users to access to gprMax functions directly from Python by importing the gprMax module. This method is recommended for those who prefer to use Python or need access to specific API-only advanced features, and is described in the :ref:`Python API <input-api>` section. There are several advantages to using the Python API:
1. Users can take advantage of the Python language - for instance, the structural elements of Python can be utilised more easily.
2. gprMax objects can be used directly within functions, classes, modules and packages. In this way, collections of components can be defined, reused, and modified. For example, complex targets can be imported from a separate module and combined with an antenna from another module.

查看文件

@@ -52,4 +52,4 @@ Here is an example of a job script for running models, e.g. A-scans to make a B-
The ``-t`` tells Grid Engine that we are using a job array followed by a range of integers which will be the IDs for each individual task (model). Task IDs must start from 1, and the total number of tasks in the range should correspond to the number of models you want to run, i.e. the integer with the ``-n`` flag passed to gprMax. The ``-i`` flag is passed to gprMax along with the specific number of the task (model) with the environment variable ``$SGE_TASK_ID``.
A job array means that exactly the same submit script is going to be run multiple times, the only difference between each run is the environment variable ``$SGE_TASK_ID``.
A job array means that exactly the same submit script is going to be run multiple times, the only difference between each run is the environment variable ``$SGE_TASK_ID``.

查看文件

@@ -1 +1 @@
.. include:: ../../toolboxes/AntennaPatterns/README.rst
.. include:: ../../toolboxes/AntennaPatterns/README.rst

查看文件

@@ -1 +1 @@
.. include:: ../../toolboxes/AustinManWoman/README.rst
.. include:: ../../toolboxes/AustinManWoman/README.rst

查看文件

@@ -1 +1 @@
.. include:: ../../toolboxes/DebyeFit/README.rst
.. include:: ../../toolboxes/DebyeFit/README.rst

查看文件

@@ -1 +1 @@
.. include:: ../../toolboxes/GPRAntennaModels/README.rst
.. include:: ../../toolboxes/GPRAntennaModels/README.rst

查看文件

@@ -1 +1 @@
.. include:: ../../toolboxes/LandmineModels/README.rst
.. include:: ../../toolboxes/LandmineModels/README.rst

查看文件

@@ -1 +1 @@
.. include:: ../../toolboxes/Materials/README.rst
.. include:: ../../toolboxes/Materials/README.rst

查看文件

@@ -1 +1 @@
.. include:: ../../toolboxes/Plotting/README.rst
.. include:: ../../toolboxes/Plotting/README.rst

查看文件

@@ -1 +1 @@
.. include:: ../../README.rst
.. include:: ../../README.rst

查看文件

@@ -1 +1 @@
.. include:: ../../toolboxes/STLtoVoxel/README.rst
.. include:: ../../toolboxes/STLtoVoxel/README.rst

查看文件

@@ -1 +1 @@
.. include:: ../../toolboxes/Utilities/README.rst
.. include:: ../../toolboxes/Utilities/README.rst

查看文件

@@ -12,7 +12,7 @@ gprMax has a choice of two methods for building a model to simulate:
1. A **text-based (ASCII) input file**, which can be created with any text editor, and uses a series of gprMax commands which begin with the hash character (``#``). This method is recommended for beginners and those not familiar with Python, and is described in the :ref:`input-hash-cmds` section.
2. A **Python API**, which includes all the functionality of method 1 as well as several more advanced features. This method is recommended for those who prefer to use Python or need access to specific API-only advanced features, and is described in this section of the documentation.
The Python API in gprMax allows users to access to gprMax functions directly from Python through importing the gprMax module. There are several advantages to using the API:
The Python API in gprMax allows users to access to gprMax functions directly from Python through importing the gprMax module. There are several advantages to using the API:
* Users can take advantage of the Python language - for instance, the structural elements of Python can be utilised more easily.
* gprMax objects can be used directly within functions, classes, modules and packages. In this way collections of components can be defined, reused and modified. For example, complex targets can be imported from a separate module and combined with an antenna from another module.
@@ -25,7 +25,7 @@ Example
:download:`antenna_wire_dipole_fs.py <../../examples/antenna_wire_dipole_fs.py>`
This example is used to give an introduction to the gprMax Python API.
This example is used to give an introduction to the gprMax Python API.
.. literalinclude:: ../../examples/antenna_wire_dipole_fs.py
:language: python
@@ -260,7 +260,7 @@ Allows you control of the specific parameters that are used to build each order
.. autoclass:: gprMax.cmds_multiuse.PMLCFS
The CFS values (which are internally specified) used for the default standard first order PML are:
The CFS values (which are internally specified) used for the default standard first order PML are:
* ``alphascalingprofile = 'constant'``
* ``alphascalingdirection = 'forward'``
* ``alphamin = 0``
@@ -275,7 +275,7 @@ The CFS values (which are internally specified) used for the default standard fi
* ``sigmamax = None``
.. note::
* The parameters will be applied to all slabs of the PML that are switched on.
* Using ``None`` for the maximum value of :math:`\sigma` forces gprMax to calculate it internally based on the relative permittivity and permeability of the underlying materials in the model.
* Using ``None`` for the maximum value of :math:`\sigma` forces gprMax to calculate it internally based on the relative permittivity and permeability of the underlying materials in the model.
* ``forward`` direction implies a minimum parameter value at the inner boundary of the PML and maximum parameter value at the edge of the computational domain, ``reverse`` is the opposite.

查看文件

@@ -585,7 +585,7 @@ Allows you to introduce an ellipsoid into the model. The syntax of the command i
#ellipsoid: f1 f2 f3 f4 f5 f6 str1 [c1]
* ``f1 f2 f3`` are the coordinates (x,y,z) of the centre of the ellipsoid.
* ``f1 f2 f3`` are the coordinates (x,y,z) of the centre of the ellipsoid.
* ``f4 f5 f6`` are the coordinates (x,y,z) of the semi-axes of the ellipsoid.
* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials.
* ``c1`` is an optional parameter which can be ``y`` or ``n``, used to switch on and off dielectric smoothing.
@@ -984,4 +984,4 @@ For example to use a PML with 20 cells (thicker than the default 10 cells) on on
.. code-block:: none
#pml_cells: 10 10 20 10 10 20
#pml_cells: 10 10 20 10 10 20

查看文件

@@ -115,8 +115,8 @@ Snapshot files contain a snapshot of the electromagnetic field values of a speci
import gprMax
for i in range(1, 31):
s = gprMax.Snapshot(p1=(0, 0, 0), p2=(x, y, z), dl=(dl, dl, dl),
time=(i/10) * 1e-9,
s = gprMax.Snapshot(p1=(0, 0, 0), p2=(x, y, z), dl=(dl, dl, dl),
time=(i/10) * 1e-9,
filename=fn.with_suffix('').parts[-1] + '_' + str(i))
scene.add(s)

查看文件

@@ -1,8 +1,8 @@
"""An antenna model similar to a GSSI 1.5GHz antenna in free space
This example model demonstrates how to use one of the built-in antenna models.
This example model demonstrates how to use one of the built-in antenna models.
The geometry is 3D and the domain filled with freespace (the default). The
The geometry is 3D and the domain filled with freespace (the default). The
antenna model method is imported from its toolbox and the objects that build the
antenna are iteratively added to the scene. The antenna can be rotated if
desired, by rotating the objects that it is built from before they are added to
@@ -27,7 +27,7 @@ z = 0.220
scene = gprMax.Scene()
title = gprMax.Title(name=fn.with_suffix('').name)
title = gprMax.Title(name=fn.with_suffix("").name)
domain = gprMax.Domain(p1=(x, y, z))
dxdydz = gprMax.Discretisation(p1=(dl, dl, dl))
time_window = gprMax.TimeWindow(time=6e-9)
@@ -39,21 +39,23 @@ scene.add(time_window)
# Import antenna model and add to model
ant_pos = (0.125, 0.094, 0.100)
gssi_objects = antenna_like_GSSI_1500(ant_pos[0], ant_pos[1], ant_pos[2],
resolution=dl)
gssi_objects = antenna_like_GSSI_1500(ant_pos[0], ant_pos[1], ant_pos[2], resolution=dl)
for obj in gssi_objects:
#obj.rotate('z', 90, origin=(ant_pos[0], ant_pos[1], ant_pos[2]))
# obj.rotate('z', 90, origin=(ant_pos[0], ant_pos[1], ant_pos[2]))
scene.add(obj)
gv1 = gprMax.GeometryView(p1=(0, 0, 0), p2=(x, y, z),
dl=(dl, dl, dl), filename='antenna_like_GSSI_1500',
output_type='n')
gv2 = gprMax.GeometryView(p1=(ant_pos[0] - 0.170/2, ant_pos[1] - 0.108/2, ant_pos[2] - 0.050),
p2=(ant_pos[0] + 0.170/2, ant_pos[1] + 0.108/2, ant_pos[2] + 0.010),
dl=(dl, dl, dl), filename='antenna_like_GSSI_1500_pcb',
output_type='f')
#scene.add(gv1)
#scene.add(gv2)
gv1 = gprMax.GeometryView(
p1=(0, 0, 0), p2=(x, y, z), dl=(dl, dl, dl), filename="antenna_like_GSSI_1500", output_type="n"
)
gv2 = gprMax.GeometryView(
p1=(ant_pos[0] - 0.170 / 2, ant_pos[1] - 0.108 / 2, ant_pos[2] - 0.050),
p2=(ant_pos[0] + 0.170 / 2, ant_pos[1] + 0.108 / 2, ant_pos[2] + 0.010),
dl=(dl, dl, dl),
filename="antenna_like_GSSI_1500_pcb",
output_type="f",
)
# scene.add(gv1)
# scene.add(gv2)
# Run model
gprMax.run(scenes=[scene], geometry_only=False, outputfile=fn, gpu=None)

查看文件

@@ -13,71 +13,66 @@ dl = 0.001
scene = gprMax.Scene()
title = gprMax.Title(name=fn.with_suffix('').name)
title = gprMax.Title(name=fn.with_suffix("").name)
dxdydz = gprMax.Discretisation(p1=(dl, dl, dl))
pml = gprMax.PMLProps(thickness=14)
scene.add(title)
scene.add(dxdydz)
scene.add(pml)
timewindow = 4.5e-9 # For 0.3m max
timewindow = 4.5e-9 # For 0.3m max
radii = np.linspace(0.1, 0.3, 20)
theta = np.linspace(3, 357, 60)
fs = np.array([0.040, 0.040, 0.040])
domain_size = np.array([2 * fs[0] + 0.170,
2 * fs[1] + 2 * radii[-1],
2 * fs[2] + 2 * radii[-1]])
domain_size = np.array([2 * fs[0] + 0.170, 2 * fs[1] + 2 * radii[-1], 2 * fs[2] + 2 * radii[-1]])
domain = gprMax.Domain(p1=(domain_size[0], domain_size[1], domain_size[2]))
time_window = gprMax.TimeWindow(time=timewindow)
scene.add(domain)
scene.add(time_window)
antennaposition = np.array([domain_size[0] / 2,
fs[1] + radii[-1],
fs[2] + radii[-1]])
gssi_objects = antenna_like_GSSI_1500(antennaposition[0],
antennaposition[1],
antennaposition[2])
antennaposition = np.array([domain_size[0] / 2, fs[1] + radii[-1], fs[2] + radii[-1]])
gssi_objects = antenna_like_GSSI_1500(antennaposition[0], antennaposition[1], antennaposition[2])
for obj in gssi_objects:
scene.add(obj)
## Can introduce soil model
# soil = gprMax.SoilPeplinski(sand_fraction=0.5, clay_fraction=0.5,
# soil = gprMax.SoilPeplinski(sand_fraction=0.5, clay_fraction=0.5,
# bulk_density=2.0, sand_density=2.66,
# water_fraction_lower=0.001,
# water_fraction_upper=0.25,
# id='mySoil')
# scene.add(soil)
# fbox = gprMax.FractalBox(p1=(0, 0, 0), p2=(domain_size[0], domain_size[1], fs[2] + radii[-1]),
# frac_dim=1.5, weighting=[1, 1, 1], n_materials=50,
# fbox = gprMax.FractalBox(p1=(0, 0, 0), p2=(domain_size[0], domain_size[1], fs[2] + radii[-1]),
# frac_dim=1.5, weighting=[1, 1, 1], n_materials=50,
# mixing_model_id=soil.id, id='mySoilBox')
# scene.add(fbox)
mat = gprMax.Material(er=5, se=0, mr=1, sm=0, id='er5')
mat = gprMax.Material(er=5, se=0, mr=1, sm=0, id="er5")
scene.add(mat)
box = gprMax.Box(p1=(0, 0, 0), p2=(domain_size[0], domain_size[1], fs[2] + radii[-1]),
material_id='er5')
box = gprMax.Box(p1=(0, 0, 0), p2=(domain_size[0], domain_size[1], fs[2] + radii[-1]), material_id="er5")
scene.add(box)
## Save the position of the antenna to file for use when processing results
np.savetxt(fn.with_suffix('').name + '_rxsorigin.txt', antennaposition, fmt="%f")
np.savetxt(fn.with_suffix("").name + "_rxsorigin.txt", antennaposition, fmt="%f")
## Generate receiver points for pattern
for radius in range(len(radii)):
## E-plane circle (yz plane, x=0, phi=pi/2,3pi/2)
x = radii[radius] * np.sin(theta * np.pi /180) * np.cos(90 * np.pi / 180)
y = radii[radius] * np.sin(theta * np.pi /180) * np.sin(90 * np.pi / 180)
z = radii[radius] * np.cos(theta * np.pi /180)
x = radii[radius] * np.sin(theta * np.pi / 180) * np.cos(90 * np.pi / 180)
y = radii[radius] * np.sin(theta * np.pi / 180) * np.sin(90 * np.pi / 180)
z = radii[radius] * np.cos(theta * np.pi / 180)
for rxpt in range(len(theta)):
rx = gprMax.Rx(p1=(x[rxpt] + antennaposition[0],
y[rxpt] + antennaposition[1],
z[rxpt] + antennaposition[2]))
rx = gprMax.Rx(p1=(x[rxpt] + antennaposition[0], y[rxpt] + antennaposition[1], z[rxpt] + antennaposition[2]))
scene.add(rx)
gv1 = gprMax.GeometryView(p1=(0, 0, 0), p2=(domain_size[0], domain_size[1], domain_size[2]),
dl=(dl, dl, dl), filename='antenna_like_GSSI_1500_patterns',
output_type='n')
gv1 = gprMax.GeometryView(
p1=(0, 0, 0),
p2=(domain_size[0], domain_size[1], domain_size[2]),
dl=(dl, dl, dl),
filename="antenna_like_GSSI_1500_patterns",
output_type="n",
)
scene.add(gv1)
gprMax.run(scenes=[scene], geometry_only=True, outputfile=fn, gpu=None)
gprMax.run(scenes=[scene], geometry_only=True, outputfile=fn, gpu=None)

查看文件

@@ -1,8 +1,8 @@
"""An antenna model similar to a MALA 1.2GHz antenna in free space
This example model demonstrates how to use one of the built-in antenna models.
This example model demonstrates how to use one of the built-in antenna models.
The geometry is 3D and the domain filled with freespace (the default). The
The geometry is 3D and the domain filled with freespace (the default). The
antenna model method is imported from its toolbox and the objects that build the
antenna are iteratively added to the scene.
"""
@@ -25,7 +25,7 @@ z = 0.220
scene = gprMax.Scene()
title = gprMax.Title(name=fn.with_suffix('').name)
title = gprMax.Title(name=fn.with_suffix("").name)
domain = gprMax.Domain(p1=(x, y, z))
dxdydz = gprMax.Discretisation(p1=(dl, dl, dl))
time_window = gprMax.TimeWindow(time=6e-9)
@@ -37,8 +37,7 @@ scene.add(time_window)
# Import antenna model and add to model
ant_pos = (0.132, 0.095, 0.100)
mala_objects = antenna_like_MALA_1200(ant_pos[0], ant_pos[1], ant_pos[2],
resolution=dl)
mala_objects = antenna_like_MALA_1200(ant_pos[0], ant_pos[1], ant_pos[2], resolution=dl)
for obj in mala_objects:
scene.add(obj)

查看文件

@@ -2,7 +2,7 @@
This example model demonstrates how to a the transmission line source, which
allows s-parameters and input impedances to be calculated after the simulation
has run.
has run.
Both API and hash commands are given next to each other as a comparison of the
two different methods that can be used to build a model.
@@ -14,45 +14,42 @@ import gprMax
fn = Path(__file__)
title = gprMax.Title(name=fn.with_suffix('').name)
#title: antenna_wire_dipole_fs
title = gprMax.Title(name=fn.with_suffix("").name)
# title: antenna_wire_dipole_fs
domain = gprMax.Domain(p1=(0.050, 0.050, 0.200))
#domain: 0.050 0.050 0.200
# domain: 0.050 0.050 0.200
dxdydz = gprMax.Discretisation(p1=(0.001, 0.001, 0.001))
#dx_dy_dz: 0.001 0.001 0.001
# dx_dy_dz: 0.001 0.001 0.001
time_window = gprMax.TimeWindow(time=10e-9)
#time_window: 10e-9
# time_window: 10e-9
waveform = gprMax.Waveform(wave_type='gaussian', amp=1, freq=1e9, id='mypulse')
#waveform: gaussian 1 1e9 mypulse
waveform = gprMax.Waveform(wave_type="gaussian", amp=1, freq=1e9, id="mypulse")
# waveform: gaussian 1 1e9 mypulse
transmission_line = gprMax.TransmissionLine(polarisation='z',
p1=(0.025, 0.025, 0.100),
resistance=73,
waveform_id='mypulse')
#transmission_line: z 0.025 0.025 0.100 73 mypulse
transmission_line = gprMax.TransmissionLine(
polarisation="z", p1=(0.025, 0.025, 0.100), resistance=73, waveform_id="mypulse"
)
# transmission_line: z 0.025 0.025 0.100 73 mypulse
## 150mm length wire
e1 = gprMax.Edge(p1=(0.025, 0.025, 0.025),
p2=(0.025, 0.025, 0.175),
material_id='pec')
#edge: 0.025 0.025 0.025 0.025 0.025 0.175 pec
e1 = gprMax.Edge(p1=(0.025, 0.025, 0.025), p2=(0.025, 0.025, 0.175), material_id="pec")
# edge: 0.025 0.025 0.025 0.025 0.025 0.175 pec
## 1mm gap at centre of dipole
e2 = gprMax.Edge(p1=(0.025, 0.025, 0.100),
p2=(0.025, 0.025, 0.101),
material_id='free_space')
#edge: 0.025 0.025 0.100 0.025 0.025 0.101 free_space
e2 = gprMax.Edge(p1=(0.025, 0.025, 0.100), p2=(0.025, 0.025, 0.101), material_id="free_space")
# edge: 0.025 0.025 0.100 0.025 0.025 0.101 free_space
gv = gprMax.GeometryView(p1=(0.020, 0.020, 0.020),
p2=(0.030, 0.030, 0.180),
dl=(0.001, 0.001, 0.001),
filename=fn.with_suffix('').name,
output_type='n')
#geometry_view: 0.020 0.020 0.020 0.030 0.030 0.180 0.001 0.001 0.001 antenna_wire_dipole_fs f
gv = gprMax.GeometryView(
p1=(0.020, 0.020, 0.020),
p2=(0.030, 0.030, 0.180),
dl=(0.001, 0.001, 0.001),
filename=fn.with_suffix("").name,
output_type="n",
)
# geometry_view: 0.020 0.020 0.020 0.030 0.030 0.180 0.001 0.001 0.001 antenna_wire_dipole_fs f
# Create a scene
scene = gprMax.Scene()
@@ -69,4 +66,4 @@ scene.add(e2)
scene.add(gv)
# Run the simulation
gprMax.run(scenes=[scene], n=1, outputfile=fn)
gprMax.run(scenes=[scene], n=1, outputfile=fn)

查看文件

@@ -12,4 +12,4 @@
#box: 0 0 0 0.240 0.170 0.002 half_space
#cylinder: 0.120 0.080 0 0.120 0.080 0.002 0.010 pec
#geometry_view: 0 0 0 0.240 0.210 0.002 0.002 0.002 0.002 cylinder_half_space n
#geometry_view: 0 0 0 0.240 0.210 0.002 0.002 0.002 0.002 cylinder_half_space n

查看文件

@@ -12,4 +12,4 @@
#rx_steps: 0.002 0 0
#box: 0 0 0 0.240 0.170 0.002 half_space
#cylinder: 0.120 0.080 0 0.120 0.080 0.002 0.010 pec
#cylinder: 0.120 0.080 0 0.120 0.080 0.002 0.010 pec

查看文件

@@ -1,16 +1,16 @@
"""B-scan using a antenna model.
"""B-scan using a antenna model.
This example model demonstrates how to create a B-scan using an antenna model.
The key part of this example is the concept of moving the antenna model in steps
within the model domain to create multiple A-scans that build up the B-scan.
within the model domain to create multiple A-scans that build up the B-scan.
Each A-scan requires its own scene and a list of scenes it built up using a for
loop. A different scene is required for each A-scan because the model geometry is
changing, as the antenna geometry must be moved to a new position. This is in
changing, as the antenna geometry must be moved to a new position. This is in
contrast to simpler models that may use a Hertzian dipole source which has no
associated 'geometry' and can be moved within a model without having to change
the scene. When the all the scenes are created, the list of scenes is then passed
to gprMax to run, noting the number of times 'n' gprMax is run corresponds to the
to gprMax to run, noting the number of times 'n' gprMax is run corresponds to the
number of scenes, i.e. A-scans.
"""
@@ -36,7 +36,7 @@ scenes = []
for i in range(1, 55):
scene = gprMax.Scene()
title = gprMax.Title(name=fn.with_suffix('').name)
title = gprMax.Title(name=fn.with_suffix("").name)
domain = gprMax.Domain(p1=(x, y, z))
dxdydz = gprMax.Discretisation(p1=(dl, dl, dl))
time_window = gprMax.TimeWindow(time=6e-9)
@@ -46,25 +46,23 @@ for i in range(1, 55):
scene.add(dxdydz)
scene.add(time_window)
mat = gprMax.Material(er=6, se=0, mr=1, sm=0, id='half_space')
c1 = gprMax.Cylinder(p1=(0.240, 0, 0.080), p2=(0.240, 0.148, 0.080), r=0.010,
material_id='pec')
mat = gprMax.Material(er=6, se=0, mr=1, sm=0, id="half_space")
c1 = gprMax.Cylinder(p1=(0.240, 0, 0.080), p2=(0.240, 0.148, 0.080), r=0.010, material_id="pec")
scene.add(mat)
scene.add(c1)
# Import antenna model and add to model
ant_pos = (0.125, 0.094, 0.100)
gssi_objects = antenna_like_GSSI_1500(0.105 + i * 0.005, 0.074, 0.170,
resolution=dl)
gssi_objects = antenna_like_GSSI_1500(0.105 + i * 0.005, 0.074, 0.170, resolution=dl)
for obj in gssi_objects:
scene.add(obj)
gv1 = gprMax.GeometryView(p1=(0, 0, 0), p2=(x, y, z), dl=(dl, dl, dl),
filename=fn.with_suffix('').name,
output_type='n')
gv1 = gprMax.GeometryView(
p1=(0, 0, 0), p2=(x, y, z), dl=(dl, dl, dl), filename=fn.with_suffix("").name, output_type="n"
)
# scene.add(gv1)
scenes.append(scene)
# Run model
gprMax.run(scenes=scenes, n=len(scenes), geometry_only=False, outputfile=fn, gpu=None)
gprMax.run(scenes=scenes, n=len(scenes), geometry_only=False, outputfile=fn, gpu=None)

查看文件

@@ -11,4 +11,4 @@
#fractal_box: 0 0 0 0.15 0.15 0.070 1.5 1 1 1 50 my_soil my_soil_box
#add_surface_roughness: 0 0 0.070 0.15 0.15 0.070 1.5 1 1 0.065 0.080 my_soil_box
#geometry_view: 0 0 0 0.15 0.15 0.1 0.001 0.001 0.001 heterogeneous_soil n
#geometry_view: 0 0 0 0.15 0.15 0.1 0.001 0.001 0.001 heterogeneous_soil n

查看文件

@@ -1 +1 @@
**Tip:** ``ipynb`` files can be viewed on GitHub. Just click them.
**Tip:** ``ipynb`` files can be viewed on GitHub. Just click them.

查看文件

@@ -2,10 +2,10 @@
This example model demonstrates how to use subgrids at a basic level.
The geometry is 3D (required for any use of subgrids) and is of a water-filled
The geometry is 3D (required for any use of subgrids) and is of a water-filled
cylindrical object in freespace. The subgrid encloses the cylinderical object
using a fine spatial discretisation (1mm), and a courser spatial discretisation
(5mm) is used in the rest of the model (main grid). A simple Hertzian dipole
using a fine spatial discretisation (1mm), and a courser spatial discretisation
(5mm) is used in the rest of the model (main grid). A simple Hertzian dipole
source is used with a waveform shaped as the first derivative of a gaussian.
"""
@@ -39,9 +39,8 @@ dxdydz = gprMax.Discretisation(p1=(dl, dl, dl))
domain = gprMax.Domain(p1=(x, y, z))
time_window = gprMax.TimeWindow(time=tw)
wf = gprMax.Waveform(wave_type='gaussiandot', amp=1, freq=1.5e9, id='mypulse')
hd = gprMax.HertzianDipole(polarisation='z', p1=(0.205, 0.400, 0.250),
waveform_id='mypulse')
wf = gprMax.Waveform(wave_type="gaussiandot", amp=1, freq=1.5e9, id="mypulse")
hd = gprMax.HertzianDipole(polarisation="z", p1=(0.205, 0.400, 0.250), waveform_id="mypulse")
rx = gprMax.Rx(p1=(0.245, 0.400, 0.250))
scene.add(title)
@@ -60,36 +59,40 @@ sg1 = (c1[0] - r, c1[1] - r, c1[2])
sg2 = (c2[0] + r, c2[1] + r, c2[2])
# Create subgrid
subgrid = gprMax.SubGridHSG(p1=sg1, p2=sg2, ratio=ratio, id='sg')
subgrid = gprMax.SubGridHSG(p1=sg1, p2=sg2, ratio=ratio, id="sg")
scene.add(subgrid)
# Create water material
eri, er, tau, sig = calculate_water_properties()
water = gprMax.Material(er=eri, se=sig, mr=1, sm=0, id='water')
water = gprMax.Material(er=eri, se=sig, mr=1, sm=0, id="water")
subgrid.add(water)
water = gprMax.AddDebyeDispersion(poles=1, er_delta=[er - eri], tau=[tau], material_ids=['water'])
water = gprMax.AddDebyeDispersion(poles=1, er_delta=[er - eri], tau=[tau], material_ids=["water"])
subgrid.add(water)
# Add cylinder to subgrid
cylinder = gprMax.Cylinder(p1=c1, p2=c2, r=r, material_id='water')
cylinder = gprMax.Cylinder(p1=c1, p2=c2, r=r, material_id="water")
subgrid.add(cylinder)
# Create some geometry views for both subgrid and main grid
gvsg = gprMax.GeometryView(p1=sg1, p2=sg2, dl=(dl_sg, dl_sg, dl_sg),
filename=fn.with_suffix('').parts[-1] + '_sg',
output_type='n')
gvsg = gprMax.GeometryView(
p1=sg1, p2=sg2, dl=(dl_sg, dl_sg, dl_sg), filename=fn.with_suffix("").parts[-1] + "_sg", output_type="n"
)
subgrid.add(gvsg)
gv1 = gprMax.GeometryView(p1=(0, 0, 0), p2=(x, y, z), dl=(dl, dl, dl),
filename=fn.with_suffix('').parts[-1],
output_type='n')
gv1 = gprMax.GeometryView(
p1=(0, 0, 0), p2=(x, y, z), dl=(dl, dl, dl), filename=fn.with_suffix("").parts[-1], output_type="n"
)
scene.add(gv1)
# Create some snapshots of entire domain
for i in range(5):
s = gprMax.Snapshot(p1=(0, 0, 0), p2=(x, y, z), dl=(dl, dl, dl),
time=(i + 0.5) * 1e-9,
filename=fn.with_suffix('').parts[-1] + '_' + str(i + 1))
s = gprMax.Snapshot(
p1=(0, 0, 0),
p2=(x, y, z),
dl=(dl, dl, dl),
time=(i + 0.5) * 1e-9,
filename=fn.with_suffix("").parts[-1] + "_" + str(i + 1),
)
scene.add(s)
gprMax.run(scenes=[scene], n=1, geometry_only=False, outputfile=fn, subgrid=True, autotranslate=True)

查看文件

@@ -1,16 +1,16 @@
"""GPR antenna model (like a GSSI 400MHz antenna) over layered media with a
"""GPR antenna model (like a GSSI 400MHz antenna) over layered media with a
rough subsurface interface.
This example model demonstrates how to use subgrids at a more advanced level -
This example model demonstrates how to use subgrids at a more advanced level -
combining use of an imported antenna model and rough subsurface interface.
The geometry is 3D (required for any use of subgrids) and is of a 2 layered
subsurface. The top layer in a sandy soil and the bottom layer a soil with
higher permittivity (both have some simple conductive loss). There is a rough
interface between the soil layers. A GPR antenna model (like a GSSI 400MHz
antenna) is imported and placed on the surface of the layered media. The antenna
is meshed using a subgrid with a fine spatial discretisation (1mm), and a
courser spatial discretisation (9mm) is used in the rest of the model (main
antenna) is imported and placed on the surface of the layered media. The antenna
is meshed using a subgrid with a fine spatial discretisation (1mm), and a
courser spatial discretisation (9mm) is used in the rest of the model (main
grid).
"""
@@ -38,7 +38,7 @@ y = 1
z = 2
# Time window
# Estimated two way travel time over 1 metre in material with highest
# Estimated two way travel time over 1 metre in material with highest
# permittivity, slowest velocity.
tw = 2 / 3e8 * (np.sqrt(3.2) + np.sqrt(9))
@@ -72,21 +72,19 @@ sg_y1 = antenna_p[1] + antenna_case[1] / 2 + bounding_box
sg_z1 = antenna_p[2] + antenna_case[2] + bounding_box
# Create subgrid
sg = gprMax.SubGridHSG(p1=[sg_x0, sg_y0, sg_z0],
p2=[sg_x1, sg_y1, sg_z1],
ratio=ratio, id='sg')
sg = gprMax.SubGridHSG(p1=[sg_x0, sg_y0, sg_z0], p2=[sg_x1, sg_y1, sg_z1], ratio=ratio, id="sg")
scene.add(sg)
# Create and add a box of homogeneous material to main grid - sandy_soil
sandy_soil = gprMax.Material(er=3.2, se=0.397e-3, mr=1, sm=0, id='sandy_soil')
sandy_soil = gprMax.Material(er=3.2, se=0.397e-3, mr=1, sm=0, id="sandy_soil")
scene.add(sandy_soil)
b1 = gprMax.Box(p1=(0, 0, 0), p2=(x, y, antenna_p[2]), material_id='sandy_soil')
b1 = gprMax.Box(p1=(0, 0, 0), p2=(x, y, antenna_p[2]), material_id="sandy_soil")
scene.add(b1)
# Position box of sandy_soil in the subgrid.
# It has to be positioned manually because it traverses the main grid/subgrid
# interface. Grid traversal is when objects extend beyond the outer surface.
# Setting autotranslate to false allows you to place objects beyond the outer
# interface. Grid traversal is when objects extend beyond the outer surface.
# Setting autotranslate to false allows you to place objects beyond the outer
# surface.
# PML separation from the outer surface
@@ -101,8 +99,7 @@ h = antenna_p[2] - sg_z0 + (ps + pc + isos) * dl_sg
# Create and add a box of homogeneous material to subgrid - sandy_soil
sg.add(sandy_soil)
b2 = gprMax.Box(p1=(0, 0, 0),
p2=(411 * dl_sg, 411 * dl_sg, h), material_id='sandy_soil')
b2 = gprMax.Box(p1=(0, 0, 0), p2=(411 * dl_sg, 411 * dl_sg, h), material_id="sandy_soil")
# Set autotranslate for the box object to false
b2.autotranslate = False
sg.add(b2)
@@ -113,39 +110,49 @@ for obj in gssi_objects:
sg.add(obj)
# Create and add a homogeneous material with a rough surface
soil = gprMax.Material(er=9, se=0.397e-3, mr=1, sm=0, id='soil')
soil = gprMax.Material(er=9, se=0.397e-3, mr=1, sm=0, id="soil")
scene.add(soil)
fb = gprMax.FractalBox(p1=(0, 0, 0), p2=(3, 1, 1), frac_dim=1.5,
weighting=(1, 1, 1), n_materials=1, mixing_model_id='soil', id='fbox', seed=1)
fb = gprMax.FractalBox(
p1=(0, 0, 0),
p2=(3, 1, 1),
frac_dim=1.5,
weighting=(1, 1, 1),
n_materials=1,
mixing_model_id="soil",
id="fbox",
seed=1,
)
scene.add(fb)
rough_surf = gprMax.AddSurfaceRoughness(p1=(0, 0, 1), p2=(3, 1, 1),
frac_dim=1.5, weighting=(1, 1),
limits=(0.4, 1.2),
fractal_box_id='fbox', seed=1)
rough_surf = gprMax.AddSurfaceRoughness(
p1=(0, 0, 1), p2=(3, 1, 1), frac_dim=1.5, weighting=(1, 1), limits=(0.4, 1.2), fractal_box_id="fbox", seed=1
)
scene.add(rough_surf)
# Create some snapshots and geometry views
for i in range(1, 51):
snap = gprMax.Snapshot(p1=(0, y / 2, 0),
p2=(x, y / 2 + dl, z),
dl=(dl, dl, dl),
filename=Path(*parts[:-1], f'{parts[-1]}_{str(i)}').name,
time=i * tw / 50,)
snap = gprMax.Snapshot(
p1=(0, y / 2, 0),
p2=(x, y / 2 + dl, z),
dl=(dl, dl, dl),
filename=Path(*parts[:-1], f"{parts[-1]}_{str(i)}").name,
time=i * tw / 50,
)
scene.add(snap)
gvsg = gprMax.GeometryView(p1=(sg_x0, sg_y0, sg_z0), p2=(sg_x1, sg_y1, sg_z1),
dl=(dl_sg, dl_sg, dl_sg),
filename=fn.with_suffix('').parts[-1] + '_sg',
output_type='n')
gvsg = gprMax.GeometryView(
p1=(sg_x0, sg_y0, sg_z0),
p2=(sg_x1, sg_y1, sg_z1),
dl=(dl_sg, dl_sg, dl_sg),
filename=fn.with_suffix("").parts[-1] + "_sg",
output_type="n",
)
sg.add(gvsg)
gv1 = gprMax.GeometryView(p1=(0, 0, 0),
p2=domain.props.p1,
dl=dl,
filename=fn.with_suffix('').parts[-1],
output_type='n')
gv1 = gprMax.GeometryView(
p1=(0, 0, 0), p2=domain.props.p1, dl=dl, filename=fn.with_suffix("").parts[-1], output_type="n"
)
scene.add(gv1)
gprMax.run(scenes=[scene], n=1, geometry_only=True, outputfile=fn, subgrid=True, autotranslate=True)

查看文件

@@ -1,4 +1,4 @@
[build-system]
requires = ['setuptools', 'wheel', 'numpy>=1.19.0', 'Cython>=0.29.21',
'jinja2']
build-backend = "setuptools.build_meta"
build-backend = "setuptools.build_meta"

查看文件

@@ -22,18 +22,41 @@ from .cmds_geometry.geometry_objects_read import GeometryObjectsRead
from .cmds_geometry.plate import Plate
from .cmds_geometry.sphere import Sphere
from .cmds_geometry.triangle import Triangle
from .cmds_multiuse import (PMLCFS, AddDebyeDispersion, AddDrudeDispersion,
AddLorentzDispersion, GeometryObjectsWrite,
GeometryView, HertzianDipole, MagneticDipole,
Material, MaterialList, MaterialRange, Rx, RxArray,
Snapshot, SoilPeplinski, TransmissionLine,
VoltageSource, Waveform)
from .cmds_singleuse import (Discretisation, Domain, ExcitationFile,
OMPThreads, PMLProps, RxSteps, SrcSteps,
TimeStepStabilityFactor, TimeWindow, Title)
from .cmds_multiuse import (
PMLCFS,
AddDebyeDispersion,
AddDrudeDispersion,
AddLorentzDispersion,
GeometryObjectsWrite,
GeometryView,
HertzianDipole,
MagneticDipole,
Material,
MaterialList,
MaterialRange,
Rx,
RxArray,
Snapshot,
SoilPeplinski,
TransmissionLine,
VoltageSource,
Waveform,
)
from .cmds_singleuse import (
Discretisation,
Domain,
ExcitationFile,
OMPThreads,
PMLProps,
RxSteps,
SrcSteps,
TimeStepStabilityFactor,
TimeWindow,
Title,
)
from .gprMax import run as run
from .hash_cmds_file import user_libs_fn_to_scene_obj
from .scene import Scene
from .subgrids.user_objects import SubGridHSG
__name__ = 'gprMax'
__name__ = "gprMax"

查看文件

@@ -2,7 +2,7 @@
import gprMax.gprMax
if __name__ == '__main__':
if __name__ == "__main__":
gprMax.gprMax.cli()
# Code profiling

查看文件

@@ -1,4 +1,4 @@
# This is where the version number is set and read by setup.py and conf.py (for the docs)
__version__ = '4.0.0b0'
codename = 'Càrn Mòr'
__version__ = "4.0.0b0"
codename = "Càrn Mòr"

查看文件

@@ -32,23 +32,23 @@ class AddGrass(UserObjectGeometry):
"""Adds grass with roots to a FractalBox class in the model.
Attributes:
p1: list of the lower left (x,y,z) coordinates of a surface on a
p1: list of the lower left (x,y,z) coordinates of a surface on a
FractalBox class.
p2: list of the upper right (x,y,z) coordinates of a surface on a
p2: list of the upper right (x,y,z) coordinates of a surface on a
FractalBox class.
frac_dim: float for the fractal dimension which, for an orthogonal
frac_dim: float for the fractal dimension which, for an orthogonal
parallelepiped, should take values between zero and three.
limits: list to define lower and upper limits for a range over which
limits: list to define lower and upper limits for a range over which
the height of the blades of grass can vary.
n_blades:int for the number of blades of grass that should be
n_blades:int for the number of blades of grass that should be
applied to the surface area.
fractal_box_id: string identifier for the FractalBox class that the
fractal_box_id: string identifier for the FractalBox class that the
grass should be applied to.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#add_grass'
self.hash = "#add_grass"
def rotate(self, axis, angle, origin=None):
"""Set parameters for rotation."""
@@ -59,26 +59,26 @@ class AddGrass(UserObjectGeometry):
def _do_rotate(self):
"""Perform rotation."""
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
pts = np.array([self.kwargs["p1"], self.kwargs["p2"]])
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
self.kwargs['p1'] = tuple(rot_pts[0, :])
self.kwargs['p2'] = tuple(rot_pts[1, :])
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def create(self, grid, uip):
"""Add Grass to fractal box."""
try:
p1 = self.kwargs['p1']
p2 = self.kwargs['p2']
fractal_box_id = self.kwargs['fractal_box_id']
frac_dim = self.kwargs['frac_dim']
limits = self.kwargs['limits']
n_blades = self.kwargs['n_blades']
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
fractal_box_id = self.kwargs["fractal_box_id"]
frac_dim = self.kwargs["frac_dim"]
limits = self.kwargs["limits"]
n_blades = self.kwargs["n_blades"]
except KeyError:
logger.exception(f'{self.__str__()} requires at least eleven parameters')
logger.exception(f"{self.__str__()} requires at least eleven parameters")
raise
try:
seed = self.kwargs['seed']
seed = self.kwargs["seed"]
except KeyError:
seed = None
@@ -90,7 +90,7 @@ class AddGrass(UserObjectGeometry):
try:
volume = volumes[0]
except NameError:
logger.exception(f'{self.__str__()} cannot find FractalBox {fractal_box_id}')
logger.exception(f"{self.__str__()} cannot find FractalBox {fractal_box_id}")
raise
p1, p2 = uip.check_box_points(p1, p2, self.__str__())
@@ -98,87 +98,96 @@ class AddGrass(UserObjectGeometry):
xf, yf, zf = p2
if frac_dim < 0:
logger.exception(f'{self.__str__()} requires a positive value for ' +
'the fractal dimension')
logger.exception(f"{self.__str__()} requires a positive value for " + "the fractal dimension")
raise ValueError
if limits[0] < 0 or limits[1] < 0:
logger.exception(f'{self.__str__()} requires a positive value for ' +
'the minimum and maximum heights for grass blades')
logger.exception(
f"{self.__str__()} requires a positive value for " + "the minimum and maximum heights for grass blades"
)
raise ValueError
# Check for valid orientations
if xs == xf:
if ys == yf or zs == zf:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if xs != volume.xs and xs != volume.xf:
logger.exception(f'{self.__str__()} must specify external surfaces on a fractal box')
logger.exception(f"{self.__str__()} must specify external surfaces on a fractal box")
raise ValueError
fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx))
# xminus surface
if xs == volume.xs:
logger.exception(f'{self.__str__()} grass can only be specified ' +
'on surfaces in the positive axis direction')
logger.exception(
f"{self.__str__()} grass can only be specified " + "on surfaces in the positive axis direction"
)
raise ValueError
# xplus surface
elif xf == volume.xf:
if fractalrange[1] > grid.nx:
logger.exception(f'{self.__str__()} cannot apply grass to ' +
'fractal box as it would exceed the domain ' +
'size in the x direction')
logger.exception(
f"{self.__str__()} cannot apply grass to "
+ "fractal box as it would exceed the domain "
+ "size in the x direction"
)
raise ValueError
requestedsurface = 'xplus'
requestedsurface = "xplus"
elif ys == yf:
if xs == xf or zs == zf:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if ys != volume.ys and ys != volume.yf:
logger.exception(f'{self.__str__()} must specify external surfaces on a fractal box')
logger.exception(f"{self.__str__()} must specify external surfaces on a fractal box")
raise ValueError
fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy))
# yminus surface
if ys == volume.ys:
logger.exception(f'{self.__str__()} grass can only be specified ' +
'on surfaces in the positive axis direction')
logger.exception(
f"{self.__str__()} grass can only be specified " + "on surfaces in the positive axis direction"
)
raise ValueError
# yplus surface
elif yf == volume.yf:
if fractalrange[1] > grid.ny:
logger.exception(f'{self.__str__()} cannot apply grass to ' +
'fractal box as it would exceed the domain ' +
'size in the y direction')
logger.exception(
f"{self.__str__()} cannot apply grass to "
+ "fractal box as it would exceed the domain "
+ "size in the y direction"
)
raise ValueError
requestedsurface = 'yplus'
requestedsurface = "yplus"
elif zs == zf:
if xs == xf or ys == yf:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if zs != volume.zs and zs != volume.zf:
logger.exception(f'{self.__str__()} must specify external surfaces on a fractal box')
logger.exception(f"{self.__str__()} must specify external surfaces on a fractal box")
raise ValueError
fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz))
# zminus surface
if zs == volume.zs:
logger.exception(f'{self.__str__()} grass can only be specified ' +
'on surfaces in the positive axis direction')
logger.exception(
f"{self.__str__()} grass can only be specified " + "on surfaces in the positive axis direction"
)
raise ValueError
# zplus surface
elif zf == volume.zf:
if fractalrange[1] > grid.nz:
logger.exception(f'{self.__str__()} cannot apply grass to ' +
'fractal box as it would exceed the domain ' +
'size in the z direction')
logger.exception(
f"{self.__str__()} cannot apply grass to "
+ "fractal box as it would exceed the domain "
+ "size in the z direction"
)
raise ValueError
requestedsurface = 'zplus'
requestedsurface = "zplus"
else:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
surface = FractalSurface(xs, xf, ys, yf, zs, zf, frac_dim)
surface.ID = 'grass'
surface.ID = "grass"
surface.surfaceID = requestedsurface
surface.seed = seed
@@ -187,11 +196,13 @@ class AddGrass(UserObjectGeometry):
surface.operatingonID = volume.ID
surface.generate_fractal_surface()
if n_blades > surface.fractalsurface.shape[0] * surface.fractalsurface.shape[1]:
logger.exception(f'{self.__str__()} the specified surface is not large ' +
'enough for the number of grass blades/roots specified')
logger.exception(
f"{self.__str__()} the specified surface is not large "
+ "enough for the number of grass blades/roots specified"
)
raise ValueError
# Scale the distribution so that the summation is equal to one,
# Scale the distribution so that the summation is equal to one,
# i.e. a probability distribution
surface.fractalsurface = surface.fractalsurface / np.sum(surface.fractalsurface)
@@ -203,23 +214,23 @@ class AddGrass(UserObjectGeometry):
R = np.random.RandomState(surface.seed)
A = R.random_sample(n_blades)
# Locate the random numbers in the bins created by the 1D vector of
# probability values, and convert the 1D index back into a x, y index
# Locate the random numbers in the bins created by the 1D vector of
# probability values, and convert the 1D index back into a x, y index
# for the original surface.
bladesindex = np.unravel_index(np.digitize(A, probability1D),
(surface.fractalsurface.shape[0],
surface.fractalsurface.shape[1]))
bladesindex = np.unravel_index(
np.digitize(A, probability1D), (surface.fractalsurface.shape[0], surface.fractalsurface.shape[1])
)
# Set the fractal range to minimum and maximum heights of the grass blades
surface.fractalrange = fractalrange
# Set the fractal surface using the pre-calculated spatial distribution
# Set the fractal surface using the pre-calculated spatial distribution
# and a random height
surface.fractalsurface = np.zeros((surface.fractalsurface.shape[0],
surface.fractalsurface.shape[1]))
surface.fractalsurface = np.zeros((surface.fractalsurface.shape[0], surface.fractalsurface.shape[1]))
for i in range(len(bladesindex[0])):
surface.fractalsurface[bladesindex[0][i], bladesindex[1][i]] = R.randint(surface.fractalrange[0],
surface.fractalrange[1], size=1)
surface.fractalsurface[bladesindex[0][i], bladesindex[1][i]] = R.randint(
surface.fractalrange[0], surface.fractalrange[1], size=1
)
# Create grass geometry parameters
g = Grass(n_blades)
@@ -227,22 +238,26 @@ class AddGrass(UserObjectGeometry):
surface.grass.append(g)
# Check to see if grass has been already defined as a material
if not any(x.ID == 'grass' for x in grid.materials):
if not any(x.ID == "grass" for x in grid.materials):
create_grass(grid)
# Check if time step for model is suitable for using grass
grass = next((x for x in grid.materials if x.ID == 'grass'))
grass = next((x for x in grid.materials if x.ID == "grass"))
testgrass = next((x for x in grass.tau if x < grid.dt), None)
if testgrass:
logger.exception(f'{self.__str__()} requires the time step for the ' +
'model to be less than the relaxation time required to model grass.')
logger.exception(
f"{self.__str__()} requires the time step for the "
+ "model to be less than the relaxation time required to model grass."
)
raise ValueError
volume.fractalsurfaces.append(surface)
logger.info(f'{self.grid_name(grid)}{n_blades} blades of grass on surface from ' +
f'{xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, ' +
f'to {xf * grid.dx:g}m, {yf * grid.dy:g}m, {zf * grid.dz:g}m ' +
f'with fractal dimension {surface.dimension:g}, fractal seeding ' +
f'{surface.seed}, and range {limits[0]:g}m to {limits[1]:g}m, ' +
f'added to {surface.operatingonID}.')
logger.info(
f"{self.grid_name(grid)}{n_blades} blades of grass on surface from "
+ f"{xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, "
+ f"to {xf * grid.dx:g}m, {yf * grid.dy:g}m, {zf * grid.dz:g}m "
+ f"with fractal dimension {surface.dimension:g}, fractal seeding "
+ f"{surface.seed}, and range {limits[0]:g}m to {limits[1]:g}m, "
+ f"added to {surface.operatingonID}."
)

查看文件

@@ -31,25 +31,25 @@ class AddSurfaceRoughness(UserObjectGeometry):
"""Adds surface roughness to a FractalBox class in the model.
Attributes:
p1: list of the lower left (x,y,z) coordinates of a surface on a
p1: list of the lower left (x,y,z) coordinates of a surface on a
FractalBox class.
p2: list of the upper right (x,y,z) coordinates of a surface on a
p2: list of the upper right (x,y,z) coordinates of a surface on a
FractalBox class.
frac_dim: float for the fractal dimension which, for an orthogonal
frac_dim: float for the fractal dimension which, for an orthogonal
parallelepiped, should take values between zero and three.
weighting: list with weightings in the first and second direction of
weighting: list with weightings in the first and second direction of
the surface.
limits: ist to define lower and upper limits for a range over which
limits: ist to define lower and upper limits for a range over which
the surface roughness can vary.
fractal_box_id: string identifier for the FractalBox class
that the surface roughness should be applied to.
seed: (optional) float parameter which controls the seeding of the random
seed: (optional) float parameter which controls the seeding of the random
number generator used to create the fractals.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#add_surface_roughness'
self.hash = "#add_surface_roughness"
def rotate(self, axis, angle, origin=None):
"""Set parameters for rotation."""
@@ -60,29 +60,31 @@ class AddSurfaceRoughness(UserObjectGeometry):
def _do_rotate(self):
"""Perform rotation."""
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
pts = np.array([self.kwargs["p1"], self.kwargs["p2"]])
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
self.kwargs['p1'] = tuple(rot_pts[0, :])
self.kwargs['p2'] = tuple(rot_pts[1, :])
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def create(self, grid, uip):
try:
p1 = self.kwargs['p1']
p2 = self.kwargs['p2']
frac_dim = self.kwargs['frac_dim']
weighting = np.array(self.kwargs['weighting'], dtype=np.float64)
limits = np.array(self.kwargs['limits'])
fractal_box_id = self.kwargs['fractal_box_id']
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
frac_dim = self.kwargs["frac_dim"]
weighting = np.array(self.kwargs["weighting"], dtype=np.float64)
limits = np.array(self.kwargs["limits"])
fractal_box_id = self.kwargs["fractal_box_id"]
except KeyError:
logger.exception(f'{self.__str__()} incorrect parameters')
logger.exception(f"{self.__str__()} incorrect parameters")
raise
try:
seed = self.kwargs['seed']
seed = self.kwargs["seed"]
except KeyError:
logger.warning(f'{self.__str__()} no value for seed detected. This ' +
'means you will get a different fractal distribution ' +
'every time the model runs.')
logger.warning(
f"{self.__str__()} no value for seed detected. This "
+ "means you will get a different fractal distribution "
+ "every time the model runs."
)
seed = None
if self.do_rotate:
@@ -93,7 +95,7 @@ class AddSurfaceRoughness(UserObjectGeometry):
if volumes:
volume = volumes[0]
else:
logger.exception(f'{self.__str__()} cannot find FractalBox {fractal_box_id}')
logger.exception(f"{self.__str__()} cannot find FractalBox {fractal_box_id}")
raise ValueError
p1, p2 = uip.check_box_points(p1, p2, self.__str__())
@@ -101,108 +103,117 @@ class AddSurfaceRoughness(UserObjectGeometry):
xf, yf, zf = p2
if frac_dim < 0:
logger.exception(f'{self.__str__()} requires a positive value for the ' +
'fractal dimension')
logger.exception(f"{self.__str__()} requires a positive value for the " + "fractal dimension")
raise ValueError
if weighting[0] < 0:
logger.exception(f'{self.__str__()} requires a positive value for the ' +
'fractal weighting in the first direction of the surface')
logger.exception(
f"{self.__str__()} requires a positive value for the "
+ "fractal weighting in the first direction of the surface"
)
raise ValueError
if weighting[1] < 0:
logger.exception(f'{self.__str__()} requires a positive value for the ' +
'fractal weighting in the second direction of the surface')
logger.exception(
f"{self.__str__()} requires a positive value for the "
+ "fractal weighting in the second direction of the surface"
)
raise ValueError
# Check for valid orientations
if xs == xf:
if ys == yf or zs == zf:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if xs != volume.xs and xs != volume.xf:
logger.exception(f'{self.__str__()} can only be used on the external ' +
'surfaces of a fractal box')
logger.exception(f"{self.__str__()} can only be used on the external " + "surfaces of a fractal box")
raise ValueError
fractalrange = (round_value(limits[0] / grid.dx),
round_value(limits[1] / grid.dx))
fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx))
# xminus surface
if xs == volume.xs:
if fractalrange[0] < 0 or fractalrange[1] > volume.xf:
logger.exception(f'{self.__str__()} cannot apply fractal surface ' +
'to fractal box as it would exceed either the ' +
'upper coordinates of the fractal box or the ' +
'domain in the x direction')
logger.exception(
f"{self.__str__()} cannot apply fractal surface "
+ "to fractal box as it would exceed either the "
+ "upper coordinates of the fractal box or the "
+ "domain in the x direction"
)
raise ValueError
requestedsurface = 'xminus'
requestedsurface = "xminus"
# xplus surface
elif xf == volume.xf:
if fractalrange[0] < volume.xs or fractalrange[1] > grid.nx:
logger.exception(f'{self.__str__()} cannot apply fractal surface ' +
'to fractal box as it would exceed either the ' +
'lower coordinates of the fractal box or the ' +
'domain in the x direction')
logger.exception(
f"{self.__str__()} cannot apply fractal surface "
+ "to fractal box as it would exceed either the "
+ "lower coordinates of the fractal box or the "
+ "domain in the x direction"
)
raise ValueError
requestedsurface = 'xplus'
requestedsurface = "xplus"
elif ys == yf:
if xs == xf or zs == zf:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if ys != volume.ys and ys != volume.yf:
logger.exception(f'{self.__str__()} can only be used on the external ' +
'surfaces of a fractal box')
logger.exception(f"{self.__str__()} can only be used on the external " + "surfaces of a fractal box")
raise ValueError
fractalrange = (round_value(limits[0] / grid.dy),
round_value(limits[1] / grid.dy))
fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy))
# yminus surface
if ys == volume.ys:
if fractalrange[0] < 0 or fractalrange[1] > volume.yf:
logger.exception(f'{self.__str__()} cannot apply fractal surface ' +
'to fractal box as it would exceed either the ' +
'upper coordinates of the fractal box or the ' +
'domain in the y direction')
logger.exception(
f"{self.__str__()} cannot apply fractal surface "
+ "to fractal box as it would exceed either the "
+ "upper coordinates of the fractal box or the "
+ "domain in the y direction"
)
raise ValueError
requestedsurface = 'yminus'
requestedsurface = "yminus"
# yplus surface
elif yf == volume.yf:
if fractalrange[0] < volume.ys or fractalrange[1] > grid.ny:
logger.exception(f'{self.__str__()} cannot apply fractal surface ' +
'to fractal box as it would exceed either the ' +
'lower coordinates of the fractal box or the ' +
'domain in the y direction')
logger.exception(
f"{self.__str__()} cannot apply fractal surface "
+ "to fractal box as it would exceed either the "
+ "lower coordinates of the fractal box or the "
+ "domain in the y direction"
)
raise ValueError
requestedsurface = 'yplus'
requestedsurface = "yplus"
elif zs == zf:
if xs == xf or ys == yf:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if zs != volume.zs and zs != volume.zf:
logger.exception(f'{self.__str__()} can only be used on the external ' +
'surfaces of a fractal box')
logger.exception(f"{self.__str__()} can only be used on the external " + "surfaces of a fractal box")
raise ValueError
fractalrange = (round_value(limits[0] / grid.dz),
round_value(limits[1] / grid.dz))
fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz))
# zminus surface
if zs == volume.zs:
if fractalrange[0] < 0 or fractalrange[1] > volume.zf:
logger.exception(f'{self.__str__()} cannot apply fractal surface ' +
'to fractal box as it would exceed either the ' +
'upper coordinates of the fractal box or the ' +
'domain in the x direction')
logger.exception(
f"{self.__str__()} cannot apply fractal surface "
+ "to fractal box as it would exceed either the "
+ "upper coordinates of the fractal box or the "
+ "domain in the x direction"
)
raise ValueError
requestedsurface = 'zminus'
requestedsurface = "zminus"
# zplus surface
elif zf == volume.zf:
if fractalrange[0] < volume.zs or fractalrange[1] > grid.nz:
logger.exception(f'{self.__str__()} cannot apply fractal surface ' +
'to fractal box as it would exceed either the ' +
'lower coordinates of the fractal box or the ' +
'domain in the z direction')
logger.exception(
f"{self.__str__()} cannot apply fractal surface "
+ "to fractal box as it would exceed either the "
+ "lower coordinates of the fractal box or the "
+ "domain in the z direction"
)
raise ValueError
requestedsurface = 'zplus'
requestedsurface = "zplus"
else:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
surface = FractalSurface(xs, xf, ys, yf, zs, zf, frac_dim)
@@ -218,17 +229,18 @@ class AddSurfaceRoughness(UserObjectGeometry):
# List of existing surfaces IDs
existingsurfaceIDs = [x.surfaceID for x in volume.fractalsurfaces]
if surface.surfaceID in existingsurfaceIDs:
logger.exception(f'{self.__str__()} has already been used on the ' +
f'{surface.surfaceID} surface')
logger.exception(f"{self.__str__()} has already been used on the " + f"{surface.surfaceID} surface")
raise ValueError
surface.generate_fractal_surface()
volume.fractalsurfaces.append(surface)
logger.info(f'{self.grid_name(grid)}Fractal surface from {xs * grid.dx:g}m, ' +
f'{ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, ' +
f'{yf * grid.dy:g}m, {zf * grid.dz:g}m with fractal dimension ' +
f'{surface.dimension:g}, fractal weightings {surface.weighting[0]:g}, ' +
f'{surface.weighting[1]:g}, fractal seeding {surface.seed}, ' +
f'and range {limits[0]:g}m to {limits[1]:g}m, added to ' +
f'{surface.operatingonID}.')
logger.info(
f"{self.grid_name(grid)}Fractal surface from {xs * grid.dx:g}m, "
+ f"{ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, "
+ f"{yf * grid.dy:g}m, {zf * grid.dz:g}m with fractal dimension "
+ f"{surface.dimension:g}, fractal weightings {surface.weighting[0]:g}, "
+ f"{surface.weighting[1]:g}, fractal seeding {surface.seed}, "
+ f"and range {limits[0]:g}m to {limits[1]:g}m, added to "
+ f"{surface.operatingonID}."
)

查看文件

@@ -31,20 +31,20 @@ class AddSurfaceWater(UserObjectGeometry):
"""Adds surface water to a FractalBox class in the model.
Attributes:
p1: list of the lower left (x,y,z) coordinates of a surface on a
p1: list of the lower left (x,y,z) coordinates of a surface on a
FractalBox class.
p2: list of the upper right (x,y,z) coordinates of a surface on a
p2: list of the upper right (x,y,z) coordinates of a surface on a
FractalBox class.
depth: float that defines the depth of the water, which should be
specified relative to the dimensions of the #fractal_box that
depth: float that defines the depth of the water, which should be
specified relative to the dimensions of the #fractal_box that
the surface water is being applied.
fractal_box_id: string identifier for the FractalBox class that the
fractal_box_id: string identifier for the FractalBox class that the
surface water should be applied to.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#add_surface_water'
self.hash = "#add_surface_water"
def rotate(self, axis, angle, origin=None):
"""Set parameters for rotation."""
@@ -55,20 +55,20 @@ class AddSurfaceWater(UserObjectGeometry):
def _do_rotate(self):
"""Perform rotation."""
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
pts = np.array([self.kwargs["p1"], self.kwargs["p2"]])
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
self.kwargs['p1'] = tuple(rot_pts[0, :])
self.kwargs['p2'] = tuple(rot_pts[1, :])
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def create(self, grid, uip):
""""Create surface water on fractal box."""
""" "Create surface water on fractal box."""
try:
p1 = self.kwargs['p1']
p2 = self.kwargs['p2']
fractal_box_id = self.kwargs['fractal_box_id']
depth = self.kwargs['depth']
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
fractal_box_id = self.kwargs["fractal_box_id"]
depth = self.kwargs["depth"]
except KeyError:
logger.exception(f'{self.__str__()} requires exactly eight parameters')
logger.exception(f"{self.__str__()} requires exactly eight parameters")
raise
if self.do_rotate:
@@ -77,7 +77,7 @@ class AddSurfaceWater(UserObjectGeometry):
if volumes := [volume for volume in grid.fractalvolumes if volume.ID == fractal_box_id]:
volume = volumes[0]
else:
logger.exception(f'{self.__str__()} cannot find FractalBox {fractal_box_id}')
logger.exception(f"{self.__str__()} cannot find FractalBox {fractal_box_id}")
raise ValueError
p1, p2 = uip.check_box_points(p1, p2, self.__str__())
@@ -85,89 +85,92 @@ class AddSurfaceWater(UserObjectGeometry):
xf, yf, zf = p2
if depth <= 0:
logger.exception(f'{self.__str__()} requires a positive value for the ' +
f'depth of water')
logger.exception(f"{self.__str__()} requires a positive value for the " + f"depth of water")
raise ValueError
# Check for valid orientations
if xs == xf:
if ys == yf or zs == zf:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if xs not in [volume.xs, volume.xf]:
logger.exception(f'{self.__str__()} can only be used on the external surfaces '
f'of a fractal box')
logger.exception(f"{self.__str__()} can only be used on the external surfaces " f"of a fractal box")
raise ValueError
# xminus surface
if xs == volume.xs:
requestedsurface = 'xminus'
requestedsurface = "xminus"
# xplus surface
elif xf == volume.xf:
requestedsurface = 'xplus'
requestedsurface = "xplus"
filldepthcells = round_value(depth / grid.dx)
filldepth = filldepthcells * grid.dx
elif ys == yf:
if zs == zf:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if ys not in [volume.ys, volume.yf]:
logger.exception(f'{self.__str__()} can only be used on the external surfaces ' +
f'of a fractal box')
logger.exception(f"{self.__str__()} can only be used on the external surfaces " + f"of a fractal box")
raise ValueError
# yminus surface
if ys == volume.ys:
requestedsurface = 'yminus'
requestedsurface = "yminus"
# yplus surface
elif yf == volume.yf:
requestedsurface = 'yplus'
requestedsurface = "yplus"
filldepthcells = round_value(depth / grid.dy)
filldepth = filldepthcells * grid.dy
elif zs == zf:
if zs not in [volume.zs, volume.zf]:
logger.exception(f'{self.__str__()} can only be used on the external surfaces '
f'of a fractal box')
logger.exception(f"{self.__str__()} can only be used on the external surfaces " f"of a fractal box")
raise ValueError
# zminus surface
if zs == volume.zs:
requestedsurface = 'zminus'
requestedsurface = "zminus"
# zplus surface
elif zf == volume.zf:
requestedsurface = 'zplus'
requestedsurface = "zplus"
filldepthcells = round_value(depth / grid.dz)
filldepth = filldepthcells * grid.dz
else:
logger.exception(f'{self.__str__()} dimensions are not specified correctly')
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
surface = next((x for x in volume.fractalsurfaces if x.surfaceID == requestedsurface), None)
if not surface:
logger.exception(f'{self.__str__()} specified surface {requestedsurface} ' +
f'does not have a rough surface applied')
logger.exception(
f"{self.__str__()} specified surface {requestedsurface} " + f"does not have a rough surface applied"
)
raise ValueError
surface.filldepth = filldepthcells
# Check that requested fill depth falls within range of surface roughness
if surface.filldepth < surface.fractalrange[0] or surface.filldepth > surface.fractalrange[1]:
logger.exception(f'{self.__str__()} requires a value for the depth of water that lies with the ' +
f'range of the requested surface roughness')
logger.exception(
f"{self.__str__()} requires a value for the depth of water that lies with the "
+ f"range of the requested surface roughness"
)
raise ValueError
# Check to see if water has been already defined as a material
if all(x.ID != 'water' for x in grid.materials):
if all(x.ID != "water" for x in grid.materials):
create_water(grid)
# Check if time step for model is suitable for using water
water = next((x for x in grid.materials if x.ID == 'water'))
water = next((x for x in grid.materials if x.ID == "water"))
if testwater := next((x for x in water.tau if x < grid.dt), None):
logger.exception(f'{self.__str__()} requires the time step for the model '
f'to be less than the relaxation time required to model water.')
logger.exception(
f"{self.__str__()} requires the time step for the model "
f"to be less than the relaxation time required to model water."
)
raise ValueError
logger.info(f'{self.grid_name(grid)}Water on surface from {xs * grid.dx:g}m, ' +
f'{ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, ' +
f'{yf * grid.dy:g}m, {zf * grid.dz:g}m with depth {filldepth:g}m, ' +
f'added to {surface.operatingonID}.')
logger.info(
f"{self.grid_name(grid)}Water on surface from {xs * grid.dx:g}m, "
+ f"{ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, "
+ f"{yf * grid.dy:g}m, {zf * grid.dz:g}m with depth {filldepth:g}m, "
+ f"added to {surface.operatingonID}."
)

查看文件

@@ -30,13 +30,13 @@ logger = logging.getLogger(__name__)
class Box(UserObjectGeometry):
"""Introduces an orthogonal parallelepiped with specific properties into
"""Introduces an orthogonal parallelepiped with specific properties into
the model.
Attributes:
p1: list of the lower left (x,y,z) coordinates of the parallelepiped.
p2: list of the upper right (x,y,z) coordinates of the parallelepiped.
material_id: string for the material identifier that must correspond
material_id: string for the material identifier that must correspond
to material that has already been defined.
material_ids: list of material identifiers in the x, y, z directions.
averaging: string (y or n) used to switch on and off dielectric smoothing.
@@ -44,7 +44,7 @@ class Box(UserObjectGeometry):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#box'
self.hash = "#box"
def rotate(self, axis, angle, origin=None):
"""Set parameters for rotation."""
@@ -55,17 +55,17 @@ class Box(UserObjectGeometry):
def _do_rotate(self):
"""Perform rotation."""
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
pts = np.array([self.kwargs["p1"], self.kwargs["p2"]])
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
self.kwargs['p1'] = tuple(rot_pts[0, :])
self.kwargs['p2'] = tuple(rot_pts[1, :])
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def create(self, grid, uip):
try:
p1 = self.kwargs['p1']
p2 = self.kwargs['p2']
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
except KeyError:
logger.exception(f'{self.__str__()} Please specify two points.')
logger.exception(f"{self.__str__()} Please specify two points.")
raise
if self.do_rotate:
@@ -74,19 +74,19 @@ class Box(UserObjectGeometry):
# Check materials have been specified
# Isotropic case
try:
materialsrequested = [self.kwargs['material_id']]
materialsrequested = [self.kwargs["material_id"]]
except KeyError:
# Anisotropic case
try:
materialsrequested = self.kwargs['material_ids']
materialsrequested = self.kwargs["material_ids"]
except KeyError:
logger.exception(f'{self.__str__()} No materials have been specified')
logger.exception(f"{self.__str__()} No materials have been specified")
raise
# Check averaging
try:
# Try user-specified averaging
averagebox = self.kwargs['averaging']
averagebox = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagebox = grid.averagevolumeobjects
@@ -103,7 +103,7 @@ class Box(UserObjectGeometry):
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
logger.exception(f'{self.__str__()} material(s) {notfound} do not exist')
logger.exception(f"{self.__str__()} material(s) {notfound} do not exist")
raise ValueError
# Isotropic case
@@ -117,34 +117,47 @@ class Box(UserObjectGeometry):
numIDx = materials[0].numID
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + '+' + materials[1].ID + '+' + materials[2].ID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
m = Material(numID, requiredID)
m.type = 'dielectric-smoothed'
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
m.er = np.mean((materials[0].er, materials[1].er,
materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se,
materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr,
materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm,
materials[2].sm), axis=0)
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
build_box(xs, xf, ys, yf, zs, zf, config.get_model_config().ompthreads,
numID, numIDx, numIDy, numIDz, averaging, grid.solid,
grid.rigidE, grid.rigidH, grid.ID)
build_box(
xs,
xf,
ys,
yf,
zs,
zf,
config.get_model_config().ompthreads,
numID,
numIDx,
numIDy,
numIDz,
averaging,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)
dielectricsmoothing = 'on' if averaging else 'off'
dielectricsmoothing = "on" if averaging else "off"
logger.info(f"{self.grid_name(grid)}Box from {p5[0]:g}m, {p5[1]:g}m, " +
f"{p5[2]:g}m, to {p6[0]:g}m, {p6[1]:g}m, {p6[2]:g}m of " +
f"material(s) {', '.join(materialsrequested)} created, " +
f"dielectric smoothing is {dielectricsmoothing}.")
logger.info(
f"{self.grid_name(grid)}Box from {p5[0]:g}m, {p5[1]:g}m, "
+ f"{p5[2]:g}m, to {p6[0]:g}m, {p6[1]:g}m, {p6[2]:g}m of "
+ f"material(s) {', '.join(materialsrequested)} created, "
+ f"dielectric smoothing is {dielectricsmoothing}."
)

查看文件

@@ -19,52 +19,53 @@
from jinja2 import Environment, PackageLoader
env = Environment(
loader=PackageLoader(__name__, 'templates'),
loader=PackageLoader(__name__, "templates"),
)
template = env.get_template('fields_updates_dispersive_template')
template = env.get_template("fields_updates_dispersive_template")
r = template.render(
functions=[
# name, double, real
{
'name_a': 'update_electric_dispersive_multipole_A_double_real',
'name_b': 'update_electric_dispersive_multipole_B_double_real',
'name_a_1': 'update_electric_dispersive_1pole_A_double_real',
'name_b_1': 'update_electric_dispersive_1pole_B_double_real',
'field_type': 'double',
'dispersive_type': 'double'
"name_a": "update_electric_dispersive_multipole_A_double_real",
"name_b": "update_electric_dispersive_multipole_B_double_real",
"name_a_1": "update_electric_dispersive_1pole_A_double_real",
"name_b_1": "update_electric_dispersive_1pole_B_double_real",
"field_type": "double",
"dispersive_type": "double",
},
# name, float, real
{
'name_a': 'update_electric_dispersive_multipole_A_float_real',
'name_b': 'update_electric_dispersive_multipole_B_float_real',
'name_a_1': 'update_electric_dispersive_1pole_A_float_real',
'name_b_1': 'update_electric_dispersive_1pole_B_float_real',
'field_type': 'float',
'dispersive_type': 'float'
"name_a": "update_electric_dispersive_multipole_A_float_real",
"name_b": "update_electric_dispersive_multipole_B_float_real",
"name_a_1": "update_electric_dispersive_1pole_A_float_real",
"name_b_1": "update_electric_dispersive_1pole_B_float_real",
"field_type": "float",
"dispersive_type": "float",
},
# name, double, complex
{
'name_a': 'update_electric_dispersive_multipole_A_double_complex',
'name_b': 'update_electric_dispersive_multipole_B_double_complex',
'name_a_1': 'update_electric_dispersive_1pole_A_double_complex',
'name_b_1': 'update_electric_dispersive_1pole_B_double_complex',
'field_type': 'double',
'dispersive_type': 'double complex',
'real_part': 'creal'
"name_a": "update_electric_dispersive_multipole_A_double_complex",
"name_b": "update_electric_dispersive_multipole_B_double_complex",
"name_a_1": "update_electric_dispersive_1pole_A_double_complex",
"name_b_1": "update_electric_dispersive_1pole_B_double_complex",
"field_type": "double",
"dispersive_type": "double complex",
"real_part": "creal",
},
# name, float, complex
{
'name_a': 'update_electric_dispersive_multipole_A_float_complex',
'name_b': 'update_electric_dispersive_multipole_B_float_complex',
'name_a_1': 'update_electric_dispersive_1pole_A_float_complex',
'name_b_1': 'update_electric_dispersive_1pole_B_float_complex',
'field_type': 'float',
'dispersive_type': 'float complex',
'real_part': 'crealf'
}]
"name_a": "update_electric_dispersive_multipole_A_float_complex",
"name_b": "update_electric_dispersive_multipole_B_float_complex",
"name_a_1": "update_electric_dispersive_1pole_A_float_complex",
"name_b_1": "update_electric_dispersive_1pole_B_float_complex",
"field_type": "float",
"dispersive_type": "float complex",
"real_part": "crealf",
},
]
)
with open('cython/dispersive_updates_test.pyx', 'w') as f:
with open("cython/dispersive_updates_test.pyx", "w") as f:
f.write(r)

查看文件

@@ -30,19 +30,19 @@ class UserObjectGeometry:
def __init__(self, **kwargs):
self.kwargs = kwargs
self.hash = '#example'
self.hash = "#example"
self.autotranslate = True
self.do_rotate = False
def __str__(self):
"""Readable string of parameters given to object."""
s = ''
s = ""
for _, v in self.kwargs.items():
if isinstance(v, (tuple, list)):
v = ' '.join([str(el) for el in v])
s += f'{str(v)} '
v = " ".join([str(el) for el in v])
s += f"{str(v)} "
return f'{self.hash}: {s[:-1]}'
return f"{self.hash}: {s[:-1]}"
def create(self, grid, uip):
"""Creates object and adds it to the grid."""
@@ -54,18 +54,18 @@ class UserObjectGeometry:
def grid_name(self, grid):
"""Returns subgrid name for use with logging info. Returns an empty
string if the grid is the main grid.
string if the grid is the main grid.
"""
if config.sim_config.general['subgrid'] and grid.name != 'main_grid':
return f'[{grid.name}] '
if config.sim_config.general["subgrid"] and grid.name != "main_grid":
return f"[{grid.name}] "
else:
return ''
return ""
def rotate_point(p, axis, angle, origin=(0, 0, 0)):
"""Rotates a point.
Args:
p: array of coordinates of point (x, y, z).
axis: string which defines the axis about which to perform rotation (x, y, or z).
@@ -91,11 +91,11 @@ def rotate_point(p, axis, angle, origin=(0, 0, 0)):
p += origin
return p
def rotate_2point_object(pts, axis, angle, origin=None):
"""Rotate a geometry object that is defined by 2 points.
Args:
pts: array ofcoordinates of points of object to be rotated.
axis: string which defines the axis about which to perform rotation (x, y, or z).
@@ -105,23 +105,23 @@ def rotate_2point_object(pts, axis, angle, origin=None):
Returns:
new_pts: array of coordinates of points of rotated object.
"""
# Use origin at centre of object if not given
if not origin:
origin = pts[0,:] + (pts[1,:] - pts[0,:]) / 2
origin = pts[0, :] + (pts[1, :] - pts[0, :]) / 2
# Check angle value is suitable
angle = int(angle)
if angle < 0 or angle > 360:
logger.exception('Angle of rotation must be between 0-360 degrees')
logger.exception("Angle of rotation must be between 0-360 degrees")
raise ValueError
if angle % 90 != 0:
logger.exception('Angle of rotation must be a multiple of 90 degrees')
logger.exception("Angle of rotation must be a multiple of 90 degrees")
raise ValueError
# Check axis is valid
if axis not in ['x', 'y', 'z']:
logger.exception('Axis of rotation must be x, y, or z')
if axis not in ["x", "y", "z"]:
logger.exception("Axis of rotation must be x, y, or z")
raise ValueError
# Save original points
@@ -136,15 +136,15 @@ def rotate_2point_object(pts, axis, angle, origin=None):
new_pts[0, :] = np.min(pts, axis=0)
new_pts[1, :] = np.max(pts, axis=0)
# Reset coordinates of invariant direction
# Reset coordinates of invariant direction
# - only needed for 2D models, has no effect on 3D models.
if axis =='x':
if axis == "x":
new_pts[0, 0] = orig_pts[0, 0]
new_pts[1, 0] = orig_pts[1, 0]
elif axis == 'y':
elif axis == "y":
new_pts[0, 1] = orig_pts[0, 1]
new_pts[1, 1] = orig_pts[1, 1]
elif axis == 'z':
elif axis == "z":
new_pts[0, 2] = orig_pts[0, 2]
new_pts[1, 2] = orig_pts[1, 2]
@@ -153,7 +153,7 @@ def rotate_2point_object(pts, axis, angle, origin=None):
def rotate_polarisation(p, polarisation, axis, angle, G):
"""Rotates a geometry object that is defined by a point and polarisation.
Args:
p: array of coordinates of point (x, y, z).
polarisation: string defining the current polarisation (x, y, or z).
@@ -166,27 +166,27 @@ def rotate_polarisation(p, polarisation, axis, angle, G):
new_polarisation: string defining the new polarisation (x, y, or z).
"""
if polarisation.lower() == 'x':
if polarisation.lower() == "x":
new_pt = (p[0] + G.dx, p[1], p[2])
if axis == 'y' and angle == 90 or angle == 270:
new_polarisation = 'z'
if axis == 'z' and angle == 90 or angle == 270:
new_polarisation = 'y'
if axis == "y" and angle == 90 or angle == 270:
new_polarisation = "z"
if axis == "z" and angle == 90 or angle == 270:
new_polarisation = "y"
elif polarisation.lower() == 'y':
elif polarisation.lower() == "y":
new_pt = (p[0], p[1] + G.dy, p[2])
if axis == 'x' and angle == 90 or angle == 270:
new_polarisation = 'z'
if axis == 'z' and angle == 90 or angle == 270:
new_polarisation = 'x'
if axis == "x" and angle == 90 or angle == 270:
new_polarisation = "z"
if axis == "z" and angle == 90 or angle == 270:
new_polarisation = "x"
elif polarisation.lower() == 'z':
elif polarisation.lower() == "z":
new_pt = (p[0], p[1], p[2] + G.dz)
if axis == 'x' and angle == 90 or angle == 270:
new_polarisation = 'y'
if axis == 'y' and angle == 90 or angle == 270:
new_polarisation = 'x'
if axis == "x" and angle == 90 or angle == 270:
new_polarisation = "y"
if axis == "y" and angle == 90 or angle == 270:
new_polarisation = "x"
pts = np.array([p, new_pt])
return pts, new_polarisation
return pts, new_polarisation

查看文件

@@ -32,13 +32,13 @@ class Cone(UserObjectGeometry):
can have different radii and one of them can be zero.
Attributes:
p1: list of the coordinates (x,y,z) of the centre of the first face
p1: list of the coordinates (x,y,z) of the centre of the first face
of the cone.
p2: list of the coordinates (x,y,z) of the centre of the second face
p2: list of the coordinates (x,y,z) of the centre of the second face
of the cone.
r1: float of the radius of the first face of the cone.
r2: float of the radius of the second face of the cone.
material_id: string for the material identifier that must correspond
material_id: string for the material identifier that must correspond
to material that has already been defined.
material_ids: list of material identifiers in the x, y, z directions.
averaging: string (y or n) used to switch on and off dielectric smoothing.
@@ -46,22 +46,22 @@ class Cone(UserObjectGeometry):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#cone'
self.hash = "#cone"
def create(self, grid, uip):
try:
p1 = self.kwargs['p1']
p2 = self.kwargs['p2']
r1 = self.kwargs['r1']
r2 = self.kwargs['r2']
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
r1 = self.kwargs["r1"]
r2 = self.kwargs["r2"]
except KeyError:
logger.exception(f'{self.__str__()} please specify two points and two radii')
logger.exception(f"{self.__str__()} please specify two points and two radii")
raise
# Check averaging
try:
# Try user-specified averaging
averagecylinder = self.kwargs['averaging']
averagecylinder = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagecylinder = grid.averagevolumeobjects
@@ -69,13 +69,13 @@ class Cone(UserObjectGeometry):
# Check materials have been specified
# Isotropic case
try:
materialsrequested = [self.kwargs['material_id']]
materialsrequested = [self.kwargs["material_id"]]
except KeyError:
# Anisotropic case
try:
materialsrequested = self.kwargs['material_ids']
materialsrequested = self.kwargs["material_ids"]
except KeyError:
logger.exception(f'{self.__str__()} no materials have been specified')
logger.exception(f"{self.__str__()} no materials have been specified")
raise
p3 = uip.round_to_grid_static_point(p1)
@@ -85,17 +85,15 @@ class Cone(UserObjectGeometry):
x2, y2, z2 = uip.round_to_grid(p2)
if r1 < 0:
logger.exception(f'{self.__str__()} the radius of the first face ' +
f'{r1:g} should be a positive value.')
logger.exception(f"{self.__str__()} the radius of the first face " + f"{r1:g} should be a positive value.")
raise ValueError
if r2 < 0:
logger.exception(f'{self.__str__()} the radius of the second face ' +
f'{r2:g} should be a positive value.')
logger.exception(f"{self.__str__()} the radius of the second face " + f"{r2:g} should be a positive value.")
raise ValueError
if r1 == 0 and r2 == 0:
logger.exception(f'{self.__str__()} both radii cannot be zero.')
logger.exception(f"{self.__str__()} both radii cannot be zero.")
raise ValueError
# Look up requested materials in existing list of material instances
@@ -103,7 +101,7 @@ class Cone(UserObjectGeometry):
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
logger.exception(f'{self.__str__()} material(s) {notfound} do not exist')
logger.exception(f"{self.__str__()} material(s) {notfound} do not exist")
raise ValueError
# Isotropic case
@@ -117,33 +115,50 @@ class Cone(UserObjectGeometry):
numIDx = materials[0].numID
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + '+' + materials[1].ID + '+' + materials[2].ID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
m = Material(numID, requiredID)
m.type = 'dielectric-smoothed'
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
m.er = np.mean((materials[0].er, materials[1].er,
materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se,
materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr,
materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm,
materials[2].sm), axis=0)
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
build_cone(x1, y1, z1, x2, y2, z2, r1, r2, grid.dx, grid.dy, grid.dz,
numID, numIDx, numIDy, numIDz, averaging, grid.solid,
grid.rigidE, grid.rigidH, grid.ID)
build_cone(
x1,
y1,
z1,
x2,
y2,
z2,
r1,
r2,
grid.dx,
grid.dy,
grid.dz,
numID,
numIDx,
numIDy,
numIDz,
averaging,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)
dielectricsmoothing = 'on' if averaging else 'off'
logger.info(f"{self.grid_name(grid)}Cone with face centres {p3[0]:g}m, " +
f"{p3[1]:g}m, {p3[2]:g}m and {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m, " +
f"with radii {r1:g}m and {r2:g}, of material(s) {', '.join(materialsrequested)} " +
f"created, dielectric smoothing is {dielectricsmoothing}.")
dielectricsmoothing = "on" if averaging else "off"
logger.info(
f"{self.grid_name(grid)}Cone with face centres {p3[0]:g}m, "
+ f"{p3[1]:g}m, {p3[2]:g}m and {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m, "
+ f"with radii {r1:g}m and {r2:g}, of material(s) {', '.join(materialsrequested)} "
+ f"created, dielectric smoothing is {dielectricsmoothing}."
)

查看文件

@@ -31,12 +31,12 @@ class Cylinder(UserObjectGeometry):
"""Introduces a circular cylinder into the model.
Attributes:
p1: list of the coordinates (x,y,z) of the centre of the first face
p1: list of the coordinates (x,y,z) of the centre of the first face
of the cylinder.
p2: list of the coordinates (x,y,z) of the centre of the second face
p2: list of the coordinates (x,y,z) of the centre of the second face
of the cylinder.
r: float of the radius of the cylinder.
material_id: string for the material identifier that must correspond
material_id: string for the material identifier that must correspond
to material that has already been defined.
material_ids: list of material identifiers in the x, y, z directions.
averaging: string (y or n) used to switch on and off dielectric smoothing.
@@ -44,21 +44,21 @@ class Cylinder(UserObjectGeometry):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#cylinder'
self.hash = "#cylinder"
def create(self, grid, uip):
try:
p1 = self.kwargs['p1']
p2 = self.kwargs['p2']
r = self.kwargs['r']
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
r = self.kwargs["r"]
except KeyError:
logger.exception(f'{self.__str__()} please specify 2 points and a radius')
logger.exception(f"{self.__str__()} please specify 2 points and a radius")
raise
# Check averaging
try:
# Try user-specified averaging
averagecylinder = self.kwargs['averaging']
averagecylinder = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagecylinder = grid.averagevolumeobjects
@@ -66,13 +66,13 @@ class Cylinder(UserObjectGeometry):
# Check materials have been specified
# Isotropic case
try:
materialsrequested = [self.kwargs['material_id']]
materialsrequested = [self.kwargs["material_id"]]
except KeyError:
# Anisotropic case
try:
materialsrequested = self.kwargs['material_ids']
materialsrequested = self.kwargs["material_ids"]
except KeyError:
logger.exception(f'{self.__str__()} no materials have been specified')
logger.exception(f"{self.__str__()} no materials have been specified")
raise
p3 = uip.round_to_grid_static_point(p1)
@@ -82,7 +82,7 @@ class Cylinder(UserObjectGeometry):
x2, y2, z2 = uip.round_to_grid(p2)
if r <= 0:
logger.exception(f'{self.__str__()} the radius {r:g} should be a positive value.')
logger.exception(f"{self.__str__()} the radius {r:g} should be a positive value.")
raise ValueError
# Look up requested materials in existing list of material instances
@@ -90,7 +90,7 @@ class Cylinder(UserObjectGeometry):
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
logger.exception(f'{self.__str__()} material(s) {notfound} do not exist')
logger.exception(f"{self.__str__()} material(s) {notfound} do not exist")
raise ValueError
# Isotropic case
@@ -104,33 +104,49 @@ class Cylinder(UserObjectGeometry):
numIDx = materials[0].numID
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + '+' + materials[1].ID + '+' + materials[2].ID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
m = Material(numID, requiredID)
m.type = 'dielectric-smoothed'
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
m.er = np.mean((materials[0].er, materials[1].er,
materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se,
materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr,
materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm,
materials[2].sm), axis=0)
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
build_cylinder(x1, y1, z1, x2, y2, z2, r, grid.dx, grid.dy, grid.dz,
numID, numIDx, numIDy, numIDz, averaging, grid.solid,
grid.rigidE, grid.rigidH, grid.ID)
build_cylinder(
x1,
y1,
z1,
x2,
y2,
z2,
r,
grid.dx,
grid.dy,
grid.dz,
numID,
numIDx,
numIDy,
numIDz,
averaging,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)
dielectricsmoothing = 'on' if averaging else 'off'
logger.info(f"{self.grid_name(grid)}Cylinder with face centres {p3[0]:g}m, " +
f"{p3[1]:g}m, {p3[2]:g}m and {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m, " +
f"with radius {r:g}m, of material(s) {', '.join(materialsrequested)} " +
f"created, dielectric smoothing is {dielectricsmoothing}.")
dielectricsmoothing = "on" if averaging else "off"
logger.info(
f"{self.grid_name(grid)}Cylinder with face centres {p3[0]:g}m, "
+ f"{p3[1]:g}m, {p3[2]:g}m and {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m, "
+ f"with radius {r:g}m, of material(s) {', '.join(materialsrequested)} "
+ f"created, dielectric smoothing is {dielectricsmoothing}."
)

查看文件

@@ -31,21 +31,21 @@ class CylindricalSector(UserObjectGeometry):
"""Introduces a cylindrical sector (shaped like a slice of pie) into the model.
Attributes:
normal: string for the direction of the axis of the cylinder from which
normal: string for the direction of the axis of the cylinder from which
the sector is defined and can be x, y, or z.
ctr1: float for the first coordinate of the centre of the cylindrical
ctr1: float for the first coordinate of the centre of the cylindrical
sector.
ctr2: float for the second coordinate of the centre of the cylindrical
ctr2: float for the second coordinate of the centre of the cylindrical
sector.
extent1: float for the first thickness from the centre of the
extent1: float for the first thickness from the centre of the
cylindrical sector.
extent2: float for the second thickness from the centre of the
extent2: float for the second thickness from the centre of the
cylindrical sector.
r: float for the radius of the cylindrical sector.
start: float for the starting angle (in degrees) for the cylindrical
start: float for the starting angle (in degrees) for the cylindrical
sector.
end: float for the angle (in degrees) swept by the cylindrical sector.
material_id: string for the material identifier that must correspond
material_id: string for the material identifier that must correspond
to material that has already been defined.
material_ids: list of material identifiers in the x, y, z directions.
averaging: string (y or n) used to switch on and off dielectric smoothing.
@@ -53,19 +53,18 @@ class CylindricalSector(UserObjectGeometry):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#cylindrical_sector'
self.hash = "#cylindrical_sector"
def create(self, grid, uip):
try:
normal = self.kwargs['normal'].lower()
ctr1 = self.kwargs['ctr1']
ctr2 = self.kwargs['ctr2']
extent1 = self.kwargs['extent1']
extent2 = self.kwargs['extent2']
start = self.kwargs['start']
end = self.kwargs['end']
r = self.kwargs['r']
normal = self.kwargs["normal"].lower()
ctr1 = self.kwargs["ctr1"]
ctr2 = self.kwargs["ctr2"]
extent1 = self.kwargs["extent1"]
extent2 = self.kwargs["extent2"]
start = self.kwargs["start"]
end = self.kwargs["end"]
r = self.kwargs["r"]
thickness = extent2 - extent1
except KeyError:
logger.exception(self.__str__())
@@ -74,7 +73,7 @@ class CylindricalSector(UserObjectGeometry):
# Check averaging
try:
# Try user-specified averaging
averagecylindricalsector = self.kwargs['averaging']
averagecylindricalsector = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagecylindricalsector = grid.averagevolumeobjects
@@ -82,31 +81,30 @@ class CylindricalSector(UserObjectGeometry):
# Check materials have been specified
# Isotropic case
try:
materialsrequested = [self.kwargs['material_id']]
materialsrequested = [self.kwargs["material_id"]]
except KeyError:
# Anisotropic case
try:
materialsrequested = self.kwargs['material_ids']
materialsrequested = self.kwargs["material_ids"]
except KeyError:
logger.exception(f'{self.__str__()} No materials have been specified')
logger.exception(f"{self.__str__()} No materials have been specified")
raise
sectorstartangle = 2 * np.pi * (start / 360)
sectorangle = 2 * np.pi * (end / 360)
if normal not in ['x', 'y', 'z']:
logger.exception(f'{self.__str__()} the normal direction must be either ' +
f'x, y or z.')
if normal not in ["x", "y", "z"]:
logger.exception(f"{self.__str__()} the normal direction must be either " + f"x, y or z.")
raise ValueError
if r <= 0:
logger.exception(f'{self.__str__()} the radius {r:g} should be a positive value.')
logger.exception(f"{self.__str__()} the radius {r:g} should be a positive value.")
if sectorstartangle < 0 or sectorangle <= 0:
logger.exception(f'{self.__str__()} the starting angle and sector angle should be ' +
f'a positive values.')
logger.exception(f"{self.__str__()} the starting angle and sector angle should be " + f"a positive values.")
raise ValueError
if sectorstartangle >= 2 * np.pi or sectorangle >= 2 * np.pi:
logger.exception(f'{self.__str__()} the starting angle and sector angle must be ' +
f'less than 360 degrees.')
logger.exception(
f"{self.__str__()} the starting angle and sector angle must be " + f"less than 360 degrees."
)
raise ValueError
# Look up requested materials in existing list of material instances
@@ -114,7 +112,7 @@ class CylindricalSector(UserObjectGeometry):
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
logger.exception(f'{self.__str__()} material(s) {notfound} do not exist')
logger.exception(f"{self.__str__()} material(s) {notfound} do not exist")
raise ValueError
if thickness > 0:
@@ -128,23 +126,19 @@ class CylindricalSector(UserObjectGeometry):
numIDx = materials[0].numID
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = f'{materials[0].ID}+{materials[1].ID}+{materials[2].ID}'
requiredID = f"{materials[0].ID}+{materials[1].ID}+{materials[2].ID}"
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
m = Material(numID, requiredID)
m.type = 'dielectric-smoothed'
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
m.er = np.mean((materials[0].er, materials[1].er,
materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se,
materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr,
materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm,
materials[2].sm), axis=0)
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
@@ -163,34 +157,56 @@ class CylindricalSector(UserObjectGeometry):
numIDz = materials[2].numID
# yz-plane cylindrical sector
if normal == 'x':
if normal == "x":
level, ctr1, ctr2 = uip.round_to_grid((extent1, ctr1, ctr2))
# xz-plane cylindrical sector
elif normal == 'y':
elif normal == "y":
ctr1, level, ctr2 = uip.round_to_grid((ctr1, extent1, ctr2))
# xy-plane cylindrical sector
elif normal == 'z':
elif normal == "z":
ctr1, ctr2, level = uip.round_to_grid((ctr1, ctr2, extent1))
build_cylindrical_sector(ctr1, ctr2, level, sectorstartangle, sectorangle,
r, normal, thickness, grid.dx, grid.dy, grid.dz,
numID, numIDx, numIDy, numIDz, averaging,
grid.solid, grid.rigidE, grid.rigidH, grid.ID)
build_cylindrical_sector(
ctr1,
ctr2,
level,
sectorstartangle,
sectorangle,
r,
normal,
thickness,
grid.dx,
grid.dy,
grid.dz,
numID,
numIDx,
numIDy,
numIDz,
averaging,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)
if thickness > 0:
dielectricsmoothing = 'on' if averaging else 'off'
logger.info(f"{self.grid_name(grid)}Cylindrical sector with centre " +
f"{ctr1:g}m, {ctr2:g}m, radius {r:g}m, starting angle " +
f"{(sectorstartangle / (2 * np.pi)) * 360:.1f} degrees, " +
f"sector angle {(sectorangle / (2 * np.pi)) * 360:.1f} degrees, " +
f"thickness {thickness:g}m, of material(s) {', '.join(materialsrequested)} " +
f"created, dielectric smoothing is {dielectricsmoothing}.")
dielectricsmoothing = "on" if averaging else "off"
logger.info(
f"{self.grid_name(grid)}Cylindrical sector with centre "
+ f"{ctr1:g}m, {ctr2:g}m, radius {r:g}m, starting angle "
+ f"{(sectorstartangle / (2 * np.pi)) * 360:.1f} degrees, "
+ f"sector angle {(sectorangle / (2 * np.pi)) * 360:.1f} degrees, "
+ f"thickness {thickness:g}m, of material(s) {', '.join(materialsrequested)} "
+ f"created, dielectric smoothing is {dielectricsmoothing}."
)
else:
logger.info(f"{self.grid_name(grid)}Cylindrical sector with centre " +
f"{ctr1:g}m, {ctr2:g}m, radius {r:g}m, starting angle " +
f"{(sectorstartangle / (2 * np.pi)) * 360:.1f} degrees, " +
f"sector angle {(sectorangle / (2 * np.pi)) * 360:.1f} " +
f"degrees, of material(s) {', '.join(materialsrequested)} " +
f"created.")
logger.info(
f"{self.grid_name(grid)}Cylindrical sector with centre "
+ f"{ctr1:g}m, {ctr2:g}m, radius {r:g}m, starting angle "
+ f"{(sectorstartangle / (2 * np.pi)) * 360:.1f} degrees, "
+ f"sector angle {(sectorangle / (2 * np.pi)) * 360:.1f} "
+ f"degrees, of material(s) {', '.join(materialsrequested)} "
+ f"created."
)

查看文件

@@ -20,8 +20,7 @@ import logging
import numpy as np
from ..cython.geometry_primitives import (build_edge_x, build_edge_y,
build_edge_z)
from ..cython.geometry_primitives import build_edge_x, build_edge_y, build_edge_z
from .cmds_geometry import UserObjectGeometry, rotate_2point_object
logger = logging.getLogger(__name__)
@@ -33,13 +32,13 @@ class Edge(UserObjectGeometry):
Attributes:
p1: list of the coordinates (x,y,z) of the starting point of the edge.
p2: list of the coordinates (x,y,z) of the ending point of the edge.
material_id: string for the material identifier that must correspond
material_id: string for the material identifier that must correspond
to material that has already been defined.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#edge'
self.hash = "#edge"
def rotate(self, axis, angle, origin=None):
"""Set parameters for rotation."""
@@ -50,19 +49,19 @@ class Edge(UserObjectGeometry):
def _do_rotate(self):
"""Performs rotation."""
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
pts = np.array([self.kwargs["p1"], self.kwargs["p2"]])
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
self.kwargs['p1'] = tuple(rot_pts[0, :])
self.kwargs['p2'] = tuple(rot_pts[1, :])
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def create(self, grid, uip):
"""Creates edge and adds it to the grid."""
try:
p1 = self.kwargs['p1']
p2 = self.kwargs['p2']
material_id = self.kwargs['material_id']
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
material_id = self.kwargs["material_id"]
except KeyError:
logger.exception(f'{self.__str__()} requires exactly 3 parameters')
logger.exception(f"{self.__str__()} requires exactly 3 parameters")
raise
if self.do_rotate:
@@ -78,15 +77,17 @@ class Edge(UserObjectGeometry):
material = next((x for x in grid.materials if x.ID == material_id), None)
if not material:
logger.exception(f'Material with ID {material_id} does not exist')
logger.exception(f"Material with ID {material_id} does not exist")
raise ValueError
# Check for valid orientations
# x-orientated edge
if ((xs != xf and (ys != yf or zs != zf))
if (
(xs != xf and (ys != yf or zs != zf))
or (ys != yf and (xs != xf or zs != zf))
or (zs != zf and (xs != xf or ys != yf))):
logger.exception(f'{self.__str__()} the edge is not specified correctly')
or (zs != zf and (xs != xf or ys != yf))
):
logger.exception(f"{self.__str__()} the edge is not specified correctly")
raise ValueError
elif xs != xf:
for i in range(xs, xf):
@@ -100,6 +101,8 @@ class Edge(UserObjectGeometry):
for k in range(zs, zf):
build_edge_z(xs, ys, k, material.numID, grid.rigidE, grid.rigidH, grid.ID)
logger.info(f'{self.grid_name(grid)}Edge from {p3[0]:g}m, {p3[1]:g}m, ' +
f'{p3[2]:g}m, to {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m of ' +
f'material {material_id} created.')
logger.info(
f"{self.grid_name(grid)}Edge from {p3[0]:g}m, {p3[1]:g}m, "
+ f"{p3[2]:g}m, to {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m of "
+ f"material {material_id} created."
)

查看文件

@@ -35,7 +35,7 @@ class Ellipsoid(UserObjectGeometry):
xr: float for x-semiaxis of the elliposid.
xy: float for y-semiaxis of the ellipsoid.
xz: float for z-semiaxis of the ellipsoid.
material_id: string for the material identifier that must correspond
material_id: string for the material identifier that must correspond
to material that has already been defined.
material_ids: list of material identifiers in the x, y, z directions.
averaging: string (y or n) used to switch on and off dielectric smoothing.
@@ -43,24 +43,23 @@ class Ellipsoid(UserObjectGeometry):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#ellipsoid'
self.hash = "#ellipsoid"
def create(self, grid, uip):
try:
p1 = self.kwargs['p1']
xr = self.kwargs['xr']
yr = self.kwargs['yr']
zr = self.kwargs['zr']
p1 = self.kwargs["p1"]
xr = self.kwargs["xr"]
yr = self.kwargs["yr"]
zr = self.kwargs["zr"]
except KeyError:
logger.exception(f'{self.__str__()} please specify a point and ' +
f'the three semiaxes.')
logger.exception(f"{self.__str__()} please specify a point and " + f"the three semiaxes.")
raise
# Check averaging
try:
# Try user-specified averaging
averageellipsoid = self.kwargs['averaging']
averageellipsoid = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averageellipsoid = grid.averagevolumeobjects
@@ -68,13 +67,13 @@ class Ellipsoid(UserObjectGeometry):
# Check materials have been specified
# Isotropic case
try:
materialsrequested = [self.kwargs['material_id']]
materialsrequested = [self.kwargs["material_id"]]
except KeyError:
# Anisotropic case
try:
materialsrequested = self.kwargs['material_ids']
materialsrequested = self.kwargs["material_ids"]
except KeyError:
logger.exception(f'{self.__str__()} no materials have been specified')
logger.exception(f"{self.__str__()} no materials have been specified")
raise
# Centre of ellipsoid
@@ -86,7 +85,7 @@ class Ellipsoid(UserObjectGeometry):
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
logger.exception(f'{self.__str__()} material(s) {notfound} do not exist')
logger.exception(f"{self.__str__()} material(s) {notfound} do not exist")
raise ValueError
# Isotropic case
@@ -100,34 +99,49 @@ class Ellipsoid(UserObjectGeometry):
numIDx = materials[0].numID
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + '+' + materials[1].ID + '+' + materials[2].ID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
m = Material(numID, requiredID)
m.type = 'dielectric-smoothed'
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
m.er = np.mean((materials[0].er, materials[1].er,
materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se,
materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr,
materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm,
materials[2].sm), axis=0)
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
build_ellipsoid(xc, yc, zc, xr, yr, zr, grid.dx, grid.dy, grid.dz, numID,
numIDx, numIDy, numIDz, averaging, grid.solid,
grid.rigidE, grid.rigidH, grid.ID)
build_ellipsoid(
xc,
yc,
zc,
xr,
yr,
zr,
grid.dx,
grid.dy,
grid.dz,
numID,
numIDx,
numIDy,
numIDz,
averaging,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)
dielectricsmoothing = 'on' if averaging else 'off'
logger.info(f"{self.grid_name(grid)}Ellipsoid with centre {p2[0]:g}m, " +
f"{p2[1]:g}m, {p2[2]:g}m, x-semiaxis {xr:g}m, " +
f"y-semiaxis {yr:g}m and z-semiaxis {zr:g}m of material(s) " +
f"{', '.join(materialsrequested)} created, dielectric " +
f"smoothing is {dielectricsmoothing}.")
dielectricsmoothing = "on" if averaging else "off"
logger.info(
f"{self.grid_name(grid)}Ellipsoid with centre {p2[0]:g}m, "
+ f"{p2[1]:g}m, {p2[2]:g}m, x-semiaxis {xr:g}m, "
+ f"y-semiaxis {yr:g}m and z-semiaxis {zr:g}m of material(s) "
+ f"{', '.join(materialsrequested)} created, dielectric "
+ f"smoothing is {dielectricsmoothing}."
)

查看文件

@@ -28,32 +28,32 @@ logger = logging.getLogger(__name__)
class FractalBox(UserObjectGeometry):
"""Introduces an orthogonal parallelepiped with fractal distributed
properties which are related to a mixing model or normal material into
"""Introduces an orthogonal parallelepiped with fractal distributed
properties which are related to a mixing model or normal material into
the model.
Attributes:
p1: list of the lower left (x,y,z) coordinates of the parallelepiped.
p2: list of the upper right (x,y,z) coordinates of the parallelepiped.
frac_dim: float for the fractal dimension which, for an orthogonal
frac_dim: float for the fractal dimension which, for an orthogonal
parallelepiped, should take values between zero and three.
weighting: list of the weightings in the x, y, z direction of the
weighting: list of the weightings in the x, y, z direction of the
parallelepiped.
n_materials: int of the number of materials to use for the fractal
distribution (defined according to the associated
mixing model). This should be set to one if using a
n_materials: int of the number of materials to use for the fractal
distribution (defined according to the associated
mixing model). This should be set to one if using a
normal material instead of a mixing model.
mixing_model_id: string identifier for the associated mixing model or
mixing_model_id: string identifier for the associated mixing model or
material.
id: string identifier for the fractal box itself.
seed: (optional) float parameter which controls the seeding of the
seed: (optional) float parameter which controls the seeding of the
random number generator used to create the fractals.
averaging: string (y or n) used to switch on and off dielectric smoothing.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#fractal_box'
self.hash = "#fractal_box"
def rotate(self, axis, angle, origin=None):
"""Set parameters for rotation."""
@@ -64,30 +64,32 @@ class FractalBox(UserObjectGeometry):
def _do_rotate(self):
"""Performs rotation."""
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
pts = np.array([self.kwargs["p1"], self.kwargs["p2"]])
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
self.kwargs['p1'] = tuple(rot_pts[0, :])
self.kwargs['p2'] = tuple(rot_pts[1, :])
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def create(self, grid, uip):
try:
p1 = self.kwargs['p1']
p2 = self.kwargs['p2']
frac_dim = self.kwargs['frac_dim']
weighting = np.array(self.kwargs['weighting'])
n_materials = self.kwargs['n_materials']
mixing_model_id = self.kwargs['mixing_model_id']
ID = self.kwargs['id']
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
frac_dim = self.kwargs["frac_dim"]
weighting = np.array(self.kwargs["weighting"])
n_materials = self.kwargs["n_materials"]
mixing_model_id = self.kwargs["mixing_model_id"]
ID = self.kwargs["id"]
except KeyError:
logger.exception(f'{self.__str__()} Incorrect parameters')
logger.exception(f"{self.__str__()} Incorrect parameters")
raise
try:
seed = self.kwargs['seed']
seed = self.kwargs["seed"]
except KeyError:
logger.warning(f'{self.__str__()} no value for seed detected. This ' +
'means you will get a different fractal distribution ' +
'every time the model runs.')
logger.warning(
f"{self.__str__()} no value for seed detected. This "
+ "means you will get a different fractal distribution "
+ "every time the model runs."
)
seed = None
if self.do_rotate:
@@ -96,9 +98,9 @@ class FractalBox(UserObjectGeometry):
# Check averaging
try:
# Go with user specified averaging
averagefractalbox = self.kwargs['averaging']
averagefractalbox = self.kwargs["averaging"]
except KeyError:
# If they havent specified - default is no dielectric smoothing for
# If they havent specified - default is no dielectric smoothing for
# a fractal box.
averagefractalbox = False
@@ -110,26 +112,27 @@ class FractalBox(UserObjectGeometry):
xf, yf, zf = p2
if frac_dim < 0:
logger.exception(f'{self.__str__()} requires a positive value for the ' +
'fractal dimension')
logger.exception(f"{self.__str__()} requires a positive value for the " + "fractal dimension")
raise ValueError
if weighting[0] < 0:
logger.exception(f'{self.__str__()} requires a positive value for the ' +
'fractal weighting in the x direction')
logger.exception(
f"{self.__str__()} requires a positive value for the " + "fractal weighting in the x direction"
)
raise ValueError
if weighting[1] < 0:
logger.exception(f'{self.__str__()} requires a positive value for the ' +
'fractal weighting in the y direction')
logger.exception(
f"{self.__str__()} requires a positive value for the " + "fractal weighting in the y direction"
)
raise ValueError
if weighting[2] < 0:
logger.exception(f'{self.__str__()} requires a positive value for the ' +
'fractal weighting in the z direction')
logger.exception(
f"{self.__str__()} requires a positive value for the " + "fractal weighting in the z direction"
)
if n_materials < 0:
logger.exception(f'{self.__str__()} requires a positive value for the ' +
'number of bins')
logger.exception(f"{self.__str__()} requires a positive value for the " + "number of bins")
raise ValueError
# Find materials to use to build fractal volume, either from mixing
# Find materials to use to build fractal volume, either from mixing
# models or normal materials.
mixingmodel = next((x for x in grid.mixingmodels if x.ID == mixing_model_id), None)
material = next((x for x in grid.materials if x.ID == mixing_model_id), None)
@@ -137,21 +140,23 @@ class FractalBox(UserObjectGeometry):
if mixingmodel:
if nbins == 1:
logger.exception(f'{self.__str__()} must be used with more than ' +
'one material from the mixing model.')
logger.exception(
f"{self.__str__()} must be used with more than " + "one material from the mixing model."
)
raise ValueError
if isinstance(mixingmodel, ListMaterial):
if nbins > len(mixingmodel.mat):
logger.exception(f'{self.__str__()} too many materials/bins ' +
'requested compared to materials in ' +
'mixing model.')
logger.exception(
f"{self.__str__()} too many materials/bins "
+ "requested compared to materials in "
+ "mixing model."
)
raise ValueError
# Create materials from mixing model as number of bins now known
# Create materials from mixing model as number of bins now known
# from fractal_box command.
mixingmodel.calculate_properties(nbins, grid)
elif not material:
logger.exception(f'{self.__str__()} mixing model or material with ' +
'ID {mixing_model_id} does not exist')
logger.exception(f"{self.__str__()} mixing model or material with " + "ID {mixing_model_id} does not exist")
raise ValueError
volume = FractalVolume(xs, xf, ys, yf, zs, zf, frac_dim)
@@ -166,14 +171,16 @@ class FractalBox(UserObjectGeometry):
volume.averaging = averagefractalbox
volume.mixingmodel = mixingmodel
dielectricsmoothing = 'on' if volume.averaging else 'off'
logger.info(f'{self.grid_name(grid)}Fractal box {volume.ID} from ' +
f'{p3[0]:g}m, {p3[1]:g}m, {p3[2]:g}m, to {p4[0]:g}m, ' +
f'{p4[1]:g}m, {p4[2]:g}m with {volume.operatingonID}, ' +
f'fractal dimension {volume.dimension:g}, fractal weightings ' +
f'{volume.weighting[0]:g}, {volume.weighting[1]:g}, ' +
f'{volume.weighting[2]:g}, fractal seeding {volume.seed}, ' +
f'with {volume.nbins} material(s) created, dielectric smoothing ' +
f'is {dielectricsmoothing}.')
dielectricsmoothing = "on" if volume.averaging else "off"
logger.info(
f"{self.grid_name(grid)}Fractal box {volume.ID} from "
+ f"{p3[0]:g}m, {p3[1]:g}m, {p3[2]:g}m, to {p4[0]:g}m, "
+ f"{p4[1]:g}m, {p4[2]:g}m with {volume.operatingonID}, "
+ f"fractal dimension {volume.dimension:g}, fractal weightings "
+ f"{volume.weighting[0]:g}, {volume.weighting[1]:g}, "
+ f"{volume.weighting[2]:g}, fractal seeding {volume.seed}, "
+ f"with {volume.nbins} material(s) created, dielectric smoothing "
+ f"is {dielectricsmoothing}."
)
grid.fractalvolumes.append(volume)

查看文件

@@ -21,8 +21,7 @@ import logging
import gprMax.config as config
import numpy as np
from ..cython.geometry_primitives import (build_voxels_from_array,
build_voxels_from_array_mask)
from ..cython.geometry_primitives import build_voxels_from_array, build_voxels_from_array_mask
from .cmds_geometry import UserObjectGeometry
logger = logging.getLogger(__name__)
@@ -30,11 +29,11 @@ logger = logging.getLogger(__name__)
class FractalBoxBuilder(UserObjectGeometry):
"""Internal class for fractal box modifications. This class should be used
internally only when surface modification have been made to a fractal box."""
internally only when surface modification have been made to a fractal box."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#fractal_box_modifications'
self.hash = "#fractal_box_modifications"
def create(self, grid, uip):
for volume in grid.fractalvolumes:
@@ -46,39 +45,40 @@ class FractalBoxBuilder(UserObjectGeometry):
volume.originalzs = volume.zs
volume.originalzf = volume.zf
# Extend the volume to accomodate any rough surfaces, grass,
# Extend the volume to accomodate any rough surfaces, grass,
# or roots
for surface in volume.fractalsurfaces:
if surface.surfaceID == 'xminus':
if surface.surfaceID == "xminus":
if surface.fractalrange[0] < volume.xs:
volume.nx += volume.xs - surface.fractalrange[0]
volume.xs = surface.fractalrange[0]
elif surface.surfaceID == 'xplus':
elif surface.surfaceID == "xplus":
if surface.fractalrange[1] > volume.xf:
volume.nx += surface.fractalrange[1] - volume.xf
volume.xf = surface.fractalrange[1]
elif surface.surfaceID == 'yminus':
elif surface.surfaceID == "yminus":
if surface.fractalrange[0] < volume.ys:
volume.ny += volume.ys - surface.fractalrange[0]
volume.ys = surface.fractalrange[0]
elif surface.surfaceID == 'yplus':
elif surface.surfaceID == "yplus":
if surface.fractalrange[1] > volume.yf:
volume.ny += surface.fractalrange[1] - volume.yf
volume.yf = surface.fractalrange[1]
elif surface.surfaceID == 'zminus':
elif surface.surfaceID == "zminus":
if surface.fractalrange[0] < volume.zs:
volume.nz += volume.zs - surface.fractalrange[0]
volume.zs = surface.fractalrange[0]
elif surface.surfaceID == 'zplus':
elif surface.surfaceID == "zplus":
if surface.fractalrange[1] > volume.zf:
volume.nz += surface.fractalrange[1] - volume.zf
volume.zf = surface.fractalrange[1]
# If there is only 1 bin then a normal material is being used,
# 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=config.sim_config.dtypes['float_or_double'])
volume.fractalvolume = np.ones(
(volume.nx, volume.ny, volume.nz), dtype=config.sim_config.dtypes["float_or_double"]
)
materialnumID = next(x.numID for x in grid.materials if x.ID == volume.operatingonID)
volume.fractalvolume *= materialnumID
else:
@@ -86,16 +86,16 @@ class FractalBoxBuilder(UserObjectGeometry):
for i in range(0, volume.nx):
for j in range(0, volume.ny):
for k in range(0, volume.nz):
numberinbin = volume.fractalvolume[i,j,k]
volume.fractalvolume[i,j,k] = volume.mixingmodel.matID[int(numberinbin)]
numberinbin = volume.fractalvolume[i, j, k]
volume.fractalvolume[i, j, k] = volume.mixingmodel.matID[int(numberinbin)]
volume.generate_volume_mask()
# Apply any rough surfaces and add any surface water to the
# Apply any rough surfaces and add any surface water to the
# 3D mask array
# TODO: Allow extract of rough surface profile (to print/file?)
for surface in volume.fractalsurfaces:
if surface.surfaceID == 'xminus':
if surface.surfaceID == "xminus":
for i in range(surface.fractalrange[0], surface.fractalrange[1]):
for j in range(surface.ys, surface.yf):
for k in range(surface.zs, surface.zf):
@@ -106,7 +106,7 @@ class FractalBoxBuilder(UserObjectGeometry):
else:
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] = 0
elif surface.surfaceID == 'xplus':
elif surface.surfaceID == "xplus":
if not surface.ID:
for i in range(surface.fractalrange[0], surface.fractalrange[1]):
for j in range(surface.ys, surface.yf):
@@ -117,7 +117,7 @@ class FractalBoxBuilder(UserObjectGeometry):
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] = 2
else:
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] = 0
elif surface.ID == 'grass':
elif surface.ID == "grass":
g = surface.grass[0]
# Build the blades of the grass
blade = 0
@@ -126,15 +126,22 @@ class FractalBoxBuilder(UserObjectGeometry):
if surface.fractalsurface[j - surface.ys, k - surface.zs] > 0:
height = 0
for i in range(volume.xs, surface.fractalrange[1]):
if (i < surface.fractalsurface[j - surface.ys, k - surface.zs] and
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1):
if (
i < surface.fractalsurface[j - surface.ys, k - surface.zs]
and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1
):
y, z = g.calculate_blade_geometry(blade, height)
# Add y, z coordinates to existing location
yy = int(j - volume.ys + y)
zz = int(k - volume.zs + z)
# If these coordinates are outwith fractal volume stop building the blade,
# If these coordinates are outwith fractal volume stop building the blade,
# otherwise set the mask for grass.
if yy < 0 or yy >= volume.mask.shape[1] or zz < 0 or zz >= volume.mask.shape[2]:
if (
yy < 0
or yy >= volume.mask.shape[1]
or zz < 0
or zz >= volume.mask.shape[2]
):
break
else:
volume.mask[i - volume.xs, yy, zz] = 3
@@ -149,15 +156,27 @@ class FractalBoxBuilder(UserObjectGeometry):
depth = 0
i = volume.xf - 1
while i > volume.xs:
if (i > volume.originalxf - (surface.fractalsurface[j - surface.ys, k - surface.zs] -
volume.originalxf) and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1):
if (
i
> volume.originalxf
- (
surface.fractalsurface[j - surface.ys, k - surface.zs]
- volume.originalxf
)
and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1
):
y, z = g.calculate_root_geometry(root, depth)
# Add y, z coordinates to existing location
yy = int(j - volume.ys + y)
zz = int(k - volume.zs + z)
# If these coordinates are outwith the fractal volume stop building the root,
# If these coordinates are outwith the fractal volume stop building the root,
# otherwise set the mask for grass.
if yy < 0 or yy >= volume.mask.shape[1] or zz < 0 or zz >= volume.mask.shape[2]:
if (
yy < 0
or yy >= volume.mask.shape[1]
or zz < 0
or zz >= volume.mask.shape[2]
):
break
else:
volume.mask[i - volume.xs, yy, zz] = 3
@@ -165,7 +184,7 @@ class FractalBoxBuilder(UserObjectGeometry):
i -= 1
root += 1
elif surface.surfaceID == 'yminus':
elif surface.surfaceID == "yminus":
for i in range(surface.xs, surface.xf):
for j in range(surface.fractalrange[0], surface.fractalrange[1]):
for k in range(surface.zs, surface.zf):
@@ -176,7 +195,7 @@ class FractalBoxBuilder(UserObjectGeometry):
else:
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] = 0
elif surface.surfaceID == 'yplus':
elif surface.surfaceID == "yplus":
if not surface.ID:
for i in range(surface.xs, surface.xf):
for j in range(surface.fractalrange[0], surface.fractalrange[1]):
@@ -187,7 +206,7 @@ class FractalBoxBuilder(UserObjectGeometry):
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] = 2
else:
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] = 0
elif surface.ID == 'grass':
elif surface.ID == "grass":
g = surface.grass[0]
# Build the blades of the grass
blade = 0
@@ -196,15 +215,22 @@ class FractalBoxBuilder(UserObjectGeometry):
if surface.fractalsurface[i - surface.xs, k - surface.zs] > 0:
height = 0
for j in range(volume.ys, surface.fractalrange[1]):
if (j < surface.fractalsurface[i - surface.xs, k - surface.zs] and
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1):
if (
j < surface.fractalsurface[i - surface.xs, k - surface.zs]
and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1
):
x, z = g.calculate_blade_geometry(blade, height)
# Add x, z coordinates to existing location
xx = int(i - volume.xs + x)
zz = int(k - volume.zs + z)
# If these coordinates are outwith fractal volume stop building the blade,
# If these coordinates are outwith fractal volume stop building the blade,
# otherwise set the mask for grass.
if xx < 0 or xx >= volume.mask.shape[0] or zz < 0 or zz >= volume.mask.shape[2]:
if (
xx < 0
or xx >= volume.mask.shape[0]
or zz < 0
or zz >= volume.mask.shape[2]
):
break
else:
volume.mask[xx, j - volume.ys, zz] = 3
@@ -219,15 +245,27 @@ class FractalBoxBuilder(UserObjectGeometry):
depth = 0
j = volume.yf - 1
while j > volume.ys:
if (j > volume.originalyf - (surface.fractalsurface[i - surface.xs, k - surface.zs] -
volume.originalyf) and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1):
if (
j
> volume.originalyf
- (
surface.fractalsurface[i - surface.xs, k - surface.zs]
- volume.originalyf
)
and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1
):
x, z = g.calculate_root_geometry(root, depth)
# Add x, z coordinates to existing location
xx = int(i - volume.xs + x)
zz = int(k - volume.zs + z)
# If these coordinates are outwith the fractal volume stop building the root,
# If these coordinates are outwith the fractal volume stop building the root,
# otherwise set the mask for grass.
if xx < 0 or xx >= volume.mask.shape[0] or zz < 0 or zz >= volume.mask.shape[2]:
if (
xx < 0
or xx >= volume.mask.shape[0]
or zz < 0
or zz >= volume.mask.shape[2]
):
break
else:
volume.mask[xx, j - volume.ys, zz] = 3
@@ -235,7 +273,7 @@ class FractalBoxBuilder(UserObjectGeometry):
j -= 1
root += 1
elif surface.surfaceID == 'zminus':
elif surface.surfaceID == "zminus":
for i in range(surface.xs, surface.xf):
for j in range(surface.ys, surface.yf):
for k in range(surface.fractalrange[0], surface.fractalrange[1]):
@@ -246,7 +284,7 @@ class FractalBoxBuilder(UserObjectGeometry):
else:
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] = 0
elif surface.surfaceID == 'zplus':
elif surface.surfaceID == "zplus":
if not surface.ID:
for i in range(surface.xs, surface.xf):
for j in range(surface.ys, surface.yf):
@@ -257,7 +295,7 @@ class FractalBoxBuilder(UserObjectGeometry):
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] = 2
else:
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] = 0
elif surface.ID == 'grass':
elif surface.ID == "grass":
g = surface.grass[0]
# Build the blades of the grass
blade = 0
@@ -266,15 +304,22 @@ class FractalBoxBuilder(UserObjectGeometry):
if surface.fractalsurface[i - surface.xs, j - surface.ys] > 0:
height = 0
for k in range(volume.zs, surface.fractalrange[1]):
if (k < surface.fractalsurface[i - surface.xs, j - surface.ys] and
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1):
if (
k < surface.fractalsurface[i - surface.xs, j - surface.ys]
and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1
):
x, y = g.calculate_blade_geometry(blade, height)
# Add x, y coordinates to existing location
xx = int(i - volume.xs + x)
yy = int(j - volume.ys + y)
# If these coordinates are outwith the fractal volume stop building the blade,
# If these coordinates are outwith the fractal volume stop building the blade,
# otherwise set the mask for grass.
if xx < 0 or xx >= volume.mask.shape[0] or yy < 0 or yy >= volume.mask.shape[1]:
if (
xx < 0
or xx >= volume.mask.shape[0]
or yy < 0
or yy >= volume.mask.shape[1]
):
break
else:
volume.mask[xx, yy, k - volume.zs] = 3
@@ -289,15 +334,27 @@ class FractalBoxBuilder(UserObjectGeometry):
depth = 0
k = volume.zf - 1
while k > volume.zs:
if (k > volume.originalzf - (surface.fractalsurface[i - surface.xs, j - surface.ys] -
volume.originalzf) and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1):
if (
k
> volume.originalzf
- (
surface.fractalsurface[i - surface.xs, j - surface.ys]
- volume.originalzf
)
and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1
):
x, y = g.calculate_root_geometry(root, depth)
# Add x, y coordinates to existing location
xx = int(i - volume.xs + x)
yy = int(j - volume.ys + y)
# If these coordinates are outwith the fractal volume stop building the root,
# If these coordinates are outwith the fractal volume stop building the root,
# otherwise set the mask for grass.
if xx < 0 or xx >= volume.mask.shape[0] or yy < 0 or yy >= volume.mask.shape[1]:
if (
xx < 0
or xx >= volume.mask.shape[0]
or yy < 0
or yy >= volume.mask.shape[1]
):
break
else:
volume.mask[xx, yy, k - volume.zs] = 3
@@ -306,33 +363,53 @@ class FractalBoxBuilder(UserObjectGeometry):
root += 1
# Build voxels from any true values of the 3D mask array
waternumID = next((x.numID for x in grid.materials if x.ID == 'water'), 0)
grassnumID = next((x.numID for x in grid.materials if x.ID == 'grass'), 0)
data = volume.fractalvolume.astype('int16', order='C')
mask = volume.mask.copy(order='C')
build_voxels_from_array_mask(volume.xs, volume.ys, volume.zs,
config.get_model_config().ompthreads,
waternumID, grassnumID, volume.averaging,
mask, data, grid.solid, grid.rigidE,
grid.rigidH, grid.ID)
waternumID = next((x.numID for x in grid.materials if x.ID == "water"), 0)
grassnumID = next((x.numID for x in grid.materials if x.ID == "grass"), 0)
data = volume.fractalvolume.astype("int16", order="C")
mask = volume.mask.copy(order="C")
build_voxels_from_array_mask(
volume.xs,
volume.ys,
volume.zs,
config.get_model_config().ompthreads,
waternumID,
grassnumID,
volume.averaging,
mask,
data,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)
else:
if volume.nbins == 1:
logger.exception(f'{self.__str__()} is being used with a ' +
'single material and no modifications, ' +
'therefore please use a #box command instead.')
logger.exception(
f"{self.__str__()} is being used with a "
+ "single material and no modifications, "
+ "therefore please use a #box command instead."
)
raise ValueError
else:
volume.generate_fractal_volume()
for i in range(0, volume.nx):
for j in range(0, volume.ny):
for k in range(0, volume.nz):
numberinbin = volume.fractalvolume[i,j,k]
volume.fractalvolume[i,j,k] = volume.mixingmodel.matID[int(numberinbin)]
numberinbin = volume.fractalvolume[i, j, k]
volume.fractalvolume[i, j, k] = volume.mixingmodel.matID[int(numberinbin)]
data = volume.fractalvolume.astype('int16', order='C')
build_voxels_from_array(volume.xs, volume.ys, volume.zs,
config.get_model_config().ompthreads, 0,
volume.averaging, data, grid.solid,
grid.rigidE, grid.rigidH, grid.ID)
data = volume.fractalvolume.astype("int16", order="C")
build_voxels_from_array(
volume.xs,
volume.ys,
volume.zs,
config.get_model_config().ompthreads,
0,
volume.averaging,
data,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)

查看文件

@@ -31,10 +31,9 @@ logger = logging.getLogger(__name__)
class GeometryObjectsRead(UserObjectGeometry):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#geometry_objects_read'
self.hash = "#geometry_objects_read"
def rotate(self, axis, angle, origin=None):
pass
@@ -42,11 +41,11 @@ class GeometryObjectsRead(UserObjectGeometry):
def create(self, grid, uip):
"""Creates the object and adds it to the grid."""
try:
p1 = self.kwargs['p1']
geofile = self.kwargs['geofile']
matfile = self.kwargs['matfile']
p1 = self.kwargs["p1"]
geofile = self.kwargs["geofile"]
matfile = self.kwargs["matfile"]
except KeyError:
logger.exception(f'{self.__str__()} requires exactly five parameters')
logger.exception(f"{self.__str__()} requires exactly five parameters")
raise
# Discretise the point using uip object. This has different behaviour
@@ -61,14 +60,18 @@ class GeometryObjectsRead(UserObjectGeometry):
if not matfile.exists():
matfile = Path(config.sim_config.input_file_path.parent, matfile)
matstr = matfile.with_suffix('').name
matstr = matfile.with_suffix("").name
numexistmaterials = len(grid.materials)
# Read materials from file
with open(matfile, 'r') as f:
with open(matfile, "r") as f:
# Read any lines that begin with a hash. Strip out any newline
# characters and comments that must begin with double hashes.
materials = [line.rstrip() + '{' + matstr + '}\n' for line in f if(line.startswith('#') and not line.startswith('##') and line.rstrip('\n'))]
materials = [
line.rstrip() + "{" + matstr + "}\n"
for line in f
if (line.startswith("#") and not line.startswith("##") and line.rstrip("\n"))
]
# Build scene
# API for multiple scenes / model runs
@@ -84,54 +87,74 @@ class GeometryObjectsRead(UserObjectGeometry):
for material in grid.materials:
if material.numID >= numexistmaterials:
if material.type:
material.type += ',\nimported'
material.type += ",\nimported"
else:
material.type = 'imported'
material.type = "imported"
# See if geometry object file exists at specified path and if not try
# See if geometry object file exists at specified path and if not try
# input file directory.
geofile = Path(geofile)
if not geofile.exists():
geofile = Path(config.sim_config.input_file_path.parent, geofile)
# Open geometry object file and read/check spatial resolution attribute
f = h5py.File(geofile, 'r')
dx_dy_dz = f.attrs['dx_dy_dz']
if round_value((dx_dy_dz[0] / grid.dx) != 1 or
round_value(dx_dy_dz[1] / grid.dy) != 1 or
round_value(dx_dy_dz[2] / grid.dz) != 1):
logger.exception(f'{self.__str__()} requires the spatial resolution ' +
'of the geometry objects file to match the spatial ' +
'resolution of the model')
f = h5py.File(geofile, "r")
dx_dy_dz = f.attrs["dx_dy_dz"]
if round_value(
(dx_dy_dz[0] / grid.dx) != 1
or round_value(dx_dy_dz[1] / grid.dy) != 1
or round_value(dx_dy_dz[2] / grid.dz) != 1
):
logger.exception(
f"{self.__str__()} requires the spatial resolution "
+ "of the geometry objects file to match the spatial "
+ "resolution of the model"
)
raise ValueError
data = f['/data'][:]
data = f["/data"][:]
# Should be int16 to allow for -1 which indicates background, i.e.
# don't build anything, but AustinMan/Woman maybe uint16
if data.dtype != 'int16':
data = data.astype('int16')
if data.dtype != "int16":
data = data.astype("int16")
# Look to see if rigid and ID arrays are present (these should be
# present if the original geometry objects were written from gprMax)
try:
rigidE = f['/rigidE'][:]
rigidH = f['/rigidH'][:]
ID = f['/ID'][:]
grid.solid[xs:xs + data.shape[0], ys:ys + data.shape[1], zs:zs + data.shape[2]] = data + numexistmaterials
grid.rigidE[:, xs:xs + rigidE.shape[1], ys:ys + rigidE.shape[2], zs:zs + rigidE.shape[3]] = rigidE
grid.rigidH[:, xs:xs + rigidH.shape[1], ys:ys + rigidH.shape[2], zs:zs + rigidH.shape[3]] = rigidH
grid.ID[:, xs:xs + ID.shape[1], ys:ys + ID.shape[2], zs:zs + ID.shape[3]] = ID + numexistmaterials
logger.info(f'{self.grid_name(grid)}Geometry objects from file {geofile} ' +
f'inserted at {xs * grid.dx:g}m, {ys * grid.dy:g}m, ' +
f'{zs * grid.dz:g}m, with corresponding materials file ' +
f'{matfile}.')
rigidE = f["/rigidE"][:]
rigidH = f["/rigidH"][:]
ID = f["/ID"][:]
grid.solid[xs : xs + data.shape[0], ys : ys + data.shape[1], zs : zs + data.shape[2]] = (
data + numexistmaterials
)
grid.rigidE[:, xs : xs + rigidE.shape[1], ys : ys + rigidE.shape[2], zs : zs + rigidE.shape[3]] = rigidE
grid.rigidH[:, xs : xs + rigidH.shape[1], ys : ys + rigidH.shape[2], zs : zs + rigidH.shape[3]] = rigidH
grid.ID[:, xs : xs + ID.shape[1], ys : ys + ID.shape[2], zs : zs + ID.shape[3]] = ID + numexistmaterials
logger.info(
f"{self.grid_name(grid)}Geometry objects from file {geofile} "
+ f"inserted at {xs * grid.dx:g}m, {ys * grid.dy:g}m, "
+ f"{zs * grid.dz:g}m, with corresponding materials file "
+ f"{matfile}."
)
except KeyError:
averaging = False
build_voxels_from_array(xs, ys, zs, config.get_model_config().ompthreads,
numexistmaterials, averaging, data,
grid.solid, grid.rigidE, grid.rigidH, grid.ID)
logger.info(f'{self.grid_name(grid)}Geometry objects from file ' +
f'(voxels only){geofile} inserted at {xs * grid.dx:g}m, ' +
f'{ys * grid.dy:g}m, {zs * grid.dz:g}m, with corresponding ' +
f'materials file {matfile}.')
build_voxels_from_array(
xs,
ys,
zs,
config.get_model_config().ompthreads,
numexistmaterials,
averaging,
data,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)
logger.info(
f"{self.grid_name(grid)}Geometry objects from file "
+ f"(voxels only){geofile} inserted at {xs * grid.dx:g}m, "
+ f"{ys * grid.dy:g}m, {zs * grid.dz:g}m, with corresponding "
+ f"materials file {matfile}."
)

查看文件

@@ -20,8 +20,7 @@ import logging
import numpy as np
from ..cython.geometry_primitives import (build_face_xy, build_face_xz,
build_face_yz)
from ..cython.geometry_primitives import build_face_xy, build_face_xz, build_face_yz
from .cmds_geometry import UserObjectGeometry, rotate_2point_object
logger = logging.getLogger(__name__)
@@ -33,14 +32,14 @@ class Plate(UserObjectGeometry):
Attributes:
p1: list of the lower left (x,y,z) coordinates of the plate.
p2: list of the upper right (x,y,z) coordinates of the plate.
material_id: string for the material identifier that must correspond
material_id: string for the material identifier that must correspond
to material that has already been defined.
material_ids: list of material identifiers in the x, y, z directions.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#plate'
self.hash = "#plate"
def rotate(self, axis, angle, origin=None):
"""Set parameters for rotation."""
@@ -51,28 +50,28 @@ class Plate(UserObjectGeometry):
def _do_rotate(self):
"""Performs rotation."""
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
pts = np.array([self.kwargs["p1"], self.kwargs["p2"]])
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
self.kwargs['p1'] = tuple(rot_pts[0, :])
self.kwargs['p2'] = tuple(rot_pts[1, :])
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def create(self, grid, uip):
try:
p1 = self.kwargs['p1']
p2 = self.kwargs['p2']
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
except KeyError:
logger.exception(f'{self.__str__()} 2 points must be specified')
logger.exception(f"{self.__str__()} 2 points must be specified")
raise
# isotropic
try:
materialsrequested = [self.kwargs['material_id']]
materialsrequested = [self.kwargs["material_id"]]
except KeyError:
# Anisotropic case
try:
materialsrequested = self.kwargs['material_ids']
materialsrequested = self.kwargs["material_ids"]
except KeyError:
logger.exception(f'{self.__str__()} No materials have been specified')
logger.exception(f"{self.__str__()} No materials have been specified")
raise
if self.do_rotate:
@@ -86,10 +85,12 @@ class Plate(UserObjectGeometry):
xf, yf, zf = p2
# Check for valid orientations
if ((xs == xf and (ys == yf or zs == zf))
if (
(xs == xf and (ys == yf or zs == zf))
or (ys == yf and (xs == xf or zs == zf))
or (zs == zf and (xs == xf or ys == yf))):
logger.exception(f'{self.__str__()} the plate is not specified correctly')
or (zs == zf and (xs == xf or ys == yf))
):
logger.exception(f"{self.__str__()} the plate is not specified correctly")
raise ValueError
# Look up requested materials in existing list of material instances
@@ -97,7 +98,7 @@ class Plate(UserObjectGeometry):
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
logger.exception(f'{self.__str__()} material(s) {notfound} do not exist')
logger.exception(f"{self.__str__()} material(s) {notfound} do not exist")
raise ValueError
# yz-plane plate
@@ -113,8 +114,7 @@ class Plate(UserObjectGeometry):
for j in range(ys, yf):
for k in range(zs, zf):
build_face_yz(xs, j, k, numIDy, numIDz, grid.rigidE,
grid.rigidH, grid.ID)
build_face_yz(xs, j, k, numIDy, numIDz, grid.rigidE, grid.rigidH, grid.ID)
# xz-plane plate
elif ys == yf:
@@ -129,8 +129,7 @@ class Plate(UserObjectGeometry):
for i in range(xs, xf):
for k in range(zs, zf):
build_face_xz(i, ys, k, numIDx, numIDz, grid.rigidE,
grid.rigidH, grid.ID)
build_face_xz(i, ys, k, numIDx, numIDz, grid.rigidE, grid.rigidH, grid.ID)
# xy-plane plate
elif zs == zf:
@@ -145,9 +144,10 @@ class Plate(UserObjectGeometry):
for i in range(xs, xf):
for j in range(ys, yf):
build_face_xy(i, j, zs, numIDx, numIDy, grid.rigidE,
grid.rigidH, grid.ID)
build_face_xy(i, j, zs, numIDx, numIDy, grid.rigidE, grid.rigidH, grid.ID)
logger.info(f"{self.grid_name(grid)}Plate from {p3[0]:g}m, {p3[1]:g}m, " +
f"{p3[2]:g}m, to {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m of " +
f"material(s) {', '.join(materialsrequested)} created.")
logger.info(
f"{self.grid_name(grid)}Plate from {p3[0]:g}m, {p3[1]:g}m, "
+ f"{p3[2]:g}m, to {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m of "
+ f"material(s) {', '.join(materialsrequested)} created."
)

查看文件

@@ -33,7 +33,7 @@ class Sphere(UserObjectGeometry):
Attributes:
p1: list of the coordinates (x,y,z) of the centre of the sphere.
r: float of radius of the sphere.
material_id: string for the material identifier that must correspond
material_id: string for the material identifier that must correspond
to material that has already been defined.
material_ids: list of material identifiers in the x, y, z directions.
averaging: string (y or n) used to switch on and off dielectric smoothing.
@@ -41,20 +41,20 @@ class Sphere(UserObjectGeometry):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#sphere'
self.hash = "#sphere"
def create(self, grid, uip):
try:
p1 = self.kwargs['p1']
r = self.kwargs['r']
p1 = self.kwargs["p1"]
r = self.kwargs["r"]
except KeyError:
logger.exception(f'{self.__str__()} please specify a point and a radius.')
logger.exception(f"{self.__str__()} please specify a point and a radius.")
raise
# Check averaging
try:
# Try user-specified averaging
averagesphere = self.kwargs['averaging']
averagesphere = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagesphere = grid.averagevolumeobjects
@@ -62,25 +62,25 @@ class Sphere(UserObjectGeometry):
# Check materials have been specified
# Isotropic case
try:
materialsrequested = [self.kwargs['material_id']]
materialsrequested = [self.kwargs["material_id"]]
except KeyError:
# Anisotropic case
try:
materialsrequested = self.kwargs['material_ids']
materialsrequested = self.kwargs["material_ids"]
except KeyError:
logger.exception(f'{self.__str__()} no materials have been specified')
logger.exception(f"{self.__str__()} no materials have been specified")
raise
# Centre of sphere
p2 = uip.round_to_grid_static_point(p1)
xc, yc, zc = uip.discretise_point(p1)
# Look up requested materials in existing list of material instances
materials = [y for x in materialsrequested for y in grid.materials if y.ID == x]
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
logger.exception(f'{self.__str__()} material(s) {notfound} do not exist')
logger.exception(f"{self.__str__()} material(s) {notfound} do not exist")
raise ValueError
# Isotropic case
@@ -94,33 +94,46 @@ class Sphere(UserObjectGeometry):
numIDx = materials[0].numID
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + '+' + materials[1].ID + '+' + materials[2].ID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
m = Material(numID, requiredID)
m.type = 'dielectric-smoothed'
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
m.er = np.mean((materials[0].er, materials[1].er,
materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se,
materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr,
materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm,
materials[2].sm), axis=0)
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
build_sphere(xc, yc, zc, r, grid.dx, grid.dy, grid.dz, numID,
numIDx, numIDy, numIDz, averaging, grid.solid,
grid.rigidE, grid.rigidH, grid.ID)
build_sphere(
xc,
yc,
zc,
r,
grid.dx,
grid.dy,
grid.dz,
numID,
numIDx,
numIDy,
numIDz,
averaging,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)
dielectricsmoothing = 'on' if averaging else 'off'
logger.info(f"{self.grid_name(grid)}Sphere with centre {p2[0]:g}m, " +
f"{p2[1]:g}m, {p2[2]:g}m, radius {r:g}m, of material(s) " +
f"{', '.join(materialsrequested)} created, dielectric " +
f"smoothing is {dielectricsmoothing}.")
dielectricsmoothing = "on" if averaging else "off"
logger.info(
f"{self.grid_name(grid)}Sphere with centre {p2[0]:g}m, "
+ f"{p2[1]:g}m, {p2[2]:g}m, radius {r:g}m, of material(s) "
+ f"{', '.join(materialsrequested)} created, dielectric "
+ f"smoothing is {dielectricsmoothing}."
)

查看文件

@@ -28,16 +28,16 @@ logger = logging.getLogger(__name__)
class Triangle(UserObjectGeometry):
"""Introduces a triangular patch or a triangular prism with specific
"""Introduces a triangular patch or a triangular prism with specific
properties into the model.
Attributes:
p1: list of the coordinates (x,y,z) of the first apex of the triangle.
p2: list of the coordinates (x,y,z) of the second apex of the triangle.
p3: list of the coordinates (x,y,z) of the third apex of the triangle.
thickness: float for the thickness of the triangular prism. If the
thickness: float for the thickness of the triangular prism. If the
thickness is zero then a triangular patch is created.
material_id: string for the material identifier that must correspond
material_id: string for the material identifier that must correspond
to material that has already been defined.
material_ids: list of material identifiers in the x, y, z directions.
averaging: string (y or n) used to switch on and off dielectric smoothing.
@@ -45,7 +45,7 @@ class Triangle(UserObjectGeometry):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.hash = '#triangle'
self.hash = "#triangle"
def rotate(self, axis, angle, origin=None):
"""Sets parameters for rotation."""
@@ -56,30 +56,30 @@ class Triangle(UserObjectGeometry):
def _do_rotate(self):
"""Performs rotation."""
p1 = rotate_point(self.kwargs['p1'], self.axis, self.angle, self.origin)
p2 = rotate_point(self.kwargs['p2'], self.axis, self.angle, self.origin)
p3 = rotate_point(self.kwargs['p3'], self.axis, self.angle, self.origin)
self.kwargs['p1'] = tuple(p1)
self.kwargs['p2'] = tuple(p2)
self.kwargs['p3'] = tuple(p3)
p1 = rotate_point(self.kwargs["p1"], self.axis, self.angle, self.origin)
p2 = rotate_point(self.kwargs["p2"], self.axis, self.angle, self.origin)
p3 = rotate_point(self.kwargs["p3"], self.axis, self.angle, self.origin)
self.kwargs["p1"] = tuple(p1)
self.kwargs["p2"] = tuple(p2)
self.kwargs["p3"] = tuple(p3)
def create(self, grid, uip):
try:
up1 = self.kwargs['p1']
up2 = self.kwargs['p2']
up3 = self.kwargs['p3']
thickness = self.kwargs['thickness']
up1 = self.kwargs["p1"]
up2 = self.kwargs["p2"]
up3 = self.kwargs["p3"]
thickness = self.kwargs["thickness"]
except KeyError:
logger.exception(f'{self.__str__()} specify 3 points and a thickness')
logger.exception(f"{self.__str__()} specify 3 points and a thickness")
raise
if self.do_rotate:
self._do_rotate()
# Check averaging
try:
# Try user-specified averaging
averagetriangularprism = self.kwargs['averaging']
averagetriangularprism = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagetriangularprism = grid.averagevolumeobjects
@@ -87,13 +87,13 @@ class Triangle(UserObjectGeometry):
# Check materials have been specified
# Isotropic case
try:
materialsrequested = [self.kwargs['material_id']]
materialsrequested = [self.kwargs["material_id"]]
except KeyError:
# Anisotropic case
try:
materialsrequested = self.kwargs['material_ids']
materialsrequested = self.kwargs["material_ids"]
except KeyError:
logger.exception(f'{self.__str__()} no materials have been specified')
logger.exception(f"{self.__str__()} no materials have been specified")
raise
p4 = uip.round_to_grid_static_point(up1)
@@ -106,23 +106,23 @@ class Triangle(UserObjectGeometry):
x1, y1, z1 = uip.round_to_grid(up1)
x2, y2, z2 = uip.round_to_grid(up2)
x3, y3, z3 = uip.round_to_grid(up3)
if thickness < 0:
logger.exception(f'{self.__str__()} requires a positive value for thickness')
logger.exception(f"{self.__str__()} requires a positive value for thickness")
raise ValueError
# Check for valid orientations
# yz-plane triangle
if x1 == x2 == x3:
normal = 'x'
normal = "x"
# xz-plane triangle
elif y1 == y2 == y3:
normal = 'y'
normal = "y"
# xy-plane triangle
elif z1 == z2 == z3:
normal = 'z'
normal = "z"
else:
logger.exception(f'{self.__str__()} the triangle is not specified correctly')
logger.exception(f"{self.__str__()} the triangle is not specified correctly")
raise ValueError
# Look up requested materials in existing list of material instances
@@ -130,7 +130,7 @@ class Triangle(UserObjectGeometry):
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
logger.exception(f'{self.__str__()} material(s) {notfound} do not exist')
logger.exception(f"{self.__str__()} material(s) {notfound} do not exist")
raise ValueError
if thickness > 0:
@@ -145,23 +145,19 @@ class Triangle(UserObjectGeometry):
numIDx = materials[0].numID
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + '+' + materials[1].ID + '+' + materials[2].ID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
m = Material(numID, requiredID)
m.type = 'dielectric-smoothed'
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
m.er = np.mean((materials[0].er, materials[1].er,
materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se,
materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr,
materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm,
materials[2].sm), axis=0)
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
@@ -179,19 +175,45 @@ class Triangle(UserObjectGeometry):
numIDy = materials[1].numID
numIDz = materials[2].numID
build_triangle(x1, y1, z1, x2, y2, z2, x3, y3, z3, normal, thickness,
grid.dx, grid.dy, grid.dz, numID, numIDx, numIDy, numIDz,
averaging, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
build_triangle(
x1,
y1,
z1,
x2,
y2,
z2,
x3,
y3,
z3,
normal,
thickness,
grid.dx,
grid.dy,
grid.dz,
numID,
numIDx,
numIDy,
numIDz,
averaging,
grid.solid,
grid.rigidE,
grid.rigidH,
grid.ID,
)
if thickness > 0:
dielectricsmoothing = 'on' if averaging else 'off'
logger.info(f"{self.grid_name(grid)}Triangle with coordinates " +
f"{p4[0]:g}m {p4[1]:g}m {p4[2]:g}m, {p5[0]:g}m {p5[1]:g}m " +
f"{p5[2]:g}m, {p6[0]:g}m {p6[1]:g}m {p6[2]:g}m and thickness " +
f"{thickness:g}m of material(s) {', '.join(materialsrequested)} " +
f"created, dielectric smoothing is {dielectricsmoothing}.")
dielectricsmoothing = "on" if averaging else "off"
logger.info(
f"{self.grid_name(grid)}Triangle with coordinates "
+ f"{p4[0]:g}m {p4[1]:g}m {p4[2]:g}m, {p5[0]:g}m {p5[1]:g}m "
+ f"{p5[2]:g}m, {p6[0]:g}m {p6[1]:g}m {p6[2]:g}m and thickness "
+ f"{thickness:g}m of material(s) {', '.join(materialsrequested)} "
+ f"created, dielectric smoothing is {dielectricsmoothing}."
)
else:
logger.info(f"{self.grid_name(grid)}Triangle with coordinates " +
f"{p4[0]:g}m {p4[1]:g}m {p4[2]:g}m, {p5[0]:g}m {p5[1]:g}m " +
f"{p5[2]:g}m, {p6[0]:g}m {p6[1]:g}m {p6[2]:g}m of material(s) " +
f"{', '.join(materialsrequested)} created.")
logger.info(
f"{self.grid_name(grid)}Triangle with coordinates "
+ f"{p4[0]:g}m {p4[1]:g}m {p4[2]:g}m, {p5[0]:g}m {p5[1]:g}m "
+ f"{p5[2]:g}m, {p6[0]:g}m {p6[1]:g}m {p6[2]:g}m of material(s) "
+ f"{', '.join(materialsrequested)} created."
)

文件差异内容过多而无法显示 加载差异

查看文件

@@ -70,9 +70,9 @@ class Title(UserObjectSingle):
def create(self, G, uip):
try:
title = self.kwargs['name']
title = self.kwargs["name"]
G.title = title
logger.info(f'Model title: {G.title}')
logger.info(f"Model title: {G.title}")
except KeyError:
pass
@@ -90,26 +90,29 @@ class Discretisation(UserObjectSingle):
def create(self, G, uip):
try:
G.dl = np.array(self.kwargs['p1'])
G.dx, G.dy, G.dz = self.kwargs['p1']
G.dl = np.array(self.kwargs["p1"])
G.dx, G.dy, G.dz = self.kwargs["p1"]
except KeyError:
logger.exception(f'{self.__str__()} discretisation requires a point')
logger.exception(f"{self.__str__()} discretisation requires a point")
raise
if G.dl[0] <= 0:
logger.exception(f'{self.__str__()} discretisation requires the '
f'x-direction spatial step to be greater than zero')
logger.exception(
f"{self.__str__()} discretisation requires the " f"x-direction spatial step to be greater than zero"
)
raise ValueError
if G.dl[1] <= 0:
logger.exception(f'{self.__str__()} discretisation requires the '
f'y-direction spatial step to be greater than zero')
logger.exception(
f"{self.__str__()} discretisation requires the " f"y-direction spatial step to be greater than zero"
)
raise ValueError
if G.dl[2] <= 0:
logger.exception(f'{self.__str__()} discretisation requires the '
f'z-direction spatial step to be greater than zero')
logger.exception(
f"{self.__str__()} discretisation requires the " f"z-direction spatial step to be greater than zero"
)
raise ValueError
logger.info(f'Spatial discretisation: {G.dl[0]:g} x {G.dl[1]:g} x {G.dl[2]:g}m')
logger.info(f"Spatial discretisation: {G.dl[0]:g} x {G.dl[1]:g} x {G.dl[2]:g}m")
class Domain(UserObjectSingle):
@@ -125,46 +128,47 @@ class Domain(UserObjectSingle):
def create(self, G, uip):
try:
G.nx, G.ny, G.nz = uip.discretise_point(self.kwargs['p1'])
G.nx, G.ny, G.nz = uip.discretise_point(self.kwargs["p1"])
except KeyError:
logger.exception(f'{self.__str__()} please specify a point')
logger.exception(f"{self.__str__()} please specify a point")
raise
if G.nx == 0 or G.ny == 0 or G.nz == 0:
logger.exception(f'{self.__str__()} requires at least one cell in '
f'every dimension')
logger.exception(f"{self.__str__()} requires at least one cell in " f"every dimension")
raise ValueError
logger.info(f"Domain size: {self.kwargs['p1'][0]:g} x {self.kwargs['p1'][1]:g} x " +
f"{self.kwargs['p1'][2]:g}m ({G.nx:d} x {G.ny:d} x {G.nz:d} = " +
f"{(G.nx * G.ny * G.nz):g} cells)")
logger.info(
f"Domain size: {self.kwargs['p1'][0]:g} x {self.kwargs['p1'][1]:g} x "
+ f"{self.kwargs['p1'][2]:g}m ({G.nx:d} x {G.ny:d} x {G.nz:d} = "
+ f"{(G.nx * G.ny * G.nz):g} cells)"
)
# Calculate time step at CFL limit; switch off appropriate PMLs for 2D
if G.nx == 1:
config.get_model_config().mode = '2D TMx'
G.pmls['thickness']['x0'] = 0
G.pmls['thickness']['xmax'] = 0
config.get_model_config().mode = "2D TMx"
G.pmls["thickness"]["x0"] = 0
G.pmls["thickness"]["xmax"] = 0
elif G.ny == 1:
config.get_model_config().mode = '2D TMy'
G.pmls['thickness']['y0'] = 0
G.pmls['thickness']['ymax'] = 0
config.get_model_config().mode = "2D TMy"
G.pmls["thickness"]["y0"] = 0
G.pmls["thickness"]["ymax"] = 0
elif G.nz == 1:
config.get_model_config().mode = '2D TMz'
G.pmls['thickness']['z0'] = 0
G.pmls['thickness']['zmax'] = 0
config.get_model_config().mode = "2D TMz"
G.pmls["thickness"]["z0"] = 0
G.pmls["thickness"]["zmax"] = 0
else:
config.get_model_config().mode = '3D'
config.get_model_config().mode = "3D"
G.calculate_dt()
logger.info(f'Mode: {config.get_model_config().mode}')
logger.info(f"Mode: {config.get_model_config().mode}")
# Sub-grids cannot be used with 2D models. There would typically be
# minimal performance benefit with sub-gridding and 2D models.
if '2D' in config.get_model_config().mode and config.sim_config.general['subgrid']:
logger.exception('Sub-gridding cannot be used with 2D models')
if "2D" in config.get_model_config().mode and config.sim_config.general["subgrid"]:
logger.exception("Sub-gridding cannot be used with 2D models")
raise ValueError
logger.info(f'Time step (at CFL limit): {G.dt:g} secs')
logger.info(f"Time step (at CFL limit): {G.dt:g} secs")
class TimeStepStabilityFactor(UserObjectSingle):
@@ -180,20 +184,21 @@ class TimeStepStabilityFactor(UserObjectSingle):
def create(self, G, uip):
try:
f = self.kwargs['f']
f = self.kwargs["f"]
except KeyError:
logger.exception(f'{self.__str__()} requires exactly one parameter')
logger.exception(f"{self.__str__()} requires exactly one parameter")
raise
if f <= 0 or f > 1:
logger.exception(f'{self.__str__()} requires the value of the time '
f'step stability factor to be between zero and one')
logger.exception(
f"{self.__str__()} requires the value of the time " f"step stability factor to be between zero and one"
)
raise ValueError
G.dt_mod = f
G.dt = G.dt * G.dt_mod
logger.info(f'Time step (modified): {G.dt:g} secs')
logger.info(f"Time step (modified): {G.dt:g} secs")
class TimeWindow(UserObjectSingle):
@@ -213,32 +218,32 @@ class TimeWindow(UserObjectSingle):
# The +/- 1 used in calculating the number of iterations is to account for
# the fact that the solver (iterations) loop runs from 0 to < G.iterations
try:
iterations = int(self.kwargs['iterations'])
iterations = int(self.kwargs["iterations"])
G.timewindow = (iterations - 1) * G.dt
G.iterations = iterations
except KeyError:
pass
try:
tmp = float(self.kwargs['time'])
tmp = float(self.kwargs["time"])
if tmp > 0:
G.timewindow = tmp
G.iterations = int(np.ceil(tmp / G.dt)) + 1
else:
logger.exception(self.__str__() + ' must have a value greater than zero')
logger.exception(self.__str__() + " must have a value greater than zero")
raise ValueError
except KeyError:
pass
if not G.timewindow:
logger.exception(self.__str__() + ' specify a time or number of iterations')
logger.exception(self.__str__() + " specify a time or number of iterations")
raise ValueError
logger.info(f'Time window: {G.timewindow:g} secs ({G.iterations} iterations)')
logger.info(f"Time window: {G.timewindow:g} secs ({G.iterations} iterations)")
class OMPThreads(UserObjectSingle):
"""Controls how many OpenMP threads (usually the number of physical CPU
"""Controls how many OpenMP threads (usually the number of physical CPU
cores available) are used when running the model.
Attributes:
@@ -251,30 +256,31 @@ class OMPThreads(UserObjectSingle):
def create(self, G, uip):
try:
n = self.kwargs['n']
n = self.kwargs["n"]
except KeyError:
logger.exception(f'{self.__str__()} requires exactly one parameter '
f'to specify the number of CPU OpenMP threads to use')
logger.exception(
f"{self.__str__()} requires exactly one parameter "
f"to specify the number of CPU OpenMP threads to use"
)
raise
if n < 1:
logger.exception(f'{self.__str__()} requires the value to be an '
f'integer not less than one')
logger.exception(f"{self.__str__()} requires the value to be an " f"integer not less than one")
raise ValueError
config.get_model_config().ompthreads = set_omp_threads(n)
class PMLProps(UserObjectSingle):
"""Specifies the formulation used and thickness (number of cells) of PML
that are used on the six sides of the model domain. Current options are
to use the Higher Order RIPML (HORIPML) - https://doi.org/10.1109/TAP.2011.2180344,
"""Specifies the formulation used and thickness (number of cells) of PML
that are used on the six sides of the model domain. Current options are
to use the Higher Order RIPML (HORIPML) - https://doi.org/10.1109/TAP.2011.2180344,
or Multipole RIPML (MRIPML) - https://doi.org/10.1109/TAP.2018.2823864.
Attributes:
formulation: string specifying formulation to be used for all PMLs
formulation: string specifying formulation to be used for all PMLs
either 'HORIPML' or 'MRIPML'.
thickness or x0, y0, z0, xmax, ymax, zmax: ints for thickness of PML
on all 6 sides or individual
thickness or x0, y0, z0, xmax, ymax, zmax: ints for thickness of PML
on all 6 sides or individual
sides of the model domain.
"""
@@ -284,37 +290,40 @@ class PMLProps(UserObjectSingle):
def create(self, G, uip):
try:
G.pmls['formulation'] = self.kwargs['formulation']
if G.pmls['formulation'] not in PML.formulations:
logger.exception(self.__str__() + f" requires the value to be " +
f"one of {' '.join(PML.formulations)}")
G.pmls["formulation"] = self.kwargs["formulation"]
if G.pmls["formulation"] not in PML.formulations:
logger.exception(
self.__str__() + f" requires the value to be " + f"one of {' '.join(PML.formulations)}"
)
except KeyError:
pass
try:
thickness = self.kwargs['thickness']
for key in G.pmls['thickness'].keys():
G.pmls['thickness'][key] = int(thickness)
thickness = self.kwargs["thickness"]
for key in G.pmls["thickness"].keys():
G.pmls["thickness"][key] = int(thickness)
except KeyError:
try:
G.pmls['thickness']['x0'] = int(self.kwargs['x0'])
G.pmls['thickness']['y0'] = int(self.kwargs['y0'])
G.pmls['thickness']['z0'] = int(self.kwargs['z0'])
G.pmls['thickness']['xmax'] = int(self.kwargs['xmax'])
G.pmls['thickness']['ymax'] = int(self.kwargs['ymax'])
G.pmls['thickness']['zmax'] = int(self.kwargs['zmax'])
G.pmls["thickness"]["x0"] = int(self.kwargs["x0"])
G.pmls["thickness"]["y0"] = int(self.kwargs["y0"])
G.pmls["thickness"]["z0"] = int(self.kwargs["z0"])
G.pmls["thickness"]["xmax"] = int(self.kwargs["xmax"])
G.pmls["thickness"]["ymax"] = int(self.kwargs["ymax"])
G.pmls["thickness"]["zmax"] = int(self.kwargs["zmax"])
except KeyError:
logger.exception(f'{self.__str__()} requires either one or six parameter(s)')
logger.exception(f"{self.__str__()} requires either one or six parameter(s)")
raise
if (2 * G.pmls['thickness']['x0'] >= G.nx or
2 * G.pmls['thickness']['y0'] >= G.ny or
2 * G.pmls['thickness']['z0'] >= G.nz or
2 * G.pmls['thickness']['xmax'] >= G.nx or
2 * G.pmls['thickness']['ymax'] >= G.ny or
2 * G.pmls['thickness']['zmax'] >= G.nz):
logger.exception(f'{self.__str__()} has too many cells for the domain size')
if (
2 * G.pmls["thickness"]["x0"] >= G.nx
or 2 * G.pmls["thickness"]["y0"] >= G.ny
or 2 * G.pmls["thickness"]["z0"] >= G.nz
or 2 * G.pmls["thickness"]["xmax"] >= G.nx
or 2 * G.pmls["thickness"]["ymax"] >= G.ny
or 2 * G.pmls["thickness"]["zmax"] >= G.nz
):
logger.exception(f"{self.__str__()} has too many cells for the domain size")
raise ValueError
@@ -331,14 +340,16 @@ class SrcSteps(UserObjectSingle):
def create(self, G, uip):
try:
G.srcsteps = uip.discretise_point(self.kwargs['p1'])
G.srcsteps = uip.discretise_point(self.kwargs["p1"])
except KeyError:
logger.exception(f'{self.__str__()} requires exactly three parameters')
logger.exception(f"{self.__str__()} requires exactly three parameters")
raise
logger.info(f'Simple sources will step {G.srcsteps[0] * G.dx:g}m, ' +
f'{G.srcsteps[1] * G.dy:g}m, {G.srcsteps[2] * G.dz:g}m ' +
'for each model run.')
logger.info(
f"Simple sources will step {G.srcsteps[0] * G.dx:g}m, "
+ f"{G.srcsteps[1] * G.dy:g}m, {G.srcsteps[2] * G.dz:g}m "
+ "for each model run."
)
class RxSteps(UserObjectSingle):
@@ -354,23 +365,25 @@ class RxSteps(UserObjectSingle):
def create(self, G, uip):
try:
G.rxsteps = uip.discretise_point(self.kwargs['p1'])
G.rxsteps = uip.discretise_point(self.kwargs["p1"])
except KeyError:
logger.exception(f'{self.__str__()} requires exactly three parameters')
logger.exception(f"{self.__str__()} requires exactly three parameters")
raise
logger.info(f'All receivers will step {G.rxsteps[0] * G.dx:g}m, ' +
f'{G.rxsteps[1] * G.dy:g}m, {G.rxsteps[2] * G.dz:g}m ' +
'for each model run.')
logger.info(
f"All receivers will step {G.rxsteps[0] * G.dx:g}m, "
+ f"{G.rxsteps[1] * G.dy:g}m, {G.rxsteps[2] * G.dz:g}m "
+ "for each model run."
)
class ExcitationFile(UserObjectSingle):
"""An ASCII file that contains columns of amplitude values that specify
"""An ASCII file that contains columns of amplitude values that specify
custom waveform shapes that can be used with sources in the model.
Attributes:
filepath: string of excitation file path.
kind: string or int specifying interpolation kind passed to
kind: string or int specifying interpolation kind passed to
scipy.interpolate.interp1d.
fill_value: float or 'extrapolate' passed to scipy.interpolate.interp1d.
"""
@@ -382,74 +395,75 @@ class ExcitationFile(UserObjectSingle):
def create(self, G, uip):
try:
kwargs = {}
excitationfile = self.kwargs['filepath']
kwargs['kind'] = self.kwargs['kind']
kwargs['fill_value'] = self.kwargs['fill_value']
excitationfile = self.kwargs["filepath"]
kwargs["kind"] = self.kwargs["kind"]
kwargs["fill_value"] = self.kwargs["fill_value"]
except KeyError:
try:
excitationfile = self.kwargs['filepath']
excitationfile = self.kwargs["filepath"]
fullargspec = inspect.getfullargspec(interpolate.interp1d)
kwargs = dict(zip(reversed(fullargspec.args),
reversed(fullargspec.defaults)))
kwargs = dict(zip(reversed(fullargspec.args), reversed(fullargspec.defaults)))
except KeyError:
logger.exception(f'{self.__str__()} requires either one or three parameter(s)')
logger.exception(f"{self.__str__()} requires either one or three parameter(s)")
raise
# See if file exists at specified path and if not try input file directory
excitationfile = Path(excitationfile)
# excitationfile = excitationfile.resolve()
if not excitationfile.exists():
excitationfile = Path(config.sim_config.input_file_path.parent,
excitationfile)
excitationfile = Path(config.sim_config.input_file_path.parent, excitationfile)
logger.info(f'Excitation file: {excitationfile}')
logger.info(f"Excitation file: {excitationfile}")
# Get waveform names
with open(excitationfile, 'r') as f:
with open(excitationfile, "r") as f:
waveformIDs = f.readline().split()
# Read all waveform values into an array
waveformvalues = np.loadtxt(excitationfile, skiprows=1,
dtype=config.sim_config.dtypes['float_or_double'])
waveformvalues = np.loadtxt(excitationfile, skiprows=1, dtype=config.sim_config.dtypes["float_or_double"])
# Time array (if specified) for interpolation, otherwise use simulation time
if waveformIDs[0].lower() == 'time':
if waveformIDs[0].lower() == "time":
waveformIDs = waveformIDs[1:]
waveformtime = waveformvalues[:, 0]
waveformvalues = waveformvalues[:, 1:]
timestr = 'user-defined time array'
timestr = "user-defined time array"
else:
waveformtime = np.arange(0, G.timewindow + G.dt, G.dt)
timestr = 'simulation time array'
timestr = "simulation time array"
for waveform in range(len(waveformIDs)):
if any(x.ID == waveformIDs[waveform] for x in G.waveforms):
logger.exception(f'Waveform with ID {waveformIDs[waveform]} already exists')
logger.exception(f"Waveform with ID {waveformIDs[waveform]} already exists")
raise ValueError
w = Waveform()
w.ID = waveformIDs[waveform]
w.type = 'user'
w.type = "user"
# Select correct column of waveform values depending on array shape
singlewaveformvalues = waveformvalues[:] if len(waveformvalues.shape) == 1 else waveformvalues[:, waveform]
# Truncate waveform array if it is longer than time array
if len(singlewaveformvalues) > len(waveformtime):
singlewaveformvalues = singlewaveformvalues[:len(waveformtime)]
singlewaveformvalues = singlewaveformvalues[: len(waveformtime)]
# Zero-pad end of waveform array if it is shorter than time array
elif len(singlewaveformvalues) < len(waveformtime):
singlewaveformvalues = np.pad(singlewaveformvalues,
(0, len(waveformtime) -
len(singlewaveformvalues)),
'constant', constant_values=0)
singlewaveformvalues = np.pad(
singlewaveformvalues,
(0, len(waveformtime) - len(singlewaveformvalues)),
"constant",
constant_values=0,
)
# Interpolate waveform values
w.userfunc = interpolate.interp1d(waveformtime, singlewaveformvalues, **kwargs)
logger.info(f"User waveform {w.ID} created using {timestr} and, if " +
f"required, interpolation parameters (kind: {kwargs['kind']}, " +
f"fill value: {kwargs['fill_value']}).")
logger.info(
f"User waveform {w.ID} created using {timestr} and, if "
+ f"required, interpolation parameters (kind: {kwargs['kind']}, "
+ f"fill value: {kwargs['fill_value']})."
)
G.waveforms.append(w)
@@ -460,9 +474,10 @@ class OutputDir(UserObjectSingle):
Attributes:
dir: string of file path to directory.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.order = 11
def create(self, grid, uip):
config.get_model_config().set_output_file_path(self.kwargs['dir'])
config.get_model_config().set_output_file_path(self.kwargs["dir"])

查看文件

@@ -48,6 +48,7 @@ model_configs = []
# ModelConfig is created
model_num = 0
def get_model_config():
"""Return ModelConfig instace for specific model."""
if sim_config.args.mpi:
@@ -55,27 +56,27 @@ def get_model_config():
else:
return model_configs[model_num]
class ModelConfig:
"""Configuration parameters for a model.
N.B. Multiple models can exist within a simulation
N.B. Multiple models can exist within a simulation
"""
def __init__(self):
self.mode = '3D'
self.mode = "3D"
self.grids = []
self.ompthreads = None
# Store information for CUDA or OpenCL solver
# dev: compute device object.
# 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
# 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.
if sim_config.general['solver'] == 'cuda' or sim_config.general['solver'] == 'opencl':
if sim_config.general['solver'] == 'cuda':
if sim_config.general["solver"] == "cuda" or sim_config.general["solver"] == "opencl":
if sim_config.general["solver"] == "cuda":
devs = sim_config.args.gpu
elif sim_config.general['solver'] == 'opencl':
elif sim_config.general["solver"] == "opencl":
devs = sim_config.args.opencl
# If a list of lists of deviceIDs is found, flatten it
@@ -89,8 +90,7 @@ class ModelConfig:
except:
deviceID = 0
self.device = {'dev': sim_config.set_model_device(deviceID),
'snapsgpu2cpu': False}
self.device = {"dev": sim_config.set_model_device(deviceID), "snapsgpu2cpu": False}
# Total memory usage for all grids in the model. Starts with 50MB overhead.
self.mem_overhead = 65e6
@@ -99,26 +99,22 @@ class ModelConfig:
self.reuse_geometry = False
# String to print at start of each model run
s = (f'\n--- Model {model_num + 1}/{sim_config.model_end}, '
f'input file: {sim_config.input_file_path}')
self.inputfilestr = (Fore.GREEN + f"{s} {'-' * (get_terminal_width() - 1 - len(s))}\n" +
Style.RESET_ALL)
s = f"\n--- Model {model_num + 1}/{sim_config.model_end}, " f"input file: {sim_config.input_file_path}"
self.inputfilestr = Fore.GREEN + f"{s} {'-' * (get_terminal_width() - 1 - len(s))}\n" + Style.RESET_ALL
# Output file path and name for specific model
self.appendmodelnumber = '' if sim_config.args.n == 1 else str(model_num + 1) # Indexed from 1
self.appendmodelnumber = "" if sim_config.args.n == 1 else str(model_num + 1) # Indexed from 1
self.set_output_file_path()
# Numerical dispersion analysis parameters
# highestfreqthres: threshold (dB) down from maximum power (0dB) of
# main frequency used to calculate highest
# 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
# maxnumericaldisp: maximum allowable percentage physical
# phase-velocity phase error.
# mingridsampling: minimum grid sampling of smallest wavelength for
# mingridsampling: minimum grid sampling of smallest wavelength for
# physical wave propagation.
self.numdispersion = {'highestfreqthres': 40,
'maxnumericaldisp': 2,
'mingridsampling': 3}
self.numdispersion = {"highestfreqthres": 40, "maxnumericaldisp": 2, "mingridsampling": 3}
# General information to configure materials
# maxpoles: Maximum number of dispersive material poles in a model.
@@ -127,41 +123,45 @@ class ModelConfig:
# drudelorentz: True/False model contains Drude or Lorentz materials.
# cudarealfunc: String to substitute into CUDA kernels for fields
# dependent on dispersive material type.
self.materials = {'maxpoles': 0,
'dispersivedtype': None,
'dispersiveCdtype': None,
'drudelorentz': None,
'cudarealfunc': ''}
self.materials = {
"maxpoles": 0,
"dispersivedtype": None,
"dispersiveCdtype": None,
"drudelorentz": None,
"cudarealfunc": "",
}
def get_scene(self):
if sim_config.scenes:
return sim_config.scenes[model_num]
else: return None
else:
return None
def get_usernamespace(self):
"""Namespace only used with #python blocks which are deprecated."""
tmp = {'number_model_runs': sim_config.model_end,
'current_model_run': model_num + 1,
'inputfile': sim_config.input_file_path.resolve()}
tmp = {
"number_model_runs": sim_config.model_end,
"current_model_run": model_num + 1,
"inputfile": sim_config.input_file_path.resolve(),
}
return dict(**sim_config.em_consts, **tmp)
def set_dispersive_material_types(self):
"""Sets data type for disperive materials. Complex if Drude or Lorentz
materials are present. Real if Debye materials.
materials are present. Real if Debye materials.
"""
if self.materials['drudelorentz']:
self.materials['crealfunc'] = '.real()'
self.materials['dispersivedtype'] = sim_config.dtypes['complex']
self.materials['dispersiveCdtype'] = sim_config.dtypes['C_complex']
if self.materials["drudelorentz"]:
self.materials["crealfunc"] = ".real()"
self.materials["dispersivedtype"] = sim_config.dtypes["complex"]
self.materials["dispersiveCdtype"] = sim_config.dtypes["C_complex"]
else:
self.materials['crealfunc'] = ''
self.materials['dispersivedtype'] = sim_config.dtypes['float_or_double']
self.materials['dispersiveCdtype'] = sim_config.dtypes['C_float_or_double']
self.materials["crealfunc"] = ""
self.materials["dispersivedtype"] = sim_config.dtypes["float_or_double"]
self.materials["dispersiveCdtype"] = sim_config.dtypes["C_float_or_double"]
def set_output_file_path(self, outputdir=None):
"""Sets output file path. Can be provided by the user via the API or an
input file command. If they haven't provided one use the input file
"""Sets output file path. Can be provided by the user via the API or an
input file command. If they haven't provided one use the input file
path instead.
Args:
@@ -172,33 +172,33 @@ class ModelConfig:
try:
self.output_file_path = Path(self.args.outputfile)
except AttributeError:
self.output_file_path = sim_config.input_file_path.with_suffix('')
self.output_file_path = sim_config.input_file_path.with_suffix("")
else:
try:
Path(outputdir).mkdir(exist_ok=True)
self.output_file_path = Path(outputdir, sim_config.input_file_path.stem)
except AttributeError:
self.output_file_path = sim_config.input_file_path.with_suffix('')
self.output_file_path = sim_config.input_file_path.with_suffix("")
parts = self.output_file_path.parts
self.output_file_path = Path(*parts[:-1], parts[-1] + self.appendmodelnumber)
self.output_file_path_ext = self.output_file_path.with_suffix('.h5')
self.output_file_path_ext = self.output_file_path.with_suffix(".h5")
def set_snapshots_dir(self):
"""Sets directory to store any snapshots.
Returns:
snapshot_dir: Path to directory to store snapshot files in.
"""
parts = self.output_file_path.with_suffix('').parts
snapshot_dir = Path(*parts[:-1], parts[-1] + '_snaps')
parts = self.output_file_path.with_suffix("").parts
snapshot_dir = Path(*parts[:-1], parts[-1] + "_snaps")
return snapshot_dir
class SimulationConfig:
"""Configuration parameters for a simulation.
N.B. A simulation can consist of multiple models.
N.B. A simulation can consist of multiple models.
"""
def __init__(self, args):
@@ -210,11 +210,11 @@ class SimulationConfig:
self.args = args
if args.mpi and args.geometry_fixed:
logger.exception('The geometry fixed option cannot be used with MPI.')
logger.exception("The geometry fixed option cannot be used with MPI.")
raise ValueError
if args.gpu and args.opencl:
logger.exception('You cannot use both CUDA and OpenCl simultaneously.')
logger.exception("You cannot use both CUDA and OpenCl simultaneously.")
raise ValueError
# General settings for the simulation
@@ -224,62 +224,62 @@ class SimulationConfig:
# solver: cpu, cuda, opencl.
# subgrid: whether the simulation uses sub-grids.
# precision: data type for electromagnetic field output (single/double).
# progressbars: progress bars on stdoout or not - switch off
# progressbars when logging level is greater than
# info (20)
# progressbars: progress bars on stdoout or not - switch off
# progressbars when logging level is greater than
# info (20)
self.general = {'solver': 'cpu',
'subgrid': False,
'precision': 'single',
'progressbars': args.log_level <= 20}
self.general = {"solver": "cpu", "subgrid": False, "precision": "single", "progressbars": args.log_level <= 20}
self.em_consts = {'c': c, # Speed of light in free space (m/s)
'e0': e0, # Permittivity of free space (F/m)
'm0': m0, # Permeability of free space (H/m)
'z0': np.sqrt(m0 / e0)} # Impedance of free space (Ohms)
self.em_consts = {
"c": c, # Speed of light in free space (m/s)
"e0": e0, # Permittivity of free space (F/m)
"m0": m0, # Permeability of free space (H/m)
"z0": np.sqrt(m0 / e0),
} # Impedance of free space (Ohms)
# Store information about host machine
self.hostinfo = get_host_info()
# CUDA
if self.args.gpu is not None:
self.general['solver'] = 'cuda'
self.general["solver"] = "cuda"
# Both single and double precision are possible on GPUs, but single
# provides best performance.
self.general['precision'] = 'single'
self.devices = {'devs': [], # pycuda device objects
'nvcc_opts': None} # nvcc compiler options
self.general["precision"] = "single"
self.devices = {"devs": [], "nvcc_opts": None} # pycuda device objects # nvcc compiler options
# Suppress nvcc warnings on Microsoft Windows
if sys.platform == 'win32': self.devices['nvcc_opts'] = ['-w']
if sys.platform == "win32":
self.devices["nvcc_opts"] = ["-w"]
# Add pycuda available GPU(s)
self.devices['devs'] = detect_cuda_gpus()
self.devices["devs"] = detect_cuda_gpus()
# OpenCL
if self.args.opencl is not None:
self.general['solver'] = 'opencl'
self.general['precision'] = 'single'
self.devices = {'devs': [], # pyopencl available device(s)
'compiler_opts': None}
self.general["solver"] = "opencl"
self.general["precision"] = "single"
self.devices = {"devs": [], "compiler_opts": None} # pyopencl available device(s)
# Suppress unused variable warnings on gcc
# if sys.platform != 'win32': self.devices['compiler_opts'] = ['-w']
# Add pyopencl available device(s)
self.devices['devs'] = detect_opencl()
self.devices["devs"] = detect_opencl()
# Subgrid parameter may not exist if user enters via CLI
try:
self.general['subgrid'] = self.args.subgrid
self.general["subgrid"] = self.args.subgrid
# Double precision should be used with subgrid for best accuracy
self.general['precision'] = 'double'
if ((self.general['subgrid'] and self.general['solver'] == 'cuda') or
(self.general['subgrid'] and self.general['solver'] == 'opencl')):
logger.exception('You cannot currently use CUDA or OpenCL-based '
'solvers with models that contain sub-grids.')
self.general["precision"] = "double"
if (self.general["subgrid"] and self.general["solver"] == "cuda") or (
self.general["subgrid"] and self.general["solver"] == "opencl"
):
logger.exception(
"You cannot currently use CUDA or OpenCL-based " "solvers with models that contain sub-grids."
)
raise ValueError
except AttributeError:
self.general['subgrid'] = False
self.general["subgrid"] = False
# Scenes parameter may not exist if user enters via CLI
try:
@@ -303,49 +303,52 @@ class SimulationConfig:
"""
found = False
for ID, dev in self.devices['devs'].items():
for ID, dev in self.devices["devs"].items():
if ID == deviceID:
found = True
return dev
if not found:
logger.exception(f'Compute device with device ID {deviceID} does '
'not exist.')
logger.exception(f"Compute device with device ID {deviceID} does " "not exist.")
raise ValueError
def _set_precision(self):
"""Data type (precision) for electromagnetic field output.
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 arrays use complex numbers.
Dispersive coefficient arrays use either float or complex numbers.
Main field arrays use floats.
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 arrays use complex numbers.
Dispersive coefficient arrays use either float or complex numbers.
Main field arrays use floats.
"""
if self.general['precision'] == 'single':
self.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': None}
if self.general['solver'] == 'cuda':
self.dtypes['C_complex'] = 'pycuda::complex<float>'
elif self.general['solver'] == 'opencl':
self.dtypes['C_complex'] = 'cfloat'
if self.general["precision"] == "single":
self.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": None,
}
if self.general["solver"] == "cuda":
self.dtypes["C_complex"] = "pycuda::complex<float>"
elif self.general["solver"] == "opencl":
self.dtypes["C_complex"] = "cfloat"
elif self.general['precision'] == 'double':
self.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': None}
if self.general['solver'] == 'cuda':
self.dtypes['C_complex'] = 'pycuda::complex<double>'
elif self.general['solver'] == 'opencl':
self.dtypes['C_complex'] = 'cdouble'
elif self.general["precision"] == "double":
self.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": None,
}
if self.general["solver"] == "cuda":
self.dtypes["C_complex"] = "pycuda::complex<double>"
elif self.general["solver"] == "opencl":
self.dtypes["C_complex"] = "cdouble"
def _set_model_start_end(self):
"""Sets range for number of models to run (internally 0 index)."""

查看文件

@@ -27,8 +27,7 @@ import gprMax.config as config
from ._version import __version__, codename
from .model_build_run import ModelBuildRun
from .solvers import create_G, create_solver
from .utilities.host_info import (print_cuda_info, print_host_info,
print_opencl_info)
from .utilities.host_info import print_cuda_info, print_host_info, print_opencl_info
from .utilities.utilities import get_terminal_width, logo, timer
logger = logging.getLogger(__name__)
@@ -36,19 +35,18 @@ logger = logging.getLogger(__name__)
class Context:
"""Standard context - models are run one after another and each model
can exploit parallelisation using either OpenMP (CPU), CUDA (GPU), or
OpenCL (CPU/GPU).
can exploit parallelisation using either OpenMP (CPU), CUDA (GPU), or
OpenCL (CPU/GPU).
"""
def __init__(self):
self.model_range = range(config.sim_config.model_start,
config.sim_config.model_end)
self.model_range = range(config.sim_config.model_start, config.sim_config.model_end)
self.tsimend = None
self.tsimstart = None
self.tsimstart = None
def run(self):
"""Run the simulation in the correct context.
Returns:
results: dict that can contain useful results/data from simulation.
"""
@@ -57,10 +55,10 @@ class Context:
self.tsimstart = timer()
self.print_logo_copyright()
print_host_info(config.sim_config.hostinfo)
if config.sim_config.general['solver'] == 'cuda':
print_cuda_info(config.sim_config.devices['devs'])
elif config.sim_config.general['solver'] == 'opencl':
print_opencl_info(config.sim_config.devices['devs'])
if config.sim_config.general["solver"] == "cuda":
print_cuda_info(config.sim_config.devices["devs"])
elif config.sim_config.general["solver"] == "opencl":
print_opencl_info(config.sim_config.devices["devs"])
# Clear list of model configs. It can be retained when gprMax is
# called in a loop, and want to avoid this.
@@ -80,7 +78,7 @@ class Context:
model = ModelBuildRun(G)
model.build()
if not config.sim_config.args.geometry_only:
solver = create_solver(G)
model.solve(solver)
@@ -92,20 +90,22 @@ class Context:
def print_logo_copyright(self):
"""Prints gprMax logo, version, and copyright/licencing information."""
logo_copyright = logo(f'{__version__} ({codename})')
logo_copyright = logo(f"{__version__} ({codename})")
logger.basic(logo_copyright)
def print_sim_time_taken(self):
"""Prints the total simulation time based on context."""
s = (f"\n=== Simulation completed in " +
f"{humanize.precisedelta(datetime.timedelta(seconds=self.tsimend - self.tsimstart), format='%0.4f')}")
s = (
f"\n=== Simulation completed in "
+ f"{humanize.precisedelta(datetime.timedelta(seconds=self.tsimend - self.tsimstart), format='%0.4f')}"
)
logger.basic(f"{s} {'=' * (get_terminal_width() - 1 - len(s))}\n")
class MPIContext(Context):
"""Mixed mode MPI/OpenMP/CUDA context - MPI task farm is used to distribute
models, and each model parallelised using either OpenMP (CPU),
CUDA (GPU), or OpenCL (CPU/GPU).
models, and each model parallelised using either OpenMP (CPU),
CUDA (GPU), or OpenCL (CPU/GPU).
"""
def __init__(self):
@@ -120,32 +120,31 @@ class MPIContext(Context):
def _run_model(self, **work):
"""Process for running a single model.
Args:
work: dict of any additional information that is passed to MPI
work: dict of any additional information that is passed to MPI
workers. By default only model number (i) is used.
"""
# Create configuration for model
config.model_num = work['i']
config.model_num = work["i"]
model_config = config.ModelConfig()
# Set GPU deviceID according to worker rank
if config.sim_config.general['solver'] == 'cuda':
model_config.device = {'dev': config.sim_config.devices['devs'][self.rank - 1],
'snapsgpu2cpu': False}
if config.sim_config.general["solver"] == "cuda":
model_config.device = {"dev": config.sim_config.devices["devs"][self.rank - 1], "snapsgpu2cpu": False}
config.model_configs = model_config
G = create_G()
model = ModelBuildRun(G)
model.build()
if not config.sim_config.args.geometry_only:
solver = create_solver(G)
model.solve(solver)
def run(self):
"""Specialise how the models are run.
Returns:
results: dict that can contain useful results/data from simulation.
"""
@@ -154,25 +153,29 @@ class MPIContext(Context):
self.tsimstart = timer()
self.print_logo_copyright()
print_host_info(config.sim_config.hostinfo)
if config.sim_config.general['solver'] == 'cuda':
print_cuda_info(config.sim_config.devices['devs'])
elif config.sim_config.general['solver'] == 'opencl':
print_opencl_info(config.sim_config.devices['devs'])
if config.sim_config.general["solver"] == "cuda":
print_cuda_info(config.sim_config.devices["devs"])
elif config.sim_config.general["solver"] == "opencl":
print_opencl_info(config.sim_config.devices["devs"])
sys.stdout.flush()
# Contruct MPIExecutor
executor = self.MPIExecutor(self._run_model, comm=self.comm)
# Check GPU resources versus number of MPI tasks
if (executor.is_master() and
config.sim_config.general['solver'] == 'cuda' and
executor.size - 1 > len(config.sim_config.devices['devs'])):
logger.exception('Not enough GPU resources for number of '
'MPI tasks requested. Number of MPI tasks '
'should be equal to number of GPUs + 1.')
if (
executor.is_master()
and config.sim_config.general["solver"] == "cuda"
and executor.size - 1 > len(config.sim_config.devices["devs"])
):
logger.exception(
"Not enough GPU resources for number of "
"MPI tasks requested. Number of MPI tasks "
"should be equal to number of GPUs + 1."
)
raise ValueError
jobs = [{'i': i} for i in self.model_range]
jobs = [{"i": i} for i in self.model_range]
# Send the workers to their work loop
executor.start()
if executor.is_master():

查看文件

@@ -8,4 +8,4 @@
{% block constmem %}
__device__ __constant__ {{REAL}} updatecoeffsE[{{N_updatecoeffsE}}];
__device__ __constant__ {{REAL}} updatecoeffsH[{{N_updatecoeffsH}}];
{% endblock constmem %}
{% endblock constmem %}

查看文件

@@ -6,17 +6,17 @@
{% block constmem %}
__constant {{REAL}} updatecoeffsE[{{N_updatecoeffsE}}] =
__constant {{REAL}} updatecoeffsE[{{N_updatecoeffsE}}] =
{
{% for i in updatecoeffsE %}
{{i}},
{% endfor %}
};
__constant {{REAL}} updatecoeffsH[{{N_updatecoeffsH}}] =
__constant {{REAL}} updatecoeffsH[{{N_updatecoeffsH}}] =
{
{% for i in updatecoeffsH %}
{{i}},
{% endfor %}
};
{% endblock constmem %}
{% endblock constmem %}

查看文件

@@ -19,19 +19,22 @@
from string import Template
update_electric = {
'args_cuda': Template("""
"args_cuda": Template(
"""
__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,
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)
"""),
'args_opencl': Template("""
"""
),
"args_opencl": Template(
"""
int NX,
int NY,
int NZ,
@@ -42,8 +45,10 @@ update_electric = {
__global const $REAL * restrict Hx,
__global const $REAL * restrict Hy,
__global const $REAL * restrict Hz
"""),
'func': Template("""
"""
),
"func": Template(
"""
// Electric field updates - normal materials.
//
// Args:
@@ -65,42 +70,47 @@ update_electric = {
// Ex component
if ((NY != 1 || NZ != 1) && x >= 0 && x < NX && y > 0 && y < NY && z > 0 && z < NZ) {
int materialEx = ID[IDX4D_ID(0,x_ID,y_ID,z_ID)];
Ex[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEx,0)] * Ex[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEx,2)] * (Hz[IDX3D_FIELDS(x,y,z)] - Hz[IDX3D_FIELDS(x,y-1,z)]) -
Ex[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEx,0)] * Ex[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEx,2)] * (Hz[IDX3D_FIELDS(x,y,z)] - Hz[IDX3D_FIELDS(x,y-1,z)]) -
updatecoeffsE[IDX2D_MAT(materialEx,3)] * (Hy[IDX3D_FIELDS(x,y,z)] - Hy[IDX3D_FIELDS(x,y,z-1)]);
}
// Ey component
if ((NX != 1 || NZ != 1) && x > 0 && x < NX && y >= 0 && y < NY && z > 0 && z < NZ) {
int materialEy = ID[IDX4D_ID(1,x_ID,y_ID,z_ID)];
Ey[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEy,0)] * Ey[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEy,3)] * (Hx[IDX3D_FIELDS(x,y,z)] - Hx[IDX3D_FIELDS(x,y,z-1)]) -
Ey[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEy,0)] * Ey[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEy,3)] * (Hx[IDX3D_FIELDS(x,y,z)] - Hx[IDX3D_FIELDS(x,y,z-1)]) -
updatecoeffsE[IDX2D_MAT(materialEy,1)] * (Hz[IDX3D_FIELDS(x,y,z)] - Hz[IDX3D_FIELDS(x-1,y,z)]);
}
// Ez component
if ((NX != 1 || NY != 1) && x > 0 && x < NX && y > 0 && y < NY && z >= 0 && z < NZ) {
int materialEz = ID[IDX4D_ID(2,x_ID,y_ID,z_ID)];
Ez[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEz,0)] * Ez[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEz,1)] * (Hy[IDX3D_FIELDS(x,y,z)] - Hy[IDX3D_FIELDS(x-1,y,z)]) -
Ez[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEz,0)] * Ez[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEz,1)] * (Hy[IDX3D_FIELDS(x,y,z)] - Hy[IDX3D_FIELDS(x-1,y,z)]) -
updatecoeffsE[IDX2D_MAT(materialEz,2)] * (Hx[IDX3D_FIELDS(x,y,z)] - Hx[IDX3D_FIELDS(x,y-1,z)]);
}
""")}
"""
),
}
update_magnetic = {
'args_cuda': Template("""
"args_cuda": Template(
"""
__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,
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)
"""),
'args_opencl': Template("""
"""
),
"args_opencl": Template(
"""
int NX,
int NY,
int NZ,
@@ -111,8 +121,10 @@ update_magnetic = {
__global const $REAL * restrict Ex,
__global const $REAL * restrict Ey,
__global const $REAL * restrict Ez
"""),
'func': Template("""
"""
),
"func": Template(
"""
// Magnetic field updates - normal materials.
//
// Args:
@@ -120,7 +132,7 @@ update_magnetic = {
// ID, E, H: Access to ID and field component arrays.
$CUDA_IDX
// Convert the linear index to subscripts for 3D field arrays
int x = i / ($NY_FIELDS * $NZ_FIELDS);
int y = (i % ($NY_FIELDS * $NZ_FIELDS)) / $NZ_FIELDS;
@@ -134,47 +146,52 @@ update_magnetic = {
// Hx component
if (NX != 1 && x > 0 && x < NX && y >= 0 && y < NY && z >= 0 && z < NZ) {
int materialHx = ID[IDX4D_ID(3,x_ID,y_ID,z_ID)];
Hx[IDX3D_FIELDS(x,y,z)] = updatecoeffsH[IDX2D_MAT(materialHx,0)] * Hx[IDX3D_FIELDS(x,y,z)] -
updatecoeffsH[IDX2D_MAT(materialHx,2)] * (Ez[IDX3D_FIELDS(x,y+1,z)] - Ez[IDX3D_FIELDS(x,y,z)]) +
Hx[IDX3D_FIELDS(x,y,z)] = updatecoeffsH[IDX2D_MAT(materialHx,0)] * Hx[IDX3D_FIELDS(x,y,z)] -
updatecoeffsH[IDX2D_MAT(materialHx,2)] * (Ez[IDX3D_FIELDS(x,y+1,z)] - Ez[IDX3D_FIELDS(x,y,z)]) +
updatecoeffsH[IDX2D_MAT(materialHx,3)] * (Ey[IDX3D_FIELDS(x,y,z+1)] - Ey[IDX3D_FIELDS(x,y,z)]);
}
// Hy component
if (NY != 1 && x >= 0 && x < NX && y > 0 && y < NY && z >= 0 && z < NZ) {
int materialHy = ID[IDX4D_ID(4,x_ID,y_ID,z_ID)];
Hy[IDX3D_FIELDS(x,y,z)] = updatecoeffsH[IDX2D_MAT(materialHy,0)] * Hy[IDX3D_FIELDS(x,y,z)] -
updatecoeffsH[IDX2D_MAT(materialHy,3)] * (Ex[IDX3D_FIELDS(x,y,z+1)] - Ex[IDX3D_FIELDS(x,y,z)]) +
Hy[IDX3D_FIELDS(x,y,z)] = updatecoeffsH[IDX2D_MAT(materialHy,0)] * Hy[IDX3D_FIELDS(x,y,z)] -
updatecoeffsH[IDX2D_MAT(materialHy,3)] * (Ex[IDX3D_FIELDS(x,y,z+1)] - Ex[IDX3D_FIELDS(x,y,z)]) +
updatecoeffsH[IDX2D_MAT(materialHy,1)] * (Ez[IDX3D_FIELDS(x+1,y,z)] - Ez[IDX3D_FIELDS(x,y,z)]);
}
// Hz component
if (NZ != 1 && x >= 0 && x < NX && y >= 0 && y < NY && z > 0 && z < NZ) {
int materialHz = ID[IDX4D_ID(5,x_ID,y_ID,z_ID)];
Hz[IDX3D_FIELDS(x,y,z)] = updatecoeffsH[IDX2D_MAT(materialHz,0)] * Hz[IDX3D_FIELDS(x,y,z)] -
updatecoeffsH[IDX2D_MAT(materialHz,1)] * (Ey[IDX3D_FIELDS(x+1,y,z)] - Ey[IDX3D_FIELDS(x,y,z)]) +
Hz[IDX3D_FIELDS(x,y,z)] = updatecoeffsH[IDX2D_MAT(materialHz,0)] * Hz[IDX3D_FIELDS(x,y,z)] -
updatecoeffsH[IDX2D_MAT(materialHz,1)] * (Ey[IDX3D_FIELDS(x+1,y,z)] - Ey[IDX3D_FIELDS(x,y,z)]) +
updatecoeffsH[IDX2D_MAT(materialHz,2)] * (Ex[IDX3D_FIELDS(x,y+1,z)] - Ex[IDX3D_FIELDS(x,y,z)]);
}
""")}
"""
),
}
update_electric_dispersive_A = {
'args_cuda': Template("""
"args_cuda": Template(
"""
__global__ void update_electric_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,
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)
"""),
'args_opencl': Template("""
"""
),
"args_opencl": Template(
"""
int NX,
int NY,
int NZ,
@@ -190,17 +207,19 @@ update_electric_dispersive_A = {
__global const $REAL* restrict Hx,
__global const $REAL* restrict Hy,
__global const $REAL* restrict Hz
"""),
'func': Template("""
"""
),
"func": Template(
"""
// Electric field updates - dispersive materials - part A of updates to electric
// field values when dispersive materials
// field values when dispersive materials
// (with multiple poles) are present.
//
// Args:
// NX, NY, NZ: Number of cells of the model domain.
// MAXPOLES: Maximum number of dispersive material poles present in model.
// updatedispersivecoeffs, T, ID, E, H: Access to update coefficients,
// dispersive, ID and field
// updatedispersivecoeffs, T, ID, E, H: Access to update coefficients,
// dispersive, ID and field
// component arrays.
@@ -227,12 +246,12 @@ update_electric_dispersive_A = {
$REAL phi = 0;
for (int pole = 0; pole < MAXPOLES; pole++) {
phi = phi + updatecoeffsdispersive[IDX2D_MATDISP(materialEx,pole*3)]$REALFUNC * Tx[IDX4D_T(pole,x_T,y_T,z_T)]$REALFUNC;
Tx[IDX4D_T(pole,x_T,y_T,z_T)] = updatecoeffsdispersive[IDX2D_MATDISP(materialEx,1+(pole*3))] * Tx[IDX4D_T(pole,x_T,y_T,z_T)] +
Tx[IDX4D_T(pole,x_T,y_T,z_T)] = updatecoeffsdispersive[IDX2D_MATDISP(materialEx,1+(pole*3))] * Tx[IDX4D_T(pole,x_T,y_T,z_T)] +
updatecoeffsdispersive[IDX2D_MATDISP(materialEx,2+(pole*3))] * Ex[IDX3D_FIELDS(x,y,z)];
}
Ex[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEx,0)] * Ex[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEx,2)] * (Hz[IDX3D_FIELDS(x,y,z)] - Hz[IDX3D_FIELDS(x,y-1,z)]) -
updatecoeffsE[IDX2D_MAT(materialEx,3)] * (Hy[IDX3D_FIELDS(x,y,z)] - Hy[IDX3D_FIELDS(x,y,z-1)]) -
Ex[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEx,0)] * Ex[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEx,2)] * (Hz[IDX3D_FIELDS(x,y,z)] - Hz[IDX3D_FIELDS(x,y-1,z)]) -
updatecoeffsE[IDX2D_MAT(materialEx,3)] * (Hy[IDX3D_FIELDS(x,y,z)] - Hy[IDX3D_FIELDS(x,y,z-1)]) -
updatecoeffsE[IDX2D_MAT(materialEx,4)] * phi;
}
@@ -242,12 +261,12 @@ update_electric_dispersive_A = {
$REAL phi = 0;
for (int pole = 0; pole < MAXPOLES; pole++) {
phi = phi + updatecoeffsdispersive[IDX2D_MATDISP(materialEy,pole*3)]$REALFUNC * Ty[IDX4D_T(pole,x_T,y_T,z_T)]$REALFUNC;
Ty[IDX4D_T(pole,x_T,y_T,z_T)] = updatecoeffsdispersive[IDX2D_MATDISP(materialEy,1+(pole*3))] * Ty[IDX4D_T(pole,x_T,y_T,z_T)] +
Ty[IDX4D_T(pole,x_T,y_T,z_T)] = updatecoeffsdispersive[IDX2D_MATDISP(materialEy,1+(pole*3))] * Ty[IDX4D_T(pole,x_T,y_T,z_T)] +
updatecoeffsdispersive[IDX2D_MATDISP(materialEy,2+(pole*3))] * Ey[IDX3D_FIELDS(x,y,z)];
}
Ey[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEy,0)] * Ey[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEy,3)] * (Hx[IDX3D_FIELDS(x,y,z)] - Hx[IDX3D_FIELDS(x,y,z-1)]) -
updatecoeffsE[IDX2D_MAT(materialEy,1)] * (Hz[IDX3D_FIELDS(x,y,z)] - Hz[IDX3D_FIELDS(x-1,y,z)]) -
Ey[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEy,0)] * Ey[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEy,3)] * (Hx[IDX3D_FIELDS(x,y,z)] - Hx[IDX3D_FIELDS(x,y,z-1)]) -
updatecoeffsE[IDX2D_MAT(materialEy,1)] * (Hz[IDX3D_FIELDS(x,y,z)] - Hz[IDX3D_FIELDS(x-1,y,z)]) -
updatecoeffsE[IDX2D_MAT(materialEy,4)] * phi;
}
@@ -257,32 +276,37 @@ update_electric_dispersive_A = {
$REAL phi = 0;
for (int pole = 0; pole < MAXPOLES; pole++) {
phi = phi + updatecoeffsdispersive[IDX2D_MATDISP(materialEz,pole*3)]$REALFUNC * Tz[IDX4D_T(pole,x_T,y_T,z_T)]$REALFUNC;
Tz[IDX4D_T(pole,x_T,y_T,z_T)] = updatecoeffsdispersive[IDX2D_MATDISP(materialEz,1+(pole*3))] * Tz[IDX4D_T(pole,x_T,y_T,z_T)] +
Tz[IDX4D_T(pole,x_T,y_T,z_T)] = updatecoeffsdispersive[IDX2D_MATDISP(materialEz,1+(pole*3))] * Tz[IDX4D_T(pole,x_T,y_T,z_T)] +
updatecoeffsdispersive[IDX2D_MATDISP(materialEz,2+(pole*3))] * Ez[IDX3D_FIELDS(x,y,z)];
}
Ez[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEz,0)] * Ez[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEz,1)] * (Hy[IDX3D_FIELDS(x,y,z)] - Hy[IDX3D_FIELDS(x-1,y,z)]) -
updatecoeffsE[IDX2D_MAT(materialEz,2)] * (Hx[IDX3D_FIELDS(x,y,z)] - Hx[IDX3D_FIELDS(x,y-1,z)]) -
Ez[IDX3D_FIELDS(x,y,z)] = updatecoeffsE[IDX2D_MAT(materialEz,0)] * Ez[IDX3D_FIELDS(x,y,z)] +
updatecoeffsE[IDX2D_MAT(materialEz,1)] * (Hy[IDX3D_FIELDS(x,y,z)] - Hy[IDX3D_FIELDS(x-1,y,z)]) -
updatecoeffsE[IDX2D_MAT(materialEz,2)] * (Hx[IDX3D_FIELDS(x,y,z)] - Hx[IDX3D_FIELDS(x,y-1,z)]) -
updatecoeffsE[IDX2D_MAT(materialEz,4)] * phi;
}
""")}
"""
),
}
update_electric_dispersive_B = {
'args_cuda': Template("""
"args_cuda": Template(
"""
__global__ void update_electric_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,
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)
"""),
'args_opencl': Template("""
"""
),
"args_opencl": Template(
"""
int NX,
int NY,
int NZ,
@@ -295,17 +319,19 @@ update_electric_dispersive_B = {
__global const $REAL* restrict Ex,
__global const $REAL* restrict Ey,
__global const $REAL* restrict Ez
"""),
'func': Template("""
"""
),
"func": Template(
"""
// Electric field updates - dispersive materials - part B of updates to electric
// field values when dispersive materials
// field values when dispersive materials
// (with multiple poles) are present.
//
// Args:
// NX, NY, NZ: Number of cells of the model domain.
// MAXPOLES: Maximum number of dispersive material poles present in model.
// updatedispersivecoeffs, T, ID, E, H: Access to update coefficients,
// dispersive, ID and field
// updatedispersivecoeffs, T, ID, E, H: Access to update coefficients,
// dispersive, ID and field
// component arrays.
@@ -325,12 +351,12 @@ update_electric_dispersive_B = {
int z_T = ((i % ($NX_T * $NY_T * $NZ_T)) % ($NY_T * $NZ_T)) % $NZ_T;
$CUDA_IDX
// Ex component
if ((NY != 1 || NZ != 1) && x >= 0 && x < NX && y > 0 && y < NY && z > 0 && z < NZ) {
int materialEx = ID[IDX4D_ID(0,x_ID,y_ID,z_ID)];
for (int pole = 0; pole < MAXPOLES; pole++) {
Tx[IDX4D_T(pole,x_T,y_T,z_T)] = Tx[IDX4D_T(pole,x_T,y_T,z_T)] -
Tx[IDX4D_T(pole,x_T,y_T,z_T)] = Tx[IDX4D_T(pole,x_T,y_T,z_T)] -
updatecoeffsdispersive[IDX2D_MATDISP(materialEx,2+(pole*3))] * Ex[IDX3D_FIELDS(x,y,z)];
}
}
@@ -339,7 +365,7 @@ update_electric_dispersive_B = {
if ((NX != 1 || NZ != 1) && x > 0 && x < NX && y >= 0 && y < NY && z > 0 && z < NZ) {
int materialEy = ID[IDX4D_ID(1,x_ID,y_ID,z_ID)];
for (int pole = 0; pole < MAXPOLES; pole++) {
Ty[IDX4D_T(pole,x_T,y_T,z_T)] = Ty[IDX4D_T(pole,x_T,y_T,z_T)] -
Ty[IDX4D_T(pole,x_T,y_T,z_T)] = Ty[IDX4D_T(pole,x_T,y_T,z_T)] -
updatecoeffsdispersive[IDX2D_MATDISP(materialEy,2+(pole*3))] * Ey[IDX3D_FIELDS(x,y,z)];
}
}
@@ -348,8 +374,10 @@ update_electric_dispersive_B = {
if ((NX != 1 || NY != 1) && x > 0 && x < NX && y > 0 && y < NY && z >= 0 && z < NZ) {
int materialEz = ID[IDX4D_ID(2,x_ID,y_ID,z_ID)];
for (int pole = 0; pole < MAXPOLES; pole++) {
Tz[IDX4D_T(pole,x_T,y_T,z_T)] = Tz[IDX4D_T(pole,x_T,y_T,z_T)] -
Tz[IDX4D_T(pole,x_T,y_T,z_T)] = Tz[IDX4D_T(pole,x_T,y_T,z_T)] -
updatecoeffsdispersive[IDX2D_MATDISP(materialEz,2+(pole*3))] * Ez[IDX3D_FIELDS(x,y,z)];
}
}
""")}
"""
),
}

查看文件

@@ -18,28 +18,32 @@
from string import Template
x_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, $REAL *Ey,
$REAL *Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
x_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, $REAL *Ey,
$REAL *Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -67,32 +71,37 @@ x_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
y_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
y_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
$REAL *Ex,
const $REAL* __restrict__ Ey,
$REAL *Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ Ey,
$REAL *Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -120,32 +129,37 @@ y_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
z_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
z_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
$REAL *Ex,
$REAL *Ey,
const $REAL* __restrict__ Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
$REAL *Ey,
const $REAL* __restrict__ Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -173,12 +187,15 @@ z_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
order1_xminus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order1_xminus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Ey and Ez field components for the xminus slab.
//
// Args:
@@ -224,7 +241,7 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHz;
}
@@ -244,15 +261,19 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHy + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHy;
}
""")}
"""
),
}
order2_xminus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order2_xminus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Ey and Ez field components for the xminus slab.
//
// Args:
@@ -303,10 +324,10 @@ order2_xminus = {'args_cuda': x_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dHz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHz;
}
@@ -331,18 +352,22 @@ order2_xminus = {'args_cuda': x_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHy + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHy + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dHy + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHy;
}
""")}
"""
),
}
order1_xplus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order1_xplus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Ey and Ez field components for the xplus slab.
//
// Args:
@@ -388,7 +413,7 @@ order1_xplus = {'args_cuda': x_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHz;
}
@@ -408,15 +433,19 @@ order1_xplus = {'args_cuda': x_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHy + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHy;
}
""")}
"""
),
}
order2_xplus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order2_xplus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Ey and Ez field components for the xplus slab.
//
// Args:
@@ -467,9 +496,9 @@ order2_xplus = {'args_cuda': x_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dHz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHz;
}
@@ -494,18 +523,22 @@ order2_xplus = {'args_cuda': x_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHy + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHy + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dHy + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHy;
}
""")}
"""
),
}
order1_yminus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order1_yminus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ez field components for the yminus slab.
//
// Args:
@@ -551,7 +584,7 @@ order1_yminus = {'args_cuda': y_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHz;
}
@@ -571,15 +604,19 @@ order1_yminus = {'args_cuda': y_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHx;
}
""")}
"""
),
}
order2_yminus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order2_yminus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ez field components for the yminus slab.
//
// Args:
@@ -630,10 +667,10 @@ order2_yminus = {'args_cuda': y_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dHz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHz;
}
@@ -658,18 +695,22 @@ order2_yminus = {'args_cuda': y_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dHx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHx;
}
""")}
"""
),
}
order1_yplus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order1_yplus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ez field components for the yplus slab.
//
// Args:
@@ -715,7 +756,7 @@ order1_yplus = {'args_cuda': y_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHz;
}
@@ -735,15 +776,19 @@ order1_yplus = {'args_cuda': y_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHx;
}
""")}
"""
),
}
order2_yplus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order2_yplus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ez field components for the yplus slab.
//
// Args:
@@ -794,10 +839,10 @@ order2_yplus = {'args_cuda': y_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dHz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHz;
}
@@ -822,18 +867,22 @@ order2_yplus = {'args_cuda': y_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(RA01 * dHx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dHx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHx;
}
""")}
"""
),
}
order1_zminus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order1_zminus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ey field components for the zminus slab.
//
// Args:
@@ -879,7 +928,7 @@ order1_zminus = {'args_cuda': z_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHy + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHy;
}
@@ -899,15 +948,19 @@ order1_zminus = {'args_cuda': z_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHx;
}
""")}
"""
),
}
order2_zminus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order2_zminus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ey field components for the zminus slab.
//
// Args:
@@ -958,10 +1011,10 @@ order2_zminus = {'args_cuda': z_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHy + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHy + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dHy + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHy;
}
@@ -986,18 +1039,22 @@ order2_zminus = {'args_cuda': z_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dHx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHx;
}
""")}
"""
),
}
order1_zplus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order1_zplus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ey field components for the zplus slab.
//
// Args:
@@ -1043,7 +1100,7 @@ order1_zplus = {'args_cuda': z_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHy + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHy;
}
@@ -1063,15 +1120,19 @@ order1_zplus = {'args_cuda': z_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHx;
}
""")}
"""
),
}
order2_zplus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order2_zplus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ey field components for the zplus slab.
//
// Args:
@@ -1122,10 +1183,10 @@ order2_zplus = {'args_cuda': z_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHy + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(RA01 * dHy + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dHy + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dHy;
}
@@ -1150,11 +1211,13 @@ order2_zplus = {'args_cuda': z_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(RA01 * dHx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dHx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dHx;
}
""")}
"""
),
}

查看文件

@@ -18,28 +18,32 @@
from string import Template
x_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, $REAL *Ey,
$REAL *Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
x_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, $REAL *Ey,
$REAL *Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -67,32 +71,37 @@ x_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
y_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
y_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
$REAL *Ex,
const $REAL* __restrict__ Ey,
$REAL *Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ Ey,
$REAL *Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -120,32 +129,37 @@ y_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
z_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
z_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
$REAL *Ex,
$REAL *Ey,
const $REAL* __restrict__ Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
$REAL *Ey,
const $REAL* __restrict__ Ez,
const $REAL* __restrict__ Hx, const $REAL* __restrict__ Hy, const $REAL* __restrict__ Hz, $REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -173,12 +187,15 @@ z_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
order1_xminus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order1_xminus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Ey and Ez field components for the xminus slab.
//
// Args:
@@ -226,9 +243,9 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(IRA1 * dHz - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHz -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHz -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -249,16 +266,20 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(IRA1 * dHy - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHy -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHy -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_xminus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order2_xminus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Ey and Ez field components for the xminus slab.
//
// Args:
@@ -311,7 +332,7 @@ order2_xminus = {'args_cuda': x_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(IRA1 * dHz - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dHz - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dHz - Psi1);
@@ -339,16 +360,20 @@ order2_xminus = {'args_cuda': x_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(IRA1 * dHy - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dHy - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dHy - Psi2);
}
""")}
"""
),
}
order1_xplus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order1_xplus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Ey and Ez field components for the xplus slab.
//
// Args:
@@ -396,9 +421,9 @@ order1_xplus = {'args_cuda': x_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(IRA1 * dHz - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHz -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHz -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -419,16 +444,20 @@ order1_xplus = {'args_cuda': x_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(IRA1 * dHy - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHy -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHy -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_xplus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order2_xplus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Ey and Ez field components for the xplus slab.
//
// Args:
@@ -481,7 +510,7 @@ order2_xplus = {'args_cuda': x_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(IRA1 * dHz - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dHz - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dHz - Psi1);
@@ -509,16 +538,20 @@ order2_xplus = {'args_cuda': x_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii-1,jj,kk)]) / dx;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(IRA1 * dHy - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dHy - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dHy - Psi2);
}
""")}
"""
),
}
order1_yminus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order1_yminus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ez field components for the yminus slab.
//
// Args:
@@ -566,9 +599,9 @@ order1_yminus = {'args_cuda': y_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(IRA1 * dHz - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHz -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHz -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -589,16 +622,20 @@ order1_yminus = {'args_cuda': y_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(IRA1 * dHx - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHx -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHx -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_yminus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order2_yminus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ez field components for the yminus slab.
//
// Args:
@@ -651,7 +688,7 @@ order2_yminus = {'args_cuda': y_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(IRA1 * dHz - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dHz - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dHz - Psi1);
@@ -679,16 +716,20 @@ order2_yminus = {'args_cuda': y_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(IRA1 * dHx - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dHx - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dHx - Psi2);
}
""")}
"""
),
}
order1_yplus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order1_yplus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ez field components for the yplus slab.
//
// Args:
@@ -736,9 +777,9 @@ order1_yplus = {'args_cuda': y_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(IRA1 * dHz - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHz -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHz -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -759,16 +800,20 @@ order1_yplus = {'args_cuda': y_args['cuda'],
// Ez
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(IRA1 * dHx - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHx -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHx -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_yplus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order2_yplus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ez field components for the yplus slab.
//
// Args:
@@ -821,7 +866,7 @@ order2_yplus = {'args_cuda': y_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHz = (Hz[IDX3D_FIELDS(ii,jj,kk)] - Hz[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(IRA1 * dHz - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dHz - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dHz - Psi1);
@@ -849,16 +894,20 @@ order2_yplus = {'args_cuda': y_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialEz = ID[IDX4D_ID(2,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj-1,kk)]) / dy;
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(ii,jj,kk)] = Ez[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
(IRA1 * dHx - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dHx - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dHx - Psi2);
}
""")}
"""
),
}
order1_zminus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order1_zminus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ey field components for the zminus slab.
//
// Args:
@@ -906,9 +955,9 @@ order1_zminus = {'args_cuda': z_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(IRA1 * dHy - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHy -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHy -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -929,16 +978,20 @@ order1_zminus = {'args_cuda': z_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(IRA1 * dHx - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHx -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHx -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_zminus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order2_zminus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ey field components for the zminus slab.
//
// Args:
@@ -991,7 +1044,7 @@ order2_zminus = {'args_cuda': z_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(IRA1 * dHy - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dHy - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dHy - Psi1);
@@ -1019,16 +1072,20 @@ order2_zminus = {'args_cuda': z_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(IRA1 * dHx - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dHx - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dHx - Psi2);
}
""")}
"""
),
}
order1_zplus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order1_zplus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ey field components for the zplus slab.
//
// Args:
@@ -1076,9 +1133,9 @@ order1_zplus = {'args_cuda': z_args['cuda'],
// Ex
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(IRA1 * dHy - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHy -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dHy -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -1099,16 +1156,20 @@ order1_zplus = {'args_cuda': z_args['cuda'],
// Ey
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(IRA1 * dHx - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHx -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dHx -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_zplus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order2_zplus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Ex and Ey field components for the zplus slab.
//
// Args:
@@ -1161,7 +1222,7 @@ order2_zplus = {'args_cuda': z_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialEx = ID[IDX4D_ID(0,ii,jj,kk)];
dHy = (Hy[IDX3D_FIELDS(ii,jj,kk)] - Hy[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(ii,jj,kk)] = Ex[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
(IRA1 * dHy - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dHy - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dHy - Psi1);
@@ -1189,9 +1250,11 @@ order2_zplus = {'args_cuda': z_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialEy = ID[IDX4D_ID(1,ii,jj,kk)];
dHx = (Hx[IDX3D_FIELDS(ii,jj,kk)] - Hx[IDX3D_FIELDS(ii,jj,kk-1)]) / dz;
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(ii,jj,kk)] = Ey[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsE[IDX2D_MAT(materialEy,4)] *
(IRA1 * dHx - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dHx - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dHx - Psi2);
}
""")}
"""
),
}

查看文件

@@ -18,28 +18,32 @@
from string import Template
x_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez, const $REAL* __restrict__ Hx, $REAL *Hy,
$REAL *Hz,
$REAL *PHI1,
$REAL *PHI2,
x_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez, const $REAL* __restrict__ Hx, $REAL *Hy,
$REAL *Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -67,33 +71,38 @@ x_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
y_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez,
y_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez,
$REAL *Hx,
const $REAL* __restrict__ Hy,
$REAL *Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ Hy,
$REAL *Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -121,33 +130,38 @@ y_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
z_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez,
z_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez,
$REAL *Hx,
$REAL *Hy,
const $REAL* __restrict__ Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -175,12 +189,15 @@ z_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
order1_xminus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order1_xminus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Hy and Hz field components for the xminus slab.
//
// Args:
@@ -191,7 +208,7 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// d: Spatial discretisation, e.g. dx, dy or dz
$CUDA_IDX
// Convert the linear index to subscripts for PML PHI1 (4D) arrays
int p1 = i / (NX_PHI1 * NY_PHI1 * NZ_PHI1);
int i1 = (i % (NX_PHI1 * NY_PHI1 * NZ_PHI1)) / (NY_PHI1 * NZ_PHI1);
@@ -226,7 +243,7 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii+1,jj,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEz;
}
@@ -246,15 +263,19 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii+1,jj,kk)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEy + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEy;
}
""")}
"""
),
}
order2_xminus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order2_xminus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Hy and Hz field components for the xminus slab.
//
// Args:
@@ -305,10 +326,10 @@ order2_xminus = {'args_cuda': x_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii+1,jj,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dEz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEz;
}
@@ -333,18 +354,22 @@ order2_xminus = {'args_cuda': x_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii+1,jj,kk)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEy + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEy + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dEy + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEy;
}
""")}
"""
),
}
order1_xplus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order1_xplus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Hy and Hz field components for the xplus slab.
//
// Args:
@@ -390,7 +415,7 @@ order1_xplus = {'args_cuda': x_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii+1,jj,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEz;
}
@@ -410,15 +435,19 @@ order1_xplus = {'args_cuda': x_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii+1,jj,kk)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEy + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEy;
}
""")}
"""
),
}
order2_xplus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order2_xplus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Hy and Hz field components for the xplus slab.
//
// Args:
@@ -469,10 +498,10 @@ order2_xplus = {'args_cuda': x_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii+1,jj,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dEz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEz;
}
@@ -497,18 +526,22 @@ order2_xplus = {'args_cuda': x_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii+1,jj,kk)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEy + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEy + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dEy + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEy;
}
""")}
"""
),
}
order1_yminus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order1_yminus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hz field components for the yminus slab.
//
// Args:
@@ -554,7 +587,7 @@ order1_yminus = {'args_cuda': y_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii,jj+1,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEz;
}
@@ -574,15 +607,19 @@ order1_yminus = {'args_cuda': y_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj+1,kk)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEx;
}
""")}
"""
),
}
order2_yminus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order2_yminus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hz field components for the yminus slab.
//
// Args:
@@ -633,10 +670,10 @@ order2_yminus = {'args_cuda': y_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii,jj+1,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dEz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEz;
}
@@ -661,17 +698,21 @@ order2_yminus = {'args_cuda': y_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj+1,kk)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dEx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEx;
}
""")}
"""
),
}
order1_yplus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order1_yplus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hz field components for the yplus slab.
//
// Args:
@@ -717,7 +758,7 @@ order1_yplus = {'args_cuda': y_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii,jj+1,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEz;
}
@@ -737,15 +778,19 @@ order1_yplus = {'args_cuda': y_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj+1,kk)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEx;
}
""")}
"""
),
}
order2_yplus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order2_yplus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hz field components for the yplus slab.
//
// Args:
@@ -796,9 +841,9 @@ order2_yplus = {'args_cuda': y_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii,jj+1,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEz + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dEz + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEz;
}
@@ -823,17 +868,21 @@ order2_yplus = {'args_cuda': y_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj+1,kk)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(RA01 * dEx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dEx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEx;
}
""")}
"""
),
}
order1_zminus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order1_zminus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hy field components for the zminus slab.
//
// Args:
@@ -879,7 +928,7 @@ order1_zminus = {'args_cuda': z_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii,jj,kk+1)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEy + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEy;
}
@@ -899,15 +948,19 @@ order1_zminus = {'args_cuda': z_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj,kk+1)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEx;
}
""")}
"""
),
}
order2_zminus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order2_zminus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hy field components for the zminus slab.
//
// Args:
@@ -958,10 +1011,10 @@ order2_zminus = {'args_cuda': z_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii,jj,kk+1)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEy + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEy + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dEy + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEy;
}
@@ -986,18 +1039,22 @@ order2_zminus = {'args_cuda': z_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj,kk+1)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dEx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEx;
}
""")}
"""
),
}
order1_zplus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order1_zplus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hy field components for the zplus slab.
//
// Args:
@@ -1043,7 +1100,7 @@ order1_zplus = {'args_cuda': z_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii,jj,kk+1)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEy + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEy;
}
@@ -1063,15 +1120,19 @@ order1_zplus = {'args_cuda': z_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj,kk+1)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEx;
}
""")}
"""
),
}
order2_zplus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order2_zplus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hy field components for the zplus slab.
//
// Args:
@@ -1122,10 +1183,10 @@ order2_zplus = {'args_cuda': z_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii,jj,kk+1)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEy + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(RA01 * dEy + RA1 * RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] +
RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)]);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] - RF1 *
(RA0 * dEy + RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] - RF0 * dEy;
}
@@ -1150,12 +1211,13 @@ order2_zplus = {'args_cuda': z_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj,kk+1)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(RA01 * dEx + RA1 * RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] +
RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)]);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] - RF1 *
(RA0 * dEx + RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] - RF0 * dEx;
}
""")}
"""
),
}

查看文件

@@ -18,28 +18,32 @@
from string import Template
x_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez, const $REAL* __restrict__ Hx, $REAL *Hy,
$REAL *Hz,
$REAL *PHI1,
$REAL *PHI2,
x_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez, const $REAL* __restrict__ Hx, $REAL *Hy,
$REAL *Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -67,33 +71,38 @@ x_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
y_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez,
y_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez,
$REAL *Hx,
const $REAL* __restrict__ Hy,
$REAL *Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ Hy,
$REAL *Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -121,33 +130,38 @@ y_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
z_args = {'cuda': Template("""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez,
z_args = {
"cuda": Template(
"""
__global__ void $FUNC(int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int NX_PHI1,
int NY_PHI1,
int NZ_PHI1,
int NX_PHI2,
int NY_PHI2,
int NZ_PHI2,
int NY_R,
const unsigned int* __restrict__ ID,
const $REAL* __restrict__ Ex, const $REAL* __restrict__ Ey, const $REAL* __restrict__ Ez,
$REAL *Hx,
$REAL *Hy,
const $REAL* __restrict__ Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ Hz,
$REAL *PHI1,
$REAL *PHI2,
const $REAL* __restrict__ RA, const $REAL* __restrict__ RB, const $REAL* __restrict__ RE, const $REAL* __restrict__ RF, $REAL d)
"""),
'opencl': Template("""
"""
),
"opencl": Template(
"""
int xs,
int xf,
int ys,
@@ -175,12 +189,15 @@ z_args = {'cuda': Template("""
__global const $REAL* restrict RE,
__global const $REAL* restrict RF,
$REAL d
""")
}
"""
),
}
order1_xminus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order1_xminus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Hy and Hz field components for the xminus slab.
//
// Args:
@@ -191,7 +208,7 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// d: Spatial discretisation, e.g. dx, dy or dz
$CUDA_IDX
// Convert the linear index to subscripts for PML PHI1 (4D) arrays
int p1 = i / (NX_PHI1 * NY_PHI1 * NZ_PHI1);
int i1 = (i % (NX_PHI1 * NY_PHI1 * NZ_PHI1)) / (NY_PHI1 * NZ_PHI1);
@@ -228,9 +245,9 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii+1,jj,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(IRA1 * dEz - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEz -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEz -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -251,16 +268,20 @@ order1_xminus = {'args_cuda': x_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii+1,jj,kk)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(IRA1 * dEy - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEy -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEy -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_xminus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order2_xminus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Hy and Hz field components for the xminus slab.
//
// Args:
@@ -313,7 +334,7 @@ order2_xminus = {'args_cuda': x_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii+1,jj,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(IRA1 * dEz - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dEz - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dEz - Psi1);
@@ -341,16 +362,20 @@ order2_xminus = {'args_cuda': x_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii+1,jj,kk)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(IRA1 * dEy - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dEy - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dEy - Psi2);
}
""")}
"""
),
}
order1_xplus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order1_xplus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Hy and Hz field components for the xplus slab.
//
// Args:
@@ -398,9 +423,9 @@ order1_xplus = {'args_cuda': x_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii+1,jj,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(IRA1 * dEz - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEz -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEz -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -421,16 +446,20 @@ order1_xplus = {'args_cuda': x_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii+1,jj,kk)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(IRA1 * dEy - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEy -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEy -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_xplus = {'args_cuda': x_args['cuda'],
'args_opencl': x_args['opencl'],
'func': Template("""
order2_xplus = {
"args_cuda": x_args["cuda"],
"args_opencl": x_args["opencl"],
"func": Template(
"""
// This function updates the Hy and Hz field components for the xplus slab.
//
// Args:
@@ -483,7 +512,7 @@ order2_xplus = {'args_cuda': x_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii+1,jj,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(IRA1 * dEz - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dEz - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dEz - Psi1);
@@ -511,16 +540,20 @@ order2_xplus = {'args_cuda': x_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii+1,jj,kk)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dx;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(IRA1 * dEy - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dEy - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dEy - Psi2);
}
""")}
"""
),
}
order1_yminus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order1_yminus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hz field components for the yminus slab.
//
// Args:
@@ -568,9 +601,9 @@ order1_yminus = {'args_cuda': y_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii,jj+1,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(IRA1 * dEz - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEz -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEz -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -591,16 +624,20 @@ order1_yminus = {'args_cuda': y_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj+1,kk)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(IRA1 * dEx - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEx -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEx -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_yminus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order2_yminus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hz field components for the yminus slab.
//
// Args:
@@ -653,7 +690,7 @@ order2_yminus = {'args_cuda': y_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii,jj+1,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(IRA1 * dEz - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dEz - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dEz - Psi1);
@@ -681,16 +718,20 @@ order2_yminus = {'args_cuda': y_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj+1,kk)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(IRA1 * dEx - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dEx - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dEx - Psi2);
}
""")}
"""
),
}
order1_yplus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order1_yplus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hz field components for the yplus slab.
//
// Args:
@@ -738,9 +779,9 @@ order1_yplus = {'args_cuda': y_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii,jj+1,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(IRA1 * dEz - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEz -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEz -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -761,16 +802,20 @@ order1_yplus = {'args_cuda': y_args['cuda'],
// Hz
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj+1,kk)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(IRA1 * dEx - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEx -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEx -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_yplus = {'args_cuda': y_args['cuda'],
'args_opencl': y_args['opencl'],
'func': Template("""
order2_yplus = {
"args_cuda": y_args["cuda"],
"args_opencl": y_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hz field components for the yplus slab.
//
// Args:
@@ -823,7 +868,7 @@ order2_yplus = {'args_cuda': y_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEz = (Ez[IDX3D_FIELDS(ii,jj+1,kk)] - Ez[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(IRA1 * dEz - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dEz - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dEz - Psi1);
@@ -851,16 +896,20 @@ order2_yplus = {'args_cuda': y_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialHz = ID[IDX4D_ID(5,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj+1,kk)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dy;
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(ii,jj,kk)] = Hz[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHz,4)] *
(IRA1 * dEx - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dEx - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dEx - Psi2);
}
""")}
"""
),
}
order1_zminus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order1_zminus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hy field components for the zminus slab.
//
// Args:
@@ -908,9 +957,9 @@ order1_zminus = {'args_cuda': z_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii,jj,kk+1)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(IRA1 * dEy - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEy -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEy -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -931,16 +980,20 @@ order1_zminus = {'args_cuda': z_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj,kk+1)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(IRA1 * dEx - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEx -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEx -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_zminus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order2_zminus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hy field components for the zminus slab.
//
// Args:
@@ -993,7 +1046,7 @@ order2_zminus = {'args_cuda': z_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii,jj,kk+1)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(IRA1 * dEy - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dEy - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dEy - Psi1);
@@ -1021,16 +1074,20 @@ order2_zminus = {'args_cuda': z_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj,kk+1)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(IRA1 * dEx - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dEx - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dEx - Psi2);
}
""")}
"""
),
}
order1_zplus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order1_zplus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hy field components for the zplus slab.
//
// Args:
@@ -1078,9 +1135,9 @@ order1_zplus = {'args_cuda': z_args['cuda'],
// Hx
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii,jj,kk+1)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(IRA1 * dEy - IRA * PHI1[IDX4D_PHI1(0,i1,j1,k1)]);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEy -
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * dEy -
RC0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)];
}
@@ -1101,16 +1158,20 @@ order1_zplus = {'args_cuda': z_args['cuda'],
// Hy
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj,kk+1)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(IRA1 * dEx - IRA * PHI2[IDX4D_PHI2(0,i2,j2,k2)]);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEx -
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * dEx -
RC0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)];
}
""")}
"""
),
}
order2_zplus = {'args_cuda': z_args['cuda'],
'args_opencl': z_args['opencl'],
'func': Template("""
order2_zplus = {
"args_cuda": z_args["cuda"],
"args_opencl": z_args["opencl"],
"func": Template(
"""
// This function updates the Hx and Hy field components for the zplus slab.
//
// Args:
@@ -1163,7 +1224,7 @@ order2_zplus = {'args_cuda': z_args['cuda'],
Psi1 = RB0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RB1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)];
materialHx = ID[IDX4D_ID(3,ii,jj,kk)];
dEy = (Ey[IDX3D_FIELDS(ii,jj,kk+1)] - Ey[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(ii,jj,kk)] = Hx[IDX3D_FIELDS(ii,jj,kk)] + updatecoeffsH[IDX2D_MAT(materialHx,4)] *
(IRA1 * dEy - IRA * Psi1);
PHI1[IDX4D_PHI1(1,i1,j1,k1)] = RE1 * PHI1[IDX4D_PHI1(1,i1,j1,k1)] + RC1 * (dEy - Psi1);
PHI1[IDX4D_PHI1(0,i1,j1,k1)] = RE0 * PHI1[IDX4D_PHI1(0,i1,j1,k1)] + RC0 * (dEy - Psi1);
@@ -1191,10 +1252,11 @@ order2_zplus = {'args_cuda': z_args['cuda'],
Psi2 = RB0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RB1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)];
materialHy = ID[IDX4D_ID(4,ii,jj,kk)];
dEx = (Ex[IDX3D_FIELDS(ii,jj,kk+1)] - Ex[IDX3D_FIELDS(ii,jj,kk)]) / dz;
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(ii,jj,kk)] = Hy[IDX3D_FIELDS(ii,jj,kk)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
(IRA1 * dEx - IRA * Psi2);
PHI2[IDX4D_PHI2(1,i2,j2,k2)] = RE1 * PHI2[IDX4D_PHI2(1,i2,j2,k2)] + RC1 * (dEx - Psi2);
PHI2[IDX4D_PHI2(0,i2,j2,k2)] = RE0 * PHI2[IDX4D_PHI2(0,i2,j2,k2)] + RC0 * (dEx - Psi2);
}
""")}
"""
),
}

查看文件

@@ -19,31 +19,35 @@
from string import Template
store_snapshot = {'args_cuda': Template("""
__global__ void store_snapshot(int p,
int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int dx,
int dy,
store_snapshot = {
"args_cuda": Template(
"""
__global__ void store_snapshot(int p,
int xs,
int xf,
int ys,
int yf,
int zs,
int zf,
int dx,
int dy,
int dz,
const $REAL* __restrict__ Ex,
const $REAL* __restrict__ Ex,
const $REAL* __restrict__ Ey,
const $REAL* __restrict__ Ez,
const $REAL* __restrict__ Ez,
const $REAL* __restrict__ Hx,
const $REAL* __restrict__ Hy,
const $REAL* __restrict__ Hy,
const $REAL* __restrict__ Hz,
$REAL *snapEx,
$REAL *snapEy,
$REAL *snapEx,
$REAL *snapEy,
$REAL *snapEz,
$REAL *snapHx,
$REAL *snapHy,
$REAL *snapHx,
$REAL *snapHy,
$REAL *snapHz)
"""),
'args_opencl': Template("""
"""
),
"args_opencl": Template(
"""
int p,
int xs,
int xf,
@@ -53,7 +57,7 @@ store_snapshot = {'args_cuda': Template("""
int zf,
int dx,
int dy,
int dz,
int dz,
__global const $REAL* restrict Ex,
__global const $REAL* restrict Ey,
__global const $REAL* restrict Ez,
@@ -66,8 +70,10 @@ store_snapshot = {'args_cuda': Template("""
__global $REAL *snapHx,
__global $REAL *snapHy,
__global $REAL *snapHz
"""),
'func': Template("""
"""
),
"func": Template(
"""
// Stores field values for a snapshot.
//
// Args:
@@ -96,27 +102,28 @@ store_snapshot = {'args_cuda': Template("""
// The electric field component value at a point comes from an average of
// the 4 electric field component values in that cell
snapEx[IDX4D_SNAPS(p,x,y,z)] = (Ex[IDX3D_FIELDS(xx,yy,zz)] +
Ex[IDX3D_FIELDS(xx,yy+1,zz)] +
Ex[IDX3D_FIELDS(xx,yy,zz+1)] +
snapEx[IDX4D_SNAPS(p,x,y,z)] = (Ex[IDX3D_FIELDS(xx,yy,zz)] +
Ex[IDX3D_FIELDS(xx,yy+1,zz)] +
Ex[IDX3D_FIELDS(xx,yy,zz+1)] +
Ex[IDX3D_FIELDS(xx,yy+1,zz+1)]) / 4;
snapEy[IDX4D_SNAPS(p,x,y,z)] = (Ey[IDX3D_FIELDS(xx,yy,zz)] +
Ey[IDX3D_FIELDS(xx+1,yy,zz)] +
Ey[IDX3D_FIELDS(xx,yy,zz+1)] +
snapEy[IDX4D_SNAPS(p,x,y,z)] = (Ey[IDX3D_FIELDS(xx,yy,zz)] +
Ey[IDX3D_FIELDS(xx+1,yy,zz)] +
Ey[IDX3D_FIELDS(xx,yy,zz+1)] +
Ey[IDX3D_FIELDS(xx+1,yy,zz+1)]) / 4;
snapEz[IDX4D_SNAPS(p,x,y,z)] = (Ez[IDX3D_FIELDS(xx,yy,zz)] +
Ez[IDX3D_FIELDS(xx+1,yy,zz)] +
Ez[IDX3D_FIELDS(xx,yy+1,zz)] +
snapEz[IDX4D_SNAPS(p,x,y,z)] = (Ez[IDX3D_FIELDS(xx,yy,zz)] +
Ez[IDX3D_FIELDS(xx+1,yy,zz)] +
Ez[IDX3D_FIELDS(xx,yy+1,zz)] +
Ez[IDX3D_FIELDS(xx+1,yy+1,zz)]) / 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
snapHx[IDX4D_SNAPS(p,x,y,z)] = (Hx[IDX3D_FIELDS(xx,yy,zz)] +
snapHx[IDX4D_SNAPS(p,x,y,z)] = (Hx[IDX3D_FIELDS(xx,yy,zz)] +
Hx[IDX3D_FIELDS(xx+1,yy,zz)]) / 2;
snapHy[IDX4D_SNAPS(p,x,y,z)] = (Hy[IDX3D_FIELDS(xx,yy,zz)] +
snapHy[IDX4D_SNAPS(p,x,y,z)] = (Hy[IDX3D_FIELDS(xx,yy,zz)] +
Hy[IDX3D_FIELDS(xx,yy+1,zz)]) / 2;
snapHz[IDX4D_SNAPS(p,x,y,z)] = (Hz[IDX3D_FIELDS(xx,yy,zz)] +
snapHz[IDX4D_SNAPS(p,x,y,z)] = (Hz[IDX3D_FIELDS(xx,yy,zz)] +
Hz[IDX3D_FIELDS(xx,yy,zz+1)]) / 2;
}
""")
}
"""
),
}

查看文件

@@ -18,21 +18,25 @@
from string import Template
update_hertzian_dipole = {'args_cuda': Template("""
__global__ void update_hertzian_dipole(int NHERTZDIPOLE,
int iteration,
$REAL dx,
$REAL dy,
$REAL dz,
const int* __restrict__ srcinfo1,
const $REAL* __restrict__ srcinfo2,
const $REAL* __restrict__ srcwaveforms,
const unsigned int* __restrict__ ID,
$REAL *Ex,
$REAL *Ey,
update_hertzian_dipole = {
"args_cuda": Template(
"""
__global__ void update_hertzian_dipole(int NHERTZDIPOLE,
int iteration,
$REAL dx,
$REAL dy,
$REAL dz,
const int* __restrict__ srcinfo1,
const $REAL* __restrict__ srcinfo2,
const $REAL* __restrict__ srcwaveforms,
const unsigned int* __restrict__ ID,
$REAL *Ex,
$REAL *Ey,
$REAL *Ez)
"""),
'args_opencl': Template("""
"""
),
"args_opencl": Template(
"""
int NHERTZDIPOLE,
int iteration,
$REAL dx,
@@ -45,8 +49,10 @@ update_hertzian_dipole = {'args_cuda': Template("""
__global $REAL *Ex,
__global $REAL *Ey,
__global $REAL *Ez
"""),
'func': Template("""
"""
),
"func": Template(
"""
// Updates electric field values for Hertzian dipole sources.
//
// Args:
@@ -74,42 +80,47 @@ update_hertzian_dipole = {'args_cuda': Template("""
// 'x' polarised source
if (polarisation == 0) {
int materialEx = ID[IDX4D_ID(0,x,y,z)];
Ex[IDX3D_FIELDS(x,y,z)] = Ex[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(x,y,z)] = Ex[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
srcwaveforms[IDX2D_SRCWAVES(i,iteration)] * dl * (1 / (dx * dy * dz));
}
// 'y' polarised source
else if (polarisation == 1) {
int materialEy = ID[IDX4D_ID(1,x,y,z)];
Ey[IDX3D_FIELDS(x,y,z)] = Ey[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(x,y,z)] = Ey[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
srcwaveforms[IDX2D_SRCWAVES(i,iteration)] * dl * (1 / (dx * dy * dz));
}
// 'z' polarised source
else if (polarisation == 2) {
int materialEz = ID[IDX4D_ID(2,x,y,z)];
Ez[IDX3D_FIELDS(x,y,z)] = Ez[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(x,y,z)] = Ez[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
srcwaveforms[IDX2D_SRCWAVES(i,iteration)] * dl * (1 / (dx * dy * dz));
}
}
""")
"""
),
}
update_magnetic_dipole = {'args_cuda': Template("""
__global__ void update_magnetic_dipole(int NMAGDIPOLE,
int iteration,
$REAL dx,
$REAL dy,
$REAL dz,
const int* __restrict__ srcinfo1,
const $REAL* __restrict__ srcinfo2,
const $REAL* __restrict__ srcwaveforms,
const unsigned int* __restrict__ ID,
$REAL *Hx,
$REAL *Hy,
update_magnetic_dipole = {
"args_cuda": Template(
"""
__global__ void update_magnetic_dipole(int NMAGDIPOLE,
int iteration,
$REAL dx,
$REAL dy,
$REAL dz,
const int* __restrict__ srcinfo1,
const $REAL* __restrict__ srcinfo2,
const $REAL* __restrict__ srcwaveforms,
const unsigned int* __restrict__ ID,
$REAL *Hx,
$REAL *Hy,
$REAL *Hz)
"""),
'args_opencl': Template("""
"""
),
"args_opencl": Template(
"""
int NMAGDIPOLE,
int iteration,
$REAL dx,
@@ -122,8 +133,10 @@ update_magnetic_dipole = {'args_cuda': Template("""
__global $REAL *Hx,
__global $REAL *Hy,
__global $REAL *Hz
"""),
'func': Template("""
"""
),
"func": Template(
"""
// Updates electric field values for Hertzian dipole sources.
//
// Args:
@@ -149,42 +162,47 @@ update_magnetic_dipole = {'args_cuda': Template("""
// 'x' polarised source
if (polarisation == 0) {
int materialHx = ID[IDX4D_ID(3,x,y,z)];
Hx[IDX3D_FIELDS(x,y,z)] = Hx[IDX3D_FIELDS(x,y,z)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
Hx[IDX3D_FIELDS(x,y,z)] = Hx[IDX3D_FIELDS(x,y,z)] - updatecoeffsH[IDX2D_MAT(materialHx,4)] *
srcwaveforms[IDX2D_SRCWAVES(i,iteration)] * (1 / (dx * dy * dz));
}
// 'y' polarised source
else if (polarisation == 1) {
int materialHy = ID[IDX4D_ID(4,x,y,z)];
Hy[IDX3D_FIELDS(x,y,z)] = Hy[IDX3D_FIELDS(x,y,z)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
Hy[IDX3D_FIELDS(x,y,z)] = Hy[IDX3D_FIELDS(x,y,z)] - updatecoeffsH[IDX2D_MAT(materialHy,4)] *
srcwaveforms[IDX2D_SRCWAVES(i,iteration)] * (1 / (dx * dy * dz));
}
// 'z' polarised source
else if (polarisation == 2) {
int materialHz = ID[IDX4D_ID(5,x,y,z)];
Hz[IDX3D_FIELDS(x,y,z)] = Hz[IDX3D_FIELDS(x,y,z)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
Hz[IDX3D_FIELDS(x,y,z)] = Hz[IDX3D_FIELDS(x,y,z)] - updatecoeffsH[IDX2D_MAT(materialHz,4)] *
srcwaveforms[IDX2D_SRCWAVES(i,iteration)] * (1 / (dx * dy * dz));
}
}
""")
"""
),
}
update_voltage_source = {'args_cuda': Template("""
__global__ void update_voltage_source(int NVOLTSRC,
int iteration,
$REAL dx,
$REAL dy,
$REAL dz,
const int* __restrict__ srcinfo1,
const $REAL* __restrict__ srcinfo2,
const $REAL* __restrict__ srcwaveforms,
const unsigned int* __restrict__ ID,
$REAL *Ex,
$REAL *Ey,
update_voltage_source = {
"args_cuda": Template(
"""
__global__ void update_voltage_source(int NVOLTSRC,
int iteration,
$REAL dx,
$REAL dy,
$REAL dz,
const int* __restrict__ srcinfo1,
const $REAL* __restrict__ srcinfo2,
const $REAL* __restrict__ srcwaveforms,
const unsigned int* __restrict__ ID,
$REAL *Ex,
$REAL *Ey,
$REAL *Ez)
"""),
'args_opencl': Template("""
"""
),
"args_opencl": Template(
"""
int NVOLTSRC,
int iteration,
$REAL dx,
@@ -197,8 +215,10 @@ update_voltage_source = {'args_cuda': Template("""
__global $REAL *Ex,
__global $REAL *Ey,
__global $REAL *Ez
"""),
'func': Template("""
"""
),
"func": Template(
"""
// Updates electric field values for voltage sources.
//
// Args:
@@ -227,7 +247,7 @@ update_voltage_source = {'args_cuda': Template("""
if (polarisation == 0) {
if (resistance != 0) {
int materialEx = ID[IDX4D_ID(0,x,y,z)];
Ex[IDX3D_FIELDS(x,y,z)] = Ex[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
Ex[IDX3D_FIELDS(x,y,z)] = Ex[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEx,4)] *
srcwaveforms[IDX2D_SRCWAVES(i,iteration)] * (1 / (resistance * dy * dz));
}
else {
@@ -239,7 +259,7 @@ update_voltage_source = {'args_cuda': Template("""
else if (polarisation == 1) {
if (resistance != 0) {
int materialEy = ID[IDX4D_ID(1,x,y,z)];
Ey[IDX3D_FIELDS(x,y,z)] = Ey[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
Ey[IDX3D_FIELDS(x,y,z)] = Ey[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEy,4)] *
srcwaveforms[IDX2D_SRCWAVES(i,iteration)] * (1 / (resistance * dx * dz));
}
else {
@@ -251,7 +271,7 @@ update_voltage_source = {'args_cuda': Template("""
else if (polarisation == 2) {
if (resistance != 0) {
int materialEz = ID[IDX4D_ID(2,x,y,z)];
Ez[IDX3D_FIELDS(x,y,z)] = Ez[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
Ez[IDX3D_FIELDS(x,y,z)] = Ez[IDX3D_FIELDS(x,y,z)] - updatecoeffsE[IDX2D_MAT(materialEz,4)] *
srcwaveforms[IDX2D_SRCWAVES(i,iteration)] * (1 / (resistance * dx * dy));
}
else {
@@ -259,5 +279,6 @@ update_voltage_source = {'args_cuda': Template("""
}
}
}
""")
}
"""
),
}

查看文件

@@ -19,19 +19,23 @@
from string import Template
store_outputs = {'args_cuda': Template("""
__global__ void store_outputs(int NRX,
int iteration,
const int* __restrict__ rxcoords,
$REAL *rxs,
const $REAL* __restrict__ Ex,
const $REAL* __restrict__ Ey,
const $REAL* __restrict__ Ez,
const $REAL* __restrict__ Hx,
const $REAL* __restrict__ Hy,
store_outputs = {
"args_cuda": Template(
"""
__global__ void store_outputs(int NRX,
int iteration,
const int* __restrict__ rxcoords,
$REAL *rxs,
const $REAL* __restrict__ Ex,
const $REAL* __restrict__ Ey,
const $REAL* __restrict__ Ez,
const $REAL* __restrict__ Hx,
const $REAL* __restrict__ Hy,
const $REAL* __restrict__ Hz)
"""),
'args_opencl': Template("""
"""
),
"args_opencl": Template(
"""
int NRX,
int iteration,
__global const int* restrict rxcoords,
@@ -42,13 +46,15 @@ store_outputs = {'args_cuda': Template("""
__global const $REAL* restrict Hx,
__global const $REAL* restrict Hy,
__global const $REAL* restrict Hz
"""),
'func': Template("""
"""
),
"func": Template(
"""
// Stores field component values for every receiver in the model.
//
// Args:
// Args:
// NRX: total number of receivers in the model.
// rxs: array to store field components for receivers - rows
// rxs: array to store field components for receivers - rows
// are field components; columns are iterations; pages are receiver.
$CUDA_IDX
@@ -65,5 +71,6 @@ store_outputs = {'args_cuda': Template("""
rxs[IDX3D_RXS(4,iteration,i)] = Hy[IDX3D_FIELDS(x,y,z)];
rxs[IDX3D_RXS(5,iteration,i)] = Hz[IDX3D_FIELDS(x,y,z)];
}
""")
}
"""
),
}

查看文件

@@ -57,14 +57,14 @@ cpdef void {{ item.name_a }}(
{{ item.field_type }}[:, :, ::1] Hy,
{{ item.field_type }}[:, :, ::1] Hz
):
"""Updates the electric field components when dispersive materials
"""Updates the electric field components when dispersive materials
(with multiple poles) are present.
Args:
nx, ny, nz: int for grid size in cells.
nthreads: int for number of threads to use.
maxpoles: int for maximum number of poles.
updatecoeffs, T, ID, E, H: memoryviews to access to update coeffients,
updatecoeffs, T, ID, E, H: memoryviews to access to update coeffients,
temporary, ID and field component arrays.
"""
@@ -82,20 +82,20 @@ cpdef void {{ item.name_a }}(
for pole in range(maxpoles):
{% if 'complex' in item.dispersive_type %}
{% if item.iswin %}
phi = (phi + updatecoeffsdispersive[material, pole * 3].real
phi = (phi + updatecoeffsdispersive[material, pole * 3].real
* Tx[pole, i, j, k].real)
{% else %}
phi = (phi + {{ item.real_part }}(updatecoeffsdispersive[material, pole * 3])
phi = (phi + {{ item.real_part }}(updatecoeffsdispersive[material, pole * 3])
* {{ item.real_part }}(Tx[pole, i, j, k]))
{% endif %}
{% else %}
phi = phi + updatecoeffsdispersive[material, pole * 3] * Tx[pole, i, j, k]
{% endif %}
Tx[pole, i, j, k] = (updatecoeffsdispersive[material, 1 + (pole * 3)]
* Tx[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)]
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]
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
@@ -108,20 +108,20 @@ cpdef void {{ item.name_a }}(
for pole in range(maxpoles):
{% if 'complex' in item.dispersive_type %}
{% if item.iswin %}
phi = (phi + updatecoeffsdispersive[material, pole * 3].real
phi = (phi + updatecoeffsdispersive[material, pole * 3].real
* Ty[pole, i, j, k].real)
{% else %}
phi = (phi + {{ item.real_part }}(updatecoeffsdispersive[material, pole * 3])
phi = (phi + {{ item.real_part }}(updatecoeffsdispersive[material, pole * 3])
* {{ item.real_part }}(Ty[pole, i, j, k]))
{% endif %}
{% else %}
phi = phi + updatecoeffsdispersive[material, pole * 3] * Ty[pole, i, j, k]
{% endif %}
Ty[pole, i, j, k] = (updatecoeffsdispersive[material, 1 + (pole * 3)]
* Ty[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)]
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]
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
@@ -134,20 +134,20 @@ cpdef void {{ item.name_a }}(
for pole in range(maxpoles):
{% if 'complex' in item.dispersive_type %}
{% if item.iswin %}
phi = (phi + updatecoeffsdispersive[material, pole * 3].real
phi = (phi + updatecoeffsdispersive[material, pole * 3].real
* Tz[pole, i, j, k].real)
{% else %}
phi = (phi + {{ item.real_part }}(updatecoeffsdispersive[material, pole * 3])
phi = (phi + {{ item.real_part }}(updatecoeffsdispersive[material, pole * 3])
* {{ item.real_part }}(Tz[pole, i, j, k]))
{% endif %}
{% else %}
phi = phi + updatecoeffsdispersive[material, pole * 3] * Tz[pole, i, j, k]
{% endif %}
Tz[pole, i, j, k] = (updatecoeffsdispersive[material, 1 + (pole * 3)]
* Tz[pole, i, j, k] + updatecoeffsdispersive[material, 2 + (pole * 3)]
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]
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)
{% endfor %}
@@ -172,14 +172,14 @@ cpdef void {{ item.name_b }}(
{{ item.field_type }}[:, :, ::1] Ey,
{{ item.field_type }}[:, :, ::1] Ez
):
"""Updates a temporary dispersive material array when disperisive materials
"""Updates a temporary dispersive material array when disperisive materials
(with multiple poles) are present.
Args:
nx, ny, nz: int for grid size in cells.
nthreads: int for number of threads to use.
maxpoles: int for maximum number of poles.
updatecoeffs, T, ID, E, H: memoryviews to access to update coeffients,
updatecoeffs, T, ID, E, H: memoryviews to access to update coeffients,
temporary, ID and field component arrays.
"""
@@ -193,8 +193,8 @@ cpdef void {{ item.name_b }}(
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)]
Tx[pole, i, j, k] = (Tx[pole, i, j, k]
- updatecoeffsdispersive[material, 2 + (pole * 3)]
* Ex[i, j, k])
# Ey component
@@ -204,8 +204,8 @@ cpdef void {{ item.name_b }}(
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)]
Ty[pole, i, j, k] = (Ty[pole, i, j, k]
- updatecoeffsdispersive[material, 2 + (pole * 3)]
* Ey[i, j, k])
# Ez component
@@ -215,8 +215,8 @@ cpdef void {{ item.name_b }}(
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)]
Tz[pole, i, j, k] = (Tz[pole, i, j, k]
- updatecoeffsdispersive[material, 2 + (pole * 3)]
* Ez[i, j, k])
{% endfor %}
@@ -246,14 +246,14 @@ cpdef void {{ item.name_a_1 }}(
{{ item.field_type }}[:, :, ::1] Hy,
{{ item.field_type }}[:, :, ::1] Hz
):
"""Updates the electric field components when dispersive materials
"""Updates the electric field components when dispersive materials
(with 1 pole) are present.
Args:
nx, ny, nz: int for grid size in cells.
nthreads: int for number of threads to use.
maxpoles: int for maximum number of poles.
updatecoeffs, T, ID, E, H: memoryviews to access to update coeffients,
updatecoeffs, T, ID, E, H: memoryviews to access to update coeffients,
temporary, ID and field component arrays.
"""
@@ -269,19 +269,19 @@ cpdef void {{ item.name_a_1 }}(
material = ID[0, i, j, k]
{% if 'complex' in item.dispersive_type %}
{% if item.iswin %}
phi = (updatecoeffsdispersive[material, 0].real
phi = (updatecoeffsdispersive[material, 0].real
* Tx[0, i, j, k].real)
{% else %}
phi = ({{ item.real_part }}(updatecoeffsdispersive[material, 0])
phi = ({{ item.real_part }}(updatecoeffsdispersive[material, 0])
* {{ item.real_part }}(Tx[0, i, j, k]))
{% endif %}
{% else %}
phi = updatecoeffsdispersive[material, 0] * Tx[0, i, j, k]
{% endif %}
Tx[0, i, j, k] = (updatecoeffsdispersive[material, 1] * 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]
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
@@ -292,19 +292,19 @@ cpdef void {{ item.name_a_1 }}(
material = ID[1, i, j, k]
{% if 'complex' in item.dispersive_type %}
{% if item.iswin %}
phi = (updatecoeffsdispersive[material, 0].real
phi = (updatecoeffsdispersive[material, 0].real
* Ty[0, i, j, k].real)
{% else %}
phi = ({{ item.real_part }}(updatecoeffsdispersive[material, 0])
phi = ({{ item.real_part }}(updatecoeffsdispersive[material, 0])
* {{ item.real_part }}(Ty[0, i, j, k]))
{% endif %}
{% else %}
phi = updatecoeffsdispersive[material, 0] * Ty[0, i, j, k]
{% endif %}
Ty[0, i, j, k] = (updatecoeffsdispersive[material, 1] * 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]
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
@@ -315,19 +315,19 @@ cpdef void {{ item.name_a_1 }}(
material = ID[2, i, j, k]
{% if 'complex' in item.dispersive_type %}
{% if item.iswin %}
phi = (updatecoeffsdispersive[material, 0].real
phi = (updatecoeffsdispersive[material, 0].real
* Tz[0, i, j, k].real)
{% else %}
phi = ({{ item.real_part }}(updatecoeffsdispersive[material, 0])
phi = ({{ item.real_part }}(updatecoeffsdispersive[material, 0])
* {{ item.real_part }}(Tz[0, i, j, k]))
{% endif %}
{% else %}
phi = updatecoeffsdispersive[material, 0] * Tz[0, i, j, k]
{% endif %}
Tz[0, i, j, k] = (updatecoeffsdispersive[material, 1] * 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]
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)
{% endfor %}
@@ -353,14 +353,14 @@ cpdef void {{ item.name_b_1 }}(
{{ item.field_type }}[:, :, ::1] Ey,
{{ item.field_type }}[:, :, ::1] Ez
):
"""Updates a temporary dispersive material array when disperisive materials
"""Updates a temporary dispersive material array when disperisive materials
(with 1 pole) are present.
Args:
nx, ny, nz: int for grid size in cells.
nthreads: int for number of threads to use.
maxpoles: int for maximum number of poles.
updatecoeffs, T, ID, E, H: memoryviews to access to update coeffients,
updatecoeffs, T, ID, E, H: memoryviews to access to update coeffients,
temporary, ID and field component arrays.
"""

查看文件

@@ -42,7 +42,7 @@ cpdef void update_electric(
Args:
nx, ny, nz: ints for grid size in cells.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays
"""
@@ -55,8 +55,8 @@ cpdef void update_electric(
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]) -
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
@@ -65,8 +65,8 @@ cpdef void update_electric(
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]) -
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
@@ -75,8 +75,8 @@ cpdef void update_electric(
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]) -
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
@@ -87,38 +87,38 @@ cpdef void update_electric(
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]) -
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]) -
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]) -
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]) -
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]) -
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]) -
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]))
@@ -141,7 +141,7 @@ cpdef void update_magnetic(
Args:
nx, ny, nz: ints for grid size in cells.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays
"""
@@ -156,8 +156,8 @@ cpdef void update_magnetic(
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]) +
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
@@ -166,8 +166,8 @@ cpdef void update_magnetic(
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]) +
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
@@ -176,8 +176,8 @@ cpdef void update_magnetic(
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]) +
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:
@@ -187,12 +187,12 @@ cpdef void update_magnetic(
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]) +
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]) +
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]) +
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]))

查看文件

@@ -24,13 +24,13 @@ 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,
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
):
"""Generates a fractal surface for a 2D array.
@@ -40,11 +40,11 @@ cpdef void generate_fractal2D(
nthreads: int for number of threads to use
b: int for constant related to fractal dimension.
weighting: memoryview for access to weighting vector.
v1: memoryview for access to positional vector at centre of array,
v1: memoryview for access to positional vector at centre of array,
scaled by weighting.
A: memoryview for access to array containing random numbers
A: memoryview for access to array containing random numbers
(to be convolved with fractal function).
fractalsurface: memoryview for access to array containing fractal
fractalsurface: memoryview for access to array containing fractal
surface data.
"""
@@ -67,14 +67,14 @@ cpdef void generate_fractal2D(
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,
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
):
"""Generates a fractal volume for a 3D array.
@@ -84,11 +84,11 @@ cpdef void generate_fractal3D(
nthreads: int for number of threads to use
b: int for constant related to fractal dimension.
weighting: memoryview for access to weighting vector.
v1: memoryview for access to positional vector at centre of array,
v1: memoryview for access to positional vector at centre of array,
scaled by weighting.
A: memoryview for access to array containing random numbers
A: memoryview for access to array containing random numbers
(to be convolved with fractal function).
fractalsurface: memoryview for access to array containing fractal
fractalsurface: memoryview for access to array containing fractal
volume data.
"""
@@ -107,6 +107,6 @@ cpdef void generate_fractal3D(
rr = ((v2x - v1[0])**2 + (v2y - v1[1])**2 + (v2z - v1[2])**2)**(1/2)
B = rr**b
if B == 0:
B = 0.9
B = 0.9
fractalvolume[i, j, k] = A[i, j, k] / B

查看文件

@@ -21,15 +21,15 @@ cimport numpy as np
cpdef write_lines(
float xs,
float ys,
float zs,
int nx,
int ny,
int nz,
float dx,
float dy,
float dz,
float xs,
float ys,
float zs,
int nx,
int ny,
int nz,
float dx,
float dy,
float dz,
np.uint32_t[:, :, :, :] ID
):
"""Generates arrays with to be written as lines (cell edges) to a VTK file.
@@ -38,7 +38,7 @@ cpdef write_lines(
xs, ys, zs: float for starting coordinates of geometry view in metres.
nx, ny, nz: int for size of the volume in cells.
dx, dy, dz: float for spatial discretisation of geometry view in metres.
ID: memoryview of sampled ID array according to geometry view spatial
ID: memoryview of sampled ID array according to geometry view spatial
discretisation.
Returns:
@@ -108,4 +108,4 @@ cpdef write_lines(
y += ys
z += zs
return x, y, z, lines
return x, y, z, lines

查看文件

@@ -330,7 +330,7 @@ cpdef void build_voxel(
Args:
i, j, k: ints for cell coordinates of voxel.
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
"""
@@ -402,7 +402,7 @@ cpdef void build_triangle(
np.uint32_t[:, :, :, ::1] ID
):
"""
Builds triangles and triangular prisms which sets values in the solid,
Builds triangles and triangular prisms which sets values in the solid,
rigid and ID arrays for a Yee voxel.
Args:
@@ -412,7 +412,7 @@ cpdef void build_triangle(
thickness: float for thickness of the triangular prism.
dx, dy, dz: floats for spatial discretisation.
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
"""
@@ -452,7 +452,7 @@ cpdef void build_triangle(
for i in range(i1, i2):
for j in range(j1, j2):
# Calculate the areas of the 3 triangles defined by the 3 vertices
# Calculate the areas of the 3 triangles defined by the 3 vertices
# of the main triangle and the point under test.
if normal == 'x':
ir = (i + 0.5) * dy
@@ -474,24 +474,24 @@ cpdef void build_triangle(
if s > 0 and t > 0 and (s + t) < 2 * area * sign:
if thicknesscells == 0:
if normal == 'x':
build_face_yz(level, i, j, numIDy, numIDz,
build_face_yz(level, i, j, numIDy, numIDz,
rigidE, rigidH, ID)
elif normal == 'y':
build_face_xz(i, level, j, numIDx, numIDz,
build_face_xz(i, level, j, numIDx, numIDz,
rigidE, rigidH, ID)
elif normal == 'z':
build_face_xy(i, j, level, numIDx, numIDy,
build_face_xy(i, j, level, numIDx, numIDy,
rigidE, rigidH, ID)
else:
for k in range(level, level + thicknesscells):
if normal == 'x':
build_voxel(k, i, j, numID, numIDx, numIDy, numIDz,
build_voxel(k, i, j, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
elif normal == 'y':
build_voxel(i, k, j, numID, numIDx, numIDy, numIDz,
build_voxel(i, k, j, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
elif normal == 'z':
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
@@ -518,11 +518,11 @@ cpdef void build_cylindrical_sector(
np.uint32_t[:, :, :, ::1] ID
):
"""
Builds cylindrical sectors which sets values in the solid, rigid and ID
Builds cylindrical sectors which sets values in the solid, rigid and ID
arrays for a Yee voxel. It defines a sector of cylinder given by the
direction of the axis of the coordinates of the cylinder face centre,
depth coordinates, sector start point, sector angle, and sector radius.
N.B Assumes sector start is always clockwise from sector end,
direction of the axis of the coordinates of the cylinder face centre,
depth coordinates, sector start point, sector angle, and sector radius.
N.B Assumes sector start is always clockwise from sector end,
i.e. sector defined in an anti-clockwise direction.
Args:
@@ -535,7 +535,7 @@ cpdef void build_cylindrical_sector(
thickness: float for thickness of the triangular prism.
dx, dy, dz: floats for spatial discretisation.
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
"""
@@ -544,7 +544,7 @@ cpdef void build_cylindrical_sector(
cdef int x1, x2, y1, y2, z1, z2, thicknesscells
if normal == 'x':
# Angles are defined from zero degrees on the positive y-axis going
# Angles are defined from zero degrees on the positive y-axis going
# towards positive z-axis.
y1 = round_value((ctr1 - radius)/dy)
y2 = round_value((ctr1 + radius)/dy)
@@ -564,18 +564,18 @@ cpdef void build_cylindrical_sector(
for y in range(y1, y2):
for z in range(z1, z2):
if is_inside_sector(y * dy + 0.5 * dy, z * dz + 0.5 * dz, ctr1,
if is_inside_sector(y * dy + 0.5 * dy, z * dz + 0.5 * dz, ctr1,
ctr2, sectorstartangle, sectorangle, radius):
if thicknesscells == 0:
build_face_yz(level, y, z, numIDy, numIDz,
build_face_yz(level, y, z, numIDy, numIDz,
rigidE, rigidH, ID)
else:
for x in range(level, level + thicknesscells):
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz,
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
elif normal == 'y':
# Angles are defined from zero degrees on the positive x-axis going
# Angles are defined from zero degrees on the positive x-axis going
# towards positive z-axis.
x1 = round_value((ctr1 - radius)/dx)
x2 = round_value((ctr1 + radius)/dx)
@@ -595,18 +595,18 @@ cpdef void build_cylindrical_sector(
for x in range(x1, x2):
for z in range(z1, z2):
if is_inside_sector(x * dx + 0.5 * dx, z * dz + 0.5 * dz, ctr1,
if is_inside_sector(x * dx + 0.5 * dx, z * dz + 0.5 * dz, ctr1,
ctr2, sectorstartangle, sectorangle, radius):
if thicknesscells == 0:
build_face_xz(x, level, z, numIDx, numIDz,
build_face_xz(x, level, z, numIDx, numIDz,
rigidE, rigidH, ID)
else:
for y in range(level, level + thicknesscells):
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz,
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
elif normal == 'z':
# Angles are defined from zero degrees on the positive x-axis going
# Angles are defined from zero degrees on the positive x-axis going
# towards positive y-axis.
x1 = round_value((ctr1 - radius)/dx)
x2 = round_value((ctr1 + radius)/dx)
@@ -626,14 +626,14 @@ cpdef void build_cylindrical_sector(
for x in range(x1, x2):
for y in range(y1, y2):
if is_inside_sector(x * dx + 0.5 * dx, y * dy + 0.5 * dy, ctr1,
if is_inside_sector(x * dx + 0.5 * dx, y * dy + 0.5 * dy, ctr1,
ctr2, sectorstartangle, sectorangle, radius):
if thicknesscells == 0:
build_face_xy(x, y, level, numIDx, numIDy,
build_face_xy(x, y, level, numIDx, numIDy,
rigidE, rigidH, ID)
else:
for z in range(level, level + thicknesscells):
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz,
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
@@ -661,7 +661,7 @@ cpdef void build_box(
xs, xf, ys, yf, zs, zf: ints for cell coordinates of entire box.
nthreads: int for number of threads to use
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
"""
@@ -741,23 +741,23 @@ cpdef void build_cylinder(
np.int8_t[:, :, :, ::1] rigidH,
np.uint32_t[:, :, :, ::1] ID
):
"""Builds cylinders which sets values in the solid, rigid and ID arrays for
"""Builds cylinders which sets values in the solid, rigid and ID arrays for
a Yee voxel.
Args:
x1, y1, z1, x2, y2, z2: floats for coordinates of the centres of cylinder
x1, y1, z1, x2, y2, z2: floats for coordinates of the centres of cylinder
faces.
r: float for radius of the cylinder.
dx, dy, dz: floats for spatial discretisation.
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
"""
cdef Py_ssize_t i, j, k
cdef int xs, xf, ys, yf, zs, zf, xc, yc, zc
cdef float f1f2mag, f2f1mag, f1ptmag, f2ptmag, dot1, dot2, factor1, factor2
cdef float f1f2mag, f2f1mag, f1ptmag, f2ptmag, dot1, dot2, factor1, factor2
cdef float theta1, theta2, distance1, distance2
cdef bint build, x_align, y_align, z_align
cdef np.ndarray f1f2, f2f1, f1pt, f2pt
@@ -765,17 +765,17 @@ cpdef void build_cylinder(
# Check if cylinder is aligned with an axis
x_align = y_align = z_align = 0
# x-aligned
if (round_value(y1 / dy) == round_value(y2 / dy) and
if (round_value(y1 / dy) == round_value(y2 / dy) and
round_value(z1 / dz) == round_value(z2 / dz)):
x_align = 1
# y-aligned
elif (round_value(x1 / dx) == round_value(x2 / dx) and
elif (round_value(x1 / dx) == round_value(x2 / dx) and
round_value(z1 / dz) == round_value(z2 / dz)):
y_align = 1
# z-aligned
elif (round_value(x1 / dx) == round_value(x2 / dx) and
elif (round_value(x1 / dx) == round_value(x2 / dx) and
round_value(y1 / dy) == round_value(y2 / dy)):
z_align = 1
@@ -843,7 +843,7 @@ cpdef void build_cylinder(
for k in range(zs, zf):
if np.sqrt((j * dy + 0.5 * dy - y1)**2 + (k * dz + 0.5 * dz - z1)**2) <= r:
for i in range(xs, xf):
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
# y-aligned cylinder
elif y_align:
@@ -851,7 +851,7 @@ cpdef void build_cylinder(
for k in range(zs, zf):
if np.sqrt((i * dx + 0.5 * dx - x1)**2 + (k * dz + 0.5 * dz - z1)**2) <= r:
for j in range(ys, yf):
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
# z-aligned cylinder
elif z_align:
@@ -859,7 +859,7 @@ cpdef void build_cylinder(
for j in range(ys, yf):
if np.sqrt((i * dx + 0.5 * dx - x1)**2 + (j * dy + 0.5 * dy - y1)**2) <= r:
for k in range(zs, zf):
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
# Not aligned with any axis
@@ -878,12 +878,12 @@ cpdef void build_cylinder(
# Build flag - default false, set to True if point is in cylinder
build = 0
# Vector from centre of first cylinder face to test point
f1pt = np.array([i * dx + 0.5 * dx - x1,
j * dy + 0.5 * dy - y1,
f1pt = np.array([i * dx + 0.5 * dx - x1,
j * dy + 0.5 * dy - y1,
k * dz + 0.5 * dz - z1], dtype=np.float32)
# Vector from centre of second cylinder face to test point
f2pt = np.array([i * dx + 0.5 * dx - x2,
j * dy + 0.5 * dy - y2,
f2pt = np.array([i * dx + 0.5 * dx - x2,
j * dy + 0.5 * dy - y2,
k * dz + 0.5 * dz - z2], dtype=np.float32)
# Magnitudes
f1ptmag = np.sqrt((f1pt*f1pt).sum(axis=0))
@@ -908,12 +908,12 @@ cpdef void build_cylinder(
theta2 = 0
distance1 = f1ptmag * np.sin(theta1)
distance2 = f2ptmag * np.sin(theta2)
if ((distance1 <= r or distance2 <= r) and
if ((distance1 <= r or distance2 <= r) and
theta1 <= np.pi/2 and theta2 <= np.pi/2):
build = 1
if build:
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
@@ -939,7 +939,7 @@ cpdef void build_cone(
np.int8_t[:, :, :, ::1] rigidH,
np.uint32_t[:, :, :, ::1] ID
):
"""Builds cones which sets values in the solid, rigid and ID arrays for
"""Builds cones which sets values in the solid, rigid and ID arrays for
a Yee voxel.
Args:
@@ -949,14 +949,14 @@ cpdef void build_cone(
r2: float for radius of the second face of the cone.
dx, dy, dz: floats for spatial discretisation.
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
"""
cdef Py_ssize_t i, j, k
cdef int xs, xf, ys, yf, zs, zf, xc, yc, zc
cdef float f1f2mag, f2f1mag, f1ptmag, f2ptmag, dot1, dot2, factor1, factor2
cdef float f1f2mag, f2f1mag, f1ptmag, f2ptmag, dot1, dot2, factor1, factor2
cdef float theta1, theta2, distance1, distance2, R1, R2
cdef float height, distance_axis_1, distance_axis_2
cdef bint build, x_align, y_align, z_align
@@ -968,17 +968,17 @@ cpdef void build_cone(
# Check if cone is aligned with an axis
x_align = y_align = z_align = 0
# x-aligned
if (round_value(y1 / dy) == round_value(y2 / dy) and
if (round_value(y1 / dy) == round_value(y2 / dy) and
round_value(z1 / dz) == round_value(z2 / dz)):
x_align = 1
# y-aligned
elif (round_value(x1 / dx) == round_value(x2 / dx) and
elif (round_value(x1 / dx) == round_value(x2 / dx) and
round_value(z1 / dz) == round_value(z2 / dz)):
y_align = 1
# z-aligned
elif (round_value(x1 / dx) == round_value(x2 / dx) and
elif (round_value(x1 / dx) == round_value(x2 / dx) and
round_value(y1 / dy) == round_value(y2 / dy)):
z_align = 1
@@ -1046,7 +1046,7 @@ cpdef void build_cone(
for k in range(zs, zf):
for i in range(xs, xf):
if np.sqrt((j * dy + 0.5 * dy - y1)**2 + (k * dz + 0.5 * dz - z1)**2) <= ((i-xs)/(xf-xs))*(r2-r1) + r1:
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
# y-aligned cone
elif y_align:
@@ -1054,7 +1054,7 @@ cpdef void build_cone(
for k in range(zs, zf):
for j in range(ys, yf):
if np.sqrt((i * dx + 0.5 * dx - x1)**2 + (k * dz + 0.5 * dz - z1)**2) <= ((j-ys)/(yf-ys))*(r2-r1) + r1:
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
# z-aligned cone
elif z_align:
@@ -1062,7 +1062,7 @@ cpdef void build_cone(
for j in range(ys, yf):
for k in range(zs, zf):
if np.sqrt((i * dx + 0.5 * dx - x1)**2 + (j * dy + 0.5 * dy - y1)**2) <= ((k-zs)/(zf-zs))*(r2-r1) + r1:
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
# Not aligned with any axis
@@ -1083,12 +1083,12 @@ cpdef void build_cone(
# Build flag - default false, set to True if point is in cone
build = 0
# Vector from centre of first cone face to test point
f1pt = np.array([i * dx + 0.5 * dx - x1,
j * dy + 0.5 * dy - y1,
f1pt = np.array([i * dx + 0.5 * dx - x1,
j * dy + 0.5 * dy - y1,
k * dz + 0.5 * dz - z1], dtype=np.float32)
# Vector from centre of second cone face to test point
f2pt = np.array([i * dx + 0.5 * dx - x2,
j * dy + 0.5 * dy - y2,
f2pt = np.array([i * dx + 0.5 * dx - x2,
j * dy + 0.5 * dy - y2,
k * dz + 0.5 * dz - z2], dtype=np.float32)
# Magnitudes
f1ptmag = np.sqrt((f1pt*f1pt).sum(axis=0))
@@ -1118,12 +1118,12 @@ cpdef void build_cone(
R1 = r1
R2 = r2
if ((distance1 <= (distance_axis_1/height)*(R2 - R1) + R1 or distance2 <= (distance_axis_2/height)*(R1 - R2) + R2) and
if ((distance1 <= (distance_axis_1/height)*(R2 - R1) + R1 or distance2 <= (distance_axis_2/height)*(R1 - R2) + R2) and
theta1 <= np.pi/2 and theta2 <= np.pi/2):
build = 1
if build:
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
@@ -1145,7 +1145,7 @@ cpdef void build_sphere(
np.int8_t[:, :, :, ::1] rigidH,
np.uint32_t[:, :, :, ::1] ID
):
"""Builds spheres which sets values in the solid, rigid and ID arrays for
"""Builds spheres which sets values in the solid, rigid and ID arrays for
a Yee voxel.
Args:
@@ -1153,7 +1153,7 @@ cpdef void build_sphere(
r: float for radius of the sphere.
dx, dy, dz: floats for spatial discretisation.
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
"""
@@ -1186,10 +1186,10 @@ cpdef void build_sphere(
for i in range(xs, xf):
for j in range(ys, yf):
for k in range(zs, zf):
if (np.sqrt((i + 0.5 - xc)**2 * dx**2 +
(j + 0.5 - yc)**2 * dy**2 +
if (np.sqrt((i + 0.5 - xc)**2 * dx**2 +
(j + 0.5 - yc)**2 * dy**2 +
(k + 0.5 - zc)**2 * dz**2) <= r):
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
@@ -1213,7 +1213,7 @@ cpdef void build_ellipsoid(
np.int8_t[:, :, :, ::1] rigidH,
np.uint32_t[:, :, :, ::1] ID
):
"""Builds ellipsoids which sets values in the solid, rigid and ID arrays for
"""Builds ellipsoids which sets values in the solid, rigid and ID arrays for
a Yee voxel.
Args:
@@ -1223,7 +1223,7 @@ cpdef void build_ellipsoid(
zr: float for z-semiaxis of the elliposid.
dx, dy, dz: floats for spatial discretisation.
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
"""
@@ -1256,10 +1256,10 @@ cpdef void build_ellipsoid(
for i in range(xs, xf):
for j in range(ys, yf):
for k in range(zs, zf):
if (((i + 0.5 - xc)**2 * dx**2)/xr**2 +
((j + 0.5 - yc)**2 * dy**2)/yr**2 +
if (((i + 0.5 - xc)**2 * dx**2)/xr**2 +
((j + 0.5 - yc)**2 * dy**2)/yr**2 +
((k + 0.5 - zc)**2 * dz**2)/zr**2 <= 1):
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
@@ -1279,12 +1279,12 @@ cpdef void build_voxels_from_array(
"""Builds Yee voxels by reading integers from an array.
Args:
xs, ys, zs: ints for cell coordinates of position of start of array in
xs, ys, zs: ints for cell coordinates of position of start of array in
domain.
nthreads: int for number of threads to use
numexistmaterials: int for number of existing materials in model prior
numexistmaterials: int for number of existing materials in model prior
to building voxels.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
data: memoryview to access array containing numeric IDs of voxels to create.
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
@@ -1345,7 +1345,7 @@ cpdef void build_voxels_from_array_mask(
xs, ys, zs: ints for cell coordinates of position of start of array in domain.
nthreads: int for number of threads to use
waternumID, grassnumID: ints for numeric ID of water and grass materials.
averaging: bint for whether material property averaging will occur for
averaging: bint for whether material property averaging will occur for
the object.
data: memoryview to access array containing numeric IDs of voxels to create.
mask: memoryview to access to array containing a mask of voxels to create.
@@ -1365,13 +1365,13 @@ cpdef void build_voxels_from_array_mask(
for k in range(zs, zf):
if mask[i - xs, j - ys, k - zs] == 1:
numID = numIDx = numIDy = numIDz = data[i - xs, j - ys, k - zs]
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
elif mask[i - xs, j - ys, k - zs] == 2:
numID = numIDx = numIDy = numIDz = waternumID
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)
elif mask[i - xs, j - ys, k - zs] == 3:
numID = numIDx = numIDy = numIDz = grassnumID
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
averaging, solid, rigidE, rigidH, ID)

查看文件

@@ -31,14 +31,14 @@ cpdef pml_average_er_mr(
float_or_double[::1] ers,
float_or_double[::1] mrs
):
"""Calculates average permittivity and permeability in PML slab (based on
"""Calculates average permittivity and permeability in PML slab (based on
underlying material er and mr from solid array). Used to build PML.
Args:
n1, n2: ints for PML size in cells perpendicular to thickness direction.
nthreads: int for number of threads to use.
solid: memoryviews to access solid array.
ers, mrs: memoryviews to access arrays containing permittivity and
ers, mrs: memoryviews to access arrays containing permittivity and
permeability.
Returns:
@@ -49,7 +49,7 @@ cpdef pml_average_er_mr(
cdef Py_ssize_t m, n
cdef int numID
# Sum and average of relative permittivities and permeabilities in PML slab
cdef float sumer, summr, averageer, averagemr
cdef float sumer, summr, averageer, averagemr
for m in prange(n1, nogil=True, schedule='static', num_threads=nthreads):
for n in range(n2):

查看文件

@@ -52,7 +52,7 @@ cpdef void order1_xminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -79,13 +79,13 @@ cpdef void order1_xminus(
# Ey
materialEy = ID[1, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii - 1, jj, kk]) / dx
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(RA01 * dHz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHz
# Ez
materialEz = ID[2, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii - 1, jj, kk]) / dx
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(RA01 * dHy + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHy
@@ -118,7 +118,7 @@ cpdef void order2_xminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -150,19 +150,19 @@ cpdef void order2_xminus(
# Ey
materialEy = ID[1, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii - 1, jj, kk]) / dx
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(RA01 * dHz + RA1 * RB0 * Phi1[0, i, j, k] +
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(RA01 * dHz + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dHz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHz
# Ez
materialEz = ID[2, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii - 1, jj, kk]) / dx
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(RA01 * dHy + RA1 * RB0 * Phi2[0, i, j, k] +
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(RA01 * dHy + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dHy + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHy
@@ -196,7 +196,7 @@ cpdef void order1_xplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -223,13 +223,13 @@ cpdef void order1_xplus(
# Ey
materialEy = ID[1, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii - 1, jj, kk]) / dx
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(RA01 * dHz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHz
# Ez
materialEz = ID[2, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii - 1, jj, kk]) / dx
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(RA01 * dHy + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHy
@@ -262,7 +262,7 @@ cpdef void order2_xplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -294,19 +294,19 @@ cpdef void order2_xplus(
# Ey
materialEy = ID[1, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii - 1, jj, kk]) / dx
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(RA01 * dHz + RA1 * RB0 * Phi1[0, i, j, k] +
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(RA01 * dHz + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dHz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHz
# Ez
materialEz = ID[2, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii - 1, jj, kk]) / dx
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(RA01 * dHy + RA1 * RB0 * Phi2[0, i, j, k] +
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(RA01 * dHy + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dHy + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHy
@@ -340,7 +340,7 @@ cpdef void order1_yminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -367,13 +367,13 @@ cpdef void order1_yminus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii, jj - 1, kk]) / dy
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(RA01 * dHz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHz
# Ez
materialEz = ID[2, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj - 1, kk]) / dy
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(RA01 * dHx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHx
@@ -406,7 +406,7 @@ cpdef void order2_yminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients, ID
updatecoeffs, ID, E, H: memoryviews to access update coefficients, ID
and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -438,19 +438,19 @@ cpdef void order2_yminus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii, jj - 1, kk]) / dy
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(RA01 * dHz + RA1 * RB0 * Phi1[0, i, j, k] +
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(RA01 * dHz + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dHz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHz
# Ez
materialEz = ID[2, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj - 1, kk]) / dy
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(RA01 * dHx + RA1 * RB0 * Phi2[0, i, j, k] +
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(RA01 * dHx + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dHx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHx
@@ -484,7 +484,7 @@ cpdef void order1_yplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -511,13 +511,13 @@ cpdef void order1_yplus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii, jj - 1, kk]) / dy
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(RA01 * dHz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHz
# Ez
materialEz = ID[2, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj - 1, kk]) / dy
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(RA01 * dHx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHx
@@ -550,7 +550,7 @@ cpdef void order2_yplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -582,19 +582,19 @@ cpdef void order2_yplus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii, jj - 1, kk]) / dy
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(RA01 * dHz + RA1 * RB0 * Phi1[0, i, j, k] +
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(RA01 * dHz + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dHz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHz
# Ez
materialEz = ID[2, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj - 1, kk]) / dy
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(RA01 * dHx + RA1 * RB0 * Phi2[0, i, j, k] +
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(RA01 * dHx + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dHx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHx
@@ -628,7 +628,7 @@ cpdef void order1_zminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -655,13 +655,13 @@ cpdef void order1_zminus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii, jj, kk - 1]) / dz
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(RA01 * dHy + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHy
# Ey
materialEy = ID[1, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj, kk - 1]) / dz
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(RA01 * dHx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHx
@@ -694,7 +694,7 @@ cpdef void order2_zminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -726,19 +726,19 @@ cpdef void order2_zminus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii, jj, kk - 1]) / dz
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(RA01 * dHy + RA1 * RB0 * Phi1[0, i, j, k] +
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(RA01 * dHy + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dHy + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHy
# Ey
materialEy = ID[1, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj, kk - 1]) / dz
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(RA01 * dHx + RA1 * RB0 * Phi2[0, i, j, k] +
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(RA01 * dHx + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dHx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHx
@@ -772,7 +772,7 @@ cpdef void order1_zplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -799,13 +799,13 @@ cpdef void order1_zplus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii, jj, kk - 1]) / dz
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(RA01 * dHy + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHy
# Ey
materialEy = ID[1, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj, kk - 1]) / dz
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(RA01 * dHx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHx
@@ -838,7 +838,7 @@ cpdef void order2_zplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -870,18 +870,18 @@ cpdef void order2_zplus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii, jj, kk - 1]) / dz
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(RA01 * dHy + RA1 * RB0 * Phi1[0, i, j, k] +
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(RA01 * dHy + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dHy + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dHy
# Ey
materialEy = ID[1, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj, kk - 1]) / dz
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(RA01 * dHx + RA1 * RB0 * Phi2[0, i, j, k] +
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(RA01 * dHx + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dHx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dHx

查看文件

@@ -52,7 +52,7 @@ cpdef void order1_xminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -81,16 +81,16 @@ cpdef void order1_xminus(
# Ey
materialEy = ID[1, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii - 1, jj, kk]) / dx
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(IRA1 * dHz - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHz -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHz -
RC0 * Phi1[0, i, j, k])
# Ez
materialEz = ID[2, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii - 1, jj, kk]) / dx
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(IRA1 * dHy - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHy -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHy -
RC0 * Phi2[0, i, j, k])
cpdef void order2_xminus(
@@ -122,7 +122,7 @@ cpdef void order2_xminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -132,7 +132,7 @@ cpdef void order2_xminus(
cdef int nx, ny, nz, materialEy, materialEz
cdef float_or_double dx, dHy, dHz, IRA, IRA1, RB0, RC0, RE0, RF0
cdef float_or_double RB1, RC1, RE1, RF1, Psi1, Psi2
dx = d
nx = xf - xs
ny = yf - ys
@@ -159,14 +159,14 @@ cpdef void order2_xminus(
# Ey
materialEy = ID[1, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii - 1, jj, kk]) / dx
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(IRA1 * dHz - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dHz - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dHz - Psi1)
# Ez
materialEz = ID[2, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii - 1, jj, kk]) / dx
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(IRA1 * dHy - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dHy - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dHy - Psi2)
@@ -201,7 +201,7 @@ cpdef void order1_xplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -230,16 +230,16 @@ cpdef void order1_xplus(
# Ey
materialEy = ID[1, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii - 1, jj, kk]) / dx
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(IRA1 * dHz - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHz -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHz -
RC0 * Phi1[0, i, j, k])
# Ez
materialEz = ID[2, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii - 1, jj, kk]) / dx
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(IRA1 * dHy - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHy -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHy -
RC0 * Phi2[0, i, j, k])
cpdef void order2_xplus(
@@ -271,7 +271,7 @@ cpdef void order2_xplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -307,14 +307,14 @@ cpdef void order2_xplus(
# Ey
materialEy = ID[1, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii - 1, jj, kk]) / dx
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] - updatecoeffsE[materialEy, 4] *
(IRA1 * dHz - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dHz - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dHz - Psi1)
# Ez
materialEz = ID[2, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii - 1, jj, kk]) / dx
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] + updatecoeffsE[materialEz, 4] *
(IRA1 * dHy - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dHy - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dHy - Psi2)
@@ -349,7 +349,7 @@ cpdef void order1_yminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -378,16 +378,16 @@ cpdef void order1_yminus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii, jj - 1, kk]) / dy
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(IRA1 * dHz - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHz -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHz -
RC0 * Phi1[0, i, j, k])
# Ez
materialEz = ID[2, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj - 1, kk]) / dy
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(IRA1 * dHx - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHx -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHx -
RC0 * Phi2[0, i, j, k])
cpdef void order2_yminus(
@@ -419,7 +419,7 @@ cpdef void order2_yminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -455,14 +455,14 @@ cpdef void order2_yminus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii, jj - 1, kk]) / dy
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(IRA1 * dHz - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dHz - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dHz - Psi1)
# Ez
materialEz = ID[2, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj - 1, kk]) / dy
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(IRA1 * dHx - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dHx - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dHx - Psi2)
@@ -497,7 +497,7 @@ cpdef void order1_yplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -526,16 +526,16 @@ cpdef void order1_yplus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii, jj - 1, kk]) / dy
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(IRA1 * dHz - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHz -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHz -
RC0 * Phi1[0, i, j, k])
# Ez
materialEz = ID[2, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj - 1, kk]) / dy
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(IRA1 * dHx - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHx -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHx -
RC0 * Phi2[0, i, j, k])
cpdef void order2_yplus(
@@ -567,7 +567,7 @@ cpdef void order2_yplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -603,14 +603,14 @@ cpdef void order2_yplus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHz = (Hz[ii, jj, kk] - Hz[ii, jj - 1, kk]) / dy
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] + updatecoeffsE[materialEx, 4] *
(IRA1 * dHz - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dHz - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dHz - Psi1)
# Ez
materialEz = ID[2, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj - 1, kk]) / dy
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
Ez[ii, jj, kk] = (Ez[ii, jj, kk] - updatecoeffsE[materialEz, 4] *
(IRA1 * dHx - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dHx - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dHx - Psi2)
@@ -645,7 +645,7 @@ cpdef void order1_zminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -674,16 +674,16 @@ cpdef void order1_zminus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii, jj, kk - 1]) / dz
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(IRA1 * dHy - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHy -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHy -
RC0 * Phi1[0, i, j, k])
# Ey
materialEy = ID[1, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj, kk - 1]) / dz
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(IRA1 * dHx - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHx -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHx -
RC0 * Phi2[0, i, j, k])
cpdef void order2_zminus(
@@ -715,7 +715,7 @@ cpdef void order2_zminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -750,14 +750,14 @@ cpdef void order2_zminus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii, jj, kk - 1]) / dz
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(IRA1 * dHy - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dHy - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dHy - Psi1)
# Ey
materialEy = ID[1, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj, kk - 1]) / dz
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(IRA1 * dHx - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dHx - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dHx - Psi2)
@@ -792,7 +792,7 @@ cpdef void order1_zplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -821,16 +821,16 @@ cpdef void order1_zplus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii, jj, kk - 1]) / dz
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(IRA1 * dHy - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHy -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dHy -
RC0 * Phi1[0, i, j, k])
# Ey
materialEy = ID[1, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj, kk - 1]) / dz
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(IRA1 * dHx - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHx -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dHx -
RC0 * Phi2[0, i, j, k])
cpdef void order2_zplus(
@@ -862,7 +862,7 @@ cpdef void order2_zplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -898,14 +898,14 @@ cpdef void order2_zplus(
# Ex
materialEx = ID[0, ii, jj, kk]
dHy = (Hy[ii, jj, kk] - Hy[ii, jj, kk - 1]) / dz
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
Ex[ii, jj, kk] = (Ex[ii, jj, kk] - updatecoeffsE[materialEx, 4] *
(IRA1 * dHy - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dHy - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dHy - Psi1)
# Ey
materialEy = ID[1, ii, jj, kk]
dHx = (Hx[ii, jj, kk] - Hx[ii, jj, kk - 1]) / dz
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
Ey[ii, jj, kk] = (Ey[ii, jj, kk] + updatecoeffsE[materialEy, 4] *
(IRA1 * dHx - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dHx - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dHx - Psi2)

查看文件

@@ -52,7 +52,7 @@ cpdef void order1_xminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -79,13 +79,13 @@ cpdef void order1_xminus(
# Hy
materialHy = ID[4, ii, jj, kk]
dEz = (Ez[ii + 1, jj, kk] - Ez[ii, jj, kk]) / dx
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(RA01 * dEz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEz
# Hz
materialHz = ID[5, ii, jj, kk]
dEy = (Ey[ii + 1, jj, kk] - Ey[ii, jj, kk]) / dx
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(RA01 * dEy + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEy
@@ -118,7 +118,7 @@ cpdef void order2_xminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -150,19 +150,19 @@ cpdef void order2_xminus(
# Hy
materialHy = ID[4, ii, jj, kk]
dEz = (Ez[ii + 1, jj, kk] - Ez[ii, jj, kk]) / dx
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(RA01 * dEz + RA1 * RB0 * Phi1[0, i, j, k] +
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(RA01 * dEz + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dEz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEz
# Hz
materialHz = ID[5, ii, jj, kk]
dEy = (Ey[ii + 1, jj, kk] - Ey[ii, jj, kk]) / dx
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(RA01 * dEy + RA1 * RB0 * Phi2[0, i, j, k] +
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(RA01 * dEy + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dEy + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEy
@@ -196,7 +196,7 @@ cpdef void order1_xplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -223,13 +223,13 @@ cpdef void order1_xplus(
# Hy
materialHy = ID[4, ii, jj, kk]
dEz = (Ez[ii + 1, jj, kk] - Ez[ii, jj, kk]) / dx
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(RA01 * dEz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEz
# Hz
materialHz = ID[5, ii, jj, kk]
dEy = (Ey[ii + 1, jj, kk] - Ey[ii, jj, kk]) / dx
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(RA01 * dEy + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEy
@@ -262,7 +262,7 @@ cpdef void order2_xplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -294,19 +294,19 @@ cpdef void order2_xplus(
# Hy
materialHy = ID[4, ii, jj, kk]
dEz = (Ez[ii + 1, jj, kk] - Ez[ii, jj, kk]) / dx
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(RA01 * dEz + RA1 * RB0 * Phi1[0, i, j, k] +
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(RA01 * dEz + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dEz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEz
# Hz
materialHz = ID[5, ii, jj, kk]
dEy = (Ey[ii + 1, jj, kk] - Ey[ii, jj, kk]) / dx
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(RA01 * dEy + RA1 * RB0 * Phi2[0, i, j, k] +
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(RA01 * dEy + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dEy + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEy
@@ -340,7 +340,7 @@ cpdef void order1_yminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -367,13 +367,13 @@ cpdef void order1_yminus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEz = (Ez[ii, jj + 1, kk] - Ez[ii, jj, kk]) / dy
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(RA01 * dEz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEz
# Hz
materialHz = ID[5, ii, jj, kk]
dEx = (Ex[ii, jj + 1, kk] - Ex[ii, jj, kk]) / dy
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(RA01 * dEx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEx
@@ -406,7 +406,7 @@ cpdef void order2_yminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -438,19 +438,19 @@ cpdef void order2_yminus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEz = (Ez[ii, jj + 1, kk] - Ez[ii, jj, kk]) / dy
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(RA01 * dEz + RA1 * RB0 * Phi1[0, i, j, k] +
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(RA01 * dEz + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dEz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEz
# Hz
materialHz = ID[5, ii, jj, kk]
dEx = (Ex[ii, jj + 1, kk] - Ex[ii, jj, kk]) / dy
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(RA01 * dEx + RA1 * RB0 * Phi2[0, i, j, k] +
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(RA01 * dEx + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dEx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEx
@@ -484,7 +484,7 @@ cpdef void order1_yplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -511,13 +511,13 @@ cpdef void order1_yplus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEz = (Ez[ii, jj + 1, kk] - Ez[ii, jj, kk]) / dy
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(RA01 * dEz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEz
# Hz
materialHz = ID[5, ii, jj, kk]
dEx = (Ex[ii, jj + 1, kk] - Ex[ii, jj, kk]) / dy
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(RA01 * dEx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEx
@@ -550,7 +550,7 @@ cpdef void order2_yplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -582,19 +582,19 @@ cpdef void order2_yplus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEz = (Ez[ii, jj + 1, kk] - Ez[ii, jj, kk]) / dy
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(RA01 * dEz + RA1 * RB0 * Phi1[0, i, j, k] +
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(RA01 * dEz + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dEz + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEz
# Hz
materialHz = ID[5, ii, jj, kk]
dEx = (Ex[ii, jj + 1, kk] - Ex[ii, jj, kk]) / dy
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(RA01 * dEx + RA1 * RB0 * Phi2[0, i, j, k] +
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(RA01 * dEx + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dEx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEx
@@ -628,7 +628,7 @@ cpdef void order1_zminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -655,13 +655,13 @@ cpdef void order1_zminus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEy = (Ey[ii, jj, kk + 1] - Ey[ii, jj, kk]) / dz
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(RA01 * dEy + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEy
# Hy
materialHy = ID[4, ii, jj, kk]
dEx = (Ex[ii, jj, kk + 1] - Ex[ii, jj, kk]) / dz
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(RA01 * dEx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEx
@@ -694,7 +694,7 @@ cpdef void order2_zminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -726,19 +726,19 @@ cpdef void order2_zminus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEy = (Ey[ii, jj, kk + 1] - Ey[ii, jj, kk]) / dz
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(RA01 * dEy + RA1 * RB0 * Phi1[0, i, j, k] +
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(RA01 * dEy + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dEy + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEy
# Hy
materialHy = ID[4, ii, jj, kk]
dEx = (Ex[ii, jj, kk + 1] - Ex[ii, jj, kk]) / dz
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(RA01 * dEx + RA1 * RB0 * Phi2[0, i, j, k] +
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(RA01 * dEx + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dEx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEx
@@ -772,7 +772,7 @@ cpdef void order1_zplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -799,13 +799,13 @@ cpdef void order1_zplus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEy = (Ey[ii, jj, kk + 1] - Ey[ii, jj, kk]) / dz
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(RA01 * dEy + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEy
# Hy
materialHy = ID[4, ii, jj, kk]
dEx = (Ex[ii, jj, kk + 1] - Ex[ii, jj, kk]) / dz
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(RA01 * dEx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEx
@@ -838,7 +838,7 @@ cpdef void order2_zplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -870,18 +870,18 @@ cpdef void order2_zplus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEy = (Ey[ii, jj, kk + 1] - Ey[ii, jj, kk]) / dz
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(RA01 * dEy + RA1 * RB0 * Phi1[0, i, j, k] +
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(RA01 * dEy + RA1 * RB0 * Phi1[0, i, j, k] +
RB1 * Phi1[1, i, j, k]))
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
Phi1[1, i, j, k] = (RE1 * Phi1[1, i, j, k] - RF1 *
(RA0 * dEy + RB0 * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] - RF0 * dEy
# Hy
materialHy = ID[4, ii, jj, kk]
dEx = (Ex[ii, jj, kk + 1] - Ex[ii, jj, kk]) / dz
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(RA01 * dEx + RA1 * RB0 * Phi2[0, i, j, k] +
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(RA01 * dEx + RA1 * RB0 * Phi2[0, i, j, k] +
RB1 * Phi2[1, i, j, k]))
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
Phi2[1, i, j, k] = (RE1 * Phi2[1, i, j, k] - RF1 *
(RA0 * dEx + RB0 * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] - RF0 * dEx

查看文件

@@ -52,7 +52,7 @@ cpdef void order1_xminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -81,16 +81,16 @@ cpdef void order1_xminus(
# Hy
materialHy = ID[4, ii, jj, kk]
dEz = (Ez[ii + 1, jj, kk] - Ez[ii, jj, kk]) / dx
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(IRA1 * dEz - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEz -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEz -
RC0 * Phi1[0, i, j, k])
# Hz
materialHz = ID[5, ii, jj, kk]
dEy = (Ey[ii + 1, jj, kk] - Ey[ii, jj, kk]) / dx
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(IRA1 * dEy - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEy -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEy -
RC0 * Phi2[0, i, j, k])
cpdef void order2_xminus(
@@ -122,7 +122,7 @@ cpdef void order2_xminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -158,14 +158,14 @@ cpdef void order2_xminus(
# Hy
materialHy = ID[4, ii, jj, kk]
dEz = (Ez[ii + 1, jj, kk] - Ez[ii, jj, kk]) / dx
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(IRA1 * dEz - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dEz - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dEz - Psi1)
# Hz
materialHz = ID[5, ii, jj, kk]
dEy = (Ey[ii + 1, jj, kk] - Ey[ii, jj, kk]) / dx
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(IRA1 * dEy - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dEy - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dEy - Psi2)
@@ -200,7 +200,7 @@ cpdef void order1_xplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -229,16 +229,16 @@ cpdef void order1_xplus(
# Hy
materialHy = ID[4, ii, jj, kk]
dEz = (Ez[ii + 1, jj, kk] - Ez[ii, jj, kk]) / dx
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(IRA1 * dEz - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEz -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEz -
RC0 * Phi1[0, i, j, k])
# Hz
materialHz = ID[5, ii, jj, kk]
dEy = (Ey[ii + 1, jj, kk] - Ey[ii, jj, kk]) / dx
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(IRA1 * dEy - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEy -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEy -
RC0 * Phi2[0, i, j, k])
cpdef void order2_xplus(
@@ -270,7 +270,7 @@ cpdef void order2_xplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -306,14 +306,14 @@ cpdef void order2_xplus(
# Hy
materialHy = ID[4, ii, jj, kk]
dEz = (Ez[ii + 1, jj, kk] - Ez[ii, jj, kk]) / dx
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] + updatecoeffsH[materialHy, 4] *
(IRA1 * dEz - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dEz - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dEz - Psi1)
# Hz
materialHz = ID[5, ii, jj, kk]
dEy = (Ey[ii + 1, jj, kk] - Ey[ii, jj, kk]) / dx
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] - updatecoeffsH[materialHz, 4] *
(IRA1 * dEy - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dEy - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dEy - Psi2)
@@ -348,7 +348,7 @@ cpdef void order1_yminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -377,16 +377,16 @@ cpdef void order1_yminus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEz = (Ez[ii, jj + 1, kk] - Ez[ii, jj, kk]) / dy
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(IRA1 * dEz - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEz -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEz -
RC0 * Phi1[0, i, j, k])
# Hz
materialHz = ID[5, ii, jj, kk]
dEx = (Ex[ii, jj + 1, kk] - Ex[ii, jj, kk]) / dy
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(IRA1 * dEx - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEx -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEx -
RC0 * Phi2[0, i, j, k])
cpdef void order2_yminus(
@@ -418,7 +418,7 @@ cpdef void order2_yminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -454,14 +454,14 @@ cpdef void order2_yminus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEz = (Ez[ii, jj + 1, kk] - Ez[ii, jj, kk]) / dy
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(IRA1 * dEz - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dEz - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dEz - Psi1)
# Hz
materialHz = ID[5, ii, jj, kk]
dEx = (Ex[ii, jj + 1, kk] - Ex[ii, jj, kk]) / dy
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(IRA1 * dEx - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dEx - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dEx - Psi2)
@@ -496,7 +496,7 @@ cpdef void order1_yplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -525,16 +525,16 @@ cpdef void order1_yplus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEz = (Ez[ii, jj + 1, kk] - Ez[ii, jj, kk]) / dy
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(IRA1 * dEz - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEz -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEz -
RC0 * Phi1[0, i, j, k])
# Hz
materialHz = ID[5, ii, jj, kk]
dEx = (Ex[ii, jj + 1, kk] - Ex[ii, jj, kk]) / dy
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(IRA1 * dEx - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEx -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEx -
RC0 * Phi2[0, i, j, k])
cpdef void order2_yplus(
@@ -566,7 +566,7 @@ cpdef void order2_yplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -602,14 +602,14 @@ cpdef void order2_yplus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEz = (Ez[ii, jj + 1, kk] - Ez[ii, jj, kk]) / dy
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] - updatecoeffsH[materialHx, 4] *
(IRA1 * dEz - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dEz - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dEz - Psi1)
# Hz
materialHz = ID[5, ii, jj, kk]
dEx = (Ex[ii, jj + 1, kk] - Ex[ii, jj, kk]) / dy
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
Hz[ii, jj, kk] = (Hz[ii, jj, kk] + updatecoeffsH[materialHz, 4] *
(IRA1 * dEx - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dEx - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dEx - Psi2)
@@ -644,7 +644,7 @@ cpdef void order1_zminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -673,16 +673,16 @@ cpdef void order1_zminus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEy = (Ey[ii, jj, kk + 1] - Ey[ii, jj, kk]) / dz
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(IRA1 * dEy - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEy -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEy -
RC0 * Phi1[0, i, j, k])
# Hy
materialHy = ID[4, ii, jj, kk]
dEx = (Ex[ii, jj, kk + 1] - Ex[ii, jj, kk]) / dz
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(IRA1 * dEx - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEx -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEx -
RC0 * Phi2[0, i, j, k])
cpdef void order2_zminus(
@@ -714,7 +714,7 @@ cpdef void order2_zminus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -750,14 +750,14 @@ cpdef void order2_zminus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEy = (Ey[ii, jj, kk + 1] - Ey[ii, jj, kk]) / dz
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(IRA1 * dEy - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dEy - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dEy - Psi1)
# Hy
materialHy = ID[4, ii, jj, kk]
dEx = (Ex[ii, jj, kk + 1] - Ex[ii, jj, kk]) / dz
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(IRA1 * dEx - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dEx - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dEx - Psi2)
@@ -792,7 +792,7 @@ cpdef void order1_zplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -821,16 +821,16 @@ cpdef void order1_zplus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEy = (Ey[ii, jj, kk + 1] - Ey[ii, jj, kk]) / dz
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(IRA1 * dEy - IRA * Phi1[0, i, j, k]))
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEy -
Phi1[0, i, j, k] = (RE0 * Phi1[0, i, j, k] + RC0 * dEy -
RC0 * Phi1[0, i, j, k])
# Hy
materialHy = ID[4, ii, jj, kk]
dEx = (Ex[ii, jj, kk + 1] - Ex[ii, jj, kk]) / dz
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(IRA1 * dEx - IRA * Phi2[0, i, j, k]))
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEx -
Phi2[0, i, j, k] = (RE0 * Phi2[0, i, j, k] + RC0 * dEx -
RC0 * Phi2[0, i, j, k])
cpdef void order2_zplus(
@@ -862,7 +862,7 @@ cpdef void order2_zplus(
Args:
xs, xf, ys, yf, zs, zf: ints for cell coordinates of PML slab.
nthreads: int for number of threads to use.
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
ID and field component arrays.
Phi, RA, RB, RE, RF: memoryviews to access PML coefficient arrays.
d: float for spatial discretisation, e.g. dx, dy or dz.
@@ -898,14 +898,14 @@ cpdef void order2_zplus(
# Hx
materialHx = ID[3, ii, jj, kk]
dEy = (Ey[ii, jj, kk + 1] - Ey[ii, jj, kk]) / dz
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
Hx[ii, jj, kk] = (Hx[ii, jj, kk] + updatecoeffsH[materialHx, 4] *
(IRA1 * dEy - IRA * Psi1))
Phi1[1, i, j, k] = RE1 * Phi1[1, i, j, k] + RC1 * (dEy - Psi1)
Phi1[0, i, j, k] = RE0 * Phi1[0, i, j, k] + RC0 * (dEy - Psi1)
# Hy
materialHy = ID[4, ii, jj, kk]
dEx = (Ex[ii, jj, kk + 1] - Ex[ii, jj, kk]) / dz
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
Hy[ii, jj, kk] = (Hy[ii, jj, kk] - updatecoeffsH[materialHy, 4] *
(IRA1 * dEx - IRA * Psi2))
Phi2[1, i, j, k] = RE1 * Phi2[1, i, j, k] + RC1 * (dEx - Psi2)
Phi2[0, i, j, k] = RE0 * Phi2[0, i, j, k] + RC0 * (dEx - Psi2)

查看文件

@@ -45,7 +45,7 @@ cpdef void calculate_snapshot_fields(
float_or_double[:, :, ::1] Hysnap,
float_or_double[:, :, ::1] Hzsnap
):
"""Calculates electric and magnetic values at points from averaging values
"""Calculates electric and magnetic values at points from averaging values
in cells.
Args:
@@ -64,30 +64,30 @@ cpdef void calculate_snapshot_fields(
# The electric field component value at a point comes from the
# average of the 4 electric field component values in that cell.
if isEx:
Exsnap[i, j, k] = (Exslice[i, j, k] +
Exsnap[i, j, k] = (Exslice[i, j, k] +
Exslice[i, j + 1, k] +
Exslice[i, j, k + 1] +
Exslice[i, j, k + 1] +
Exslice[i, j + 1, k + 1]) / 4
if isEy:
Eysnap[i, j, k] = (Eyslice[i, j, k] +
Eysnap[i, j, k] = (Eyslice[i, j, k] +
Eyslice[i + 1, j, k] +
Eyslice[i, j, k + 1] +
Eyslice[i, j, k + 1] +
Eyslice[i + 1, j, k + 1]) / 4
if isEz:
Ezsnap[i, j, k] = (Ezslice[i, j, k] +
Ezsnap[i, j, k] = (Ezslice[i, j, k] +
Ezslice[i + 1, j, k] +
Ezslice[i, j + 1, k] +
Ezslice[i, j + 1, k] +
Ezslice[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 neighbouring cell.
if isHx:
Hxsnap[i, j, k] = (Hxslice[i, j, k] +
Hxsnap[i, j, k] = (Hxslice[i, j, k] +
Hxslice[i + 1, j, k]) / 2
if isHy:
Hysnap[i, j, k] = (Hyslice[i, j, k] +
Hysnap[i, j, k] = (Hyslice[i, j, k] +
Hyslice[i, j + 1, k]) / 2
if isHz:
Hzsnap[i, j, k] = (Hzslice[i, j, k] +
Hzsnap[i, j, k] = (Hzslice[i, j, k] +
Hzslice[i, j, k + 1]) / 2

查看文件

@@ -29,17 +29,17 @@ from gprMax.materials import Material
cpdef void create_electric_average(
int i,
int j,
int k,
int numID1,
int numID2,
int numID3,
int numID4,
int componentID,
int i,
int j,
int k,
int numID1,
int numID2,
int numID3,
int numID4,
int componentID,
G
):
"""Creates a new material by averaging the dielectric properties of the
"""Creates a new material by averaging the dielectric properties of the
surrounding cells.
Args:
@@ -50,7 +50,7 @@ cpdef void create_electric_average(
"""
# Make an ID composed of the names of the four materials that will be averaged
requiredID = (G.materials[numID1].ID + '+' + G.materials[numID2].ID + '+' +
requiredID = (G.materials[numID1].ID + '+' + G.materials[numID2].ID + '+' +
G.materials[numID3].ID + '+' + G.materials[numID4].ID)
# Check if this material already exists
@@ -69,13 +69,13 @@ cpdef void create_electric_average(
m = Material(newNumID, requiredID)
m.type = 'dielectric-smoothed'
# Create averaged constituents for material
m.er = np.mean((G.materials[numID1].er, G.materials[numID2].er,
m.er = np.mean((G.materials[numID1].er, G.materials[numID2].er,
G.materials[numID3].er, G.materials[numID4].er), axis=0)
m.se = np.mean((G.materials[numID1].se, G.materials[numID2].se,
m.se = np.mean((G.materials[numID1].se, G.materials[numID2].se,
G.materials[numID3].se, G.materials[numID4].se), axis=0)
m.mr = np.mean((G.materials[numID1].mr, G.materials[numID2].mr,
m.mr = np.mean((G.materials[numID1].mr, G.materials[numID2].mr,
G.materials[numID3].mr, G.materials[numID4].mr), axis=0)
m.sm = np.mean((G.materials[numID1].sm, G.materials[numID2].sm,
m.sm = np.mean((G.materials[numID1].sm, G.materials[numID2].sm,
G.materials[numID3].sm, G.materials[numID4].sm), axis=0)
# Append the new material object to the materials list
@@ -85,15 +85,15 @@ cpdef void create_electric_average(
cpdef void create_magnetic_average(
int i,
int j,
int k,
int numID1,
int numID2,
int componentID,
int i,
int j,
int k,
int numID1,
int numID2,
int componentID,
G
):
"""Creates a new material by averaging the dielectric properties of the
"""Creates a new material by averaging the dielectric properties of the
surrounding cells.
Args:
@@ -133,9 +133,9 @@ cpdef void create_magnetic_average(
cpdef void build_electric_components(
np.uint32_t[:, :, ::1] solid,
np.int8_t[:, :, :, ::1] rigidE,
np.uint32_t[:, :, :, ::1] ID,
np.uint32_t[:, :, ::1] solid,
np.int8_t[:, :, :, ::1] rigidE,
np.uint32_t[:, :, :, ::1] ID,
G
):
"""Builds the electric field components in the ID array.
@@ -172,7 +172,7 @@ cpdef void build_electric_components(
ID[IDEx, i, j, k] = numID1
else:
# Averaging is required
create_electric_average(i, j, k, numID1, numID2,
create_electric_average(i, j, k, numID1, numID2,
numID3, numID4, IDEx, G)
# Ey component
@@ -190,7 +190,7 @@ cpdef void build_electric_components(
ID[IDEy, i, j, k] = numID1
else:
# Averaging is required
create_electric_average(i, j, k, numID1, numID2,
create_electric_average(i, j, k, numID1, numID2,
numID3, numID4, IDEy, G)
# Ez component
@@ -208,7 +208,7 @@ cpdef void build_electric_components(
ID[IDEz, i, j, k] = numID1
else:
# Averaging is required
create_electric_average(i, j, k, numID1, numID2,
create_electric_average(i, j, k, numID1, numID2,
numID3, numID4, IDEz, G)
# Extra loops for Ex component
@@ -229,7 +229,7 @@ cpdef void build_electric_components(
ID[IDEx, i, j, k] = numID1
else:
# Averaging is required
create_electric_average(i, j, k, numID1, numID2,
create_electric_average(i, j, k, numID1, numID2,
numID3, numID4, IDEx, G)
# Extra loops for Ey component
@@ -250,7 +250,7 @@ cpdef void build_electric_components(
ID[IDEy, i, j, k] = numID1
else:
# Averaging is required
create_electric_average(i, j, k, numID1, numID2,
create_electric_average(i, j, k, numID1, numID2,
numID3, numID4, IDEy, G)
# Extra loops for Ez component
@@ -271,14 +271,14 @@ cpdef void build_electric_components(
ID[IDEz, i, j, k] = numID1
else:
# Averaging is required
create_electric_average(i, j, k, numID1, numID2,
create_electric_average(i, j, k, numID1, numID2,
numID3, numID4, IDEz, G)
cpdef void build_magnetic_components(
np.uint32_t[:, :, ::1] solid,
np.int8_t[:, :, :, ::1] rigidH,
np.uint32_t[:, :, :, ::1] ID,
np.uint32_t[:, :, ::1] solid,
np.int8_t[:, :, :, ::1] rigidH,
np.uint32_t[:, :, :, ::1] ID,
G
):
"""Builds the magnetic field components in the ID array.

查看文件

@@ -24,9 +24,9 @@ cimport numpy as np
# is 4D with the 1st dimension holding the 12 electric edge components of a
# cell - Ex1, Ex2, Ex3, Ex4, Ey1, Ey2, Ey3, Ey4, Ez1, Ez2, Ez3, Ez4
cdef bint get_rigid_Ex(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidE
) nogil:
@@ -47,9 +47,9 @@ cdef bint get_rigid_Ex(
cdef bint get_rigid_Ey(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidE
) nogil:
cdef bint result
@@ -69,9 +69,9 @@ cdef bint get_rigid_Ey(
cdef bint get_rigid_Ez(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidE
) nogil:
cdef bint result
@@ -91,9 +91,9 @@ cdef bint get_rigid_Ez(
cdef void set_rigid_Ex(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidE
) nogil:
rigidE[0, i, j, k] = True
@@ -106,9 +106,9 @@ cdef void set_rigid_Ex(
cdef void set_rigid_Ey(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidE
) nogil:
rigidE[4, i, j, k] = True
@@ -121,9 +121,9 @@ cdef void set_rigid_Ey(
cdef void set_rigid_Ez(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidE
) nogil:
rigidE[8, i, j, k] = True
@@ -136,18 +136,18 @@ cdef void set_rigid_Ez(
cdef void set_rigid_E(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidE
) nogil:
rigidE[:, i, j, k] = True
cdef void unset_rigid_E(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidE
) nogil:
rigidE[:, i, j, k] = False
@@ -156,9 +156,9 @@ cdef void unset_rigid_E(
# is 4D with the 1st dimension holding the 6 magnetic edge components - Hx1,
# Hx2, Hy1, Hy2, Hz1, Hz2
cdef bint get_rigid_Hx(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidH
) nogil:
cdef bint result
@@ -172,9 +172,9 @@ cdef bint get_rigid_Hx(
cdef bint get_rigid_Hy(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidH
) nogil:
cdef bint result
@@ -188,9 +188,9 @@ cdef bint get_rigid_Hy(
cdef bint get_rigid_Hz(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidH
) nogil:
cdef bint result
@@ -204,9 +204,9 @@ cdef bint get_rigid_Hz(
cdef void set_rigid_Hx(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidH
) nogil:
rigidH[0, i, j, k] = True
@@ -215,9 +215,9 @@ cdef void set_rigid_Hx(
cdef void set_rigid_Hy(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidH
) nogil:
rigidH[2, i, j, k] = True
@@ -226,9 +226,9 @@ cdef void set_rigid_Hy(
cdef void set_rigid_Hz(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidH
) nogil:
rigidH[4, i, j, k] = True
@@ -237,18 +237,18 @@ cdef void set_rigid_Hz(
cdef void set_rigid_H(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidH
) nogil:
rigidH[:, i, j, k] = True
cdef void unset_rigid_H(
int i,
int j,
int k,
int i,
int j,
int k,
np.int8_t[:, :, :, ::1] rigidH
) nogil:
rigidH[:, i, j, k] = False

查看文件

@@ -38,14 +38,13 @@ def store_outputs(G):
for rx in G.rxs:
for output in rx.outputs:
# Store electric or magnetic field components
if 'I' not in output:
if "I" not in output:
field = locals()[output]
rx.outputs[output][iteration] = field[rx.xcoord, rx.ycoord, rx.zcoord]
# 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]
@@ -65,9 +64,9 @@ def write_hdf5_outputfile(outputfile, G):
# Create output file and write top-level meta data
if G.rxs or sg_rxs:
f = h5py.File(outputfile, 'w')
f.attrs['gprMax'] = __version__
f.attrs['Title'] = G.title
f = h5py.File(outputfile, "w")
f.attrs["gprMax"] = __version__
f.attrs["Title"] = G.title
# Write meta data and data for main grid
if G.rxs:
@@ -76,11 +75,11 @@ def write_hdf5_outputfile(outputfile, G):
# Write meta data and data for any subgrids
if sg_rxs:
for sg in G.subgrids:
grp = f.create_group(f'/subgrids/{sg.name}')
grp = f.create_group(f"/subgrids/{sg.name}")
write_hd5_data(grp, sg, is_subgrid=True)
if G.rxs or sg_rxs:
logger.basic(f'Written output file: {outputfile.name}')
logger.basic(f"Written output file: {outputfile.name}")
def write_hd5_data(basegrp, G, is_subgrid=False):
@@ -93,55 +92,55 @@ def write_hd5_data(basegrp, G, is_subgrid=False):
"""
# Write meta data for grid
basegrp.attrs['Iterations'] = G.iterations
basegrp.attrs['nx_ny_nz'] = (G.nx, G.ny, G.nz)
basegrp.attrs['dx_dy_dz'] = (G.dx, G.dy, G.dz)
basegrp.attrs['dt'] = G.dt
basegrp.attrs["Iterations"] = G.iterations
basegrp.attrs["nx_ny_nz"] = (G.nx, G.ny, G.nz)
basegrp.attrs["dx_dy_dz"] = (G.dx, G.dy, G.dz)
basegrp.attrs["dt"] = G.dt
nsrc = len(G.voltagesources + G.hertziandipoles + G.magneticdipoles + G.transmissionlines)
basegrp.attrs['nsrc'] = nsrc
basegrp.attrs['nrx'] = len(G.rxs)
basegrp.attrs['srcsteps'] = G.srcsteps
basegrp.attrs['rxsteps'] = G.rxsteps
basegrp.attrs["nsrc"] = nsrc
basegrp.attrs["nrx"] = len(G.rxs)
basegrp.attrs["srcsteps"] = G.srcsteps
basegrp.attrs["rxsteps"] = G.rxsteps
if is_subgrid:
# Write additional meta data about subgrid
basegrp.attrs['is_os_sep'] = G.is_os_sep
basegrp.attrs['pml_separation'] = G.pml_separation
basegrp.attrs['subgrid_pml_thickness'] = G.pml['thickness']['x0']
basegrp.attrs['filter'] = G.filter
basegrp.attrs['ratio'] = G.ratio
basegrp.attrs['interpolation'] = G.interpolation
basegrp.attrs["is_os_sep"] = G.is_os_sep
basegrp.attrs["pml_separation"] = G.pml_separation
basegrp.attrs["subgrid_pml_thickness"] = G.pml["thickness"]["x0"]
basegrp.attrs["filter"] = G.filter
basegrp.attrs["ratio"] = G.ratio
basegrp.attrs["interpolation"] = G.interpolation
# Create group for sources (except transmission lines); add type and positional data attributes
srclist = G.voltagesources + G.hertziandipoles + G.magneticdipoles
for srcindex, src in enumerate(srclist):
grp = basegrp.create_group(f'srcs/src{str(srcindex + 1)}')
grp.attrs['Type'] = type(src).__name__
grp.attrs['Position'] = (src.xcoord * G.dx, src.ycoord * G.dy, src.zcoord * G.dz)
grp = basegrp.create_group(f"srcs/src{str(srcindex + 1)}")
grp.attrs["Type"] = type(src).__name__
grp.attrs["Position"] = (src.xcoord * G.dx, src.ycoord * G.dy, src.zcoord * G.dz)
# Create group for transmission lines; add positional data, line resistance and
# line discretisation attributes; write arrays for line voltages and currents
for tlindex, tl in enumerate(G.transmissionlines):
grp = basegrp.create_group('tls/tl' + str(tlindex + 1))
grp.attrs['Position'] = (tl.xcoord * G.dx, tl.ycoord * G.dy, tl.zcoord * G.dz)
grp.attrs['Resistance'] = tl.resistance
grp.attrs['dl'] = tl.dl
grp = basegrp.create_group("tls/tl" + str(tlindex + 1))
grp.attrs["Position"] = (tl.xcoord * G.dx, tl.ycoord * G.dy, tl.zcoord * G.dz)
grp.attrs["Resistance"] = tl.resistance
grp.attrs["dl"] = tl.dl
# Save incident voltage and current
grp['Vinc'] = tl.Vinc
grp['Iinc'] = tl.Iinc
grp["Vinc"] = tl.Vinc
grp["Iinc"] = tl.Iinc
# Save total voltage and current
basegrp['tls/tl' + str(tlindex + 1) + '/Vtotal'] = tl.Vtotal
basegrp['tls/tl' + str(tlindex + 1) + '/Itotal'] = tl.Itotal
basegrp["tls/tl" + str(tlindex + 1) + "/Vtotal"] = tl.Vtotal
basegrp["tls/tl" + str(tlindex + 1) + "/Itotal"] = tl.Itotal
# Create group, add positional data and write field component arrays for receivers
for rxindex, rx in enumerate(G.rxs):
grp = basegrp.create_group('rxs/rx' + str(rxindex + 1))
grp = basegrp.create_group("rxs/rx" + str(rxindex + 1))
if rx.ID:
grp.attrs['Name'] = rx.ID
grp.attrs['Position'] = (rx.xcoord * G.dx, rx.ycoord * G.dy, rx.zcoord * G.dz)
grp.attrs["Name"] = rx.ID
grp.attrs["Position"] = (rx.xcoord * G.dx, rx.ycoord * G.dy, rx.zcoord * G.dz)
for output in rx.outputs:
basegrp['rxs/rx' + str(rxindex + 1) + '/' + output] = rx.outputs[output]
basegrp["rxs/rx" + str(rxindex + 1) + "/" + output] = rx.outputs[output]
def Ix(x, y, z, Hx, Hy, Hz, G):

查看文件

@@ -24,19 +24,19 @@ import gprMax.config as config
from .cython.fractals_generate import generate_fractal2D, generate_fractal3D
from .utilities.utilities import round_value
np.seterr(divide='raise')
np.seterr(divide="raise")
class FractalSurface:
"""Fractal surfaces."""
surfaceIDs = ['xminus', 'xplus', 'yminus', 'yplus', 'zminus', 'zplus']
surfaceIDs = ["xminus", "xplus", "yminus", "yplus", "zminus", "zplus"]
def __init__(self, xs, xf, ys, yf, zs, zf, dimension):
"""
Args:
xs, xf, ys, yf, zs, zf: floats for the extent of the fractal surface
(one pair of coordinates must be equal
(one pair of coordinates must be equal
to correctly define a surface).
dimension: float for the fractal dimension that controls the fractal
distribution.
@@ -83,8 +83,7 @@ class FractalSurface:
self.fractalsurface = np.zeros(surfacedims, dtype=self.dtype)
# 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
rng = np.random.default_rng(seed=self.seed)
@@ -96,8 +95,16 @@ class FractalSurface:
A = fftpack.fftshift(A)
# Generate fractal
generate_fractal2D(surfacedims[0], surfacedims[1], config.get_model_config().ompthreads,
self.b, self.weighting, v1, A, self.fractalsurface)
generate_fractal2D(
surfacedims[0],
surfacedims[1],
config.get_model_config().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)
# Set DC component of FFT to zero
@@ -105,16 +112,18 @@ class FractalSurface:
# Take the real part (numerical errors can give rise to an imaginary part)
# of the IFFT, and convert type to floattype. N.B calculation of fractals
# must always be carried out at double precision, i.e. float64, complex128
self.fractalsurface = np.real(fftpack.ifftn(self.fractalsurface)).astype(config.sim_config.dtypes['float_or_double'],
copy=False)
self.fractalsurface = np.real(fftpack.ifftn(self.fractalsurface)).astype(
config.sim_config.dtypes["float_or_double"], copy=False
)
# Scale the fractal volume according to requested range
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:
@@ -177,8 +186,9 @@ class FractalVolume:
self.fractalvolume = np.zeros((self.nx, self.ny, self.nz), dtype=self.dtype)
# 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
rng = np.random.default_rng(seed=self.seed)
@@ -190,18 +200,28 @@ class FractalVolume:
A = fftpack.fftshift(A)
# Generate fractal
generate_fractal3D(self.nx, self.ny, self.nz, config.get_model_config().ompthreads,
self.b, self.weighting, v1, A, self.fractalvolume)
generate_fractal3D(
self.nx,
self.ny,
self.nz,
config.get_model_config().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)
# Set DC component of FFT to zero
self.fractalvolume[0, 0, 0] = 0
# Take the real part (numerical errors can give rise to an imaginary part)
# Take the real part (numerical errors can give rise to an imaginary part)
# of the IFFT, and convert type to floattype. N.B calculation of fractals
# must always be carried out at double precision, i.e. float64, complex128
self.fractalvolume = np.real(fftpack.ifftn(self.fractalvolume)).astype(config.sim_config.dtypes['float_or_double'],
copy=False)
self.fractalvolume = np.real(fftpack.ifftn(self.fractalvolume)).astype(
config.sim_config.dtypes["float_or_double"], copy=False
)
# Bin fractal values
bins = np.linspace(np.amin(self.fractalvolume), np.amax(self.fractalvolume), self.nbins)
@@ -211,8 +231,8 @@ class FractalVolume:
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.
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)
@@ -235,8 +255,7 @@ class Grass:
"""
self.numblades = numblades
self.geometryparams = np.zeros((self.numblades, 6),
dtype=config.sim_config.dtypes['float_or_double'])
self.geometryparams = np.zeros((self.numblades, 6), dtype=config.sim_config.dtypes["float_or_double"])
self.seed = None
# Randomly defined parameters that will be used to calculate geometry
@@ -264,10 +283,16 @@ class Grass:
x, y: floats for the 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)

查看文件

@@ -32,37 +32,39 @@ import gprMax.config as config
from ._version import __version__
from .cython.geometry_outputs import write_lines
from .subgrids.grid import SubGridBaseGrid
from .utilities.utilities import (get_terminal_width,
numeric_list_to_float_list,
numeric_list_to_int_list)
from .utilities.utilities import get_terminal_width, numeric_list_to_float_list, numeric_list_to_int_list
logger = logging.getLogger(__name__)
def save_geometry_views(gvs):
"""Creates and saves geometryviews.
Args:
gvs: list of all GeometryViews.
"""
logger.info('')
logger.info("")
for i, gv in enumerate(gvs):
gv.set_filename()
vtk_data = gv.prep_vtk()
pbar = tqdm(total=gv.nbytes, unit='byte', unit_scale=True,
desc=f'Writing geometry view file {i + 1}/{len(gvs)}, '
f'{gv.filename.name}{gv.vtkfiletype.ext}',
ncols=get_terminal_width() - 1, file=sys.stdout,
disable=not config.sim_config.general['progressbars'])
pbar = tqdm(
total=gv.nbytes,
unit="byte",
unit_scale=True,
desc=f"Writing geometry view file {i + 1}/{len(gvs)}, " f"{gv.filename.name}{gv.vtkfiletype.ext}",
ncols=get_terminal_width() - 1,
file=sys.stdout,
disable=not config.sim_config.general["progressbars"],
)
gv.write_vtk(vtk_data)
pbar.update(gv.nbytes)
pbar.close()
logger.info('')
class GeometryView():
logger.info("")
class GeometryView:
"""Base class for Geometry Views."""
def __init__(self, xs, ys, zs, xf, yf, zf, dx, dy, dz, filename, grid):
@@ -93,10 +95,8 @@ class GeometryView():
def set_filename(self):
"""Constructs filename from user-supplied name and model run number."""
parts = config.get_model_config().output_file_path.parts
self.filename = Path(*parts[:-1],
self.filename +
config.get_model_config().appendmodelnumber)
self.filename = Path(*parts[:-1], self.filename + config.get_model_config().appendmodelnumber)
class GeometryViewLines(GeometryView):
"""Unstructured grid (.vtu) for a per-cell-edge geometry view."""
@@ -104,40 +104,47 @@ class GeometryViewLines(GeometryView):
def __init__(self, *args):
super().__init__(*args)
self.vtkfiletype = VtkUnstructuredGrid
def prep_vtk(self):
"""Prepares data for writing to VTK file.
Returns:
vtk_data: dict of coordinates, data, and comments for VTK file.
"""
# Sample ID array according to geometry view spatial discretisation
# Sample ID array according to geometry view spatial discretisation
# Only create a new array if subsampling is required
if (self.grid.ID.shape != (self.xf, self.yf, self.zf) or
(self.dx, self.dy, self.dz) != (1, 1, 1) or
(self.xs, self.ys, self.zs) != (0, 0, 0)):
if (
self.grid.ID.shape != (self.xf, self.yf, self.zf)
or (self.dx, self.dy, self.dz) != (1, 1, 1)
or (self.xs, self.ys, self.zs) != (0, 0, 0)
):
# Require contiguous for evtk library
ID = np.ascontiguousarray(self.grid.ID[:, self.xs:self.xf:self.dx,
self.ys:self.yf:self.dy,
self.zs:self.zf:self.dz])
ID = np.ascontiguousarray(
self.grid.ID[:, self.xs : self.xf : self.dx, self.ys : self.yf : self.dy, self.zs : self.zf : self.dz]
)
else:
# This array is contiguous by design
ID = self.grid.ID
x, y, z, lines = write_lines((self.xs * self.grid.dx),
(self.ys * self.grid.dy),
(self.zs * self.grid.dz),
self.nx, self.ny, self.nz,
(self.dx * self.grid.dx),
(self.dy * self.grid.dy),
(self.dz * self.grid.dz), ID)
x, y, z, lines = write_lines(
(self.xs * self.grid.dx),
(self.ys * self.grid.dy),
(self.zs * self.grid.dz),
self.nx,
self.ny,
self.nz,
(self.dx * self.grid.dx),
(self.dy * self.grid.dy),
(self.dz * self.grid.dz),
ID,
)
# Add offset to subgrid geometry to correctly locate within main grid
if isinstance(self.grid, SubGridBaseGrid):
x += (self.grid.i0 * self.grid.dx * self.grid.ratio)
y += (self.grid.j0 * self.grid.dy * self.grid.ratio)
z += (self.grid.k0 * self.grid.dz * self.grid.ratio)
x += self.grid.i0 * self.grid.dx * self.grid.ratio
y += self.grid.j0 * self.grid.dy * self.grid.ratio
z += self.grid.k0 * self.grid.dz * self.grid.ratio
# Write information about any PMLs, sources, receivers
comments = Comments(self.grid, self)
@@ -147,28 +154,31 @@ class GeometryViewLines(GeometryView):
comments = json.dumps(info)
# Number of bytes of data to be written to file
offsets_size = np.arange(start = 2, step = 2, stop = len(x) + 1,
dtype = 'int32').nbytes
connect_size = len(x) * np.dtype('int32').itemsize
cell_type_size = len(x) * np.dtype('uint8').itemsize
self.nbytes = (x.nbytes + y.nbytes + z.nbytes + lines.nbytes + offsets_size
+ connect_size + cell_type_size)
vtk_data = {'x': x, 'y': y, 'z': z, 'data': lines, 'comments': comments}
offsets_size = np.arange(start=2, step=2, stop=len(x) + 1, dtype="int32").nbytes
connect_size = len(x) * np.dtype("int32").itemsize
cell_type_size = len(x) * np.dtype("uint8").itemsize
self.nbytes = x.nbytes + y.nbytes + z.nbytes + lines.nbytes + offsets_size + connect_size + cell_type_size
vtk_data = {"x": x, "y": y, "z": z, "data": lines, "comments": comments}
return vtk_data
def write_vtk(self, vtk_data):
"""Writes geometry information to a VTK file.
Args:
vtk_data: dict of coordinates, data, and comments for VTK file.
"""
# Write the VTK file .vtu
linesToVTK(str(self.filename), vtk_data['x'], vtk_data['y'],
vtk_data['z'], cellData={"Material": vtk_data['data']},
comments=[vtk_data['comments']])
# Write the VTK file .vtu
linesToVTK(
str(self.filename),
vtk_data["x"],
vtk_data["y"],
vtk_data["z"],
cellData={"Material": vtk_data["data"]},
comments=[vtk_data["comments"]],
)
class GeometryViewVoxels(GeometryView):
@@ -177,23 +187,25 @@ class GeometryViewVoxels(GeometryView):
def __init__(self, *args):
super().__init__(*args)
self.vtkfiletype = VtkImageData
def prep_vtk(self):
"""Prepares data for writing to VTK file.
Returns:
vtk_data: dict of data and comments for VTK file.
"""
# Sample solid array according to geometry view spatial discretisation
# Only create a new array if subsampling is required
if (self.grid.solid.shape != (self.xf, self.yf, self.zf) or
(self.dx, self.dy, self.dz) != (1, 1, 1) or
(self.xs, self.ys, self.zs) != (0, 0, 0)):
if (
self.grid.solid.shape != (self.xf, self.yf, self.zf)
or (self.dx, self.dy, self.dz) != (1, 1, 1)
or (self.xs, self.ys, self.zs) != (0, 0, 0)
):
# Require contiguous for evtk library
solid = np.ascontiguousarray(self.grid.solid[self.xs:self.xf:self.dx,
self.ys:self.yf:self.dy,
self.zs:self.zf:self.dz])
solid = np.ascontiguousarray(
self.grid.solid[self.xs : self.xf : self.dx, self.ys : self.yf : self.dy, self.zs : self.zf : self.dz]
)
else:
# This array is contiguous by design
solid = self.grid.solid
@@ -205,39 +217,39 @@ class GeometryViewVoxels(GeometryView):
self.nbytes = solid.nbytes
vtk_data = {'data': solid, 'comments': comments}
vtk_data = {"data": solid, "comments": comments}
return vtk_data
def write_vtk(self, vtk_data):
"""Writes geometry information to a VTK file.
Args:
vtk_data: dict of data and comments for VTK file.
"""
if isinstance(self.grid, SubGridBaseGrid):
origin = ((self.grid.i0 * self.grid.dx * self.grid.ratio),
(self.grid.j0 * self.grid.dy * self.grid.ratio),
(self.grid.k0 * self.grid.dz * self.grid.ratio))
origin = (
(self.grid.i0 * self.grid.dx * self.grid.ratio),
(self.grid.j0 * self.grid.dy * self.grid.ratio),
(self.grid.k0 * self.grid.dz * self.grid.ratio),
)
else:
origin = ((self.xs * self.grid.dx),
(self.ys * self.grid.dy),
(self.zs * self.grid.dz))
origin = ((self.xs * self.grid.dx), (self.ys * self.grid.dy), (self.zs * self.grid.dz))
# Write the VTK file .vti
imageToVTK(str(self.filename),
origin=origin,
spacing=((self.dx * self.grid.dx),
(self.dy * self.grid.dy),
(self.dz * self.grid.dz)),
cellData={"Material": vtk_data['data']},
comments=[vtk_data['comments']])
imageToVTK(
str(self.filename),
origin=origin,
spacing=((self.dx * self.grid.dx), (self.dy * self.grid.dy), (self.dz * self.grid.dz)),
cellData={"Material": vtk_data["data"]},
comments=[vtk_data["comments"]],
)
class Comments():
class Comments:
"""Comments can be strings included in the header of XML VTK file, and are
used to hold extra (gprMax) information about the VTK data.
used to hold extra (gprMax) information about the VTK data.
"""
def __init__(self, grid, gv):
@@ -248,49 +260,54 @@ class Comments():
def get_gprmax_info(self):
"""Returns gprMax specific information relating material, source,
and receiver names to numeric identifiers.
and receiver names to numeric identifiers.
"""
# Comments for Paraview macro
comments = {'gprMax_version': __version__,
'dx_dy_dz': self.dx_dy_dz_comment(),
'nx_ny_nz': self.nx_ny_nz_comment(),
'Materials': self.materials_comment()} # Write the name and numeric ID for each material
comments = {
"gprMax_version": __version__,
"dx_dy_dz": self.dx_dy_dz_comment(),
"nx_ny_nz": self.nx_ny_nz_comment(),
"Materials": self.materials_comment(),
} # Write the name and numeric ID for each material
# Write information on PMLs, sources, and receivers
if not self.materials_only:
# Information on PML thickness
if self.grid.pmls['slabs']:
comments['PMLthickness'] = self.pml_gv_comment()
srcs = (self.grid.hertziandipoles + self.grid.magneticdipoles +
self.grid.voltagesources + self.grid.transmissionlines)
if self.grid.pmls["slabs"]:
comments["PMLthickness"] = self.pml_gv_comment()
srcs = (
self.grid.hertziandipoles
+ self.grid.magneticdipoles
+ self.grid.voltagesources
+ self.grid.transmissionlines
)
if srcs:
comments['Sources'] = self.srcs_rx_gv_comment(srcs)
comments["Sources"] = self.srcs_rx_gv_comment(srcs)
if self.grid.rxs:
comments['Receivers'] = self.srcs_rx_gv_comment(self.grid.rxs)
comments["Receivers"] = self.srcs_rx_gv_comment(self.grid.rxs)
return comments
def pml_gv_comment(self):
grid = self.grid
# Only render PMLs if they are in the geometry view
pmlstorender = dict.fromkeys(grid.pmls['thickness'], 0)
pmlstorender = dict.fromkeys(grid.pmls["thickness"], 0)
# Casting to int required as json does not handle numpy types
if grid.pmls['thickness']['x0'] - self.gv.xs > 0:
pmlstorender['x0'] = int(grid.pmls['thickness']['x0'] - self.gv.xs)
if grid.pmls['thickness']['y0'] - self.gv.ys > 0:
pmlstorender['y0'] = int(grid.pmls['thickness']['y0'] - self.gv.ys)
if grid.pmls['thickness']['z0'] - self.gv.zs > 0:
pmlstorender['z0'] = int(grid.pmls['thickness']['z0'] - self.gv.zs)
if self.gv.xf > grid.nx - grid.pmls['thickness']['xmax']:
pmlstorender['xmax'] = int(self.gv.xf - (grid.nx - grid.pmls['thickness']['xmax']))
if self.gv.yf > grid.ny - grid.pmls['thickness']['ymax']:
pmlstorender['ymax'] = int(self.gv.yf - (grid.ny - grid.pmls['thickness']['ymax']))
if self.gv.zf > grid.nz - grid.pmls['thickness']['zmax']:
pmlstorender['zmax'] = int(self.gv.zf - (grid.nz - grid.pmls['thickness']['zmax']))
if grid.pmls["thickness"]["x0"] - self.gv.xs > 0:
pmlstorender["x0"] = int(grid.pmls["thickness"]["x0"] - self.gv.xs)
if grid.pmls["thickness"]["y0"] - self.gv.ys > 0:
pmlstorender["y0"] = int(grid.pmls["thickness"]["y0"] - self.gv.ys)
if grid.pmls["thickness"]["z0"] - self.gv.zs > 0:
pmlstorender["z0"] = int(grid.pmls["thickness"]["z0"] - self.gv.zs)
if self.gv.xf > grid.nx - grid.pmls["thickness"]["xmax"]:
pmlstorender["xmax"] = int(self.gv.xf - (grid.nx - grid.pmls["thickness"]["xmax"]))
if self.gv.yf > grid.ny - grid.pmls["thickness"]["ymax"]:
pmlstorender["ymax"] = int(self.gv.yf - (grid.ny - grid.pmls["thickness"]["ymax"]))
if self.gv.zf > grid.nz - grid.pmls["thickness"]["zmax"]:
pmlstorender["zmax"] = int(self.gv.zf - (grid.nz - grid.pmls["thickness"]["zmax"]))
return list(pmlstorender.values())
@@ -298,13 +315,10 @@ class Comments():
"""Used to name sources and/or receivers."""
sc = []
for src in srcs:
p = (src.xcoord * self.grid.dx,
src.ycoord * self.grid.dy,
src.zcoord * self.grid.dz)
p = (src.xcoord * self.grid.dx, src.ycoord * self.grid.dy, src.zcoord * self.grid.dz)
p = numeric_list_to_float_list(p)
s = {'name': src.ID,
'position': p}
s = {"name": src.ID, "position": p}
sc.append(s)
return sc
@@ -317,7 +331,7 @@ class Comments():
def materials_comment(self):
if not self.averaged_materials:
return [m.ID for m in self.grid.materials if m.type != 'dielectric-smoothed']
return [m.ID for m in self.grid.materials if m.type != "dielectric-smoothed"]
else:
return [m.ID for m in self.grid.materials]
@@ -344,25 +358,16 @@ class GeometryObjects:
self.basefilename = basefilename
# Set filenames
parts = config.sim_config.input_file_path.with_suffix('').parts
parts = config.sim_config.input_file_path.with_suffix("").parts
self.filename_hdf5 = Path(*parts[:-1], self.basefilename)
self.filename_hdf5 = self.filename_hdf5.with_suffix('.h5')
self.filename_materials = Path(*parts[:-1], f'{self.basefilename}_materials')
self.filename_materials = self.filename_materials.with_suffix('.txt')
self.filename_hdf5 = self.filename_hdf5.with_suffix(".h5")
self.filename_materials = Path(*parts[:-1], f"{self.basefilename}_materials")
self.filename_materials = self.filename_materials.with_suffix(".txt")
# Sizes of arrays to write necessary to update progress bar
self.solidsize = ((self.nx + 1) *
(self.ny + 1) *
(self.nz + 1) *
np.dtype(np.uint32).itemsize)
self.rigidsize = (18 * (self.nx + 1) *
(self.ny + 1) *
(self.nz + 1) *
np.dtype(np.int8).itemsize)
self.IDsize = (6 * (self.nx + 1) *
(self.ny + 1) *
(self.nz + 1) *
np.dtype(np.uint32).itemsize)
self.solidsize = (self.nx + 1) * (self.ny + 1) * (self.nz + 1) * np.dtype(np.uint32).itemsize
self.rigidsize = 18 * (self.nx + 1) * (self.ny + 1) * (self.nz + 1) * np.dtype(np.int8).itemsize
self.IDsize = 6 * (self.nx + 1) * (self.ny + 1) * (self.nz + 1) * np.dtype(np.uint32).itemsize
self.datawritesize = self.solidsize + self.rigidsize + self.IDsize
def write_hdf5(self, G, pbar):
@@ -373,55 +378,50 @@ class GeometryObjects:
pbar: Progress bar class instance.
"""
with h5py.File(self.filename_hdf5, 'w') as fdata:
fdata.attrs['gprMax'] = __version__
fdata.attrs['Title'] = G.title
fdata.attrs['dx_dy_dz'] = (G.dx, G.dy, G.dz)
with h5py.File(self.filename_hdf5, "w") as fdata:
fdata.attrs["gprMax"] = __version__
fdata.attrs["Title"] = G.title
fdata.attrs["dx_dy_dz"] = (G.dx, G.dy, G.dz)
# Get minimum and maximum integers of materials in geometry objects volume
minmat = np.amin(G.ID[:, self.xs:self.xf + 1,
self.ys:self.yf + 1, self.zs:self.zf + 1])
maxmat = np.amax(G.ID[:, self.xs:self.xf + 1,
self.ys:self.yf + 1, self.zs:self.zf + 1])
fdata['/data'] = G.solid[self.xs:self.xf + 1, self.ys:self.yf +
1, self.zs:self.zf + 1].astype('int16') - minmat
minmat = np.amin(G.ID[:, self.xs : self.xf + 1, self.ys : self.yf + 1, self.zs : self.zf + 1])
maxmat = np.amax(G.ID[:, self.xs : self.xf + 1, self.ys : self.yf + 1, self.zs : self.zf + 1])
fdata["/data"] = (
G.solid[self.xs : self.xf + 1, self.ys : self.yf + 1, self.zs : self.zf + 1].astype("int16") - minmat
)
pbar.update(self.solidsize)
fdata['/rigidE'] = G.rigidE[:, self.xs:self.xf +
1, self.ys:self.yf + 1, self.zs:self.zf + 1]
fdata['/rigidH'] = G.rigidH[:, self.xs:self.xf +
1, self.ys:self.yf + 1, self.zs:self.zf + 1]
fdata["/rigidE"] = G.rigidE[:, self.xs : self.xf + 1, self.ys : self.yf + 1, self.zs : self.zf + 1]
fdata["/rigidH"] = G.rigidH[:, self.xs : self.xf + 1, self.ys : self.yf + 1, self.zs : self.zf + 1]
pbar.update(self.rigidsize)
fdata['/ID'] = G.ID[:, self.xs:self.xf + 1,
self.ys:self.yf + 1, self.zs:self.zf + 1] - minmat
fdata["/ID"] = G.ID[:, self.xs : self.xf + 1, self.ys : self.yf + 1, self.zs : self.zf + 1] - minmat
pbar.update(self.IDsize)
# Write materials list to a text file
# This includes all materials in range whether used in volume or not
with open(self.filename_materials, 'w') as fmaterials:
with open(self.filename_materials, "w") as fmaterials:
for numID in range(minmat, maxmat + 1):
for material in G.materials:
if material.numID == numID:
fmaterials.write(f'#material: {material.er:g} {material.se:g} '
f'{material.mr:g} {material.sm:g} {material.ID}\n')
if hasattr(material, 'poles'):
if 'debye' in material.type:
dispersionstr = ('#add_dispersion_debye: '
f'{material.poles:g} ')
fmaterials.write(
f"#material: {material.er:g} {material.se:g} "
f"{material.mr:g} {material.sm:g} {material.ID}\n"
)
if hasattr(material, "poles"):
if "debye" in material.type:
dispersionstr = "#add_dispersion_debye: " f"{material.poles:g} "
for pole in range(material.poles):
dispersionstr += (f'{material.deltaer[pole]:g} '
f'{material.tau[pole]:g} ')
elif 'lorenz' in material.type:
dispersionstr = (f'#add_dispersion_lorenz: '
f'{material.poles:g} ')
dispersionstr += f"{material.deltaer[pole]:g} " f"{material.tau[pole]:g} "
elif "lorenz" in material.type:
dispersionstr = f"#add_dispersion_lorenz: " f"{material.poles:g} "
for pole in range(material.poles):
dispersionstr += (f'{material.deltaer[pole]:g} '
f'{material.tau[pole]:g} '
f'{material.alpha[pole]:g} ')
elif 'drude' in material.type:
dispersionstr = (f'#add_dispersion_drude: '
f'{material.poles:g} ')
dispersionstr += (
f"{material.deltaer[pole]:g} "
f"{material.tau[pole]:g} "
f"{material.alpha[pole]:g} "
)
elif "drude" in material.type:
dispersionstr = f"#add_dispersion_drude: " f"{material.poles:g} "
for pole in range(material.poles):
dispersionstr += (f'{material.tau[pole]:g} '
f'{material.alpha[pole]:g} ')
dispersionstr += f"{material.tau[pole]:g} " f"{material.alpha[pole]:g} "
dispersionstr += material.ID
fmaterials.write(dispersionstr + '\n')
fmaterials.write(dispersionstr + "\n")

查看文件

@@ -24,135 +24,140 @@ from .contexts import Context, MPIContext
from .utilities.logging import logging_config
# Arguments (used for API) and their default values (used for API and CLI)
args_defaults = {'scenes': None,
'inputfile': None,
'outputfile': None,
'n': 1,
'i': None,
'mpi': False,
'gpu': None,
'opencl': None,
'subgrid': False,
'autotranslate': False,
'geometry_only': False,
'geometry_fixed': False,
'write_processed': False,
'log_level': 20, # Level DEBUG = 10; INFO = 20; BASIC = 25
'log_file': False}
args_defaults = {
"scenes": None,
"inputfile": None,
"outputfile": None,
"n": 1,
"i": None,
"mpi": False,
"gpu": None,
"opencl": None,
"subgrid": False,
"autotranslate": False,
"geometry_only": False,
"geometry_fixed": False,
"write_processed": False,
"log_level": 20, # Level DEBUG = 10; INFO = 20; BASIC = 25
"log_file": False,
}
# Argument help messages (used for CLI argparse)
help_msg = {'scenes': '(list, req): Scenes to run the model. '
'Multiple scene objects can given in order to run multiple '
'simulation runs. Each scene must contain the essential '
'simulation objects',
'inputfile': '(str, opt): Input file path. Can also run simulation '
'by providing an input file.',
'outputfile': '(str, req): File path to the output data file.',
'n': '(int, req): Number of required simulation runs.',
'i': '(int, opt): Model number to start/restart simulation '
'from. It would typically be used to restart a series of '
'models from a specific model number, with the n argument, '
'e.g. to restart from A-scan 45 when creating a B-scan '
'with 60 traces.',
'mpi': '(bool, opt): Flag to use Message Passing Interface (MPI) '
'task farm. This option is most usefully combined with n to '
'allow individual models to be farmed out using a MPI task '
'farm, e.g. to create a B-scan with 60 traces and use MPI to '
'farm out each trace. For further details see the parallel '
'performance section of the User Guide.',
'gpu': '(list/bool, opt): Flag to use NVIDIA GPU or list of NVIDIA '
'GPU device ID(s) for specific GPU card(s).',
'opencl': '(list/bool, opt): Flag to use OpenCL or list of OpenCL '
'device ID(s) for specific compute device(s).',
'subgrid': '(bool, opt): Flag to use sub-gridding.',
'autotranslate': '(bool, opt): For sub-gridding - auto translate '
'objects with main grid coordinates to their '
'equivalent local grid coordinate within the '
'subgrid. If this option is off users must specify '
'sub-grid object point within the global subgrid space.',
'geometry_only': '(bool, opt): Build a model and produce any '
'geometry views but do not run the simulation.',
'geometry_fixed': '(bool, opt): Run a series of models where the '
'geometry does not change between models.',
'write_processed': '(bool, opt): Writes another input file after '
'any Python code (#python blocks) and in the '
'original input file has been processed.',
'log_level': '(int, opt): Level of logging to use.',
'log_file': '(bool, opt): Write logging information to file.'}
help_msg = {
"scenes": "(list, req): Scenes to run the model. "
"Multiple scene objects can given in order to run multiple "
"simulation runs. Each scene must contain the essential "
"simulation objects",
"inputfile": "(str, opt): Input file path. Can also run simulation " "by providing an input file.",
"outputfile": "(str, req): File path to the output data file.",
"n": "(int, req): Number of required simulation runs.",
"i": "(int, opt): Model number to start/restart simulation "
"from. It would typically be used to restart a series of "
"models from a specific model number, with the n argument, "
"e.g. to restart from A-scan 45 when creating a B-scan "
"with 60 traces.",
"mpi": "(bool, opt): Flag to use Message Passing Interface (MPI) "
"task farm. This option is most usefully combined with n to "
"allow individual models to be farmed out using a MPI task "
"farm, e.g. to create a B-scan with 60 traces and use MPI to "
"farm out each trace. For further details see the parallel "
"performance section of the User Guide.",
"gpu": "(list/bool, opt): Flag to use NVIDIA GPU or list of NVIDIA " "GPU device ID(s) for specific GPU card(s).",
"opencl": "(list/bool, opt): Flag to use OpenCL or list of OpenCL " "device ID(s) for specific compute device(s).",
"subgrid": "(bool, opt): Flag to use sub-gridding.",
"autotranslate": "(bool, opt): For sub-gridding - auto translate "
"objects with main grid coordinates to their "
"equivalent local grid coordinate within the "
"subgrid. If this option is off users must specify "
"sub-grid object point within the global subgrid space.",
"geometry_only": "(bool, opt): Build a model and produce any " "geometry views but do not run the simulation.",
"geometry_fixed": "(bool, opt): Run a series of models where the " "geometry does not change between models.",
"write_processed": "(bool, opt): Writes another input file after "
"any Python code (#python blocks) and in the "
"original input file has been processed.",
"log_level": "(int, opt): Level of logging to use.",
"log_file": "(bool, opt): Write logging information to file.",
}
def run(scenes=args_defaults['scenes'],
inputfile=args_defaults['inputfile'],
outputfile=args_defaults['outputfile'],
n=args_defaults['n'],
i=args_defaults['i'],
mpi=args_defaults['mpi'],
gpu=args_defaults['gpu'],
opencl=args_defaults['opencl'],
subgrid=args_defaults['subgrid'],
autotranslate=args_defaults['autotranslate'],
geometry_only=args_defaults['geometry_only'],
geometry_fixed=args_defaults['geometry_fixed'],
write_processed=args_defaults['write_processed'],
log_level=args_defaults['log_level'],
log_file=args_defaults['log_file']):
"""Entry point for application programming interface (API). Runs the
def run(
scenes=args_defaults["scenes"],
inputfile=args_defaults["inputfile"],
outputfile=args_defaults["outputfile"],
n=args_defaults["n"],
i=args_defaults["i"],
mpi=args_defaults["mpi"],
gpu=args_defaults["gpu"],
opencl=args_defaults["opencl"],
subgrid=args_defaults["subgrid"],
autotranslate=args_defaults["autotranslate"],
geometry_only=args_defaults["geometry_only"],
geometry_fixed=args_defaults["geometry_fixed"],
write_processed=args_defaults["write_processed"],
log_level=args_defaults["log_level"],
log_file=args_defaults["log_file"],
):
"""Entry point for application programming interface (API). Runs the
simulation for the given list of scenes.
Args:
scenes: list of the scenes to run the model. Multiple scene objects can
be given in order to run multiple simulation runs. Each scene
scenes: list of the scenes to run the model. Multiple scene objects can
be given in order to run multiple simulation runs. Each scene
must contain the essential simulation objects.
inputfile: optional string for input file path. Can also run simulation
inputfile: optional string for input file path. Can also run simulation
by providing an input file.
outputfile: string for file path to the output data file
n: optional int for number of required simulation runs.
i: optional int for model number to start/restart simulation from.
It would typically be used to restart a series of models from a
specific model number, with the n argument, e.g. to restart from
i: optional int for model number to start/restart simulation from.
It would typically be used to restart a series of models from a
specific model number, with the n argument, e.g. to restart from
A-scan 45 when creating a B-scan with 60 traces.
mpi: optional boolean flag to use Message Passing Interface (MPI) task
farm. This option is most usefully combined with n to allow
individual models to be farmed out using a MPI task farm,
e.g. to create a B-scan with 60 traces and use MPI to farm out
each trace. For further details see the performance section of
mpi: optional boolean flag to use Message Passing Interface (MPI) task
farm. This option is most usefully combined with n to allow
individual models to be farmed out using a MPI task farm,
e.g. to create a B-scan with 60 traces and use MPI to farm out
each trace. For further details see the performance section of
the User Guide
gpu: optional list/boolean to use NVIDIA GPU or list of NVIDIA GPU device
gpu: optional list/boolean to use NVIDIA GPU or list of NVIDIA GPU device
ID(s) for specific GPU card(s).
opencl: optional list/boolean to use OpenCL or list of OpenCL device ID(s)
opencl: optional list/boolean to use OpenCL or list of OpenCL device ID(s)
for specific compute device(s).
subgrid: optional boolean to use sub-gridding.
autotranslate: optional boolean for sub-gridding to auto translate
objects with main grid coordinates to their equivalent
local grid coordinate within the subgrid. If this option
is off users must specify sub-grid object point within
autotranslate: optional boolean for sub-gridding to auto translate
objects with main grid coordinates to their equivalent
local grid coordinate within the subgrid. If this option
is off users must specify sub-grid object point within
the global subgrid space.
geometry_only: optional boolean to build a model and produce any
geometry_only: optional boolean to build a model and produce any
geometry views but do not run the simulation.
geometry_fixed: optional boolean to run a series of models where the
geometry_fixed: optional boolean to run a series of models where the
geometry does not change between models.
write_processed: optional boolean to write another input file after any
#python blocks (which are deprecated) in the
write_processed: optional boolean to write another input file after any
#python blocks (which are deprecated) in the
original input file has been processed.
log_level: optional int for level of logging to use.
log_file: optional boolean to write logging information to file.
"""
args = argparse.Namespace(**{'scenes': scenes,
'inputfile': inputfile,
'outputfile': outputfile,
'n': n,
'i': i,
'mpi': mpi,
'gpu': gpu,
'opencl': opencl,
'subgrid': subgrid,
'autotranslate': autotranslate,
'geometry_only': geometry_only,
'geometry_fixed': geometry_fixed,
'write_processed': write_processed,
'log_level': log_level,
'log_file': log_file})
args = argparse.Namespace(
**{
"scenes": scenes,
"inputfile": inputfile,
"outputfile": outputfile,
"n": n,
"i": i,
"mpi": mpi,
"gpu": gpu,
"opencl": opencl,
"subgrid": subgrid,
"autotranslate": autotranslate,
"geometry_only": geometry_only,
"geometry_fixed": geometry_fixed,
"write_processed": write_processed,
"log_level": log_level,
"log_file": log_file,
}
)
run_main(args)
@@ -161,32 +166,30 @@ def cli():
"""Entry point for command line interface (CLI)."""
# Parse command line arguments
parser = argparse.ArgumentParser(prog='gprMax',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('inputfile', help=help_msg['inputfile'])
parser.add_argument('-n', default=args_defaults['n'], type=int, help=help_msg['n'])
parser.add_argument('-i', type=int, help=help_msg['i'])
parser.add_argument('-mpi', action='store_true', default=args_defaults['mpi'],
help=help_msg['mpi'])
parser.add_argument('-gpu', type=int, action='append', nargs='*',
help=help_msg['gpu'])
parser.add_argument('-opencl', type=int, action='append', nargs='*',
help=help_msg['opencl'])
parser.add_argument('--geometry-only', action='store_true',
default=args_defaults['geometry_only'],
help=help_msg['geometry_only'])
parser.add_argument('--geometry-fixed', action='store_true',
default=args_defaults['geometry_fixed'],
help=help_msg['geometry_fixed'])
parser.add_argument('--write-processed', action='store_true',
default=args_defaults['write_processed'],
help=help_msg['write_processed'])
parser.add_argument('--log-level', type=int,
default=args_defaults['log_level'],
help=help_msg['log_level'])
parser.add_argument('--log-file', action='store_true',
default=args_defaults['log_file'],
help=help_msg['log_file'])
parser = argparse.ArgumentParser(prog="gprMax", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("inputfile", help=help_msg["inputfile"])
parser.add_argument("-n", default=args_defaults["n"], type=int, help=help_msg["n"])
parser.add_argument("-i", type=int, help=help_msg["i"])
parser.add_argument("-mpi", action="store_true", default=args_defaults["mpi"], help=help_msg["mpi"])
parser.add_argument("-gpu", type=int, action="append", nargs="*", help=help_msg["gpu"])
parser.add_argument("-opencl", type=int, action="append", nargs="*", help=help_msg["opencl"])
parser.add_argument(
"--geometry-only", action="store_true", default=args_defaults["geometry_only"], help=help_msg["geometry_only"]
)
parser.add_argument(
"--geometry-fixed",
action="store_true",
default=args_defaults["geometry_fixed"],
help=help_msg["geometry_fixed"],
)
parser.add_argument(
"--write-processed",
action="store_true",
default=args_defaults["write_processed"],
help=help_msg["write_processed"],
)
parser.add_argument("--log-level", type=int, default=args_defaults["log_level"], help=help_msg["log_level"])
parser.add_argument("--log-file", action="store_true", default=args_defaults["log_file"], help=help_msg["log_file"])
args = parser.parse_args()
results = run_main(args)
@@ -201,7 +204,7 @@ def run_main(args):
args: namespace with arguments from either API or CLI.
Returns:
results: dict that can contain useful results/data from simulation.
results: dict that can contain useful results/data from simulation.
Enables these to be propagated to calling script.
"""
@@ -210,7 +213,7 @@ def run_main(args):
logging_config(level=args.log_level, log_file=args.log_file)
config.sim_config = config.SimulationConfig(args)
# MPI running with (OpenMP/CUDA/OpenCL)
if config.sim_config.args.mpi:
context = MPIContext()
@@ -220,4 +223,4 @@ def run_main(args):
context = Context()
results = context.run()
return results
return results

查看文件

@@ -26,17 +26,17 @@ import gprMax.config as config
from .pml import PML
from .utilities.utilities import fft_power, round_value
np.seterr(invalid='raise')
np.seterr(invalid="raise")
class FDTDGrid:
"""Holds attributes associated with entire grid. A convenient way for
accessing regularly used parameters.
accessing regularly used parameters.
"""
def __init__(self):
self.title = ''
self.name = 'main_grid'
self.title = ""
self.name = "main_grid"
self.mem_use = 0
self.nx = 0
@@ -46,22 +46,22 @@ class FDTDGrid:
self.dy = 0
self.dz = 0
self.dt = 0
self.dt_mod = None # Time step stability factor
self.iteration = 0 # Current iteration number
self.iterations = 0 # Total number of iterations
self.dt_mod = None # Time step stability factor
self.iteration = 0 # Current iteration number
self.iterations = 0 # Total number of iterations
self.timewindow = 0
# PML parameters - set some defaults to use if not user provided
self.pmls = {}
self.pmls['formulation'] = 'HORIPML'
self.pmls['cfs'] = []
self.pmls['slabs'] = []
self.pmls["formulation"] = "HORIPML"
self.pmls["cfs"] = []
self.pmls["slabs"] = []
# Ordered dictionary required so that PMLs are always updated in the
# same order. The order itself does not matter, however, if must be the
# same from model to model otherwise the numerical precision from adding
# the PML corrections will be different.
self.pmls['thickness'] = OrderedDict((key, 10) for key in PML.boundaryIDs)
self.pmls["thickness"] = OrderedDict((key, 10) for key in PML.boundaryIDs)
self.materials = []
self.mixingmodels = []
self.averagevolumeobjects = True
@@ -81,11 +81,11 @@ class FDTDGrid:
def within_bounds(self, p):
if p[0] < 0 or p[0] > self.nx:
raise ValueError('x')
raise ValueError("x")
if p[1] < 0 or p[1] > self.ny:
raise ValueError('y')
raise ValueError("y")
if p[2] < 0 or p[2] > self.nz:
raise ValueError('z')
raise ValueError("z")
def discretise_point(self, p):
x = round_value(float(p[0]) / self.dx)
@@ -95,25 +95,25 @@ class FDTDGrid:
def round_to_grid(self, p):
p = self.discretise_point(p)
p_r = (p[0] * self.dx,
p[1] * self.dy,
p[2] * self.dz)
p_r = (p[0] * self.dx, p[1] * self.dy, p[2] * self.dz)
return p_r
def within_pml(self, p):
if (p[0] < self.pmls['thickness']['x0'] or
p[0] > self.nx - self.pmls['thickness']['xmax'] or
p[1] < self.pmls['thickness']['y0'] or
p[1] > self.ny - self.pmls['thickness']['ymax'] or
p[2] < self.pmls['thickness']['z0'] or
p[2] > self.nz - self.pmls['thickness']['zmax']):
if (
p[0] < self.pmls["thickness"]["x0"]
or p[0] > self.nx - self.pmls["thickness"]["xmax"]
or p[1] < self.pmls["thickness"]["y0"]
or p[1] > self.ny - self.pmls["thickness"]["ymax"]
or p[2] < self.pmls["thickness"]["z0"]
or p[2] > self.nz - self.pmls["thickness"]["zmax"]
):
return True
else:
return False
def initialise_geometry_arrays(self):
"""Initialise an array for volumetric material IDs (solid);
boolean arrays for specifying whether materials can have dielectric
boolean arrays for specifying whether materials can have dielectric
smoothing (rigid); and an array for cell edge IDs (ID).
Solid and ID arrays are initialised to free_space (one);
rigid arrays to allow dielectric smoothing (zero).
@@ -122,59 +122,55 @@ class FDTDGrid:
self.rigidE = np.zeros((12, self.nx, self.ny, self.nz), dtype=np.int8)
self.rigidH = np.zeros((6, self.nx, self.ny, self.nz), dtype=np.int8)
self.ID = np.ones((6, self.nx + 1, self.ny + 1, self.nz + 1), dtype=np.uint32)
self.IDlookup = {'Ex': 0, 'Ey': 1, 'Ez': 2, 'Hx': 3, 'Hy': 4, 'Hz': 5}
self.IDlookup = {"Ex": 0, "Ey": 1, "Ez": 2, "Hx": 3, "Hy": 4, "Hz": 5}
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=config.sim_config.dtypes['float_or_double'])
self.Ey = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.sim_config.dtypes['float_or_double'])
self.Ez = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.sim_config.dtypes['float_or_double'])
self.Hx = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.sim_config.dtypes['float_or_double'])
self.Hy = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.sim_config.dtypes['float_or_double'])
self.Hz = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.sim_config.dtypes['float_or_double'])
self.Ex = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.sim_config.dtypes["float_or_double"])
self.Ey = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.sim_config.dtypes["float_or_double"])
self.Ez = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.sim_config.dtypes["float_or_double"])
self.Hx = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.sim_config.dtypes["float_or_double"])
self.Hy = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.sim_config.dtypes["float_or_double"])
self.Hz = np.zeros((self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.sim_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=config.sim_config.dtypes['float_or_double'])
self.updatecoeffsH = np.zeros((len(self.materials), 5),
dtype=config.sim_config.dtypes['float_or_double'])
self.updatecoeffsE = np.zeros((len(self.materials), 5), dtype=config.sim_config.dtypes["float_or_double"])
self.updatecoeffsH = np.zeros((len(self.materials), 5), dtype=config.sim_config.dtypes["float_or_double"])
def initialise_dispersive_arrays(self):
"""Initialise field arrays when there are dispersive materials present."""
self.Tx = np.zeros((config.get_model_config().materials['maxpoles'],
self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.get_model_config().materials['dispersivedtype'])
self.Ty = np.zeros((config.get_model_config().materials['maxpoles'],
self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.get_model_config().materials['dispersivedtype'])
self.Tz = np.zeros((config.get_model_config().materials['maxpoles'],
self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.get_model_config().materials['dispersivedtype'])
self.Tx = np.zeros(
(config.get_model_config().materials["maxpoles"], self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.get_model_config().materials["dispersivedtype"],
)
self.Ty = np.zeros(
(config.get_model_config().materials["maxpoles"], self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.get_model_config().materials["dispersivedtype"],
)
self.Tz = np.zeros(
(config.get_model_config().materials["maxpoles"], self.nx + 1, self.ny + 1, self.nz + 1),
dtype=config.get_model_config().materials["dispersivedtype"],
)
def initialise_dispersive_update_coeff_array(self):
"""Initialise array for storing update coefficients when there are dispersive
materials present.
materials present.
"""
self.updatecoeffsdispersive = np.zeros((len(self.materials), 3 *
config.get_model_config().materials['maxpoles']),
dtype=config.get_model_config().materials['dispersivedtype'])
self.updatecoeffsdispersive = np.zeros(
(len(self.materials), 3 * config.get_model_config().materials["maxpoles"]),
dtype=config.get_model_config().materials["dispersivedtype"],
)
def reset_fields(self):
"""Clear arrays for field components and PMLs."""
# Clear arrays for field components
self.initialise_field_arrays()
if config.get_model_config().materials['maxpoles'] > 0:
if config.get_model_config().materials["maxpoles"] > 0:
self.initialise_dispersive_arrays()
# Clear arrays for fields in PML
for pml in self.pmls['slabs']:
for pml in self.pmls["slabs"]:
pml.initialise_field_arrays()
def mem_est_basic(self):
@@ -190,28 +186,33 @@ class FDTDGrid:
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(config.sim_config.dtypes['float_or_double']).itemsize)
fieldarrays = (
(6 + 6)
* (self.nx + 1)
* (self.ny + 1)
* (self.nz + 1)
* np.dtype(config.sim_config.dtypes["float_or_double"]).itemsize
)
# PML arrays
pmlarrays = 0
for (k, v) in self.pmls['thickness'].items():
for k, v in self.pmls["thickness"].items():
if v > 0:
if 'x' in k:
pmlarrays += ((v + 1) * self.ny * (self.nz + 1))
pmlarrays += ((v + 1) * (self.ny + 1) * self.nz)
pmlarrays += (v * self.ny * (self.nz + 1))
pmlarrays += (v * (self.ny + 1) * self.nz)
elif 'y' in k:
pmlarrays += (self.nx * (v + 1) * (self.nz + 1))
pmlarrays += ((self.nx + 1) * (v + 1) * self.nz)
pmlarrays += ((self.nx + 1) * v * self.nz)
pmlarrays += (self.nx * v * (self.nz + 1))
elif 'z' in k:
pmlarrays += (self.nx * (self.ny + 1) * (v + 1))
pmlarrays += ((self.nx + 1) * self.ny * (v + 1))
pmlarrays += ((self.nx + 1) * self.ny * v)
pmlarrays += (self.nx * (self.ny + 1) * v)
if "x" in k:
pmlarrays += (v + 1) * self.ny * (self.nz + 1)
pmlarrays += (v + 1) * (self.ny + 1) * self.nz
pmlarrays += v * self.ny * (self.nz + 1)
pmlarrays += v * (self.ny + 1) * self.nz
elif "y" in k:
pmlarrays += self.nx * (v + 1) * (self.nz + 1)
pmlarrays += (self.nx + 1) * (v + 1) * self.nz
pmlarrays += (self.nx + 1) * v * self.nz
pmlarrays += self.nx * v * (self.nz + 1)
elif "z" in k:
pmlarrays += self.nx * (self.ny + 1) * (v + 1)
pmlarrays += (self.nx + 1) * self.ny * (v + 1)
pmlarrays += (self.nx + 1) * self.ny * v
pmlarrays += self.nx * (self.ny + 1) * v
mem_use = int(fieldarrays + solidarray + rigidarrays + pmlarrays)
@@ -224,9 +225,14 @@ class FDTDGrid:
mem_use: int of memory (bytes).
"""
mem_use = int(3 * config.get_model_config().materials['maxpoles'] *
(self.nx + 1) * (self.ny + 1) * (self.nz + 1) *
np.dtype(config.get_model_config().materials['dispersivedtype']).itemsize)
mem_use = int(
3
* config.get_model_config().materials["maxpoles"]
* (self.nx + 1)
* (self.ny + 1)
* (self.nz + 1)
* np.dtype(config.get_model_config().materials["dispersivedtype"]).itemsize
)
return mem_use
def mem_est_fractals(self):
@@ -236,22 +242,20 @@ class FDTDGrid:
Returns:
mem_use: int of memory (bytes).
"""
mem_use = 0
for vol in self.fractalvolumes:
mem_use += (vol.nx * vol.ny * vol.nz * vol.dtype.itemsize)
mem_use += vol.nx * vol.ny * vol.nz * vol.dtype.itemsize
for surface in vol.fractalsurfaces:
surfacedims = surface.get_surface_dims()
mem_use += (surfacedims[0] *
surfacedims[1] *
surface.dtype.itemsize)
mem_use += surfacedims[0] * surfacedims[1] * surface.dtype.itemsize
return mem_use
def tmx(self):
"""Add PEC boundaries to invariant direction in 2D TMx mode.
N.B. 2D modes are a single cell slice of 3D grid.
N.B. 2D modes are a single cell slice of 3D grid.
"""
# Ey & Ez components
self.ID[1, 0, :, :] = 0
@@ -261,7 +265,7 @@ class FDTDGrid:
def tmy(self):
"""Add PEC boundaries to invariant direction in 2D TMy mode.
N.B. 2D modes are a single cell slice of 3D grid.
N.B. 2D modes are a single cell slice of 3D grid.
"""
# Ex & Ez components
self.ID[0, :, 0, :] = 0
@@ -271,7 +275,7 @@ class FDTDGrid:
def tmz(self):
"""Add PEC boundaries to invariant direction in 2D TMz mode.
N.B. 2D modes are a single cell slice of 3D grid.
N.B. 2D modes are a single cell slice of 3D grid.
"""
# Ex & Ey components
self.ID[0, :, :, 0] = 0
@@ -281,18 +285,16 @@ class FDTDGrid:
def calculate_dt(self):
"""Calculate time step at the CFL limit."""
if config.get_model_config().mode == '2D TMx':
self.dt = 1 / (config.sim_config.em_consts['c'] *
np.sqrt((1 / self.dy**2) + (1 / self.dz**2)))
elif config.get_model_config().mode == '2D TMy':
self.dt = 1 / (config.sim_config.em_consts['c'] *
np.sqrt((1 / self.dx**2) + (1 / self.dz**2)))
elif config.get_model_config().mode == '2D TMz':
self.dt = 1 / (config.sim_config.em_consts['c'] *
np.sqrt((1 / self.dx**2) + (1 / self.dy**2)))
if config.get_model_config().mode == "2D TMx":
self.dt = 1 / (config.sim_config.em_consts["c"] * np.sqrt((1 / self.dy**2) + (1 / self.dz**2)))
elif config.get_model_config().mode == "2D TMy":
self.dt = 1 / (config.sim_config.em_consts["c"] * np.sqrt((1 / self.dx**2) + (1 / self.dz**2)))
elif config.get_model_config().mode == "2D TMz":
self.dt = 1 / (config.sim_config.em_consts["c"] * np.sqrt((1 / self.dx**2) + (1 / self.dy**2)))
else:
self.dt = 1 / (config.sim_config.em_consts['c'] *
np.sqrt((1 / self.dx**2) + (1 / self.dy**2) + (1 / self.dz**2)))
self.dt = 1 / (
config.sim_config.em_consts["c"] * np.sqrt((1 / self.dx**2) + (1 / self.dy**2) + (1 / self.dz**2))
)
# Round down time step to nearest float with precision one less than
# hardware maximum. Avoids inadvertently exceeding the CFL due to
@@ -313,44 +315,47 @@ class CUDAGrid(FDTDGrid):
def set_blocks_per_grid(self):
"""Set the blocks per grid size used for updating the electric and
magnetic field arrays on a GPU.
magnetic field arrays on a GPU.
"""
self.bpg = (int(np.ceil(((self.nx + 1) * (self.ny + 1) *
(self.nz + 1)) / self.tpb[0])), 1, 1)
self.bpg = (int(np.ceil(((self.nx + 1) * (self.ny + 1) * (self.nz + 1)) / self.tpb[0])), 1, 1)
def htod_geometry_arrays(self, queue=None):
"""Initialise an array for cell edge IDs (ID) on compute device.
Args:
queue: pyopencl queue.
"""
if config.sim_config.general['solver'] == 'cuda':
if config.sim_config.general["solver"] == "cuda":
import pycuda.gpuarray as gpuarray
self.ID_dev = gpuarray.to_gpu(self.ID)
elif config.sim_config.general['solver'] == 'opencl':
elif config.sim_config.general["solver"] == "opencl":
import pyopencl.array as clarray
self.ID_dev = clarray.to_device(queue, self.ID)
self.ID_dev = clarray.to_device(queue, self.ID)
def htod_field_arrays(self, queue=None):
"""Initialise field arrays on compute device.
Args:
queue: pyopencl queue.
"""
if config.sim_config.general['solver'] == 'cuda':
if config.sim_config.general["solver"] == "cuda":
import pycuda.gpuarray as gpuarray
self.Ex_dev = gpuarray.to_gpu(self.Ex)
self.Ey_dev = gpuarray.to_gpu(self.Ey)
self.Ez_dev = gpuarray.to_gpu(self.Ez)
self.Hx_dev = gpuarray.to_gpu(self.Hx)
self.Hy_dev = gpuarray.to_gpu(self.Hy)
self.Hz_dev = gpuarray.to_gpu(self.Hz)
elif config.sim_config.general['solver'] == 'opencl':
elif config.sim_config.general["solver"] == "opencl":
import pyopencl.array as clarray
self.Ex_dev = clarray.to_device(queue, self.Ex)
self.Ey_dev = clarray.to_device(queue, self.Ey)
self.Ez_dev = clarray.to_device(queue, self.Ez)
@@ -360,19 +365,21 @@ class CUDAGrid(FDTDGrid):
def htod_dispersive_arrays(self, queue=None):
"""Initialise dispersive material coefficient arrays on compute device.
Args:
queue: pyopencl queue.
"""
if config.sim_config.general['solver'] == 'cuda':
if config.sim_config.general["solver"] == "cuda":
import pycuda.gpuarray as gpuarray
self.Tx_dev = gpuarray.to_gpu(self.Tx)
self.Ty_dev = gpuarray.to_gpu(self.Ty)
self.Tz_dev = gpuarray.to_gpu(self.Tz)
self.updatecoeffsdispersive_dev = gpuarray.to_gpu(self.updatecoeffsdispersive)
elif config.sim_config.general['solver'] == 'opencl':
elif config.sim_config.general["solver"] == "opencl":
import pyopencl.array as clarray
self.Tx_dev = clarray.to_device(queue, self.Tx)
self.Ty_dev = clarray.to_device(queue, self.Ty)
self.Tz_dev = clarray.to_device(queue, self.Tz)
@@ -405,27 +412,23 @@ def dispersion_analysis(G):
# material: material with maximum permittivity
# maxfreq: maximum significant frequency
# error: error message
results = {'deltavp': None,
'N': None,
'material': None,
'maxfreq': [],
'error': ''}
results = {"deltavp": None, "N": None, "material": None, "maxfreq": [], "error": ""}
# Find maximum significant frequency
if G.waveforms:
for waveform in G.waveforms:
if waveform.type == 'sine' or waveform.type == 'contsine':
results['maxfreq'].append(4 * waveform.freq)
if waveform.type == "sine" or waveform.type == "contsine":
results["maxfreq"].append(4 * waveform.freq)
elif waveform.type == 'impulse':
results['error'] = 'impulse waveform used.'
elif waveform.type == "impulse":
results["error"] = "impulse waveform used."
elif waveform.type == 'user':
results['error'] = 'user waveform detected.'
elif waveform.type == "user":
results["error"] = "user waveform detected."
else:
# User-defined waveform
if waveform.type == 'user':
if waveform.type == "user":
iterations = G.iterations
# Built-in waveform
@@ -450,12 +453,19 @@ def dispersion_analysis(G):
# Set maximum frequency to a threshold drop from maximum power, ignoring DC value
try:
freqthres = np.where(power[freqmaxpower:] < -config.get_model_config().numdispersion['highestfreqthres'])[0][0] + freqmaxpower
results['maxfreq'].append(freqs[freqthres])
freqthres = (
np.where(
power[freqmaxpower:] < -config.get_model_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.')
results["error"] = (
"unable to calculate maximum power "
+ "from waveform, most likely due to "
+ "undersampling."
)
# Ignore case where someone is using a waveform with zero amplitude, i.e. on a receiver
elif waveform.amp == 0:
@@ -463,40 +473,41 @@ def dispersion_analysis(G):
# If waveform is truncated don't do any further analysis
else:
results['error'] = ('waveform does not fit within specified ' +
'time window and is therefore being truncated.')
results["error"] = (
"waveform does not fit within specified " + "time window and is therefore being truncated."
)
else:
results['error'] = 'no waveform detected.'
results["error"] = "no waveform detected."
if results['maxfreq']:
results['maxfreq'] = max(results['maxfreq'])
if results["maxfreq"]:
results["maxfreq"] = max(results["maxfreq"])
# Find minimum wavelength (material with maximum permittivity)
maxer = 0
matmaxer = ''
matmaxer = ""
for x in G.materials:
if x.se != float('inf'):
if x.se != float("inf"):
er = x.er
# If there are dispersive materials calculate the complex
# If there are dispersive materials calculate the complex
# relative permittivity at maximum frequency and take the real part
if x.__class__.__name__ == 'DispersiveMaterial':
er = x.calculate_er(results['maxfreq'])
if x.__class__.__name__ == "DispersiveMaterial":
er = x.calculate_er(results["maxfreq"])
er = er.real
if er > maxer:
maxer = er
matmaxer = x.ID
results['material'] = next(x for x in G.materials if x.ID == matmaxer)
results["material"] = next(x for x in G.materials if x.ID == matmaxer)
# Minimum velocity
minvelocity = config.c / np.sqrt(maxer)
# Minimum wavelength
minwavelength = minvelocity / results['maxfreq']
minwavelength = minvelocity / results["maxfreq"]
# Maximum spatial step
if '3D' in config.get_model_config().mode:
if "3D" in config.get_model_config().mode:
delta = max(G.dx, G.dy, G.dz)
elif '2D' in config.get_model_config().mode:
elif "2D" in config.get_model_config().mode:
if G.nx == 1:
delta = max(G.dy, G.dz)
elif G.ny == 1:
@@ -508,17 +519,17 @@ def dispersion_analysis(G):
S = (config.c * G.dt) / delta
# Grid sampling density
results['N'] = minwavelength / delta
results["N"] = minwavelength / delta
# Check grid sampling will result in physical wave propagation
if int(np.floor(results['N'])) >= config.get_model_config().numdispersion['mingridsampling']:
if int(np.floor(results["N"])) >= config.get_model_config().numdispersion["mingridsampling"]:
# Numerical phase velocity
vp = np.pi / (results['N'] * np.arcsin((1 / S) * np.sin((np.pi * S) / results['N'])))
vp = np.pi / (results["N"] * np.arcsin((1 / S) * np.sin((np.pi * S) / results["N"])))
# Physical phase velocity error (percentage)
results['deltavp'] = (((vp * config.c) - config.c) / config.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']))
results["N"] = int(np.floor(results["N"]))
return results
return results

查看文件

@@ -40,7 +40,7 @@ def process_python_include_code(inputfile, usernamespace):
Args:
inputfile: file object for input file.
usernamespace: namespace that can be accessed by user in any Python code
usernamespace: namespace that can be accessed by user in any Python code
blocks in input file.
Returns:
@@ -48,7 +48,7 @@ def process_python_include_code(inputfile, usernamespace):
"""
# Strip out any newline characters and comments that must begin with double hashes
inputlines = [line.rstrip() for line in inputfile if(not line.startswith('##') and line.rstrip('\n'))]
inputlines = [line.rstrip() for line in inputfile if (not line.startswith("##") and line.rstrip("\n"))]
# Rewind input file in preparation for any subsequent reading function
inputfile.seek(0)
@@ -57,32 +57,34 @@ def process_python_include_code(inputfile, usernamespace):
processedlines = []
x = 0
while(x < len(inputlines)):
while x < len(inputlines):
# Process any Python code
if(inputlines[x].startswith('#python:')):
logger.warning('#python blocks are deprecated and will be removed in ' +
'the next release of gprMax. Please convert your ' +
'model to use our Python API instead.\n')
if inputlines[x].startswith("#python:"):
logger.warning(
"#python blocks are deprecated and will be removed in "
+ "the next release of gprMax. Please convert your "
+ "model to use our Python API instead.\n"
)
# String to hold Python code to be executed
pythoncode = ''
pythoncode = ""
x += 1
while not inputlines[x].startswith('#end_python:'):
while not inputlines[x].startswith("#end_python:"):
# Add all code in current code block to string
pythoncode += inputlines[x] + '\n'
pythoncode += inputlines[x] + "\n"
x += 1
if x == len(inputlines):
logger.exception('Cannot find the end of the Python code ' +
'block, i.e. missing #end_python: command.')
logger.exception(
"Cannot find the end of the Python code " + "block, i.e. missing #end_python: command."
)
raise SyntaxError
# Compile code for faster execution
pythoncompiledcode = compile(pythoncode, '<string>', 'exec')
pythoncompiledcode = compile(pythoncode, "<string>", "exec")
# Redirect stdout to a text stream
sys.stdout = result = StringIO()
# Execute code block & make available only usernamespace
exec(pythoncompiledcode, usernamespace)
# String containing buffer of executed code
codeout = result.getvalue().split('\n')
codeout = result.getvalue().split("\n")
result.close()
# Reset stdio
@@ -92,8 +94,8 @@ def process_python_include_code(inputfile, usernamespace):
hashcmds = []
pythonout = []
for line in codeout:
if line.startswith('#'):
hashcmds.append(line + '\n')
if line.startswith("#"):
hashcmds.append(line + "\n")
elif line:
pythonout.append(line)
@@ -102,12 +104,12 @@ def process_python_include_code(inputfile, usernamespace):
# Print any generated output that is not commands
if pythonout:
logger.info(f'Python messages (from stdout/stderr): {pythonout}\n')
logger.info(f"Python messages (from stdout/stderr): {pythonout}\n")
# Add any other commands to list
elif(inputlines[x].startswith('#')):
elif inputlines[x].startswith("#"):
# Add gprMax command to list
inputlines[x] += ('\n')
inputlines[x] += "\n"
processedlines.append(inputlines[x])
x += 1
@@ -126,18 +128,18 @@ def process_include_files(hashcmds):
hashcmds: list of input commands.
Returns:
processedincludecmds: list of input commands after processing any
processedincludecmds: list of input commands after processing any
include file commands.
"""
processedincludecmds = []
x = 0
while x < len(hashcmds):
if hashcmds[x].startswith('#include_file:'):
if hashcmds[x].startswith("#include_file:"):
includefile = hashcmds[x].split()
if len(includefile) != 2:
logger.exception('#include_file requires exactly one parameter')
logger.exception("#include_file requires exactly one parameter")
raise ValueError
includefile = includefile[1]
@@ -147,9 +149,13 @@ def process_include_files(hashcmds):
if not includefile.exists():
includefile = Path(config.sim_config.input_file_path.parent, includefile)
with open(includefile, 'r') as f:
with open(includefile, "r") as f:
# Strip out any newline characters and comments that must begin with double hashes
includelines = [includeline.rstrip() + '\n' for includeline in f if(not includeline.startswith('##') and includeline.rstrip('\n'))]
includelines = [
includeline.rstrip() + "\n"
for includeline in f
if (not includeline.startswith("##") and includeline.rstrip("\n"))
]
# Add lines from include file
processedincludecmds.extend(includelines)
@@ -172,62 +178,99 @@ def write_processed_file(processedlines):
"""
parts = config.get_model_config().output_file_path.parts
processedfile = (Path(*parts[:-1], parts[-1] + '_processed.in'))
processedfile = Path(*parts[:-1], parts[-1] + "_processed.in")
with open(processedfile, 'w') as f:
with open(processedfile, "w") as f:
for item in processedlines:
f.write(f'{item}')
f.write(f"{item}")
logger.info(f'Written input commands, after processing any Python ' +
f'code and include commands, to file: {processedfile}\n')
logger.info(
f"Written input commands, after processing any Python "
+ f"code and include commands, to file: {processedfile}\n"
)
def check_cmd_names(processedlines, checkessential=True):
"""Checks the validity of commands, i.e. are they gprMax commands,
and that all essential commands are present.
Args:
processedlines: list of input commands after Python processing.
checkessential: boolean to check for essential commands or not.
Returns:
singlecmds: dict of commands that can only occur once in the model.
multiplecmds: dict of commands that can have multiple instances in the
multiplecmds: dict of commands that can have multiple instances in the
model.
geometry: list of geometry commands in the model.
"""
# Dictionaries of available commands
# Essential commands neccessary to run a gprMax model
essentialcmds = ['#domain', '#dx_dy_dz', '#time_window']
essentialcmds = ["#domain", "#dx_dy_dz", "#time_window"]
# Commands that there should only be one instance of in a model
singlecmds = dict.fromkeys(['#domain', '#dx_dy_dz', '#time_window',
'#title', '#omp_threads',
'#time_step_stability_factor', '#pml_cells',
'#excitation_file', '#src_steps', '#rx_steps',
'#output_dir'], None)
singlecmds = dict.fromkeys(
[
"#domain",
"#dx_dy_dz",
"#time_window",
"#title",
"#omp_threads",
"#time_step_stability_factor",
"#pml_cells",
"#excitation_file",
"#src_steps",
"#rx_steps",
"#output_dir",
],
None,
)
# Commands that there can be multiple instances of in a model
# - these will be lists within the dictionary
multiplecmds = {key: [] for key in ['#geometry_view',
'#geometry_objects_write', '#material',
'#material_range', '#material_list',
'#soil_peplinski',
'#add_dispersion_debye',
'#add_dispersion_lorentz',
'#add_dispersion_drude',
'#waveform', '#voltage_source',
'#hertzian_dipole', '#magnetic_dipole',
'#transmission_line', '#rx', '#rx_array',
'#snapshot', '#include_file']}
multiplecmds = {
key: []
for key in [
"#geometry_view",
"#geometry_objects_write",
"#material",
"#material_range",
"#material_list",
"#soil_peplinski",
"#add_dispersion_debye",
"#add_dispersion_lorentz",
"#add_dispersion_drude",
"#waveform",
"#voltage_source",
"#hertzian_dipole",
"#magnetic_dipole",
"#transmission_line",
"#rx",
"#rx_array",
"#snapshot",
"#include_file",
]
}
# Geometry object building commands that there can be multiple instances
# of in a model - these will be lists within the dictionary
geometrycmds = ['#geometry_objects_read', '#edge', '#plate', '#triangle',
'#box', '#sphere', '#ellipsoid', '#cone', '#cylinder',
'#cylindrical_sector', '#fractal_box',
'#add_surface_roughness', '#add_surface_water', '#add_grass']
geometrycmds = [
"#geometry_objects_read",
"#edge",
"#plate",
"#triangle",
"#box",
"#sphere",
"#ellipsoid",
"#cone",
"#cylinder",
"#cylindrical_sector",
"#fractal_box",
"#add_surface_roughness",
"#add_surface_water",
"#add_grass",
]
# List to store all geometry object commands in order from input file
geometry = []
@@ -235,26 +278,28 @@ def check_cmd_names(processedlines, checkessential=True):
# add command parameters to appropriate dictionary values or lists
countessentialcmds = 0
lindex = 0
while(lindex < len(processedlines)):
cmd = processedlines[lindex].split(':')
while lindex < len(processedlines):
cmd = processedlines[lindex].split(":")
cmdname = cmd[0]
cmdparams = cmd[1]
# Check if there is space between command name and parameters, i.e.
# check first character of parameter string. Ignore case when there
# are no parameters for a command, e.g. for #taguchi:
if ' ' not in cmdparams[0] and len(cmdparams.strip('\n')) != 0:
logger.exception('There must be a space between the command name ' +
'and parameters in ' + processedlines[lindex])
if " " not in cmdparams[0] and len(cmdparams.strip("\n")) != 0:
logger.exception(
"There must be a space between the command name " + "and parameters in " + processedlines[lindex]
)
raise SyntaxError
# Check if command name is valid
if (cmdname not in essentialcmds and
cmdname not in singlecmds and
cmdname not in multiplecmds and
cmdname not in geometrycmds):
logger.exception('Your input file contains an invalid command: ' +
cmdname)
if (
cmdname not in essentialcmds
and cmdname not in singlecmds
and cmdname not in multiplecmds
and cmdname not in geometrycmds
):
logger.exception("Your input file contains an invalid command: " + cmdname)
raise SyntaxError
# Count essential commands
@@ -264,25 +309,26 @@ def check_cmd_names(processedlines, checkessential=True):
# Assign command parameters as values to dictionary keys
if cmdname in singlecmds:
if singlecmds[cmdname] is None:
singlecmds[cmdname] = cmd[1].strip(' \t\n')
singlecmds[cmdname] = cmd[1].strip(" \t\n")
else:
logger.exception('You can only have a single instance of ' +
cmdname + ' in your model')
logger.exception("You can only have a single instance of " + cmdname + " in your model")
raise SyntaxError
elif cmdname in multiplecmds:
multiplecmds[cmdname].append(cmd[1].strip(' \t\n'))
multiplecmds[cmdname].append(cmd[1].strip(" \t\n"))
elif cmdname in geometrycmds:
geometry.append(processedlines[lindex].strip(' \t\n'))
geometry.append(processedlines[lindex].strip(" \t\n"))
lindex += 1
if checkessential:
if (countessentialcmds < len(essentialcmds)):
logger.exception('Your input file is missing essential commands ' +
'required to run a model. Essential commands are: ' +
', '.join(essentialcmds))
if countessentialcmds < len(essentialcmds):
logger.exception(
"Your input file is missing essential commands "
+ "required to run a model. Essential commands are: "
+ ", ".join(essentialcmds)
)
raise SyntaxError
return singlecmds, multiplecmds, geometry
@@ -328,19 +374,17 @@ def parse_hash_commands(scene):
"""
with open(config.sim_config.input_file_path) as inputfile:
usernamespace = config.get_model_config().get_usernamespace()
# Read input file and process any Python and include file commands
processedlines = process_python_include_code(inputfile, usernamespace)
# Print constants/variables in user-accessable namespace
uservars = ''
uservars = ""
for key, value in sorted(usernamespace.items()):
if key != '__builtins__':
uservars += f'{key}: {value}, '
logger.info(f'Constants/variables used/available for Python scripting: ' +
f'{{{uservars[:-2]}}}\n')
if key != "__builtins__":
uservars += f"{key}: {value}, "
logger.info(f"Constants/variables used/available for Python scripting: " + f"{{{uservars[:-2]}}}\n")
# Write a file containing the input commands after Python or include
# file commands have been processed
@@ -356,6 +400,7 @@ def parse_hash_commands(scene):
class Capturing(list):
"""Context manager to capture standard output stream."""
# https://stackoverflow.com/questions/16571150/how-to-capture-stdout-output-from-a-python-function-call
def __enter__(self):
@@ -365,13 +410,13 @@ class Capturing(list):
def __exit__(self, *args):
self.extend(self._stringio.getvalue().splitlines())
del self._stringio # free up some memory
del self._stringio # free up some memory
sys.stdout = self._stdout
def user_libs_fn_to_scene_obj(f, *args, **kwargs):
"""Function to convert library functions in the toolboxes directory
into geometry objects which can be added to the scene.
into geometry objects which can be added to the scene.
"""
with Capturing() as str_cmds:

查看文件

@@ -41,27 +41,27 @@ logger = logging.getLogger(__name__)
def check_averaging(averaging):
"""Check and set material averaging value.
Args:
averaging: string for input value from hash command - should be 'y'
or 'n'.
Args:
averaging: string for input value from hash command - should be 'y'
or 'n'.
Returns:
averaging: boolean for geometry object material averaging.
"""
Returns:
averaging: boolean for geometry object material averaging.
"""
if averaging == 'y':
if averaging == "y":
averaging = True
elif averaging == 'n':
elif averaging == "n":
averaging = False
else:
logger.exception('Averaging should be either y or n')
logger.exception("Averaging should be either y or n")
return averaging
def process_geometrycmds(geometry):
"""Checks the validity of command parameters, creates instances of classes
of parameters, and calls functions to directly set arrays solid, rigid
"""Checks the validity of command parameters, creates instances of classes
of parameters, and calls functions to directly set arrays solid, rigid
and ID.
Args:
@@ -76,13 +76,11 @@ def process_geometrycmds(geometry):
for object in geometry:
tmp = object.split()
if tmp[0] == '#geometry_objects_read:':
from .cmds_geometry.geometry_objects_read import \
GeometryObjectsRead
if tmp[0] == "#geometry_objects_read:":
from .cmds_geometry.geometry_objects_read import GeometryObjectsRead
if len(tmp) != 6:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires exactly five parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires exactly five parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -90,47 +88,49 @@ def process_geometrycmds(geometry):
gor = GeometryObjectsRead(p1=p1, geofile=tmp[4], matfile=tmp[5])
scene_objects.append(gor)
elif tmp[0] == '#edge:':
elif tmp[0] == "#edge:":
if len(tmp) != 8:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires exactly seven parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires exactly seven parameters")
raise ValueError
edge = Edge(p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
p2=(float(tmp[4]), float(tmp[5]), float(tmp[6])),
material_id=tmp[7])
edge = Edge(
p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
p2=(float(tmp[4]), float(tmp[5]), float(tmp[6])),
material_id=tmp[7],
)
scene_objects.append(edge)
elif tmp[0] == '#plate:':
elif tmp[0] == "#plate:":
if len(tmp) < 8:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least seven parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least seven parameters")
raise ValueError
# Isotropic case
if len(tmp) == 8:
plate = Plate(p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
p2=(float(tmp[4]), float(tmp[5]), float(tmp[6])),
material_id=tmp[7])
plate = Plate(
p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
p2=(float(tmp[4]), float(tmp[5]), float(tmp[6])),
material_id=tmp[7],
)
# Anisotropic case
elif len(tmp) == 9:
plate = Plate(p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
p2=(float(tmp[4]), float(tmp[5]), float(tmp[6])),
material_ids=tmp[7:])
plate = Plate(
p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
p2=(float(tmp[4]), float(tmp[5]), float(tmp[6])),
material_ids=tmp[7:],
)
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(plate)
elif tmp[0] == '#triangle:':
elif tmp[0] == "#triangle:":
if len(tmp) < 12:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least eleven parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least eleven parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -140,31 +140,26 @@ def process_geometrycmds(geometry):
# Isotropic case with no user specified averaging
if len(tmp) == 12:
triangle = Triangle(p1=p1, p2=p2, p3=p3, thickness=thickness,
material_id=tmp[11])
triangle = Triangle(p1=p1, p2=p2, p3=p3, thickness=thickness, material_id=tmp[11])
# Isotropic case with user specified averaging
elif len(tmp) == 13:
averaging = check_averaging(tmp[12].lower())
triangle = Triangle(p1=p1, p2=p2, p3=p3, thickness=thickness,
material_id=tmp[11], averaging=averaging)
triangle = Triangle(p1=p1, p2=p2, p3=p3, thickness=thickness, material_id=tmp[11], averaging=averaging)
# Uniaxial anisotropic case
elif len(tmp) == 14:
triangle = Triangle(p1=p1, p2=p2, p3=p3, thickness=thickness,
material_ids=tmp[11:])
triangle = Triangle(p1=p1, p2=p2, p3=p3, thickness=thickness, material_ids=tmp[11:])
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(triangle)
elif tmp[0] == '#box:':
elif tmp[0] == "#box:":
if len(tmp) < 8:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least seven parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least seven parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -184,16 +179,14 @@ def process_geometrycmds(geometry):
box = Box(p1=p1, p2=p2, material_ids=tmp[7:])
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(box)
elif tmp[0] == '#cylinder:':
elif tmp[0] == "#cylinder:":
if len(tmp) < 9:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least eight parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least eight parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -207,24 +200,21 @@ def process_geometrycmds(geometry):
# Isotropic case with user specified averaging
elif len(tmp) == 10:
averaging = check_averaging(tmp[9].lower())
cylinder = Cylinder(p1=p1, p2=p2, r=r, material_id=tmp[8],
averaging=averaging)
cylinder = Cylinder(p1=p1, p2=p2, r=r, material_id=tmp[8], averaging=averaging)
# Uniaxial anisotropic case
elif len(tmp) == 11:
cylinder = Cylinder(p1=p1, p2=p2, r=r, material_ids=tmp[8:])
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(cylinder)
elif tmp[0] == '#cone:':
elif tmp[0] == "#cone:":
if len(tmp) < 10:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least nine parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least nine parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -239,24 +229,21 @@ def process_geometrycmds(geometry):
# Isotropic case with user specified averaging
elif len(tmp) == 11:
averaging = check_averaging(tmp[10].lower())
cone = Cone(p1=p1, p2=p2, r1=r1, r2=r2, material_id=tmp[9],
averaging=averaging)
cone = Cone(p1=p1, p2=p2, r1=r1, r2=r2, material_id=tmp[9], averaging=averaging)
# Uniaxial anisotropic case
elif len(tmp) == 12:
cone = Cone(p1=p1, p2=p2, r1=r1, r2=r2, material_ids=tmp[9:])
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(cone)
elif tmp[0] == '#cylindrical_sector:':
elif tmp[0] == "#cylindrical_sector:":
if len(tmp) < 10:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least nine parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least nine parameters")
raise ValueError
normal = tmp[1].lower()
@@ -270,41 +257,57 @@ def process_geometrycmds(geometry):
# Isotropic case with no user specified averaging
if len(tmp) == 10:
cylindrical_sector = CylindricalSector(normal=normal, ctr1=ctr1,
ctr2=ctr2, extent1=extent1,
extent2=extent2, r=r,
start=start, end=end,
material_id=tmp[9])
cylindrical_sector = CylindricalSector(
normal=normal,
ctr1=ctr1,
ctr2=ctr2,
extent1=extent1,
extent2=extent2,
r=r,
start=start,
end=end,
material_id=tmp[9],
)
# Isotropic case with user specified averaging
elif len(tmp) == 11:
averaging = check_averaging(tmp[10].lower())
cylindrical_sector = CylindricalSector(normal=normal, ctr1=ctr1,
ctr2=ctr2, extent1=extent1,
extent2=extent2, r=r,
start=start, end=end,
averaging=averaging,
material_id=tmp[9])
cylindrical_sector = CylindricalSector(
normal=normal,
ctr1=ctr1,
ctr2=ctr2,
extent1=extent1,
extent2=extent2,
r=r,
start=start,
end=end,
averaging=averaging,
material_id=tmp[9],
)
# Uniaxial anisotropic case
elif len(tmp) == 12:
cylindrical_sector = CylindricalSector(normal=normal, ctr1=ctr1,
ctr2=ctr2, extent1=extent1,
extent2=extent2, r=r,
start=start, end=end,
material_ids=tmp[9:])
cylindrical_sector = CylindricalSector(
normal=normal,
ctr1=ctr1,
ctr2=ctr2,
extent1=extent1,
extent2=extent2,
r=r,
start=start,
end=end,
material_ids=tmp[9:],
)
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(cylindrical_sector)
elif tmp[0] == '#sphere:':
elif tmp[0] == "#sphere:":
if len(tmp) < 6:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least five parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least five parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -317,24 +320,21 @@ def process_geometrycmds(geometry):
# Isotropic case with user specified averaging
elif len(tmp) == 7:
averaging = check_averaging(tmp[6].lower())
sphere = Sphere(p1=p1, r=r, material_id=tmp[5],
averaging=averaging)
sphere = Sphere(p1=p1, r=r, material_id=tmp[5], averaging=averaging)
# Uniaxial anisotropic case
elif len(tmp) == 8:
sphere = Sphere(p1=p1, r=r, material_id=tmp[5:])
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(sphere)
elif tmp[0] == '#ellipsoid:':
elif tmp[0] == "#ellipsoid:":
if len(tmp) < 8:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least seven parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least seven parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -344,33 +344,28 @@ def process_geometrycmds(geometry):
# Isotropic case with no user specified averaging
if len(tmp) == 8:
ellipsoid = Ellipsoid(p1=p1, xr=xr, yr=yr, zr=zr,
material_id=tmp[7])
ellipsoid = Ellipsoid(p1=p1, xr=xr, yr=yr, zr=zr, material_id=tmp[7])
# Isotropic case with user specified averaging
elif len(tmp) == 9:
averaging = check_averaging(tmp[8].lower())
ellipsoid = Ellipsoid(p1=p1, xr=xr, yr=yr, zr=zr,
material_id=tmp[7], averaging=averaging)
ellipsoid = Ellipsoid(p1=p1, xr=xr, yr=yr, zr=zr, material_id=tmp[7], averaging=averaging)
# Uniaxial anisotropic case
elif len(tmp) == 8:
ellipsoid = Ellipsoid(p1=p1, xr=xr, yr=yr, zr=zr,
material_id=tmp[7:])
ellipsoid = Ellipsoid(p1=p1, xr=xr, yr=yr, zr=zr, material_id=tmp[7:])
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(ellipsoid)
elif tmp[0] == '#fractal_box:':
elif tmp[0] == "#fractal_box:":
# Default is no dielectric smoothing for a fractal box
if len(tmp) < 14:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least thirteen parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least thirteen parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -382,22 +377,40 @@ def process_geometrycmds(geometry):
ID = tmp[13]
if len(tmp) == 14:
fb = FractalBox(p1=p1, p2=p2, frac_dim=frac_dim,
weighting=weighting, n_materials=n_materials,
mixing_model_id=mixing_model_id, id=ID)
fb = FractalBox(
p1=p1,
p2=p2,
frac_dim=frac_dim,
weighting=weighting,
n_materials=n_materials,
mixing_model_id=mixing_model_id,
id=ID,
)
elif len(tmp) == 15:
fb = FractalBox(p1=p1, p2=p2, frac_dim=frac_dim,
weighting=weighting, n_materials=n_materials,
mixing_model_id=mixing_model_id, id=ID,
seed=tmp[14])
fb = FractalBox(
p1=p1,
p2=p2,
frac_dim=frac_dim,
weighting=weighting,
n_materials=n_materials,
mixing_model_id=mixing_model_id,
id=ID,
seed=tmp[14],
)
elif len(tmp) == 16:
fb = FractalBox(p1=p1, p2=p2, frac_dim=frac_dim,
weighting=weighting, n_materials=n_materials,
mixing_model_id=mixing_model_id, id=ID,
seed=tmp[14], averaging=tmp[15].lower())
fb = FractalBox(
p1=p1,
p2=p2,
frac_dim=frac_dim,
weighting=weighting,
n_materials=n_materials,
mixing_model_id=mixing_model_id,
id=ID,
seed=tmp[14],
averaging=tmp[15].lower(),
)
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(fb)
@@ -406,10 +419,9 @@ def process_geometrycmds(geometry):
for object in geometry:
tmp = object.split()
if tmp[0] == '#add_surface_roughness:':
if tmp[0] == "#add_surface_roughness:":
if len(tmp) < 13:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least twelve parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least twelve parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -420,25 +432,33 @@ def process_geometrycmds(geometry):
fractal_box_id = tmp[12]
if len(tmp) == 13:
asr = AddSurfaceRoughness(p1=p1, p2=p2, frac_dim=frac_dim,
weighting=weighting, limits=limits,
fractal_box_id=fractal_box_id)
asr = AddSurfaceRoughness(
p1=p1,
p2=p2,
frac_dim=frac_dim,
weighting=weighting,
limits=limits,
fractal_box_id=fractal_box_id,
)
elif len(tmp) == 14:
asr = AddSurfaceRoughness(p1=p1, p2=p2, frac_dim=frac_dim,
weighting=weighting, limits=limits,
fractal_box_id=fractal_box_id,
seed=int(tmp[13]))
asr = AddSurfaceRoughness(
p1=p1,
p2=p2,
frac_dim=frac_dim,
weighting=weighting,
limits=limits,
fractal_box_id=fractal_box_id,
seed=int(tmp[13]),
)
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(asr)
if tmp[0] == '#add_surface_water:':
if tmp[0] == "#add_surface_water:":
if len(tmp) != 9:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires exactly eight parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires exactly eight parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -446,14 +466,12 @@ def process_geometrycmds(geometry):
depth = float(tmp[7])
fractal_box_id = tmp[8]
asf = AddSurfaceWater(p1=p1, p2=p2, depth=depth,
fractal_box_id=fractal_box_id)
asf = AddSurfaceWater(p1=p1, p2=p2, depth=depth, fractal_box_id=fractal_box_id)
scene_objects.append(asf)
if tmp[0] == '#add_grass:':
if tmp[0] == "#add_grass:":
if len(tmp) < 12:
logger.exception("'" + ' '.join(tmp) + "'" +
' requires at least eleven parameters')
logger.exception("'" + " ".join(tmp) + "'" + " requires at least eleven parameters")
raise ValueError
p1 = (float(tmp[1]), float(tmp[2]), float(tmp[3]))
@@ -464,19 +482,28 @@ def process_geometrycmds(geometry):
fractal_box_id = tmp[11]
if len(tmp) == 12:
grass = AddGrass(p1=p1, p2=p2, frac_dim=frac_dim,
limits=limits, n_blades=n_blades,
fractal_box_id=fractal_box_id)
grass = AddGrass(
p1=p1,
p2=p2,
frac_dim=frac_dim,
limits=limits,
n_blades=n_blades,
fractal_box_id=fractal_box_id,
)
elif len(tmp) == 13:
grass = AddGrass(p1=p1, p2=p2, frac_dim=frac_dim,
limits=limits, n_blades=n_blades,
fractal_box_id=fractal_box_id,
seed=int(tmp[12]))
grass = AddGrass(
p1=p1,
p2=p2,
frac_dim=frac_dim,
limits=limits,
n_blades=n_blades,
fractal_box_id=fractal_box_id,
seed=int(tmp[12]),
)
else:
logger.exception("'" + ' '.join(tmp) + "'" +
' too many parameters have been given')
logger.exception("'" + " ".join(tmp) + "'" + " too many parameters have been given")
raise ValueError
scene_objects.append(grass)
return scene_objects
return scene_objects

查看文件

@@ -18,12 +18,25 @@
import logging
from .cmds_multiuse import (AddDebyeDispersion, AddDrudeDispersion,
AddLorentzDispersion, GeometryObjectsWrite,
GeometryView, HertzianDipole, MagneticDipole,
Material, MaterialList, MaterialRange, Rx, RxArray,
Snapshot, SoilPeplinski, TransmissionLine,
VoltageSource, Waveform)
from .cmds_multiuse import (
AddDebyeDispersion,
AddDrudeDispersion,
AddLorentzDispersion,
GeometryObjectsWrite,
GeometryView,
HertzianDipole,
MagneticDipole,
Material,
MaterialList,
MaterialRange,
Rx,
RxArray,
Snapshot,
SoilPeplinski,
TransmissionLine,
VoltageSource,
Waveform,
)
logger = logging.getLogger(__name__)
@@ -41,137 +54,143 @@ def process_multicmds(multicmds):
scene_objects = []
cmdname = '#waveform'
cmdname = "#waveform"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) != 4:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires exactly four parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires exactly four parameters")
raise ValueError
waveform = Waveform(wave_type=tmp[0], amp=float(tmp[1]),
freq=float(tmp[2]), id=tmp[3])
waveform = Waveform(wave_type=tmp[0], amp=float(tmp[1]), freq=float(tmp[2]), id=tmp[3])
scene_objects.append(waveform)
cmdname = '#voltage_source'
cmdname = "#voltage_source"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) == 6:
voltage_source = VoltageSource(polarisation=tmp[0].lower(),
p1=(float(tmp[1]), float(tmp[2]),
float(tmp[3])), resistance=float(tmp[4]),
waveform_id=tmp[5])
voltage_source = VoltageSource(
polarisation=tmp[0].lower(),
p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
resistance=float(tmp[4]),
waveform_id=tmp[5],
)
elif len(tmp) == 8:
voltage_source = VoltageSource(polarisation=tmp[0].lower(),
p1=(float(tmp[1]), float(tmp[2]),
float(tmp[3])), resistance=float(tmp[4]),
waveform_id=tmp[5], start=float(tmp[6]),
end=float(tmp[7]))
voltage_source = VoltageSource(
polarisation=tmp[0].lower(),
p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
resistance=float(tmp[4]),
waveform_id=tmp[5],
start=float(tmp[6]),
end=float(tmp[7]),
)
else:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at least six parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at least six parameters")
raise ValueError
scene_objects.append(voltage_source)
cmdname = '#hertzian_dipole'
cmdname = "#hertzian_dipole"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) < 5:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at least five parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at least five parameters")
raise ValueError
if len(tmp) == 5:
hertzian_dipole = HertzianDipole(polarisation=tmp[0], p1=(float(tmp[1]),
float(tmp[2]), float(tmp[3])),
waveform_id=tmp[4])
hertzian_dipole = HertzianDipole(
polarisation=tmp[0], p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])), waveform_id=tmp[4]
)
elif len(tmp) == 7:
hertzian_dipole = HertzianDipole(polarisation=tmp[0], p1=(float(tmp[1]),
float(tmp[2]), float(tmp[3])),
waveform_id=tmp[4], start=float(tmp[5]),
end=float(tmp[6]))
hertzian_dipole = HertzianDipole(
polarisation=tmp[0],
p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
waveform_id=tmp[4],
start=float(tmp[5]),
end=float(tmp[6]),
)
else:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' too many parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " too many parameters")
raise ValueError
scene_objects.append(hertzian_dipole)
cmdname = '#magnetic_dipole'
cmdname = "#magnetic_dipole"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) < 5:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at least five parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at least five parameters")
raise ValueError
if len(tmp) == 5:
magnetic_dipole = MagneticDipole(polarisation=tmp[0], p1=(float(tmp[1]),
float(tmp[2]), float(tmp[3])),
waveform_id=tmp[4])
magnetic_dipole = MagneticDipole(
polarisation=tmp[0], p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])), waveform_id=tmp[4]
)
elif len(tmp) == 7:
magnetic_dipole = MagneticDipole(polarisation=tmp[0], p1=(float(tmp[1]),
float(tmp[2]), float(tmp[3])),
waveform_id=tmp[4], start=float(tmp[5]),
end=float(tmp[6]))
magnetic_dipole = MagneticDipole(
polarisation=tmp[0],
p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
waveform_id=tmp[4],
start=float(tmp[5]),
end=float(tmp[6]),
)
else:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' too many parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " too many parameters")
raise ValueError
scene_objects.append(magnetic_dipole)
cmdname = '#transmission_line'
cmdname = "#transmission_line"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) < 6:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at least six parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at least six parameters")
raise ValueError
if len(tmp) == 6:
tl = TransmissionLine(polarisation=tmp[0], p1=(float(tmp[1]),
float(tmp[2]), float(tmp[3])),
resistance=float(tmp[4]), waveform_id=tmp[5])
tl = TransmissionLine(
polarisation=tmp[0],
p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
resistance=float(tmp[4]),
waveform_id=tmp[5],
)
elif len(tmp) == 8:
tl = TransmissionLine(polarisation=tmp[0], p1=(float(tmp[1]),
float(tmp[2]), float(tmp[3])),
resistance=float(tmp[4]), waveform_id=tmp[5],
start=tmp[6], end=tmp[7])
tl = TransmissionLine(
polarisation=tmp[0],
p1=(float(tmp[1]), float(tmp[2]), float(tmp[3])),
resistance=float(tmp[4]),
waveform_id=tmp[5],
start=tmp[6],
end=tmp[7],
)
else:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' too many parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " too many parameters")
raise ValueError
scene_objects.append(tl)
cmdname = '#rx'
cmdname = "#rx"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) != 3 and len(tmp) < 5:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' has an incorrect number of parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " has an incorrect number of parameters")
raise ValueError
if len(tmp) == 3:
rx = Rx(p1=(float(tmp[0]), float(tmp[1]), float(tmp[2])))
else:
rx = Rx(p1=(float(tmp[0]), float(tmp[1]), float(tmp[2])),
id=tmp[3], outputs=' '.join(tmp[4:]))
rx = Rx(p1=(float(tmp[0]), float(tmp[1]), float(tmp[2])), id=tmp[3], outputs=" ".join(tmp[4:]))
scene_objects.append(rx)
cmdname = '#rx_array'
cmdname = "#rx_array"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) != 9:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires exactly nine parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires exactly nine parameters")
raise ValueError
p1 = (float(tmp[0]), float(tmp[1]), float(tmp[2]))
@@ -181,13 +200,12 @@ def process_multicmds(multicmds):
rx_array = RxArray(p1=p1, p2=p2, dl=dl)
scene_objects.append(rx_array)
cmdname = '#snapshot'
cmdname = "#snapshot"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) != 11:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires exactly eleven parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires exactly eleven parameters")
raise ValueError
p1 = (float(tmp[0]), float(tmp[1]), float(tmp[2]))
@@ -197,64 +215,57 @@ def process_multicmds(multicmds):
try:
iterations = int(tmp[9])
snapshot = Snapshot(p1=p1, p2=p2, dl=dl, iterations=iterations,
filename=filename)
snapshot = Snapshot(p1=p1, p2=p2, dl=dl, iterations=iterations, filename=filename)
except ValueError:
time = float(tmp[9])
snapshot = Snapshot(p1=p1, p2=p2, dl=dl, time=time,
filename=filename)
snapshot = Snapshot(p1=p1, p2=p2, dl=dl, time=time, filename=filename)
scene_objects.append(snapshot)
cmdname = '#material'
cmdname = "#material"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) != 5:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires exactly five parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires exactly five parameters")
raise ValueError
material = Material(er=float(tmp[0]), se=float(tmp[1]),
mr=float(tmp[2]), sm=float(tmp[3]), id=tmp[4])
material = Material(er=float(tmp[0]), se=float(tmp[1]), mr=float(tmp[2]), sm=float(tmp[3]), id=tmp[4])
scene_objects.append(material)
cmdname = '#add_dispersion_debye'
cmdname = "#add_dispersion_debye"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) < 4:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at least four parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at least four parameters")
raise ValueError
poles = int(tmp[0])
er_delta = []
tau = []
material_ids = tmp[(2 * poles) + 1:len(tmp)]
material_ids = tmp[(2 * poles) + 1 : len(tmp)]
for pole in range(1, 2 * poles, 2):
er_delta.append(float(tmp[pole]))
tau.append(float(tmp[pole + 1]))
debye_dispersion = AddDebyeDispersion(poles=poles, er_delta=er_delta,
tau=tau, material_ids=material_ids)
debye_dispersion = AddDebyeDispersion(poles=poles, er_delta=er_delta, tau=tau, material_ids=material_ids)
scene_objects.append(debye_dispersion)
cmdname = '#add_dispersion_lorentz'
cmdname = "#add_dispersion_lorentz"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) < 5:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at least five parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at least five parameters")
raise ValueError
poles = int(tmp[0])
material_ids = tmp[(3 * poles) + 1:len(tmp)]
material_ids = tmp[(3 * poles) + 1 : len(tmp)]
er_delta = []
tau = []
alpha = []
@@ -264,24 +275,22 @@ def process_multicmds(multicmds):
tau.append(float(tmp[pole + 1]))
alpha.append(float(tmp[pole + 2]))
lorentz_dispersion = AddLorentzDispersion(poles=poles,
material_ids=material_ids,
er_delta=er_delta, tau=tau,
alpha=alpha)
lorentz_dispersion = AddLorentzDispersion(
poles=poles, material_ids=material_ids, er_delta=er_delta, tau=tau, alpha=alpha
)
scene_objects.append(lorentz_dispersion)
cmdname = '#add_dispersion_drude'
cmdname = "#add_dispersion_drude"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) < 5:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at least five parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at least five parameters")
raise ValueError
poles = int(tmp[0])
material_ids = tmp[(3 * poles) + 1:len(tmp)]
material_ids = tmp[(3 * poles) + 1 : len(tmp)]
tau = []
alpha = []
@@ -289,53 +298,49 @@ def process_multicmds(multicmds):
tau.append(float(tmp[pole]))
alpha.append(float(tmp[pole + 1]))
drude_dispersion = AddDrudeDispersion(poles=poles,
material_ids=material_ids,
tau=tau, alpha=alpha)
drude_dispersion = AddDrudeDispersion(poles=poles, material_ids=material_ids, tau=tau, alpha=alpha)
scene_objects.append(drude_dispersion)
cmdname = '#soil_peplinski'
cmdname = "#soil_peplinski"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) != 7:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at exactly seven parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at exactly seven parameters")
raise ValueError
soil = SoilPeplinski(sand_fraction=float(tmp[0]),
clay_fraction=float(tmp[1]),
bulk_density=float(tmp[2]),
sand_density=float(tmp[3]),
water_fraction_lower=float(tmp[4]),
water_fraction_upper=float(tmp[5]),
id=tmp[6])
soil = SoilPeplinski(
sand_fraction=float(tmp[0]),
clay_fraction=float(tmp[1]),
bulk_density=float(tmp[2]),
sand_density=float(tmp[3]),
water_fraction_lower=float(tmp[4]),
water_fraction_upper=float(tmp[5]),
id=tmp[6],
)
scene_objects.append(soil)
cmdname = '#geometry_view'
cmdname = "#geometry_view"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) != 11:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires exactly eleven parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires exactly eleven parameters")
raise ValueError
p1 = float(tmp[0]), float(tmp[1]), float(tmp[2])
p2 = float(tmp[3]), float(tmp[4]), float(tmp[5])
dl = float(tmp[6]), float(tmp[7]), float(tmp[8])
geometry_view = GeometryView(p1=p1, p2=p2, dl=dl, filename=tmp[9],
output_type=tmp[10])
geometry_view = GeometryView(p1=p1, p2=p2, dl=dl, filename=tmp[9], output_type=tmp[10])
scene_objects.append(geometry_view)
cmdname = '#geometry_objects_write'
cmdname = "#geometry_objects_write"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) != 7:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires exactly seven parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires exactly seven parameters")
raise ValueError
p1 = float(tmp[0]), float(tmp[1]), float(tmp[2])
@@ -343,43 +348,42 @@ def process_multicmds(multicmds):
gow = GeometryObjectsWrite(p1=p1, p2=p2, filename=tmp[6])
scene_objects.append(gow)
cmdname = '#material_range'
cmdname = "#material_range"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) != 9:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at exactly nine parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at exactly nine parameters")
raise ValueError
material_range = MaterialRange(er_lower=float(tmp[0]),
er_upper=float(tmp[1]),
sigma_lower=float(tmp[2]),
sigma_upper=float(tmp[3]),
mr_lower=float(tmp[4]),
mr_upper=float(tmp[5]),
ro_lower=float(tmp[6]),
ro_upper=float(tmp[7]),
id=tmp[8])
material_range = MaterialRange(
er_lower=float(tmp[0]),
er_upper=float(tmp[1]),
sigma_lower=float(tmp[2]),
sigma_upper=float(tmp[3]),
mr_lower=float(tmp[4]),
mr_upper=float(tmp[5]),
ro_lower=float(tmp[6]),
ro_upper=float(tmp[7]),
id=tmp[8],
)
scene_objects.append(material_range)
cmdname = '#material_list'
cmdname = "#material_list"
if multicmds[cmdname] is not None:
for cmdinstance in multicmds[cmdname]:
tmp = cmdinstance.split()
if len(tmp) < 2:
logger.exception("'" + cmdname + ': ' + ' '.join(tmp) + "'" +
' requires at least 2 parameters')
logger.exception("'" + cmdname + ": " + " ".join(tmp) + "'" + " requires at least 2 parameters")
raise ValueError
tokens = len(tmp)
lmats = []
for iter in range(tokens-1):
for iter in range(tokens - 1):
lmats.append(tmp[iter])
material_list = MaterialList(list_of_materials=lmats,
id=tmp[tokens-1])
material_list = MaterialList(list_of_materials=lmats, id=tmp[tokens - 1])
scene_objects.append(material_list)
return scene_objects
return scene_objects

查看文件

@@ -18,10 +18,19 @@
import logging
from .cmds_singleuse import (Discretisation, Domain, ExcitationFile,
OMPThreads, OutputDir, PMLProps, RxSteps,
SrcSteps, TimeStepStabilityFactor, TimeWindow,
Title)
from .cmds_singleuse import (
Discretisation,
Domain,
ExcitationFile,
OMPThreads,
OutputDir,
PMLProps,
RxSteps,
SrcSteps,
TimeStepStabilityFactor,
TimeWindow,
Title,
)
logger = logging.getLogger(__name__)
@@ -40,62 +49,65 @@ def process_singlecmds(singlecmds):
scene_objects = []
# Check validity of command parameters in order needed
cmd = '#title'
cmd = "#title"
if singlecmds[cmd] is not None:
title = Title(name=str(singlecmds[cmd]))
scene_objects.append(title)
cmd = '#output_dir'
cmd = "#output_dir"
if singlecmds[cmd] is not None:
output_dir = OutputDir(dir=singlecmds[cmd])
scene_objects.append(output_dir)
# Number of threads for CPU-based (OpenMP) parallelised parts of code
cmd = '#omp_threads'
cmd = "#omp_threads"
if singlecmds[cmd] is not None:
tmp = tuple(int(x) for x in singlecmds[cmd].split())
if len(tmp) != 1:
logger.exception(f'{cmd} requires exactly one parameter to specify ' +
f'the number of CPU OpenMP threads to use')
logger.exception(
f"{cmd} requires exactly one parameter to specify " + f"the number of CPU OpenMP threads to use"
)
raise ValueError
omp_threads = OMPThreads(n=tmp[0])
scene_objects.append(omp_threads)
cmd = '#dx_dy_dz'
cmd = "#dx_dy_dz"
if singlecmds[cmd] is not None:
tmp = [float(x) for x in singlecmds[cmd].split()]
if len(tmp) != 3:
logger.exception(f'{cmd} requires exactly three parameters')
logger.exception(f"{cmd} requires exactly three parameters")
raise ValueError
dl = (tmp[0], tmp[1], tmp[2])
discretisation = Discretisation(p1=dl)
scene_objects.append(discretisation)
cmd = '#domain'
cmd = "#domain"
if singlecmds[cmd] is not None:
tmp = [float(x) for x in singlecmds[cmd].split()]
if len(tmp) != 3:
logger.exception(f'{cmd} requires exactly three parameters')
logger.exception(f"{cmd} requires exactly three parameters")
raise ValueError
p1 = (tmp[0], tmp[1], tmp[2])
domain = Domain(p1=p1)
scene_objects.append(domain)
cmd = '#time_step_stability_factor'
cmd = "#time_step_stability_factor"
if singlecmds[cmd] is not None:
tmp = tuple(float(x) for x in singlecmds[cmd].split())
tsf = TimeStepStabilityFactor(f=tmp[0])
scene_objects.append(tsf)
cmd = '#time_window'
cmd = "#time_window"
if singlecmds[cmd] is not None:
tmp = singlecmds[cmd].split()
if len(tmp) != 1:
logger.exception(f'{cmd} requires exactly one parameter to specify the ' +
f'time window. Either in seconds or number of iterations.')
logger.exception(
f"{cmd} requires exactly one parameter to specify the "
+ f"time window. Either in seconds or number of iterations."
)
raise ValueError
tmp = tmp[0].lower()
@@ -110,40 +122,37 @@ def process_singlecmds(singlecmds):
scene_objects.append(tw)
cmd = '#pml_cells'
cmd = "#pml_cells"
if singlecmds[cmd] is not None:
tmp = singlecmds[cmd].split()
if len(tmp) not in [1, 6]:
logger.exception(f'{cmd} requires either one or six parameter(s)')
logger.exception(f"{cmd} requires either one or six parameter(s)")
raise ValueError
if len(tmp) == 1:
pml_cells = PMLProps(thickness=int(tmp[0]))
else:
pml_cells = PMLProps(x0=int(tmp[0]),
y0=int(tmp[1]),
z0=int(tmp[2]),
xmax=int(tmp[3]),
ymax=int(tmp[4]),
zmax=int(tmp[5]))
pml_cells = PMLProps(
x0=int(tmp[0]), y0=int(tmp[1]), z0=int(tmp[2]), xmax=int(tmp[3]), ymax=int(tmp[4]), zmax=int(tmp[5])
)
scene_objects.append(pml_cells)
cmd = '#src_steps'
cmd = "#src_steps"
if singlecmds[cmd] is not None:
tmp = singlecmds[cmd].split()
if len(tmp) != 3:
logger.exception(f'{cmd} requires exactly three parameters')
logger.exception(f"{cmd} requires exactly three parameters")
raise ValueError
p1 = (float(tmp[0]), float(tmp[1]), float(tmp[2]))
src_steps = SrcSteps(p1=p1)
scene_objects.append(src_steps)
cmd = '#rx_steps'
cmd = "#rx_steps"
if singlecmds[cmd] is not None:
tmp = singlecmds[cmd].split()
if len(tmp) != 3:
logger.exception(f'{cmd} requires exactly three parameters')
logger.exception(f"{cmd} requires exactly three parameters")
raise ValueError
p1 = (float(tmp[0]), float(tmp[1]), float(tmp[2]))
@@ -151,11 +160,11 @@ def process_singlecmds(singlecmds):
scene_objects.append(rx_steps)
# Excitation file for user-defined source waveforms
cmd = '#excitation_file'
cmd = "#excitation_file"
if singlecmds[cmd] is not None:
tmp = singlecmds[cmd].split()
if len(tmp) not in [1, 3]:
logger.exception(f'{cmd} requires either one or three parameter(s)')
logger.exception(f"{cmd} requires either one or three parameter(s)")
raise ValueError
if len(tmp) > 1:

查看文件

@@ -25,9 +25,10 @@ import gprMax.config as config
logger = logging.getLogger(__name__)
class Material:
"""Super-class to describe generic, non-dispersive materials,
their properties and update coefficients.
their properties and update coefficients.
"""
def __init__(self, numID, ID):
@@ -39,7 +40,7 @@ class Material:
self.numID = numID
self.ID = ID
self.type = ''
self.type = ""
# Default material averaging
self.averagable = True
@@ -71,10 +72,10 @@ class Material:
G: FDTDGrid class describing a grid in a model.
"""
EA = (config.sim_config.em_consts['e0'] * self.er / G.dt) + 0.5 * self.se
EB = (config.sim_config.em_consts['e0'] * self.er / G.dt) - 0.5 * self.se
EA = (config.sim_config.em_consts["e0"] * self.er / G.dt) + 0.5 * self.se
EB = (config.sim_config.em_consts["e0"] * self.er / G.dt) - 0.5 * self.se
if self.ID == 'pec' or self.se == float('inf'):
if self.ID == "pec" or self.se == float("inf"):
self.CA = 0
self.CBx = 0
self.CBy = 0
@@ -104,7 +105,7 @@ class Material:
class DispersiveMaterial(Material):
"""Class to describe materials with frequency dependent properties, e.g.
Debye, Drude, Lorenz.
Debye, Drude, Lorenz.
"""
# Properties of water from: http://dx.doi.org/10.1109/TGRS.2006.873208
@@ -135,46 +136,64 @@ class DispersiveMaterial(Material):
# 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.get_model_config().materials['maxpoles'],
dtype=config.get_model_config().materials['dispersivedtype'])
self.q = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.get_model_config().materials['dispersivedtype'])
self.zt = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.get_model_config().materials['dispersivedtype'])
self.zt2 = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.get_model_config().materials['dispersivedtype'])
self.eqt = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.get_model_config().materials['dispersivedtype'])
self.eqt2 = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.get_model_config().materials['dispersivedtype'])
self.w = np.zeros(
config.get_model_config().materials["maxpoles"],
dtype=config.get_model_config().materials["dispersivedtype"],
)
self.q = np.zeros(
config.get_model_config().materials["maxpoles"],
dtype=config.get_model_config().materials["dispersivedtype"],
)
self.zt = np.zeros(
config.get_model_config().materials["maxpoles"],
dtype=config.get_model_config().materials["dispersivedtype"],
)
self.zt2 = np.zeros(
config.get_model_config().materials["maxpoles"],
dtype=config.get_model_config().materials["dispersivedtype"],
)
self.eqt = np.zeros(
config.get_model_config().materials["maxpoles"],
dtype=config.get_model_config().materials["dispersivedtype"],
)
self.eqt2 = np.zeros(
config.get_model_config().materials["maxpoles"],
dtype=config.get_model_config().materials["dispersivedtype"],
)
for x in range(self.poles):
if 'debye' in self.type:
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:
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:
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
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.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.sim_config.em_consts['e0'] * self.er / G.dt) + 0.5 * self.se -
(config.sim_config.em_consts['e0'] / G.dt) * np.sum(self.zt2.real))
EB = ((config.sim_config.em_consts['e0'] * self.er / G.dt) - 0.5 * self.se -
(config.sim_config.em_consts['e0'] / G.dt) * np.sum(self.zt2.real))
EA = (
(config.sim_config.em_consts["e0"] * self.er / G.dt)
+ 0.5 * self.se
- (config.sim_config.em_consts["e0"] / G.dt) * np.sum(self.zt2.real)
)
EB = (
(config.sim_config.em_consts["e0"] * self.er / G.dt)
- 0.5 * self.se
- (config.sim_config.em_consts["e0"] / G.dt) * np.sum(self.zt2.real)
)
self.CA = EB / EA
self.CBx = (1 / G.dx) * 1 / EA
@@ -198,30 +217,30 @@ class DispersiveMaterial(Material):
er = self.er
w = 2 * np.pi * freq
er += self.se / (1j * w * config.sim_config.em_consts['e0'])
if 'debye' in self.type:
er += self.se / (1j * w * config.sim_config.em_consts["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:
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:
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])
ersum += self.tau[pole] ** 2 / (w**2 - 1j * w * self.alpha[pole])
er -= ersum
return er
class PeplinskiSoil:
"""Soil objects that are characterised according to a mixing model
by Peplinski (http://dx.doi.org/10.1109/36.387598).
by Peplinski (http://dx.doi.org/10.1109/36.387598).
"""
def __init__(self, ID, sandfraction, clayfraction, bulkdensity,
sandpartdensity, watervolfraction):
def __init__(self, ID, sandfraction, clayfraction, bulkdensity, sandpartdensity, watervolfraction):
"""
Args:
ID: string for name of the soil.
@@ -230,8 +249,8 @@ class PeplinskiSoil:
bulkdensity: float of bulk density of the soil (g/cm3).
sandpartdensity: float of density of the sand particles in the
soil (g/cm3).
watervolfraction: tuple of floats of two numbers that specify a
range for the volumetric water fraction of the
watervolfraction: tuple of floats of two numbers that specify a
range for the volumetric water fraction of the
soil.
"""
@@ -242,7 +261,7 @@ class PeplinskiSoil:
self.rs = sandpartdensity
self.mu = watervolfraction
# Store all of the material IDs which allows for more general mixing models.
self.matID = []
self.matID = []
def calculate_properties(self, nbins, G):
"""Calculates the real and imaginery part of a Debye model for the soil
@@ -260,10 +279,10 @@ class PeplinskiSoil:
watereri, waterer, watertau, watersig = calculate_water_properties(T, S)
f = 1.3e9
w = 2 * np.pi * f
erealw = watereri + ((waterer - watereri) / (1 + (w * watertau)**2))
erealw = watereri + ((waterer - watereri) / (1 + (w * watertau) ** 2))
a = 0.65 # Experimentally derived constant
es = (1.01 + 0.44 * self.rs)**2 - 0.062 #  Relative permittivity of sand particles
es = (1.01 + 0.44 * self.rs) ** 2 - 0.062 #  Relative permittivity of sand particles
b1 = 1.2748 - 0.519 * self.S - 0.152 * self.C
b2 = 1.33797 - 0.603 * self.S - 0.166 * self.C
@@ -272,44 +291,43 @@ class PeplinskiSoil:
# For frequencies in the range 1.4GHz to 18GHz
# sigf = -1.645 + 1.939 * self.rb - 2.25622 * self.S + 1.594 * self.C
# Generate a set of bins based on the given volumetric water fraction
# values. Changed to make sure mid points are contained completely within the ranges.
# Generate a set of bins based on the given volumetric water fraction
# values. Changed to make sure mid points are contained completely within the ranges.
# The limiting values of the ranges are not included in this.
mubins = np.linspace(self.mu[0], self.mu[1], nbins + 1)
# Generate a range of volumetric water fraction values the mid-point of
# Generate a range of volumetric water fraction values the mid-point of
# each bin to make materials from
mumaterials = 0.5 * (mubins[1:nbins+1] + mubins[0:nbins])
mumaterials = 0.5 * (mubins[1 : nbins + 1] + mubins[0:nbins])
# Create an iterator
muiter = np.nditer(mumaterials, flags=['c_index'])
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)
# Real part for frequencies in the range 0.3GHz to 1.3GHz (linear
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) * DispersiveMaterial.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]))
sig = muiter[0] ** (b2 / a) * ((sigf * (self.rs - self.rb)) / (self.rs * muiter[0]))
# Check to see if the material already exists before creating a new one
requiredID = '|{:.4f}|'.format(float(muiter[0]))
requiredID = "|{:.4f}|".format(float(muiter[0]))
material = next((x for x in G.materials if x.ID == requiredID), None)
if muiter.index == 0:
if material:
self.matID.append(material.numID)
self.matID.append(material.numID)
if not material:
m = DispersiveMaterial(len(G.materials), requiredID)
m.type = 'debye'
m.type = "debye"
m.averagable = False
m.poles = 1
if m.poles > config.get_model_config().materials['maxpoles']:
config.get_model_config().materials['maxpoles'] = m.poles
if m.poles > config.get_model_config().materials["maxpoles"]:
config.get_model_config().materials["maxpoles"] = m.poles
m.er = eri
m.se = sig
m.deltaer.append(er - eri)
@@ -318,35 +336,35 @@ class PeplinskiSoil:
self.matID.append(m.numID)
muiter.iternext()
class RangeMaterial:
"""Material objects defined by a given range of their parameters to be used
for fractal spatial distributions.
"""Material objects defined by a given range of their parameters to be used
for fractal spatial distributions.
"""
def __init__(self, ID, er_range, se_range, mr_range, sm_range):
"""
Args:
ID: string for name of the material range.
er_range: tuple of floats for relative permittivity range of the
er_range: tuple of floats for relative permittivity range of the
materials.
se_range: tuple of floats for electric conductivity range of the
se_range: tuple of floats for electric conductivity range of the
materials.
mr_range: tuple of floats for magnetic permeability of materials.
sm_range: tuple of floats for magnetic loss range of materials.
mr_range: tuple of floats for magnetic permeability of materials.
sm_range: tuple of floats for magnetic loss range of materials.
"""
self.ID = ID
self.er = er_range
self.sig = se_range
self.mu = mr_range
self.mu = mr_range
self.ro = sm_range
# Store all of the material IDs which allows for more general mixing models.
self.matID = []
self.matID = []
def calculate_properties(self, nbins, G):
"""Calculates the specific properties of each of the materials.
"""Calculates the specific properties of each of the materials.
Args:
nbins: int for number of bins to use to create the different materials.
@@ -354,53 +372,53 @@ class RangeMaterial:
"""
# Generate a set of relative permittivity bins based on the given range
erbins = np.linspace(self.er[0], self.er[1], nbins+1)
erbins = np.linspace(self.er[0], self.er[1], nbins + 1)
# Generate a range of relative permittivity values the mid-point of
# Generate a range of relative permittivity values the mid-point of
# each bin to make materials from
ermaterials = 0.5 * (erbins[1:nbins+1] + erbins[0:nbins])
ermaterials = 0.5 * (erbins[1 : nbins + 1] + erbins[0:nbins])
# Generate a set of conductivity bins based on the given range
sigmabins = np.linspace(self.sig[0], self.sig[1], nbins + 1)
# Generate a range of conductivity values the mid-point of
# Generate a range of conductivity values the mid-point of
# each bin to make materials from
sigmamaterials = 0.5 * (sigmabins[1:nbins+1] + sigmabins[0:nbins])
sigmamaterials = 0.5 * (sigmabins[1 : nbins + 1] + sigmabins[0:nbins])
# Generate a set of magnetic permeability bins based on the given range
mubins = np.linspace(self.mu[0], self.mu[1], nbins + 1)
# Generate a range of magnetic permeability values the mid-point of
# Generate a range of magnetic permeability values the mid-point of
# each bin to make materials from
mumaterials = 0.5 * (mubins[1:nbins+1] + mubins[0:nbins])
mumaterials = 0.5 * (mubins[1 : nbins + 1] + mubins[0:nbins])
# Generate a set of magnetic loss bins based on the given range
robins = np.linspace(self.ro[0], self.ro[1], nbins + 1)
# Generate a range of magnetic loss values the mid-point of each bin to
# Generate a range of magnetic loss values the mid-point of each bin to
# make materials from
romaterials = 0.5 * (robins[1:nbins+1] + robins[0:nbins])
romaterials = 0.5 * (robins[1 : nbins + 1] + robins[0:nbins])
# Iterate over the bins
for iter in np.arange(nbins):
# Relative permittivity
# Relative permittivity
er = ermaterials[iter]
# Effective conductivity
se = sigmamaterials[iter]
se = sigmamaterials[iter]
# Magnetic permeability
mr = mumaterials[iter]
# Magnetic loss
sm = romaterials[iter]
# Check to see if the material already exists before creating a new one
requiredID = f'|{float(er):.4f}+{float(se):.4f}+{float(mr):.4f}+{float(sm):.4f}|'
requiredID = f"|{float(er):.4f}+{float(se):.4f}+{float(mr):.4f}+{float(sm):.4f}|"
material = next((x for x in G.materials if x.ID == requiredID), None)
if iter == 0:
if material:
self.matID.append(material.numID)
if not material:
m = Material(len(G.materials), requiredID)
m.type = ''
m.type = ""
m.averagable = True
m.er = er
m.se = se
@@ -411,23 +429,23 @@ class RangeMaterial:
class ListMaterial:
"""A list of predefined materials to be used for fractal spatial distributions.
This class does not create new materials but collects them to be used
in a stochastic distribution by a fractal box.
"""A list of predefined materials to be used for fractal spatial distributions.
This class does not create new materials but collects them to be used
in a stochastic distribution by a fractal box.
"""
def __init__(self, ID, listofmaterials):
"""
Args:
ID: string for name of the material list.
listofmaterials: list of material IDs.
listofmaterials: list of material IDs.
"""
self.ID = ID
self.mat = listofmaterials
# Store all of the material IDs which allows for more general mixing models.
self.matID = []
self.matID = []
def calculate_properties(self, nbins, G):
"""Calculates the properties of the materials.
@@ -442,12 +460,12 @@ class ListMaterial:
# Check if the material already exists before creating a new one
material = next((x for x in G.materials if x.ID == requiredID), None)
self.matID.append(material.numID)
if not material:
logger.exception(self.__str__() + f' material(s) {material} do not exist')
logger.exception(self.__str__() + f" material(s) {material} do not exist")
raise ValueError
def create_built_in_materials(G):
"""Creates pre-defined (built-in) materials.
@@ -455,14 +473,14 @@ def create_built_in_materials(G):
G: FDTDGrid class describing a grid in a model.
"""
m = Material(0, 'pec')
m.se = float('inf')
m.type = 'builtin'
m = Material(0, "pec")
m.se = float("inf")
m.type = "builtin"
m.averagable = False
G.materials.append(m)
m = Material(1, 'free_space')
m.type = 'builtin'
m = Material(1, "free_space")
m.type = "builtin"
G.materials.append(m)
@@ -483,12 +501,12 @@ def calculate_water_properties(T=25, S=0):
# Properties of water from: https://doi.org/10.1109/JOE.1977.1145319
eri = 4.9
er = 88.045 - 0.4147 * T + 6.295e-4 * T**2 + 1.075e-5 * T**3
tau = (1 / (2 * np.pi)) * (1.1109e-10 - 3.824e-12 * T + 6.938e-14 * T**2 -
5.096e-16 * T**3)
tau = (1 / (2 * np.pi)) * (1.1109e-10 - 3.824e-12 * T + 6.938e-14 * T**2 - 5.096e-16 * T**3)
delta = 25 - T
beta = (2.033e-2 + 1.266e-4 * delta + 2.464e-6 * delta**2 - S *
(1.849e-5 - 2.551e-7 * delta + 2.551e-8 * delta**2))
beta = (
2.033e-2 + 1.266e-4 * delta + 2.464e-6 * delta**2 - S * (1.849e-5 - 2.551e-7 * delta + 2.551e-8 * delta**2)
)
sig_25s = S * (0.182521 - 1.46192e-3 * S + 2.09324e-5 * S**2 - 1.28205e-7 * S**3)
sig = sig_25s * np.exp(-delta * beta)
@@ -506,18 +524,18 @@ def create_water(G, T=25, S=0):
"""
eri, er, tau, sig = calculate_water_properties(T, S)
m = DispersiveMaterial(len(G.materials), 'water')
m = DispersiveMaterial(len(G.materials), "water")
m.averagable = False
m.type = 'builtin, debye'
m.type = "builtin, debye"
m.poles = 1
m.er = eri
m.se = sig
m.deltaer.append(er - eri)
m.tau.append(tau)
G.materials.append(m)
if config.get_model_config().materials['maxpoles'] == 0:
config.get_model_config().materials['maxpoles'] = 1
if config.get_model_config().materials["maxpoles"] == 0:
config.get_model_config().materials["maxpoles"] = 1
def create_grass(G):
@@ -533,17 +551,17 @@ def create_grass(G):
tau = 1.0793e-11
sig = 0
m = DispersiveMaterial(len(G.materials), 'grass')
m = DispersiveMaterial(len(G.materials), "grass")
m.averagable = False
m.type = 'builtin, debye'
m.type = "builtin, debye"
m.poles = 1
m.er = eri
m.se = sig
m.deltaer.append(er - eri)
m.tau.append(tau)
G.materials.append(m)
if config.get_model_config().materials['maxpoles'] == 0:
config.get_model_config().materials['maxpoles'] = 1
if config.get_model_config().materials["maxpoles"] == 0:
config.get_model_config().materials["maxpoles"] = 1
def process_materials(G):
@@ -558,13 +576,37 @@ def process_materials(G):
print a table.
"""
if config.get_model_config().materials['maxpoles'] == 0:
materialsdata = [['\nID', '\nName', '\nType', '\neps_r', 'sigma\n[S/m]',
'\nmu_r', 'sigma*\n[Ohm/m]', 'Dielectric\nsmoothable']]
if config.get_model_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 specific material
@@ -576,39 +618,44 @@ def process_materials(G):
G.updatecoeffsH[material.numID, :] = material.DA, material.DBx, material.DBy, material.DBz, material.srcm
# Add update coefficients to overall storage for dispersive materials
if hasattr(material, 'poles'):
if hasattr(material, "poles"):
z = 0
for pole in range(config.get_model_config().materials['maxpoles']):
G.updatecoeffsdispersive[material.numID, z:z + 3] = (config.sim_config.em_consts['e0'] *
material.eqt2[pole], material.eqt[pole], material.zt[pole])
for pole in range(config.get_model_config().materials["maxpoles"]):
G.updatecoeffsdispersive[material.numID, z : z + 3] = (
config.sim_config.em_consts["e0"] * material.eqt2[pole],
material.eqt[pole],
material.zt[pole],
)
z += 3
# Construct information on material properties for printing table
materialtext = [str(material.numID),
material.ID[:50] if len(material.ID) > 50 else material.ID,
material.type,
f'{material.er:g}',
f'{material.se:g}']
if config.get_model_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))
materialtext.extend(['', '', ''])
elif 'lorentz' in material.type:
materialtext.append(', '.join('{:g}'.format(deltaer) for deltaer in material.deltaer))
materialtext.append('')
materialtext.append(', '.join('{:g}'.format(tau) for tau in material.tau))
materialtext.append(', '.join('{:g}'.format(alpha) for alpha in material.alpha))
materialtext.append('')
elif 'drude' in material.type:
materialtext.extend(['', ''])
materialtext.append(', '.join('{:g}'.format(tau) for tau in material.tau))
materialtext.append('')
materialtext.append(', '.join('{:g}'.format(alpha) for alpha in material.alpha))
materialtext = [
str(material.numID),
material.ID[:50] if len(material.ID) > 50 else material.ID,
material.type,
f"{material.er:g}",
f"{material.se:g}",
]
if config.get_model_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))
materialtext.extend(["", "", ""])
elif "lorentz" in material.type:
materialtext.append(", ".join("{:g}".format(deltaer) for deltaer in material.deltaer))
materialtext.append("")
materialtext.append(", ".join("{:g}".format(tau) for tau in material.tau))
materialtext.append(", ".join("{:g}".format(alpha) for alpha in material.alpha))
materialtext.append("")
elif "drude" in material.type:
materialtext.extend(["", ""])
materialtext.append(", ".join("{:g}".format(tau) for tau in material.tau))
materialtext.append("")
materialtext.append(", ".join("{:g}".format(alpha) for alpha in material.alpha))
else:
materialtext.extend(['', '', '', '', ''])
materialtext.extend(["", "", "", "", ""])
materialtext.extend((f'{material.mr:g}', f'{material.sm:g}', material.averagable))
materialtext.extend((f"{material.mr:g}", f"{material.sm:g}", material.averagable))
materialsdata.append(materialtext)
return materialsdata
return materialsdata

查看文件

@@ -33,8 +33,7 @@ from tqdm import tqdm
import gprMax.config as config
from .cython.yee_cell_build import (build_electric_components,
build_magnetic_components)
from .cython.yee_cell_build import build_electric_components, build_magnetic_components
from .fields_outputs import write_hdf5_outputfile
from .geometry_outputs import save_geometry_views
from .grid import dispersion_analysis
@@ -43,8 +42,7 @@ from .materials import process_materials
from .pml import CFS, build_pml, print_pml_info
from .scene import Scene
from .snapshots import save_snapshots
from .utilities.host_info import (mem_check_build_all, mem_check_run_all,
set_omp_threads)
from .utilities.host_info import mem_check_build_all, mem_check_run_all, set_omp_threads
from .utilities.utilities import get_terminal_width
logger = logging.getLogger(__name__)
@@ -75,19 +73,21 @@ class ModelBuildRun:
# Normal model reading/building process; bypassed if geometry information to be reused
self.reuse_geometry() if config.get_model_config().reuse_geometry else self.build_geometry()
logger.info(f'\nOutput directory: {config.get_model_config().output_file_path.parent.resolve()}')
logger.info(f"\nOutput directory: {config.get_model_config().output_file_path.parent.resolve()}")
# Adjust position of simple sources and receivers if required
if G.srcsteps[0] != 0 or G.srcsteps[1] != 0 or G.srcsteps[2] != 0:
for source in itertools.chain(G.hertziandipoles, G.magneticdipoles):
if config.model_num == 0:
if (source.xcoord + G.srcsteps[0] * config.sim_config.model_end < 0 or
source.xcoord + G.srcsteps[0] * config.sim_config.model_end > G.nx or
source.ycoord + G.srcsteps[1] * config.sim_config.model_end < 0 or
source.ycoord + G.srcsteps[1] * config.sim_config.model_end > G.ny or
source.zcoord + G.srcsteps[2] * config.sim_config.model_end < 0 or
source.zcoord + G.srcsteps[2] * config.sim_config.model_end > G.nz):
logger.exception('Source(s) will be stepped to a position outside the domain.')
if (
source.xcoord + G.srcsteps[0] * config.sim_config.model_end < 0
or source.xcoord + G.srcsteps[0] * config.sim_config.model_end > G.nx
or source.ycoord + G.srcsteps[1] * config.sim_config.model_end < 0
or source.ycoord + G.srcsteps[1] * config.sim_config.model_end > G.ny
or source.zcoord + G.srcsteps[2] * config.sim_config.model_end < 0
or source.zcoord + G.srcsteps[2] * config.sim_config.model_end > G.nz
):
logger.exception("Source(s) will be stepped to a position outside the domain.")
raise ValueError
source.xcoord = source.xcoordorigin + config.model_num * G.srcsteps[0]
source.ycoord = source.ycoordorigin + config.model_num * G.srcsteps[1]
@@ -95,13 +95,15 @@ class ModelBuildRun:
if G.rxsteps[0] != 0 or G.rxsteps[1] != 0 or G.rxsteps[2] != 0:
for receiver in G.rxs:
if config.model_num == 0:
if (receiver.xcoord + G.rxsteps[0] * config.sim_config.model_end < 0 or
receiver.xcoord + G.rxsteps[0] * config.sim_config.model_end > G.nx or
receiver.ycoord + G.rxsteps[1] * config.sim_config.model_end < 0 or
receiver.ycoord + G.rxsteps[1] * config.sim_config.model_end > G.ny or
receiver.zcoord + G.rxsteps[2] * config.sim_config.model_end < 0 or
receiver.zcoord + G.rxsteps[2] * config.sim_config.model_end > G.nz):
logger.exception('Receiver(s) will be stepped to a position outside the domain.')
if (
receiver.xcoord + G.rxsteps[0] * config.sim_config.model_end < 0
or receiver.xcoord + G.rxsteps[0] * config.sim_config.model_end > G.nx
or receiver.ycoord + G.rxsteps[1] * config.sim_config.model_end < 0
or receiver.ycoord + G.rxsteps[1] * config.sim_config.model_end > G.ny
or receiver.zcoord + G.rxsteps[2] * config.sim_config.model_end < 0
or receiver.zcoord + G.rxsteps[2] * config.sim_config.model_end > G.nz
):
logger.exception("Receiver(s) will be stepped to a position outside the domain.")
raise ValueError
receiver.xcoord = receiver.xcoordorigin + config.model_num * G.rxsteps[0]
receiver.ycoord = receiver.ycoordorigin + config.model_num * G.rxsteps[1]
@@ -109,29 +111,34 @@ class ModelBuildRun:
# Write files for any geometry views and geometry object outputs
gvs = G.geometryviews + [gv for sg in G.subgrids for gv in sg.geometryviews]
if (not gvs and not G.geometryobjectswrite and config.sim_config.args.geometry_only):
logger.exception('\nNo geometry views or geometry objects found.')
if not gvs and not G.geometryobjectswrite and config.sim_config.args.geometry_only:
logger.exception("\nNo geometry views or geometry objects found.")
raise ValueError
save_geometry_views(gvs)
if G.geometryobjectswrite:
logger.info('')
logger.info("")
for i, go in enumerate(G.geometryobjectswrite):
pbar = tqdm(total=go.datawritesize, unit='byte', unit_scale=True,
desc=f'Writing geometry object file {i + 1}/{len(G.geometryobjectswrite)}, ' +
f'{go.filename_hdf5.name}',
ncols=get_terminal_width() - 1, file=sys.stdout,
disable=not config.sim_config.general['progressbars'])
pbar = tqdm(
total=go.datawritesize,
unit="byte",
unit_scale=True,
desc=f"Writing geometry object file {i + 1}/{len(G.geometryobjectswrite)}, "
+ f"{go.filename_hdf5.name}",
ncols=get_terminal_width() - 1,
file=sys.stdout,
disable=not config.sim_config.general["progressbars"],
)
go.write_hdf5(G, pbar)
pbar.close()
logger.info('')
logger.info("")
def build_geometry(self):
G = self.G
logger.info(config.get_model_config().inputfilestr)
# Build objects in the scene and check memory for building
# Build objects in the scene and check memory for building
self.build_scene()
# Print info on any subgrids
@@ -143,15 +150,17 @@ class ModelBuildRun:
# Check for dispersive materials (and specific type)
for grid in grids:
if config.get_model_config().materials['maxpoles'] != 0:
config.get_model_config().materials['drudelorentz'] = any([m for m in grid.materials if 'drude' in m.type or 'lorentz' in m.type])
if config.get_model_config().materials["maxpoles"] != 0:
config.get_model_config().materials["drudelorentz"] = any(
[m for m in grid.materials if "drude" in m.type or "lorentz" in m.type]
)
# Set data type if any dispersive materials (must be done before memory checks)
if config.get_model_config().materials['maxpoles'] != 0:
if config.get_model_config().materials["maxpoles"] != 0:
config.get_model_config().set_dispersive_material_types()
# Check memory requirements to build model/scene (different to memory
# requirements to run model when FractalVolumes/FractalSurfaces are
# Check memory requirements to build model/scene (different to memory
# requirements to run model when FractalVolumes/FractalSurfaces are
# used as these can require significant additional memory)
total_mem_build, mem_strs_build = mem_check_build_all(grids)
@@ -159,22 +168,26 @@ class ModelBuildRun:
total_mem_run, mem_strs_run = mem_check_run_all(grids)
if total_mem_build > total_mem_run:
logger.info(f'\nMemory required (estimated): {" + ".join(mem_strs_build)} + '
f'~{humanize.naturalsize(config.get_model_config().mem_overhead)} '
f'overhead = {humanize.naturalsize(total_mem_build)}')
logger.info(
f'\nMemory required (estimated): {" + ".join(mem_strs_build)} + '
f"~{humanize.naturalsize(config.get_model_config().mem_overhead)} "
f"overhead = {humanize.naturalsize(total_mem_build)}"
)
else:
logger.info(f'\nMemory required (estimated): {" + ".join(mem_strs_run)} + '
f'~{humanize.naturalsize(config.get_model_config().mem_overhead)} '
f'overhead = {humanize.naturalsize(total_mem_run)}')
logger.info(
f'\nMemory required (estimated): {" + ".join(mem_strs_run)} + '
f"~{humanize.naturalsize(config.get_model_config().mem_overhead)} "
f"overhead = {humanize.naturalsize(total_mem_run)}"
)
# Build grids
gridbuilders = [GridBuilder(grid) for grid in grids]
for gb in gridbuilders:
# Set default CFS parameter for PMLs if not user provided
if not gb.grid.pmls['cfs']:
gb.grid.pmls['cfs'] = [CFS()]
if not gb.grid.pmls["cfs"]:
gb.grid.pmls["cfs"] = [CFS()]
logger.info(print_pml_info(gb.grid))
if not all(value == 0 for value in gb.grid.pmls['thickness'].values()):
if not all(value == 0 for value in gb.grid.pmls["thickness"].values()):
gb.build_pmls()
if gb.grid.averagevolumeobjects:
gb.build_components()
@@ -182,50 +195,62 @@ class ModelBuildRun:
gb.update_voltage_source_materials()
gb.grid.initialise_field_arrays()
gb.grid.initialise_std_update_coeff_arrays()
if config.get_model_config().materials['maxpoles'] > 0:
if config.get_model_config().materials["maxpoles"] > 0:
gb.grid.initialise_dispersive_arrays()
gb.grid.initialise_dispersive_update_coeff_array()
gb.build_materials()
# Check to see if numerical dispersion might be a problem
results = dispersion_analysis(gb.grid)
if results['error']:
logger.warning(f"\nNumerical dispersion analysis [{gb.grid.name}] "
f"not carried out as {results['error']}")
elif results['N'] < config.get_model_config().numdispersion['mingridsampling']:
logger.exception(f"\nNon-physical wave propagation in [{gb.grid.name}] "
f"detected. Material '{results['material'].ID}' "
f"has wavelength sampled by {results['N']} cells, "
f"less than required minimum for physical wave "
f"propagation. Maximum significant frequency "
f"estimated as {results['maxfreq']:g}Hz")
if results["error"]:
logger.warning(
f"\nNumerical dispersion analysis [{gb.grid.name}] " f"not carried out as {results['error']}"
)
elif results["N"] < config.get_model_config().numdispersion["mingridsampling"]:
logger.exception(
f"\nNon-physical wave propagation in [{gb.grid.name}] "
f"detected. Material '{results['material'].ID}' "
f"has wavelength sampled by {results['N']} cells, "
f"less than required minimum for physical wave "
f"propagation. Maximum significant frequency "
f"estimated as {results['maxfreq']:g}Hz"
)
raise ValueError
elif (results['deltavp'] and np.abs(results['deltavp']) >
config.get_model_config().numdispersion['maxnumericaldisp']):
logger.warning(f"\n[{gb.grid.name}] has potentially significant "
f"numerical dispersion. Estimated largest physical "
f"phase-velocity error is {results['deltavp']:.2f}% "
f"in material '{results['material'].ID}' whose "
f"wavelength sampled by {results['N']} cells. "
f"Maximum significant frequency estimated as "
f"{results['maxfreq']:g}Hz")
elif results['deltavp']:
logger.info(f"\nNumerical dispersion analysis [{gb.grid.name}]: "
f"estimated largest physical phase-velocity error is "
f"{results['deltavp']:.2f}% in material '{results['material'].ID}' "
f"whose wavelength sampled by {results['N']} cells. "
f"Maximum significant frequency estimated as "
f"{results['maxfreq']:g}Hz")
elif (
results["deltavp"]
and np.abs(results["deltavp"]) > config.get_model_config().numdispersion["maxnumericaldisp"]
):
logger.warning(
f"\n[{gb.grid.name}] has potentially significant "
f"numerical dispersion. Estimated largest physical "
f"phase-velocity error is {results['deltavp']:.2f}% "
f"in material '{results['material'].ID}' whose "
f"wavelength sampled by {results['N']} cells. "
f"Maximum significant frequency estimated as "
f"{results['maxfreq']:g}Hz"
)
elif results["deltavp"]:
logger.info(
f"\nNumerical dispersion analysis [{gb.grid.name}]: "
f"estimated largest physical phase-velocity error is "
f"{results['deltavp']:.2f}% in material '{results['material'].ID}' "
f"whose wavelength sampled by {results['N']} cells. "
f"Maximum significant frequency estimated as "
f"{results['maxfreq']:g}Hz"
)
def reuse_geometry(self):
s = (f'\n--- Model {config.get_model_config().appendmodelnumber}/{config.sim_config.model_end}, '
f'input file (not re-processed, i.e. geometry fixed): '
f'{config.sim_config.input_file_path}')
config.get_model_config().inputfilestr = (Fore.GREEN + f"{s} {'-' * (get_terminal_width() - 1 - len(s))}\n" +
Style.RESET_ALL)
s = (
f"\n--- Model {config.get_model_config().appendmodelnumber}/{config.sim_config.model_end}, "
f"input file (not re-processed, i.e. geometry fixed): "
f"{config.sim_config.input_file_path}"
)
config.get_model_config().inputfilestr = (
Fore.GREEN + f"{s} {'-' * (get_terminal_width() - 1 - len(s))}\n" + Style.RESET_ALL
)
logger.basic(config.get_model_config().inputfilestr)
for grid in [self.G] + self.G.subgrids:
grid.iteration = 0 # Reset current iteration number
grid.iteration = 0 # Reset current iteration number
grid.reset_fields()
def build_scene(self):
@@ -244,8 +269,8 @@ class ModelBuildRun:
return scene
def write_output_data(self):
"""Writes output data, i.e. field data for receivers and snapshots to
file(s).
"""Writes output data, i.e. field data for receivers and snapshots to
file(s).
"""
write_hdf5_outputfile(config.get_model_config().output_file_path_ext, self.G)
@@ -262,32 +287,42 @@ class ModelBuildRun:
"""
# Print information about and check OpenMP threads
if config.sim_config.general['solver'] == 'cpu':
logger.basic(f"\nModel {config.model_num + 1}/{config.sim_config.model_end} "
f"on {config.sim_config.hostinfo['hostname']} "
f"with OpenMP backend using {config.get_model_config().ompthreads} thread(s)")
if config.get_model_config().ompthreads > config.sim_config.hostinfo['physicalcores']:
logger.warning(f"You have specified more threads ({config.get_model_config().ompthreads}) "
f"than available physical CPU cores ({config.sim_config.hostinfo['physicalcores']}). "
f"This may lead to degraded performance.")
elif config.sim_config.general['solver'] in ['cuda', 'opencl']:
if config.sim_config.general['solver'] == 'opencl':
solvername = 'OpenCL'
platformname = ' on ' + ' '.join(config.get_model_config().device['dev'].platform.name.split())
devicename = ' '.join(config.get_model_config().device['dev'].name.split())
if config.sim_config.general["solver"] == "cpu":
logger.basic(
f"\nModel {config.model_num + 1}/{config.sim_config.model_end} "
f"on {config.sim_config.hostinfo['hostname']} "
f"with OpenMP backend using {config.get_model_config().ompthreads} thread(s)"
)
if config.get_model_config().ompthreads > config.sim_config.hostinfo["physicalcores"]:
logger.warning(
f"You have specified more threads ({config.get_model_config().ompthreads}) "
f"than available physical CPU cores ({config.sim_config.hostinfo['physicalcores']}). "
f"This may lead to degraded performance."
)
elif config.sim_config.general["solver"] in ["cuda", "opencl"]:
if config.sim_config.general["solver"] == "opencl":
solvername = "OpenCL"
platformname = " on " + " ".join(config.get_model_config().device["dev"].platform.name.split())
devicename = " ".join(config.get_model_config().device["dev"].name.split())
else:
solvername = 'CUDA'
platformname = ''
devicename = ' '.join(config.get_model_config().device['dev'].name().split())
logger.basic(f"\nModel {config.model_num + 1}/{config.sim_config.model_end} "
f"on {config.sim_config.hostinfo['hostname']} "
f"with {solvername} backend using {devicename}{platformname}")
solvername = "CUDA"
platformname = ""
devicename = " ".join(config.get_model_config().device["dev"].name().split())
logger.basic(
f"\nModel {config.model_num + 1}/{config.sim_config.model_end} "
f"on {config.sim_config.hostinfo['hostname']} "
f"with {solvername} backend using {devicename}{platformname}"
)
# Prepare iterator
if config.sim_config.general['progressbars']:
iterator = tqdm(range(self.G.iterations), desc='|--->',
ncols=get_terminal_width() - 1, file=sys.stdout,
disable=not config.sim_config.general['progressbars'])
if config.sim_config.general["progressbars"]:
iterator = tqdm(
range(self.G.iterations),
desc="|--->",
ncols=get_terminal_width() - 1,
file=sys.stdout,
disable=not config.sim_config.general["progressbars"],
)
else:
iterator = range(self.G.iterations)
@@ -299,12 +334,16 @@ class ModelBuildRun:
# Print information about memory usage and solving time for a model
# Add a string on GPU memory usage if applicable
mem_str = f' host + ~{humanize.naturalsize(solver.memused)} GPU' if config.sim_config.general['solver'] == 'cuda' else ''
mem_str = (
f" host + ~{humanize.naturalsize(solver.memused)} GPU"
if config.sim_config.general["solver"] == "cuda"
else ""
)
logger.info(f'\nMemory used (estimated): ' +
f'~{humanize.naturalsize(self.p.memory_full_info().uss)}{mem_str}')
logger.info(f"Time taken: " +
f"{humanize.precisedelta(datetime.timedelta(seconds=solver.solvetime), format='%0.4f')}")
logger.info(f"\nMemory used (estimated): " + f"~{humanize.naturalsize(self.p.memory_full_info().uss)}{mem_str}")
logger.info(
f"Time taken: " + f"{humanize.precisedelta(datetime.timedelta(seconds=solver.solvetime), format='%0.4f')}"
)
class GridBuilder:
@@ -312,11 +351,14 @@ class GridBuilder:
self.grid = grid
def build_pmls(self):
pbar = tqdm(total=sum(1 for value in self.grid.pmls['thickness'].values() if value > 0),
desc=f'Building PML boundaries [{self.grid.name}]',
ncols=get_terminal_width() - 1, file=sys.stdout,
disable=not config.sim_config.general['progressbars'])
for pml_id, thickness in self.grid.pmls['thickness'].items():
pbar = tqdm(
total=sum(1 for value in self.grid.pmls["thickness"].values() if value > 0),
desc=f"Building PML boundaries [{self.grid.name}]",
ncols=get_terminal_width() - 1,
file=sys.stdout,
disable=not config.sim_config.general["progressbars"],
)
for pml_id, thickness in self.grid.pmls["thickness"].items():
if thickness > 0:
build_pml(self.grid, pml_id, thickness)
pbar.update()
@@ -325,10 +367,14 @@ class GridBuilder:
def build_components(self):
# Build the model, i.e. set the material properties (ID) for every edge
# of every Yee cell
logger.info('')
pbar = tqdm(total=2, desc=f'Building Yee cells [{self.grid.name}]',
ncols=get_terminal_width() - 1, file=sys.stdout,
disable=not config.sim_config.general['progressbars'])
logger.info("")
pbar = tqdm(
total=2,
desc=f"Building Yee cells [{self.grid.name}]",
ncols=get_terminal_width() - 1,
file=sys.stdout,
disable=not config.sim_config.general["progressbars"],
)
build_electric_components(self.grid.solid, self.grid.rigidE, self.grid.ID, self.grid)
pbar.update()
build_magnetic_components(self.grid.solid, self.grid.rigidH, self.grid.ID, self.grid)
@@ -336,11 +382,11 @@ class GridBuilder:
pbar.close()
def tm_grid_update(self):
if config.get_model_config().mode == '2D TMx':
if config.get_model_config().mode == "2D TMx":
self.grid.tmx()
elif config.get_model_config().mode == '2D TMy':
elif config.get_model_config().mode == "2D TMy":
self.grid.tmy()
elif config.get_model_config().mode == '2D TMz':
elif config.get_model_config().mode == "2D TMz":
self.grid.tmz()
def update_voltage_source_materials(self):
@@ -355,7 +401,7 @@ class GridBuilder:
materialsdata = process_materials(self.grid)
materialstable = SingleTable(materialsdata)
materialstable.outer_border = False
materialstable.justify_columns[0] = 'right'
materialstable.justify_columns[0] = "right"
logger.info(f'\nMaterials [{self.grid.name}]:')
logger.info(f"\nMaterials [{self.grid.name}]:")
logger.info(materialstable.table)

查看文件

@@ -37,7 +37,7 @@ EXIT
Send by master to worker to initiate worker shutdown and then
send back to master to signal shutdown has completed.
"""
Tags = IntEnum('Tags', 'READY START DONE EXIT')
Tags = IntEnum("Tags", "READY START DONE EXIT")
class MPIExecutor(object):
@@ -122,11 +122,11 @@ class MPIExecutor(object):
def __init__(self, func, master=0, comm=None):
"""Initializes a new executor instance.
Attributes:
func: callable worker function. Jobs will be passed as keyword
arguments, so `func` must support this. This is usually the
case, but can be a problem when builtin functions are used,
func: callable worker function. Jobs will be passed as keyword
arguments, so `func` must support this. This is usually the
case, but can be a problem when builtin functions are used,
e.g. `abs()`.
master: int of the rank of the master. Must be in `comm`. All other
ranks in `comm` will be treated as workers.
@@ -136,22 +136,22 @@ class MPIExecutor(object):
if comm is None:
self.comm = MPI.COMM_WORLD
elif not comm.Is_intra():
raise TypeError('MPI.Intracomm expected')
raise TypeError("MPI.Intracomm expected")
else:
self.comm = comm
self.rank = self.comm.rank
self.size = self.comm.size
if self.size < 2:
raise RuntimeError('MPIExecutor must run with at least 2 processes')
raise RuntimeError("MPIExecutor must run with at least 2 processes")
self._up = False
master = int(master)
if master < 0:
raise ValueError('Master rank must be non-negative')
raise ValueError("Master rank must be non-negative")
elif master >= self.size:
raise ValueError('Master not in comm')
raise ValueError("Master not in comm")
else:
self.master = master
@@ -159,17 +159,17 @@ class MPIExecutor(object):
self.workers = tuple(set(range(self.size)) - {self.master})
# the worker function
if not callable(func):
raise TypeError('Func must be a callable')
raise TypeError("Func must be a callable")
self.func = func
# holds the state of workers on the master
self.busy = [False] * len(self.workers)
if self.is_master():
logger.basic(f'\n({self.comm.name}) - Master: {self.master}, Workers: {self.workers}')
logger.basic(f"\n({self.comm.name}) - Master: {self.master}, Workers: {self.workers}")
def __enter__(self):
"""Context manager enter. Only the master returns an executor, all other
ranks return None.
"""Context manager enter. Only the master returns an executor, all other
ranks return None.
"""
self.start()
if self.is_master():
@@ -188,10 +188,10 @@ class MPIExecutor(object):
return True
def is_idle(self):
"""Returns a bool indicating whether the executor is idle. The executor
is considered to be not idle if *any* worker process is busy with a
job. That means, it is idle only if *all* workers are idle.
Note: This member must not be called on a worker.
"""Returns a bool indicating whether the executor is idle. The executor
is considered to be not idle if *any* worker process is busy with a
job. That means, it is idle only if *all* workers are idle.
Note: This member must not be called on a worker.
"""
assert self.is_master()
return not any(self.busy)
@@ -205,16 +205,16 @@ class MPIExecutor(object):
return not self.is_master()
def start(self):
"""Starts up workers. A check is performed on the master whether the
executor has already been terminated, in which case a RuntimeError
is raised on the master.
"""Starts up workers. A check is performed on the master whether the
executor has already been terminated, in which case a RuntimeError
is raised on the master.
"""
if self.is_master():
if self._up:
raise RuntimeError('Start has already been called')
raise RuntimeError("Start has already been called")
self._up = True
logger.debug(f'({self.comm.name}) - Starting up MPIExecutor master/workers...')
logger.debug(f"({self.comm.name}) - Starting up MPIExecutor master/workers...")
if self.is_worker():
self.__wait()
@@ -222,12 +222,12 @@ class MPIExecutor(object):
"""Joins the workers."""
if not self.is_master():
return
logger.debug(f'({self.comm.name}) - Terminating. Sending sentinel to all workers.')
logger.debug(f"({self.comm.name}) - Terminating. Sending sentinel to all workers.")
# Send sentinel to all workers
for worker in self.workers:
self.comm.send(None, dest=worker, tag=Tags.EXIT)
logger.debug(f'({self.comm.name}) - Waiting for all workers to terminate.')
logger.debug(f"({self.comm.name}) - Waiting for all workers to terminate.")
down = [False] * len(self.workers)
while True:
@@ -239,28 +239,28 @@ class MPIExecutor(object):
break
self._up = False
logger.debug(f'({self.comm.name}) - All workers terminated.')
logger.debug(f"({self.comm.name}) - All workers terminated.")
def submit(self, jobs, sleep=0.0):
"""Submits a list of jobs to the workers and returns the results.
Args:
jobs: list of keyword argument dicts. Each dict describes a job and
jobs: list of keyword argument dicts. Each dict describes a job and
will be unpacked and supplied to the work function.
sleep: float of number of seconds the master will sleep for when
trying to find an idle worker. The default value is 0.0,
sleep: float of number of seconds the master will sleep for when
trying to find an idle worker. The default value is 0.0,
which means the master will not sleep at all.
Returns:
results: list of results, i.e. the return values of the work
function, received from the workers. The order of
results: list of results, i.e. the return values of the work
function, received from the workers. The order of
results is identical to the order of `jobs`.
"""
if not self._up:
raise RuntimeError('Cannot run jobs without a call to start()')
raise RuntimeError("Cannot run jobs without a call to start()")
logger.basic(f'Running {len(jobs):d} jobs.')
assert self.is_master(), 'run() must not be called on a worker process'
logger.basic(f"Running {len(jobs):d} jobs.")
assert self.is_master(), "run() must not be called on a worker process"
my_jobs = jobs.copy()
num_jobs = len(my_jobs)
@@ -269,7 +269,7 @@ class MPIExecutor(object):
for i, worker in enumerate(self.workers):
if self.comm.Iprobe(source=worker, tag=Tags.DONE):
job_idx, result = self.comm.recv(source=worker, tag=Tags.DONE)
logger.debug(f'({self.comm.name}) - Received finished job {job_idx} from worker {worker:d}.')
logger.debug(f"({self.comm.name}) - Received finished job {job_idx} from worker {worker:d}.")
results[job_idx] = result
self.busy[i] = False
elif self.comm.Iprobe(source=worker, tag=Tags.READY):
@@ -277,49 +277,49 @@ class MPIExecutor(object):
self.comm.recv(source=worker, tag=Tags.READY)
self.busy[i] = True
job_idx = num_jobs - len(my_jobs)
logger.debug(f'({self.comm.name}) - Sending job {job_idx} to worker {worker:d}.')
logger.debug(f"({self.comm.name}) - Sending job {job_idx} to worker {worker:d}.")
self.comm.send((job_idx, my_jobs.pop(0)), dest=worker, tag=Tags.START)
elif self.comm.Iprobe(source=worker, tag=Tags.EXIT):
logger.debug(f'({self.comm.name}) - Worker on rank {worker:d} has terminated.')
logger.debug(f"({self.comm.name}) - Worker on rank {worker:d} has terminated.")
self.comm.recv(source=worker, tag=Tags.EXIT)
self.busy[i] = False
time.sleep(sleep)
logger.debug(f'({self.comm.name}) - Finished all jobs.')
logger.debug(f"({self.comm.name}) - Finished all jobs.")
return results
def __wait(self):
"""The worker main loop. The worker will enter the loop after `start()`
has been called and stay here until it receives the sentinel,
e.g. by calling `join()` on the master. In the mean time, the worker
is accepting work.
"""The worker main loop. The worker will enter the loop after `start()`
has been called and stay here until it receives the sentinel,
e.g. by calling `join()` on the master. In the mean time, the worker
is accepting work.
"""
assert self.is_worker()
status = MPI.Status()
logger.debug(f'({self.comm.name}) - Starting up worker.')
logger.debug(f"({self.comm.name}) - Starting up worker.")
while True:
self.comm.send(None, dest=self.master, tag=Tags.READY)
logger.debug(f'({self.comm.name}) - Worker on rank {self.rank} waiting for job.')
logger.debug(f"({self.comm.name}) - Worker on rank {self.rank} waiting for job.")
data = self.comm.recv(source=self.master, tag=MPI.ANY_TAG, status=status)
tag = status.tag
if tag == Tags.START:
job_idx, work = data
logger.debug(f'({self.comm.name}) - Received job {job_idx} (work={work}).')
logger.debug(f"({self.comm.name}) - Received job {job_idx} (work={work}).")
result = self.__guarded_work(work)
logger.debug(f'({self.comm.name}) - Finished job. Sending results to master.')
logger.debug(f"({self.comm.name}) - Finished job. Sending results to master.")
self.comm.send((job_idx, result), dest=self.master, tag=Tags.DONE)
elif tag == Tags.EXIT:
logger.debug(f'({self.comm.name}) - Received sentinel from master.')
logger.debug(f"({self.comm.name}) - Received sentinel from master.")
break
logger.debug(f'({self.comm.name}) - Terminating worker.')
logger.debug(f"({self.comm.name}) - Terminating worker.")
self.comm.send(None, dest=self.master, tag=Tags.EXIT)
def __guarded_work(self, work):
@@ -327,7 +327,7 @@ class MPIExecutor(object):
N.B. All exceptions that occur in the work function `func` are caught
and logged. The worker returns `None` to the master in that case
instead of the actual result.
Args:
work: dict ofeyword arguments that are unpacked and given to the
work function.

查看文件

@@ -29,21 +29,28 @@ class CFSParameter:
"""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}
scalingdirections = ['forward', 'reverse']
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: string identifier for CFS parameter, can be: 'alpha', 'kappa' or
ID: string identifier for CFS parameter, can be: 'alpha', 'kappa' or
'sigma'.
scaling: string for type of scaling, can be: 'polynomial'.
scalingprofile: string for type of scaling profile from
scalingprofile: string for type of scaling profile from
scalingprofiles.
scalingdirection: string for direction of scaling profile from
scalingdirection: string for direction of scaling profile from
scalingdirections.
min: float for minimum value for parameter.
max: float for maximum value for parameter.
@@ -68,9 +75,9 @@ class CFS:
sigma: CFSParameter sigma parameter for CFS.
"""
self.alpha = CFSParameter(ID='alpha', scalingprofile='constant')
self.kappa = CFSParameter(ID='kappa', scalingprofile='constant', min=1, max=1)
self.sigma = CFSParameter(ID='sigma', scalingprofile='quartic', min=0, max=None)
self.alpha = CFSParameter(ID="alpha", scalingprofile="constant")
self.kappa = CFSParameter(ID="kappa", scalingprofile="constant", min=1, max=1)
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
@@ -85,7 +92,7 @@ class CFS:
# 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)) / (config.sim_config.em_consts['z0'] * d * np.sqrt(er * mr))
self.sigma.max = (0.8 * (m + 1)) / (config.sim_config.em_consts["z0"] * d * np.sqrt(er * mr))
def scaling_polynomial(self, order, Evalues, Hvalues):
"""Applies the polynomial to be used for the scaling profile for
@@ -105,8 +112,7 @@ class CFS:
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]
@@ -127,37 +133,37 @@ class CFS:
PML update.
"""
# Extra cell of thickness added to allow correct scaling of electric and
# Extra cell of thickness added to allow correct scaling of electric and
# magnetic values
Evalues = np.zeros(thickness + 1, dtype=config.sim_config.dtypes['float_or_double'])
Hvalues = np.zeros(thickness + 1, dtype=config.sim_config.dtypes['float_or_double'])
Evalues = np.zeros(thickness + 1, dtype=config.sim_config.dtypes["float_or_double"])
Hvalues = np.zeros(thickness + 1, dtype=config.sim_config.dtypes["float_or_double"])
if parameter.scalingprofile == 'constant':
if parameter.scalingprofile == "constant":
Evalues += parameter.max
Hvalues += parameter.max
elif parameter.scaling == 'polynomial':
elif parameter.scaling == "polynomial":
Evalues, Hvalues = self.scaling_polynomial(
CFSParameter.scalingprofiles[parameter.scalingprofile],
Evalues, Hvalues)
if parameter.ID == 'alpha':
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
elif parameter.ID == 'kappa':
elif parameter.ID == "kappa":
Evalues = Evalues * (self.kappa.max - self.kappa.min) + self.kappa.min
Hvalues = Hvalues * (self.kappa.max - self.kappa.min) + self.kappa.min
elif parameter.ID == 'sigma':
elif parameter.ID == "sigma":
Evalues = Evalues * (self.sigma.max - self.sigma.min) + self.sigma.min
Hvalues = Hvalues * (self.sigma.max - self.sigma.min) + self.sigma.min
if parameter.scalingdirection == 'reverse':
if parameter.scalingdirection == "reverse":
Evalues = Evalues[::-1]
Hvalues = Hvalues[::-1]
# Magnetic values must be shifted one element to the left after
# Magnetic values must be shifted one element to the left after
# reversal
Hvalues = np.roll(Hvalues, -1)
# Extra cell of thickness not required and therefore removed after
# Extra cell of thickness not required and therefore removed after
# scaling
Evalues = Evalues[:-1]
Hvalues = Hvalues[:-1]
@@ -171,17 +177,17 @@ class PML:
# Available PML formulations:
# Higher Order RIPML (HORIPML) see: https://doi.org/10.1109/TAP.2011.2180344
# Multipole RIPML (MRIPML) see: https://doi.org/10.1109/TAP.2018.2823864
formulations = ['HORIPML', 'MRIPML']
formulations = ["HORIPML", "MRIPML"]
# PML slabs IDs at boundaries of domain.
boundaryIDs = ['x0', 'y0', 'z0', 'xmax', 'ymax', 'zmax']
boundaryIDs = ["x0", "y0", "z0", "xmax", "ymax", "zmax"]
# Indicates direction of increasing absorption
# xminus, yminus, zminus - absorption increases in negative direction of
# xminus, yminus, zminus - absorption increases in negative direction of
# x-axis, y-axis, or z-axis
# xplus, yplus, zplus - absorption increases in positive direction of
# xplus, yplus, zplus - absorption increases in positive direction of
# x-axis, y-axis, or z-axis
directions = ['xminus', 'yminus', 'zminus', 'xplus', 'yplus', 'zplus']
directions = ["xminus", "yminus", "zminus", "xplus", "yplus", "zplus"]
def __init__(self, G, ID=None, direction=None, xs=0, xf=0, ys=0, yf=0, zs=0, zf=0):
"""
@@ -206,50 +212,62 @@ class PML:
self.nz = zf - zs
# Spatial discretisation and thickness
if self.direction[0] == 'x':
if self.direction[0] == "x":
self.d = self.G.dx
self.thickness = self.nx
elif self.direction[0] == 'y':
elif self.direction[0] == "y":
self.d = self.G.dy
self.thickness = self.ny
elif self.direction[0] == 'z':
elif self.direction[0] == "z":
self.d = self.G.dz
self.thickness = self.nz
self.CFS = self.G.pmls['cfs']
self.CFS = self.G.pmls["cfs"]
self.initialise_field_arrays()
def initialise_field_arrays(self):
"""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=config.sim_config.dtypes['float_or_double'])
self.EPhi2 = np.zeros((len(self.CFS), self.nx + 1, self.ny + 1, self.nz),
dtype=config.sim_config.dtypes['float_or_double'])
self.HPhi1 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz),
dtype=config.sim_config.dtypes['float_or_double'])
self.HPhi2 = np.zeros((len(self.CFS), self.nx, self.ny, self.nz + 1),
dtype=config.sim_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=config.sim_config.dtypes['float_or_double'])
self.EPhi2 = np.zeros((len(self.CFS), self.nx + 1, self.ny + 1, self.nz),
dtype=config.sim_config.dtypes['float_or_double'])
self.HPhi1 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz),
dtype=config.sim_config.dtypes['float_or_double'])
self.HPhi2 = np.zeros((len(self.CFS), self.nx, self.ny, self.nz + 1),
dtype=config.sim_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=config.sim_config.dtypes['float_or_double'])
self.EPhi2 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz + 1),
dtype=config.sim_config.dtypes['float_or_double'])
self.HPhi1 = np.zeros((len(self.CFS), self.nx + 1, self.ny, self.nz),
dtype=config.sim_config.dtypes['float_or_double'])
self.HPhi2 = np.zeros((len(self.CFS), self.nx, self.ny + 1, self.nz),
dtype=config.sim_config.dtypes['float_or_double'])
if self.direction[0] == "x":
self.EPhi1 = np.zeros(
(len(self.CFS), self.nx + 1, self.ny, self.nz + 1), dtype=config.sim_config.dtypes["float_or_double"]
)
self.EPhi2 = np.zeros(
(len(self.CFS), self.nx + 1, self.ny + 1, self.nz), dtype=config.sim_config.dtypes["float_or_double"]
)
self.HPhi1 = np.zeros(
(len(self.CFS), self.nx, self.ny + 1, self.nz), dtype=config.sim_config.dtypes["float_or_double"]
)
self.HPhi2 = np.zeros(
(len(self.CFS), self.nx, self.ny, self.nz + 1), dtype=config.sim_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=config.sim_config.dtypes["float_or_double"]
)
self.EPhi2 = np.zeros(
(len(self.CFS), self.nx + 1, self.ny + 1, self.nz), dtype=config.sim_config.dtypes["float_or_double"]
)
self.HPhi1 = np.zeros(
(len(self.CFS), self.nx + 1, self.ny, self.nz), dtype=config.sim_config.dtypes["float_or_double"]
)
self.HPhi2 = np.zeros(
(len(self.CFS), self.nx, self.ny, self.nz + 1), dtype=config.sim_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=config.sim_config.dtypes["float_or_double"]
)
self.EPhi2 = np.zeros(
(len(self.CFS), self.nx + 1, self.ny, self.nz + 1), dtype=config.sim_config.dtypes["float_or_double"]
)
self.HPhi1 = np.zeros(
(len(self.CFS), self.nx + 1, self.ny, self.nz), dtype=config.sim_config.dtypes["float_or_double"]
)
self.HPhi2 = np.zeros(
(len(self.CFS), self.nx, self.ny + 1, self.nz), dtype=config.sim_config.dtypes["float_or_double"]
)
def calculate_update_coeffs(self, er, mr):
"""Calculates electric and magnetic update coefficients for the PML.
@@ -259,22 +277,14 @@ class PML:
mr: float of average permeability of underlying material
"""
self.ERA = np.zeros((len(self.CFS), self.thickness),
dtype=config.sim_config.dtypes['float_or_double'])
self.ERB = np.zeros((len(self.CFS), self.thickness),
dtype=config.sim_config.dtypes['float_or_double'])
self.ERE = np.zeros((len(self.CFS), self.thickness),
dtype=config.sim_config.dtypes['float_or_double'])
self.ERF = np.zeros((len(self.CFS), self.thickness),
dtype=config.sim_config.dtypes['float_or_double'])
self.HRA = np.zeros((len(self.CFS), self.thickness),
dtype=config.sim_config.dtypes['float_or_double'])
self.HRB = np.zeros((len(self.CFS), self.thickness),
dtype=config.sim_config.dtypes['float_or_double'])
self.HRE = np.zeros((len(self.CFS), self.thickness),
dtype=config.sim_config.dtypes['float_or_double'])
self.HRF = np.zeros((len(self.CFS), self.thickness),
dtype=config.sim_config.dtypes['float_or_double'])
self.ERA = np.zeros((len(self.CFS), self.thickness), dtype=config.sim_config.dtypes["float_or_double"])
self.ERB = np.zeros((len(self.CFS), self.thickness), dtype=config.sim_config.dtypes["float_or_double"])
self.ERE = np.zeros((len(self.CFS), self.thickness), dtype=config.sim_config.dtypes["float_or_double"])
self.ERF = np.zeros((len(self.CFS), self.thickness), dtype=config.sim_config.dtypes["float_or_double"])
self.HRA = np.zeros((len(self.CFS), self.thickness), dtype=config.sim_config.dtypes["float_or_double"])
self.HRB = np.zeros((len(self.CFS), self.thickness), dtype=config.sim_config.dtypes["float_or_double"])
self.HRE = np.zeros((len(self.CFS), self.thickness), dtype=config.sim_config.dtypes["float_or_double"])
self.HRF = np.zeros((len(self.CFS), self.thickness), dtype=config.sim_config.dtypes["float_or_double"])
for x, cfs in enumerate(self.CFS):
if not cfs.sigma.max:
@@ -284,76 +294,108 @@ class PML:
Esigma, Hsigma = cfs.calculate_values(self.thickness, cfs.sigma)
# Define different parameters depending on PML formulation
if self.G.pmls['formulation'] == 'HORIPML':
if self.G.pmls["formulation"] == "HORIPML":
# HORIPML electric update coefficients
tmp = ((2 * config.sim_config.em_consts['e0'] * Ekappa) +
self.G.dt * (Ealpha * Ekappa + Esigma))
self.ERA[x, :] = ((2 * config.sim_config.em_consts['e0'] +
self.G.dt * Ealpha) / tmp)
self.ERB[x, :] = ((2 * config.sim_config.em_consts['e0'] * Ekappa)
/ tmp)
self.ERE[x, :] = (((2 * config.sim_config.em_consts['e0'] * Ekappa) -
self.G.dt * (Ealpha * Ekappa + Esigma)) / tmp)
tmp = (2 * config.sim_config.em_consts["e0"] * Ekappa) + self.G.dt * (Ealpha * Ekappa + Esigma)
self.ERA[x, :] = (2 * config.sim_config.em_consts["e0"] + self.G.dt * Ealpha) / tmp
self.ERB[x, :] = (2 * config.sim_config.em_consts["e0"] * Ekappa) / tmp
self.ERE[x, :] = (
(2 * config.sim_config.em_consts["e0"] * Ekappa) - self.G.dt * (Ealpha * Ekappa + Esigma)
) / tmp
self.ERF[x, :] = (2 * Esigma * self.G.dt) / (Ekappa * tmp)
# HORIPML magnetic update coefficients
tmp = ((2 * config.sim_config.em_consts['e0'] * Hkappa) +
self.G.dt * (Halpha * Hkappa + Hsigma))
self.HRA[x, :] = ((2 * config.sim_config.em_consts['e0'] +
self.G.dt * Halpha) / tmp)
self.HRB[x, :] = ((2 * config.sim_config.em_consts['e0'] * Hkappa)
/ tmp)
self.HRE[x, :] = (((2 * config.sim_config.em_consts['e0'] * Hkappa) -
self.G.dt * (Halpha * Hkappa + Hsigma)) / tmp)
tmp = (2 * config.sim_config.em_consts["e0"] * Hkappa) + self.G.dt * (Halpha * Hkappa + Hsigma)
self.HRA[x, :] = (2 * config.sim_config.em_consts["e0"] + self.G.dt * Halpha) / tmp
self.HRB[x, :] = (2 * config.sim_config.em_consts["e0"] * Hkappa) / tmp
self.HRE[x, :] = (
(2 * config.sim_config.em_consts["e0"] * Hkappa) - self.G.dt * (Halpha * Hkappa + Hsigma)
) / tmp
self.HRF[x, :] = (2 * Hsigma * self.G.dt) / (Hkappa * tmp)
elif self.G.pmls['formulation'] == 'MRIPML':
elif self.G.pmls["formulation"] == "MRIPML":
# MRIPML electric update coefficients
tmp = 2 * config.sim_config.em_consts['e0'] + self.G.dt * Ealpha
tmp = 2 * config.sim_config.em_consts["e0"] + self.G.dt * Ealpha
self.ERA[x, :] = Ekappa + (self.G.dt * Esigma) / tmp
self.ERB[x, :] = (2 * config.sim_config.em_consts['e0']) / tmp
self.ERE[x, :] = (((2 * config.sim_config.em_consts['e0'])
- self.G.dt * Ealpha) / tmp)
self.ERB[x, :] = (2 * config.sim_config.em_consts["e0"]) / tmp
self.ERE[x, :] = ((2 * config.sim_config.em_consts["e0"]) - self.G.dt * Ealpha) / tmp
self.ERF[x, :] = (2 * Esigma * self.G.dt) / tmp
# MRIPML magnetic update coefficients
tmp = 2 * config.sim_config.em_consts['e0'] + self.G.dt * Halpha
tmp = 2 * config.sim_config.em_consts["e0"] + self.G.dt * Halpha
self.HRA[x, :] = Hkappa + (self.G.dt * Hsigma) / tmp
self.HRB[x, :] = (2 * config.sim_config.em_consts['e0']) / tmp
self.HRE[x, :] = (((2 * config.sim_config.em_consts['e0'])
- self.G.dt * Halpha) / tmp)
self.HRB[x, :] = (2 * config.sim_config.em_consts["e0"]) / tmp
self.HRE[x, :] = ((2 * config.sim_config.em_consts["e0"]) - self.G.dt * Halpha) / tmp
self.HRF[x, :] = (2 * Hsigma * self.G.dt) / tmp
def update_electric(self):
"""This functions updates electric field components with the PML
correction.
"""This functions updates electric field components with the PML
correction.
"""
pmlmodule = 'gprMax.cython.pml_updates_electric_' + self.G.pmls['formulation']
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,
config.get_model_config().ompthreads, self.G.updatecoeffsE, self.G.ID,
self.G.Ex, self.G.Ey, self.G.Ez, self.G.Hx, self.G.Hy, self.G.Hz,
self.EPhi1, self.EPhi2, self.ERA, self.ERB, self.ERE, self.ERF, self.d)
pmlmodule = "gprMax.cython.pml_updates_electric_" + self.G.pmls["formulation"]
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,
config.get_model_config().ompthreads,
self.G.updatecoeffsE,
self.G.ID,
self.G.Ex,
self.G.Ey,
self.G.Ez,
self.G.Hx,
self.G.Hy,
self.G.Hz,
self.EPhi1,
self.EPhi2,
self.ERA,
self.ERB,
self.ERE,
self.ERF,
self.d,
)
def update_magnetic(self):
"""This functions updates magnetic field components with the PML
correction.
"""This functions updates magnetic field components with the PML
correction.
"""
pmlmodule = 'gprMax.cython.pml_updates_magnetic_' + self.G.pmls['formulation']
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,
config.get_model_config().ompthreads, self.G.updatecoeffsH, self.G.ID,
self.G.Ex, self.G.Ey, self.G.Ez, self.G.Hx, self.G.Hy, self.G.Hz,
self.HPhi1, self.HPhi2, self.HRA, self.HRB, self.HRE, self.HRF, self.d)
pmlmodule = "gprMax.cython.pml_updates_magnetic_" + self.G.pmls["formulation"]
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,
config.get_model_config().ompthreads,
self.G.updatecoeffsH,
self.G.ID,
self.G.Ex,
self.G.Ey,
self.G.Ez,
self.G.Hx,
self.G.Hy,
self.G.Hz,
self.HPhi1,
self.HPhi2,
self.HRA,
self.HRB,
self.HRE,
self.HRF,
self.d,
)
class CUDAPML(PML):
"""Perfectly Matched Layer (PML) Absorbing Boundary Conditions (ABC) for
solving on GPU using CUDA.
solving on GPU using CUDA.
"""
def __init__(self, *args, **kwargs):
@@ -379,10 +421,17 @@ class CUDAPML(PML):
def set_blocks_per_grid(self):
"""Sets the blocks per grid size used for updating the PML field arrays
on a GPU."""
self.bpg = (int(np.ceil(((self.EPhi1_dev.shape[1] + 1) *
(self.EPhi1_dev.shape[2] + 1) *
(self.EPhi1_dev.shape[3] + 1)) / self.G.tpb[0])), 1, 1)
on a GPU."""
self.bpg = (
int(
np.ceil(
((self.EPhi1_dev.shape[1] + 1) * (self.EPhi1_dev.shape[2] + 1) * (self.EPhi1_dev.shape[3] + 1))
/ self.G.tpb[0]
)
),
1,
1,
)
def get_update_funcs(self, kernelselectric, kernelsmagnetic):
"""Gets update functions from PML kernels.
@@ -394,79 +443,81 @@ class CUDAPML(PML):
magnetic updates.
"""
self.update_electric_dev = kernelselectric.get_function('order' +
str(len(self.CFS)) +
'_' + self.direction)
self.update_magnetic_dev = kernelsmagnetic.get_function('order' +
str(len(self.CFS)) +
'_' + self.direction)
self.update_electric_dev = kernelselectric.get_function("order" + str(len(self.CFS)) + "_" + self.direction)
self.update_magnetic_dev = kernelsmagnetic.get_function("order" + str(len(self.CFS)) + "_" + self.direction)
def update_electric(self):
"""Updates electric field components with the PML correction on the GPU."""
self.update_electric_dev(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_dev.shape[1]),
np.int32(self.EPhi1_dev.shape[2]),
np.int32(self.EPhi1_dev.shape[3]),
np.int32(self.EPhi2_dev.shape[1]),
np.int32(self.EPhi2_dev.shape[2]),
np.int32(self.EPhi2_dev.shape[3]),
np.int32(self.thickness),
self.G.ID_dev.gpudata,
self.G.Ex_dev.gpudata,
self.G.Ey_dev.gpudata,
self.G.Ez_dev.gpudata,
self.G.Hx_dev.gpudata,
self.G.Hy_dev.gpudata,
self.G.Hz_dev.gpudata,
self.EPhi1_dev.gpudata,
self.EPhi2_dev.gpudata,
self.ERA_dev.gpudata,
self.ERB_dev.gpudata,
self.ERE_dev.gpudata,
self.ERF_dev.gpudata,
config.sim_config.dtypes['float_or_double'](self.d),
block=self.G.tpb, grid=self.bpg)
self.update_electric_dev(
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_dev.shape[1]),
np.int32(self.EPhi1_dev.shape[2]),
np.int32(self.EPhi1_dev.shape[3]),
np.int32(self.EPhi2_dev.shape[1]),
np.int32(self.EPhi2_dev.shape[2]),
np.int32(self.EPhi2_dev.shape[3]),
np.int32(self.thickness),
self.G.ID_dev.gpudata,
self.G.Ex_dev.gpudata,
self.G.Ey_dev.gpudata,
self.G.Ez_dev.gpudata,
self.G.Hx_dev.gpudata,
self.G.Hy_dev.gpudata,
self.G.Hz_dev.gpudata,
self.EPhi1_dev.gpudata,
self.EPhi2_dev.gpudata,
self.ERA_dev.gpudata,
self.ERB_dev.gpudata,
self.ERE_dev.gpudata,
self.ERF_dev.gpudata,
config.sim_config.dtypes["float_or_double"](self.d),
block=self.G.tpb,
grid=self.bpg,
)
def update_magnetic(self):
"""Updates magnetic field components with the PML correction on the GPU."""
self.update_magnetic_dev(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_dev.shape[1]),
np.int32(self.HPhi1_dev.shape[2]),
np.int32(self.HPhi1_dev.shape[3]),
np.int32(self.HPhi2_dev.shape[1]),
np.int32(self.HPhi2_dev.shape[2]),
np.int32(self.HPhi2_dev.shape[3]),
np.int32(self.thickness),
self.G.ID_dev.gpudata,
self.G.Ex_dev.gpudata,
self.G.Ey_dev.gpudata,
self.G.Ez_dev.gpudata,
self.G.Hx_dev.gpudata,
self.G.Hy_dev.gpudata,
self.G.Hz_dev.gpudata,
self.HPhi1_dev.gpudata,
self.HPhi2_dev.gpudata,
self.HRA_dev.gpudata,
self.HRB_dev.gpudata,
self.HRE_dev.gpudata,
self.HRF_dev.gpudata,
config.sim_config.dtypes['float_or_double'](self.d),
block=self.G.tpb, grid=self.bpg)
self.update_magnetic_dev(
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_dev.shape[1]),
np.int32(self.HPhi1_dev.shape[2]),
np.int32(self.HPhi1_dev.shape[3]),
np.int32(self.HPhi2_dev.shape[1]),
np.int32(self.HPhi2_dev.shape[2]),
np.int32(self.HPhi2_dev.shape[3]),
np.int32(self.thickness),
self.G.ID_dev.gpudata,
self.G.Ex_dev.gpudata,
self.G.Ey_dev.gpudata,
self.G.Ez_dev.gpudata,
self.G.Hx_dev.gpudata,
self.G.Hy_dev.gpudata,
self.G.Hz_dev.gpudata,
self.HPhi1_dev.gpudata,
self.HPhi2_dev.gpudata,
self.HRA_dev.gpudata,
self.HRB_dev.gpudata,
self.HRE_dev.gpudata,
self.HRF_dev.gpudata,
config.sim_config.dtypes["float_or_double"](self.d),
block=self.G.tpb,
grid=self.bpg,
)
class OpenCLPML(PML):
"""Perfectly Matched Layer (PML) Absorbing Boundary Conditions (ABC) for
solving on compute device using OpenCL.
solving on compute device using OpenCL.
"""
def __init__(self, *args, **kwargs):
@@ -474,7 +525,7 @@ class OpenCLPML(PML):
def set_queue(self, queue):
"""Passes in pyopencl queue.
Args:
queue: pyopencl queue.
"""
@@ -505,72 +556,76 @@ class OpenCLPML(PML):
pass
def update_electric(self):
"""Updates electric field components with the PML correction on the
compute device.
"""Updates electric field components with the PML correction on the
compute device.
"""
event = self.update_electric_dev(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_dev.shape[1]),
np.int32(self.EPhi1_dev.shape[2]),
np.int32(self.EPhi1_dev.shape[3]),
np.int32(self.EPhi2_dev.shape[1]),
np.int32(self.EPhi2_dev.shape[2]),
np.int32(self.EPhi2_dev.shape[3]),
np.int32(self.thickness),
self.G.ID_dev,
self.G.Ex_dev,
self.G.Ey_dev,
self.G.Ez_dev,
self.G.Hx_dev,
self.G.Hy_dev,
self.G.Hz_dev,
self.EPhi1_dev,
self.EPhi2_dev,
self.ERA_dev,
self.ERB_dev,
self.ERE_dev,
self.ERF_dev,
config.sim_config.dtypes['float_or_double'](self.d))
event = self.update_electric_dev(
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_dev.shape[1]),
np.int32(self.EPhi1_dev.shape[2]),
np.int32(self.EPhi1_dev.shape[3]),
np.int32(self.EPhi2_dev.shape[1]),
np.int32(self.EPhi2_dev.shape[2]),
np.int32(self.EPhi2_dev.shape[3]),
np.int32(self.thickness),
self.G.ID_dev,
self.G.Ex_dev,
self.G.Ey_dev,
self.G.Ez_dev,
self.G.Hx_dev,
self.G.Hy_dev,
self.G.Hz_dev,
self.EPhi1_dev,
self.EPhi2_dev,
self.ERA_dev,
self.ERB_dev,
self.ERE_dev,
self.ERF_dev,
config.sim_config.dtypes["float_or_double"](self.d),
)
event.wait()
def update_magnetic(self):
"""Updates magnetic field components with the PML correction on the
compute device.
"""Updates magnetic field components with the PML correction on the
compute device.
"""
event = self.update_magnetic_dev(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_dev.shape[1]),
np.int32(self.HPhi1_dev.shape[2]),
np.int32(self.HPhi1_dev.shape[3]),
np.int32(self.HPhi2_dev.shape[1]),
np.int32(self.HPhi2_dev.shape[2]),
np.int32(self.HPhi2_dev.shape[3]),
np.int32(self.thickness),
self.G.ID_dev,
self.G.Ex_dev,
self.G.Ey_dev,
self.G.Ez_dev,
self.G.Hx_dev,
self.G.Hy_dev,
self.G.Hz_dev,
self.HPhi1_dev,
self.HPhi2_dev,
self.HRA_dev,
self.HRB_dev,
self.HRE_dev,
self.HRF_dev,
config.sim_config.dtypes['float_or_double'](self.d))
event = self.update_magnetic_dev(
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_dev.shape[1]),
np.int32(self.HPhi1_dev.shape[2]),
np.int32(self.HPhi1_dev.shape[3]),
np.int32(self.HPhi2_dev.shape[1]),
np.int32(self.HPhi2_dev.shape[2]),
np.int32(self.HPhi2_dev.shape[3]),
np.int32(self.thickness),
self.G.ID_dev,
self.G.Ex_dev,
self.G.Ey_dev,
self.G.Ez_dev,
self.G.Hx_dev,
self.G.Hy_dev,
self.G.Hz_dev,
self.HPhi1_dev,
self.HPhi2_dev,
self.HRA_dev,
self.HRB_dev,
self.HRE_dev,
self.HRF_dev,
config.sim_config.dtypes["float_or_double"](self.d),
)
event.wait()
def print_pml_info(G):
"""Prints information about PMLs.
@@ -578,24 +633,26 @@ def print_pml_info(G):
G: FDTDGrid class describing a grid in a model.
"""
# No PML
if all(value == 0 for value in G.pmls['thickness'].values()):
return f'\nPML boundaries [{G.name}]: switched off'
if all(value == 0 for value in G.pmls["thickness"].values()):
return f"\nPML boundaries [{G.name}]: switched off"
if all(value == G.pmls['thickness']['x0'] for value in G.pmls['thickness'].values()):
pmlinfo = str(G.pmls['thickness']['x0'])
if all(value == G.pmls["thickness"]["x0"] for value in G.pmls["thickness"].values()):
pmlinfo = str(G.pmls["thickness"]["x0"])
else:
pmlinfo = ''
for key, value in G.pmls['thickness'].items():
pmlinfo += f'{key}: {value}, '
pmlinfo = ""
for key, value in G.pmls["thickness"].items():
pmlinfo += f"{key}: {value}, "
pmlinfo = pmlinfo[:-2]
return (f"\nPML boundaries [{G.name}]: {{formulation: {G.pmls['formulation']}, "
f"order: {len(G.pmls['cfs'])}, thickness (cells): {pmlinfo}}}")
return (
f"\nPML boundaries [{G.name}]: {{formulation: {G.pmls['formulation']}, "
f"order: {len(G.pmls['cfs'])}, thickness (cells): {pmlinfo}}}"
)
def build_pml(G, pml_ID, thickness):
"""Builds instances of the PML and calculates the initial parameters and
coefficients including setting profile (based on underlying material
"""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:
@@ -604,7 +661,7 @@ def build_pml(G, pml_ID, thickness):
thickness: int with thickness of PML slab in cells.
"""
# Arrays to hold values of permittivity and permeability (avoids accessing
# Arrays to hold values of permittivity and permeability (avoids accessing
# Material class in Cython.)
ers = np.zeros(len(G.materials))
mrs = np.zeros(len(G.materials))
@@ -613,57 +670,39 @@ def build_pml(G, pml_ID, thickness):
ers[i] = m.er
mrs[i] = m.mr
if config.sim_config.general['solver'] == 'cpu':
if config.sim_config.general["solver"] == "cpu":
pml_type = PML
elif config.sim_config.general['solver'] == 'cuda':
elif config.sim_config.general["solver"] == "cuda":
pml_type = CUDAPML
elif config.sim_config.general['solver'] == 'opencl':
elif config.sim_config.general["solver"] == "opencl":
pml_type = OpenCLPML
if pml_ID == 'x0':
pml = pml_type(G, ID=pml_ID, direction='xminus',
xs=0, xf=thickness,
ys=0, yf=G.ny,
zs=0, zf=G.nz)
elif pml_ID == 'xmax':
pml = pml_type(G, ID=pml_ID, direction='xplus',
xs=G.nx-thickness, xf=G.nx,
ys=0, yf=G.ny,
zs=0, zf=G.nz)
elif pml_ID == 'y0':
pml = pml_type(G, ID=pml_ID, direction='yminus',
xs=0, xf=G.nx,
ys=0, yf=thickness,
zs=0, zf=G.nz)
elif pml_ID == 'ymax':
pml = pml_type(G, ID=pml_ID, direction='yplus',
xs=0, xf=G.nx,
ys=G.ny-thickness, yf=G.ny,
zs=0, zf=G.nz)
elif pml_ID == 'z0':
pml = pml_type(G, ID=pml_ID, direction='zminus',
xs=0, xf=G.nx,
ys=0, yf=G.ny,
zs=0, zf=thickness)
elif pml_ID == 'zmax':
pml = pml_type(G, ID=pml_ID, direction='zplus',
xs=0, xf=G.nx,
ys=0, yf=G.ny,
zs=G.nz-thickness, zf=G.nz)
if pml_ID == "x0":
pml = pml_type(G, ID=pml_ID, direction="xminus", xs=0, xf=thickness, ys=0, yf=G.ny, zs=0, zf=G.nz)
elif pml_ID == "xmax":
pml = pml_type(G, ID=pml_ID, direction="xplus", xs=G.nx - thickness, xf=G.nx, ys=0, yf=G.ny, zs=0, zf=G.nz)
elif pml_ID == "y0":
pml = pml_type(G, ID=pml_ID, direction="yminus", xs=0, xf=G.nx, ys=0, yf=thickness, zs=0, zf=G.nz)
elif pml_ID == "ymax":
pml = pml_type(G, ID=pml_ID, direction="yplus", xs=0, xf=G.nx, ys=G.ny - thickness, yf=G.ny, zs=0, zf=G.nz)
elif pml_ID == "z0":
pml = pml_type(G, ID=pml_ID, direction="zminus", xs=0, xf=G.nx, ys=0, yf=G.ny, zs=0, zf=thickness)
elif pml_ID == "zmax":
pml = pml_type(G, ID=pml_ID, direction="zplus", xs=0, xf=G.nx, ys=0, yf=G.ny, zs=G.nz - thickness, zf=G.nz)
if pml_ID[0] == 'x':
averageer, averagemr = pml_average_er_mr(G.ny, G.nz,
config.get_model_config().ompthreads,
G.solid[pml.xs, :, :], ers, mrs)
elif pml_ID[0] == 'y':
averageer, averagemr = pml_average_er_mr(G.nx, G.nz,
config.get_model_config().ompthreads,
G.solid[:, pml.ys, :], ers, mrs)
elif pml_ID[0] == 'z':
averageer, averagemr = pml_average_er_mr(G.nx, G.ny,
config.get_model_config().ompthreads,
G.solid[:, :, pml.zs], ers, mrs)
pml.CFS = G.pmls['cfs']
if pml_ID[0] == "x":
averageer, averagemr = pml_average_er_mr(
G.ny, G.nz, config.get_model_config().ompthreads, G.solid[pml.xs, :, :], ers, mrs
)
elif pml_ID[0] == "y":
averageer, averagemr = pml_average_er_mr(
G.nx, G.nz, config.get_model_config().ompthreads, G.solid[:, pml.ys, :], ers, mrs
)
elif pml_ID[0] == "z":
averageer, averagemr = pml_average_er_mr(
G.nx, G.ny, config.get_model_config().ompthreads, G.solid[:, :, pml.zs], ers, mrs
)
pml.CFS = G.pmls["cfs"]
pml.calculate_update_coeffs(averageer, averagemr)
G.pmls['slabs'].append(pml)
G.pmls["slabs"].append(pml)

查看文件

@@ -23,14 +23,13 @@ import numpy as np
class Rx:
"""Receiver output points."""
allowableoutputs = ['Ex', 'Ey', 'Ez', 'Hx', 'Hy', 'Hz', 'Ix', 'Iy', 'Iz']
allowableoutputs = ["Ex", "Ey", "Ez", "Hx", "Hy", "Hz", "Ix", "Iy", "Iz"]
defaultoutputs = allowableoutputs[:-3]
allowableoutputs_dev = allowableoutputs[:-3]
maxnumoutputs_dev = 0
def __init__(self):
self.ID = None
self.outputs = {}
self.xcoord = None
@@ -65,19 +64,22 @@ def htod_rx_arrays(G, queue=None):
if len(rx.outputs) > Rx.maxnumoutputs_dev:
Rx.maxnumoutputs_dev = len(rx.outputs)
# Array to store field components for receivers on compute device -
# Array to store field components for receivers on compute device -
# rows are field components; columns are iterations; pages are receivers
rxs = np.zeros((len(Rx.allowableoutputs_dev), G.iterations, len(G.rxs)),
dtype=config.sim_config.dtypes['float_or_double'])
rxs = np.zeros(
(len(Rx.allowableoutputs_dev), G.iterations, len(G.rxs)), dtype=config.sim_config.dtypes["float_or_double"]
)
# Copy arrays to compute device
if config.sim_config.general['solver'] == 'cuda':
if config.sim_config.general["solver"] == "cuda":
import pycuda.gpuarray as gpuarray
rxcoords_dev = gpuarray.to_gpu(rxcoords)
rxs_dev = gpuarray.to_gpu(rxs)
elif config.sim_config.general['solver'] == 'opencl':
elif config.sim_config.general["solver"] == "opencl":
import pyopencl.array as clarray
rxcoords_dev = clarray.to_device(queue, rxcoords)
rxs_dev = clarray.to_device(queue, rxs)
@@ -85,7 +87,7 @@ def htod_rx_arrays(G, queue=None):
def dtoh_rx_array(rxs_dev, rxcoords_dev, G):
"""Copy output from receivers array used on compute device back to receiver
"""Copy output from receivers array used on compute device back to receiver
objects.
Args:
@@ -93,13 +95,15 @@ def dtoh_rx_array(rxs_dev, rxcoords_dev, G):
rxs_dev: float array of receiver data on compute device - rows are field
components; columns are iterations; pages are receivers.
G: FDTDGrid class describing a grid in a model.
"""
for rx in G.rxs:
for rxd in range(len(G.rxs)):
if (rx.xcoord == rxcoords_dev[rxd, 0] and
rx.ycoord == rxcoords_dev[rxd, 1] and
rx.zcoord == rxcoords_dev[rxd, 2]):
if (
rx.xcoord == rxcoords_dev[rxd, 0]
and rx.ycoord == rxcoords_dev[rxd, 1]
and rx.zcoord == rxcoords_dev[rxd, 2]
):
for output in rx.outputs.keys():
rx.outputs[output] = rxs_dev[Rx.allowableoutputs_dev.index(output), :, rxd]

查看文件

@@ -21,8 +21,7 @@ import logging
from .cmds_geometry.cmds_geometry import UserObjectGeometry
from .cmds_geometry.fractal_box_builder import FractalBoxBuilder
from .cmds_multiuse import UserObjectMulti
from .cmds_singleuse import (Discretisation, Domain, TimeWindow,
UserObjectSingle)
from .cmds_singleuse import Discretisation, Domain, TimeWindow, UserObjectSingle
from .materials import create_built_in_materials
from .subgrids.user_objects import SubGridBase as SubGridUserBase
from .user_inputs import create_user_input_points
@@ -43,7 +42,7 @@ class Scene:
"""Add the user object to the scene.
Args:
user_object: user object to add to the scene. For example,
user_object: user object to add to the scene. For example,
:class:`gprMax.cmds_single_use.Domain`
"""
if isinstance(user_object, UserObjectMulti):
@@ -53,7 +52,7 @@ class Scene:
elif isinstance(user_object, UserObjectSingle):
self.single_cmds.append(user_object)
else:
logger.exception('This object is unknown to gprMax')
logger.exception("This object is unknown to gprMax")
raise ValueError
def process_subgrid_commands(self):
@@ -91,7 +90,7 @@ class Scene:
try:
obj.create(grid, uip)
except ValueError:
logger.exception('Error creating user input object')
logger.exception("Error creating user input object")
raise
return self
@@ -100,24 +99,26 @@ class Scene:
# Check for duplicate commands and warn user if they exist
cmds_unique = list(set(self.single_cmds))
if len(cmds_unique) != len(self.single_cmds):
logger.exception('Duplicate single-use commands exist in the input.')
logger.exception("Duplicate single-use commands exist in the input.")
raise ValueError
# Check essential commands and warn user if missing
for cmd_type in self.essential_cmds:
d = any(isinstance(cmd, cmd_type) for cmd in cmds_unique)
if not d:
logger.exception('Your input file is missing essential commands ' +
'required to run a model. Essential commands ' +
'are: Domain, Discretisation, Time Window')
logger.exception(
"Your input file is missing essential commands "
+ "required to run a model. Essential commands "
+ "are: Domain, Discretisation, Time Window"
)
raise ValueError
self.process_cmds(cmds_unique, G)
def create_internal_objects(self, G):
"""Calls the UserObject.create() function in the correct way - API
presents the user with UserObjects in order to build the internal
Rx(), Cylinder() etc... objects.
"""Calls the UserObject.create() function in the correct way - API
presents the user with UserObjects in order to build the internal
Rx(), Cylinder() etc... objects.
"""
# Fractal box commands have an additional nonuser object which
@@ -142,4 +143,4 @@ class Scene:
self.process_cmds(self.geometry_cmds, G, sort=False)
# Process all the commands for subgrids
self.process_subgrid_commands()
self.process_subgrid_commands()

查看文件

@@ -36,7 +36,7 @@ logger = logging.getLogger(__name__)
def save_snapshots(grid):
"""Saves snapshots to file(s).
Args:
grid: FDTDGrid class describing a grid in a model.
"""
@@ -44,31 +44,35 @@ def save_snapshots(grid):
# Create directory for snapshots
snapshotdir = config.get_model_config().set_snapshots_dir()
snapshotdir.mkdir(exist_ok=True)
logger.info('')
logger.info(f'Snapshot directory: {snapshotdir.resolve()}')
logger.info("")
logger.info(f"Snapshot directory: {snapshotdir.resolve()}")
for i, snap in enumerate(grid.snapshots):
fn = snapshotdir / Path(snap.filename)
snap.filename = fn.with_suffix(snap.fileext)
pbar = tqdm(total=snap.nbytes, leave=True, unit='byte',
unit_scale=True, desc=f'Writing snapshot file {i + 1} '
f'of {len(grid.snapshots)}, '
f'{snap.filename.name}',
ncols=get_terminal_width() - 1, file=sys.stdout,
disable=not config.sim_config.general['progressbars'])
pbar = tqdm(
total=snap.nbytes,
leave=True,
unit="byte",
unit_scale=True,
desc=f"Writing snapshot file {i + 1} " f"of {len(grid.snapshots)}, " f"{snap.filename.name}",
ncols=get_terminal_width() - 1,
file=sys.stdout,
disable=not config.sim_config.general["progressbars"],
)
snap.write_file(pbar, grid)
pbar.close()
logger.info('')
logger.info("")
class Snapshot:
"""Snapshots of the electric and magnetic field values."""
allowableoutputs = {'Ex': None, 'Ey': None, 'Ez': None,
'Hx': None, 'Hy': None, 'Hz': None}
allowableoutputs = {"Ex": None, "Ey": None, "Ez": None, "Hx": None, "Hy": None, "Hz": None}
# Snapshots can be output as VTK ImageData (.vti) format or
# Snapshots can be output as VTK ImageData (.vti) format or
# HDF5 format (.h5) files
fileexts = ['.vti', '.h5']
fileexts = [".vti", ".h5"]
# Dimensions of largest requested snapshot
nx_max = 0
@@ -80,9 +84,22 @@ class Snapshot:
# GPU - blocks per grid - set according to largest requested snapshot
bpg = 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,
fileext=None, outputs=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,
fileext=None,
outputs=None,
):
"""
Args:
xs, xf, ys, yf, zs, zf: ints for the extent of the volume in cells.
@@ -118,14 +135,14 @@ class Snapshot:
self.snapfields = {}
for k, v in self.outputs.items():
if v:
self.snapfields[k] = np.zeros((self.nx, self.ny, self.nz),
dtype=config.sim_config.dtypes['float_or_double'])
self.nbytes += (self.snapfields[k].nbytes)
self.snapfields[k] = np.zeros(
(self.nx, self.ny, self.nz), dtype=config.sim_config.dtypes["float_or_double"]
)
self.nbytes += self.snapfields[k].nbytes
else:
# If output is not required for snapshot just use a mimimal
# If output is not required for snapshot just use a mimimal
# size of array - still required to pass to Cython function
self.snapfields[k] = np.zeros((1, 1, 1),
dtype=config.sim_config.dtypes['float_or_double'])
self.snapfields[k] = np.zeros((1, 1, 1), dtype=config.sim_config.dtypes["float_or_double"])
def store(self, G):
"""Store (in memory) electric and magnetic field values for snapshot.
@@ -142,35 +159,35 @@ class Snapshot:
Hyslice = np.ascontiguousarray(G.Hy[self.sx, self.sy, self.sz])
Hzslice = np.ascontiguousarray(G.Hz[self.sx, self.sy, self.sz])
# Calculate field values at points (comes from averaging field
# Calculate field values at points (comes from averaging field
# components in cells)
calculate_snapshot_fields(
self.nx,
self.ny,
self.nz,
config.get_model_config().ompthreads,
self.outputs['Ex'],
self.outputs['Ey'],
self.outputs['Ez'],
self.outputs['Hx'],
self.outputs['Hy'],
self.outputs['Hz'],
self.outputs["Ex"],
self.outputs["Ey"],
self.outputs["Ez"],
self.outputs["Hx"],
self.outputs["Hy"],
self.outputs["Hz"],
Exslice,
Eyslice,
Ezslice,
Hxslice,
Hyslice,
Hzslice,
self.snapfields['Ex'],
self.snapfields['Ey'],
self.snapfields['Ez'],
self.snapfields['Hx'],
self.snapfields['Hy'],
self.snapfields['Hz']
self.snapfields["Ex"],
self.snapfields["Ey"],
self.snapfields["Ez"],
self.snapfields["Hx"],
self.snapfields["Hy"],
self.snapfields["Hz"],
)
def write_file(self, pbar, G):
"""Writes snapshot file either as VTK ImageData (.vti) format
"""Writes snapshot file either as VTK ImageData (.vti) format
or HDF5 format (.h5) files
Args:
@@ -178,9 +195,9 @@ class Snapshot:
G: FDTDGrid class describing a grid in a model.
"""
if self.fileext == '.vti':
if self.fileext == ".vti":
self.write_vtk(pbar, G)
elif self.fileext == '.h5':
elif self.fileext == ".h5":
self.write_hdf5(pbar, G)
def write_vtk(self, pbar, G):
@@ -195,31 +212,33 @@ class Snapshot:
for k, v in self.outputs.items():
if v:
if k == 'Ex':
celldata[k] = self.snapfields['Ex']
if k == 'Ey':
celldata[k] = self.snapfields['Ey']
if k == 'Ez':
celldata[k] = self.snapfields['Ez']
if k == 'Hx':
celldata[k] = self.snapfields['Hx']
if k == 'Hy':
celldata[k] = self.snapfields['Hy']
if k == 'Hz':
celldata[k] = self.snapfields['Hz']
if k == "Ex":
celldata[k] = self.snapfields["Ex"]
if k == "Ey":
celldata[k] = self.snapfields["Ey"]
if k == "Ez":
celldata[k] = self.snapfields["Ez"]
if k == "Hx":
celldata[k] = self.snapfields["Hx"]
if k == "Hy":
celldata[k] = self.snapfields["Hy"]
if k == "Hz":
celldata[k] = self.snapfields["Hz"]
imageToVTK(str(self.filename.with_suffix('')),
origin=((self.xs * self.dx * G.dx),
(self.ys * self.dy * G.dy),
(self.zs * self.dz * G.dz)),
spacing=((self.dx * G.dx),
(self.dy * G.dy),
(self.dz * G.dz)),
cellData=celldata)
pbar.update(n=len(celldata) * self.nx * self.ny * self.nz *
np.dtype(config.sim_config.dtypes['float_or_double']).itemsize)
imageToVTK(
str(self.filename.with_suffix("")),
origin=((self.xs * self.dx * G.dx), (self.ys * self.dy * G.dy), (self.zs * self.dz * G.dz)),
spacing=((self.dx * G.dx), (self.dy * G.dy), (self.dz * G.dz)),
cellData=celldata,
)
pbar.update(
n=len(celldata)
* self.nx
* self.ny
* self.nz
* np.dtype(config.sim_config.dtypes["float_or_double"]).itemsize
)
def write_hdf5(self, pbar, G):
"""Writes snapshot file in HDF5 (.h5) format.
@@ -229,31 +248,31 @@ class Snapshot:
G: FDTDGrid class describing a grid in a model.
"""
f = h5py.File(self.filename, 'w')
f.attrs['gprMax'] = __version__
f.attrs['Title'] = G.title
f.attrs['nx_ny_nz'] = (self.nx, self.ny, self.nz)
f.attrs['dx_dy_dz'] = (self.dx * G.dx, self.dy * G.dy, self.dz * G.dz)
f.attrs['time'] = self.time * G.dt
f = h5py.File(self.filename, "w")
f.attrs["gprMax"] = __version__
f.attrs["Title"] = G.title
f.attrs["nx_ny_nz"] = (self.nx, self.ny, self.nz)
f.attrs["dx_dy_dz"] = (self.dx * G.dx, self.dy * G.dy, self.dz * G.dz)
f.attrs["time"] = self.time * G.dt
if self.outputs['Ex']:
f['Ex'] = self.snapfields['Ex']
pbar.update(n=self.snapfields['Ex'].nbytes)
if self.outputs['Ey']:
f['Ey'] = self.snapfields['Ey']
pbar.update(n=self.snapfields['Ey'].nbytes)
if self.outputs['Ez']:
f['Ez'] = self.snapfields['Ez']
pbar.update(n=self.snapfields['Ez'].nbytes)
if self.outputs['Hx']:
f['Hx'] = self.snapfields['Hx']
pbar.update(n=self.snapfields['Hx'].nbytes)
if self.outputs['Hy']:
f['Hy'] = self.snapfields['Hy']
pbar.update(n=self.snapfields['Hy'].nbytes)
if self.outputs['Hz']:
f['Hz'] = self.snapfields['Hz']
pbar.update(n=self.snapfields['Hz'].nbytes)
if self.outputs["Ex"]:
f["Ex"] = self.snapfields["Ex"]
pbar.update(n=self.snapfields["Ex"].nbytes)
if self.outputs["Ey"]:
f["Ey"] = self.snapfields["Ey"]
pbar.update(n=self.snapfields["Ey"].nbytes)
if self.outputs["Ez"]:
f["Ez"] = self.snapfields["Ez"]
pbar.update(n=self.snapfields["Ez"].nbytes)
if self.outputs["Hx"]:
f["Hx"] = self.snapfields["Hx"]
pbar.update(n=self.snapfields["Hx"].nbytes)
if self.outputs["Hy"]:
f["Hy"] = self.snapfields["Hy"]
pbar.update(n=self.snapfields["Hy"].nbytes)
if self.outputs["Hz"]:
f["Hz"] = self.snapfields["Hz"]
pbar.update(n=self.snapfields["Hz"].nbytes)
f.close()
@@ -278,37 +297,44 @@ def htod_snapshot_array(G, queue=None):
if snap.nz > Snapshot.nz_max:
Snapshot.nz_max = snap.nz
if config.sim_config.general['solver'] == 'cuda':
if config.sim_config.general["solver"] == "cuda":
# 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)
elif config.sim_config.general['solver'] == 'opencl':
Snapshot.bpg = (
int(np.ceil(((Snapshot.nx_max) * (Snapshot.ny_max) * (Snapshot.nz_max)) / Snapshot.tpb[0])),
1,
1,
)
elif config.sim_config.general["solver"] == "opencl":
# Workgroup size - according to largest requested snapshot
Snapshot.wgs = (int(np.ceil(((Snapshot.nx_max) *
(Snapshot.ny_max) *
(Snapshot.nz_max)))), 1, 1)
Snapshot.wgs = (int(np.ceil(((Snapshot.nx_max) * (Snapshot.ny_max) * (Snapshot.nz_max)))), 1, 1)
# 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.get_model_config().device['snapsgpu2cpu'] else len(G.snapshots)
snapEx = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.sim_config.dtypes['float_or_double'])
snapEy = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.sim_config.dtypes['float_or_double'])
snapEz = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.sim_config.dtypes['float_or_double'])
snapHx = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.sim_config.dtypes['float_or_double'])
snapHy = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.sim_config.dtypes['float_or_double'])
snapHz = np.zeros((numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max),
dtype=config.sim_config.dtypes['float_or_double'])
numsnaps = 1 if config.get_model_config().device["snapsgpu2cpu"] else len(G.snapshots)
snapEx = np.zeros(
(numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=config.sim_config.dtypes["float_or_double"]
)
snapEy = np.zeros(
(numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=config.sim_config.dtypes["float_or_double"]
)
snapEz = np.zeros(
(numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=config.sim_config.dtypes["float_or_double"]
)
snapHx = np.zeros(
(numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=config.sim_config.dtypes["float_or_double"]
)
snapHy = np.zeros(
(numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=config.sim_config.dtypes["float_or_double"]
)
snapHz = np.zeros(
(numsnaps, Snapshot.nx_max, Snapshot.ny_max, Snapshot.nz_max), dtype=config.sim_config.dtypes["float_or_double"]
)
# Copy arrays to compute device
if config.sim_config.general['solver'] == 'cuda':
if config.sim_config.general["solver"] == "cuda":
import pycuda.gpuarray as gpuarray
snapEx_dev = gpuarray.to_gpu(snapEx)
snapEy_dev = gpuarray.to_gpu(snapEy)
snapEz_dev = gpuarray.to_gpu(snapEz)
@@ -316,8 +342,9 @@ def htod_snapshot_array(G, queue=None):
snapHy_dev = gpuarray.to_gpu(snapHy)
snapHz_dev = gpuarray.to_gpu(snapHz)
elif config.sim_config.general['solver'] == 'opencl':
elif config.sim_config.general["solver"] == "opencl":
import pyopencl.array as clarray
snapEx_dev = clarray.to_device(queue, snapEx)
snapEy_dev = clarray.to_device(queue, snapEy)
snapEz_dev = clarray.to_device(queue, snapEz)
@@ -328,9 +355,8 @@ def htod_snapshot_array(G, queue=None):
return snapEx_dev, snapEy_dev, snapEz_dev, snapHx_dev, snapHy_dev, snapHz_dev
def dtoh_snapshot_array(snapEx_dev, snapEy_dev, snapEz_dev,
snapHx_dev, snapHy_dev, snapHz_dev, i, snap):
"""Copies snapshot array used on compute device back to snapshot objects and
def dtoh_snapshot_array(snapEx_dev, snapEy_dev, snapEz_dev, snapHx_dev, snapHy_dev, snapHz_dev, i, snap):
"""Copies snapshot array used on compute device back to snapshot objects and
store in format for Paraview.
Args:
@@ -339,9 +365,9 @@ def dtoh_snapshot_array(snapEx_dev, snapEy_dev, snapEz_dev,
snap: Snapshot class instance
"""
snap.snapfields['Ex'] = snapEx_dev[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf]
snap.snapfields['Ey'] = snapEy_dev[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf]
snap.snapfields['Ez'] = snapEz_dev[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf]
snap.snapfields['Hx'] = snapHx_dev[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf]
snap.snapfields['Hy'] = snapHy_dev[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf]
snap.snapfields['Hz'] = snapHz_dev[i, snap.xs:snap.xf, snap.ys:snap.yf, snap.zs:snap.zf]
snap.snapfields["Ex"] = snapEx_dev[i, snap.xs : snap.xf, snap.ys : snap.yf, snap.zs : snap.zf]
snap.snapfields["Ey"] = snapEy_dev[i, snap.xs : snap.xf, snap.ys : snap.yf, snap.zs : snap.zf]
snap.snapfields["Ez"] = snapEz_dev[i, snap.xs : snap.xf, snap.ys : snap.yf, snap.zs : snap.zf]
snap.snapfields["Hx"] = snapHx_dev[i, snap.xs : snap.xf, snap.ys : snap.yf, snap.zs : snap.zf]
snap.snapfields["Hy"] = snapHy_dev[i, snap.xs : snap.xf, snap.ys : snap.yf, snap.zs : snap.zf]
snap.snapfields["Hz"] = snapHz_dev[i, snap.xs : snap.xf, snap.ys : snap.yf, snap.zs : snap.zf]

查看文件

@@ -30,11 +30,11 @@ def create_G():
G: FDTDGrid class describing a grid in a model.
"""
if config.sim_config.general['solver'] == 'cpu':
if config.sim_config.general["solver"] == "cpu":
G = FDTDGrid()
elif config.sim_config.general['solver'] == 'cuda':
elif config.sim_config.general["solver"] == "cuda":
G = CUDAGrid()
elif config.sim_config.general['solver'] == 'opencl':
elif config.sim_config.general["solver"] == "opencl":
G = OpenCLGrid()
return G
@@ -45,10 +45,10 @@ def create_solver(G):
N.B. A large range of different functions exist to advance the time step for
dispersive materials. The correct function is set by the
set_dispersive_updates method, based on the required numerical
precision and dispersive material type.
This is done for solvers running on CPU, i.e. where Cython is used.
CUDA and OpenCL dispersive material functions are handled through
set_dispersive_updates method, based on the required numerical
precision and dispersive material type.
This is done for solvers running on CPU, i.e. where Cython is used.
CUDA and OpenCL dispersive material functions are handled through
templating and substitution at runtime.
Args:
@@ -58,23 +58,24 @@ def create_solver(G):
solver: Solver object.
"""
if config.sim_config.general['subgrid']:
if config.sim_config.general["subgrid"]:
updates = create_subgrid_updates(G)
if config.get_model_config().materials['maxpoles'] != 0:
# Set dispersive update functions for both SubgridUpdates and
if config.get_model_config().materials["maxpoles"] != 0:
# Set dispersive update functions for both SubgridUpdates and
# SubgridUpdaters subclasses
updates.set_dispersive_updates()
for u in updates.updaters: u.set_dispersive_updates()
solver = Solver(updates, hsg=True)
elif config.sim_config.general['solver'] == 'cpu':
for u in updates.updaters:
u.set_dispersive_updates()
solver = Solver(updates, hsg=True)
elif config.sim_config.general["solver"] == "cpu":
updates = CPUUpdates(G)
if config.get_model_config().materials['maxpoles'] != 0:
if config.get_model_config().materials["maxpoles"] != 0:
updates.set_dispersive_updates()
solver = Solver(updates)
elif config.sim_config.general['solver'] == 'cuda':
elif config.sim_config.general["solver"] == "cuda":
updates = CUDAUpdates(G)
solver = Solver(updates)
elif config.sim_config.general['solver'] == 'opencl':
elif config.sim_config.general["solver"] == "opencl":
updates = OpenCLUpdates(G)
solver = Solver(updates)
@@ -119,9 +120,9 @@ class Solver:
if self.hsg:
self.updates.hsg_1()
self.updates.update_electric_b()
if config.sim_config.general['solver'] == 'cuda':
self.memused = self.updates.calculate_memory_used(iteration)
if config.sim_config.general["solver"] == "cuda":
self.memused = self.updates.calculate_memory_used(iteration)
self.updates.finalise()
self.solvetime = self.updates.calculate_solve_time()
self.updates.cleanup()
self.updates.cleanup()

某些文件未显示,因为此 diff 中更改的文件太多 显示更多