A 3D FDM electromagnetic solver with real-time visualization. Inputs into the simulation are time-varying charge density and current density fields. Boundaries are absorbing. A CPU implementation (NumPy) and a GPU implementation (PyCUDA) are available.
This is a work in progress. Currently the CUDA implementation only follows Gauss's and Ampere's laws. NumPy implementation is complete, but unverified.
An incomplete simulation of a dipole radiator
Refer to example.py
for a concrete example that was used to render the simulation shown above.
- Create an EM field domain
from src import emfield
field = emfield.Field(
size, # Grid size [x size, y size, z size],
scale, # Spatial resolution
timestep, # Time resolution
compute # Solver implementation, "numpy" or "cuda"
)
- Modify the charge density and current density fields
field.charge_density[...] = 0 # 3D scalar field,
# NumPy array (x size, y size, z size)
field.current_density[...] = 0 # 3D vector field,
# NumPy array (x size, y size, z size, 3)
- Compute a simulation time step
field.update()
- Retrieve resulting E and B fields
E_field = field.efield[1, ...] # 3D vector field,
# NumPy array (x size, y size, z size, 3)
B_field = field.bfield[1, ...] # 3D vector field,
# NumPy array (x size, y size, z size, 3)
# efield[0, ...] and bfield[0, ...] contain the previous values
# of the fields
- Create a window
from src import gui, fieldvis
window = gui.Window(
size # Size in pixels [width, height]
)
- Create a visualizer instance
visualizer = fieldvis.FieldVisualizer(
field # EM field domain
)
- Clear the window
window.fill(
color=[0, 0, 0] # Integer color values from 0 to 255 [R, G, B]
)
- Render a slice of the domain into a 2D pixel array
array = visualizer.eFieldRgb(
index, # Index (depth) of the desired 2D slice
axis, # Axis along which to slice (0: x, 1: y, 2: z)
intensity # Brightness scale
)
- Draw the array onto the window
window.drawArray(
array, # 2D pixel array
size, # Scale of the drawn array as a factor of window size
# from 0 to 1 [x scale, y scale]
position # Position of the drawn array as a factor of window size
# from 0 to 1 [x position, y position]
)
- Throttle the refresh rate
window.sleep(
fps # Desired frames per second (or slower if simulation cannot keep up)
)
- Refresh the window
# Boolean, False if exit button was pressed, True otherwise
app_continue = window.update()
- Close the window
window.close()
Function | Description | Formula |
---|---|---|
FieldVisualizer.eFieldRgb | E (vector) field | R,G,B = intensity * X,Y,Z |
FieldVisualizer.bFieldRgb | B (vector) field | R,G,B = intensity * X,Y,Z |
FieldVisualizer.eFieldMagnitude | E magnitude (scalar) field | R=G=B = intensity * |X,Y,Z| |
FieldVisualizer.bFieldMagnitude | B magnitude (scalar) field | R=G=B = intensity * |X,Y,Z| |
FieldVisualizer.chargeDensity | Charge density (scalar) field | R = intensity * |X| * (X > 0) G = 0 B = intensity * |X| * (X < 0) |
FieldVisualizer.currentDensity | Current density (vector) field | R,G,B = intensity * X,Y,Z |
FieldVisualizer.chargeDensityTransparent | Charge density (scalar) field | R = (X > 0) G = 0 B = (X < 0) A = intensity * |X| |
FieldVisualizer.currentDensityTransparent | Current density (vector) field | R,G,B = X,Y,Z / |X,Y,Z| A = intensity * |X,Y,Z| |