Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
fb4fac6
fix: bug related to an empty path, was preventing cadquery STL export
elenafuengar Nov 19, 2025
6ec07df
style: apply RUFFs suggestions + add logo with private function
elenafuengar Nov 19, 2025
2a32aec
refact: include stl_colors in prepare stl dicts, now it will always c…
elenafuengar Nov 20, 2025
a68990a
style: modify materials and colors dictionaries
elenafuengar Nov 20, 2025
5629281
feature: allow logger to be saved from any class, by passing the mate…
elenafuengar Nov 20, 2025
6b5e9d0
feature: add method `inspect()` to interactively show all the solids …
elenafuengar Nov 20, 2025
2b5c191
fix: apply codeQL findings + fix test failing
elenafuengar Nov 21, 2025
f0f9b02
feature: add progress bar to STL importing when grid is large >5M cells
elenafuengar Nov 21, 2025
5b19781
fix: solve some visualization errors + homogenize parameters `offscre…
elenafuengar Nov 24, 2025
3f9a1b9
feature: add `solver.inspect()` to notebook 002
elenafuengar Nov 24, 2025
6e53f24
test: reorganize test, now all 3D interactive plotting routines are i…
elenafuengar Nov 24, 2025
e713135
test: solve deprecation warnings and off_screen/on_screen test passin…
elenafuengar Nov 25, 2025
5de157c
style: change default stainless steel material to `silver`
elenafuengar Nov 25, 2025
f75be71
tests: use vtk-osmesa to run the 3D plotting offscreen
elenafuengar Nov 25, 2025
40aba8d
tests: update interactive plots, now not skipped thanks to vtk-osmesa…
elenafuengar Nov 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/manual_tests_CPU.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
- name: pip install
run: |
pip install wakis['notebook']
pip uninstall vtk -y
pip install --extra-index-url https://wheels.vtk.org vtk-osmesa
- name: Print versions
run: conda list
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/nightly_tests_CPU.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ jobs:
- name: pip install
run: |
pip install wakis['notebook']
pip uninstall vtk -y
pip install --extra-index-url https://wheels.vtk.org vtk-osmesa
- name: Print versions
run: conda list
- name: Checkout wakis
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/pull_request_CPU.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ jobs:
run: |
cd wakis
pip install .['notebook']
pip uninstall vtk -y
pip install --extra-index-url https://wheels.vtk.org vtk-osmesa

- name: Print installed packages
run: conda list
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ FDTD_*
ECT_*
*/img*
*.png
*.html
*.gif
*.old*
*.svg
Expand Down
270 changes: 233 additions & 37 deletions notebooks/002_Wakefield_simulation.ipynb

Large diffs are not rendered by default.

103 changes: 46 additions & 57 deletions tests/test_003_planewave_sphere.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import os, sys
import numpy as np
import os
import sys
import pyvista as pv
import matplotlib.pyplot as plt
from scipy.constants import c

sys.path.append('../wakis')

from wakis import SolverFIT3D
from wakis import GridFIT3D
from wakis import GridFIT3D
from wakis.sources import PlaneWave

import pytest
import pytest

flag_interactive = False # Set to true to run PyVista tests
# Turn False when running local
flag_offscreen = True

class TestPlanewave:

img_folder = 'tests/003_img/'

def test_simulation(self):
print("\n---------- Initializing simulation ------------------")
# Number of mesh cells
Expand All @@ -23,7 +27,7 @@ def test_simulation(self):
Nz = 120

# Embedded boundaries
stl_file = 'tests/stl/003_sphere.stl'
stl_file = 'tests/stl/003_sphere.stl'
surf = pv.read(stl_file)

stl_solids = {'Sphere': stl_file}
Expand All @@ -44,90 +48,75 @@ def test_simulation(self):
xmax, ymax, zmax = (xmax+padx), (ymax+pady), (zmax+padz)

global grid
grid = GridFIT3D(xmin, xmax, ymin, ymax, zmin, zmax, Nx, Ny, Nz,
stl_solids=stl_solids,
grid = GridFIT3D(xmin, xmax, ymin, ymax, zmin, zmax, Nx, Ny, Nz,
stl_solids=stl_solids,
stl_rotate=stl_rotate,
stl_scale=stl_scale,
stl_materials=stl_materials)

# Boundary conditions and
# Boundary conditions and
bc_low=['periodic', 'periodic', 'pec']
bc_high=['periodic', 'periodic', 'pml']


# -------------- Output folder ---------------------
if not os.path.exists(self.img_folder):
os.mkdir(self.img_folder)

# simulation
global solver
solver = SolverFIT3D(grid, use_stl=True, bc_low=bc_low, bc_high=bc_high)

# source
f = 15/((solver.z.max()-solver.z.min())/c)
source = PlaneWave(xs=slice(1, Nx-1), ys=slice(1,Ny-1), zs=1,
source = PlaneWave(xs=slice(1, Nx-1), ys=slice(1,Ny-1), zs=1,
f=f, beta=1.0)

Nt = int(1.0*(solver.z.max()-solver.z.min())/c/solver.dt)
solver.emsolve(Nt, source)

def test_plot2D(self):
def test_plot1D(self):
global solver
solver.plot2D('Ex', plane='ZY', pos=0.5, cmap='rainbow',
add_patch='Sphere', patch_alpha=0.3,
off_screen=False)
if not flag_interactive:
plt.close()
def test_plot2D_offscreen(self):
solver.plot1D('Ex', line='z', pos=[0.7, 0.6, 0.5, 0.4, 0.3, 0.2],
xscale='linear', yscale='linear',
off_screen=flag_offscreen, n=solver.Nt,
colors=['#5ccfe6', '#fdb6d0', '#ffae57', '#bae67e', '#ffd580', '#a2aabc'],
title=self.img_folder+'1Dplot_Ex')

def test_plot2D(self):
global solver
solver.plot2D('Hy', plane='ZY', pos=0.5, cmap='bwr',
solver.plot2D('Hy', plane='ZY', pos=0.5, cmap='bwr',
add_patch='Sphere', patch_alpha=0.1, interpolation='spline36',
off_screen=True, n=solver.Nt, title='003_2Dplot_Hy')
if not flag_interactive:
os.remove(f'003_2Dplot_Hy_{str(solver.Nt).zfill(6)}.png')

@pytest.mark.skipif(not flag_interactive, reason="Requires interactive plotting")
off_screen=flag_offscreen, n=solver.Nt,
title=self.img_folder+'2Dplot_Hy')

@pytest.mark.skipif(flag_offscreen, reason="Requires interactive plotting")
def test_plot3D_interactive(self):
global solver
solver.plot3D(field='E', component='x', cmap='jet',
add_stl='Sphere', stl_opacity=0.1, stl_colors='white',
clip_interactive=True, clip_normal='-y',
off_screen=False)

@pytest.mark.skipif(not flag_interactive, reason="Requires Xserver connection for plotting")
off_screen=False)

def test_plot3D_offscreen(self):
global solver
solver.plot3D(field='H', component='y', cmap='bwr',
add_stl='Sphere', stl_opacity=0.1, stl_colors='white',
clip_box=True, clip_bounds=None,
off_screen=True, title='003_3Dplot_Hy')
if not flag_interactive:
os.remove('003_3Dplot_Hy.png')

@pytest.mark.skipif(not flag_interactive, reason="Requires interactive plotting")
clip_box=True, clip_bounds=None,
off_screen=flag_offscreen, title=self.img_folder+'3Dplot_Hy')

@pytest.mark.skipif(flag_offscreen, reason="Requires interactive plotting")
def test_plot3DonSTL_interactive(self):
global solver
solver.plot3DonSTL('Ex', cmap='jet',
solver.plot3DonSTL('Ex', cmap='jet',
stl_with_field='Sphere', field_opacity=1.,
stl_transparent='Sphere', stl_opacity=0.3, stl_colors='white',
clip_interactive=True, clip_normal='-y',
off_screen=False, zoom=1.0)

@pytest.mark.skipif(not flag_interactive, reason="Requires Xserver connection for plotting")

def test_plot3DonSTL_offscreen(self):
global solver
solver.plot3DonSTL('Ex', cmap='jet',
solver.plot3DonSTL('Ex', cmap='jet',
stl_with_field='Sphere', field_opacity=1.,
stl_transparent=None, stl_opacity=0., stl_colors=None,
off_screen=True, zoom=1.0, title='003_3DplotOnSTL_Hy')
if not flag_interactive:
os.remove('003_3DplotOnSTL_Hy.png')


@pytest.mark.skipif(not flag_interactive, reason="Requires interactive plotting")
def test_grid_inspect(self):
global grid
grid.inspect(add_stl=None, stl_opacity=0.5, stl_colors=None,
anti_aliasing='ssa')

@pytest.mark.skipif(not flag_interactive, reason="Requires interactive plotting")
def test_grid_plot_solids(self):
global grid
grid.plot_solids(bounding_box=False, opacity=1.0, specular=0.5,
anti_aliasing=None)
off_screen=flag_offscreen, zoom=1.0,
title=self.img_folder+'3DplotOnSTL_Hy')
45 changes: 11 additions & 34 deletions tests/test_007_mpi_lossy_cavity.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,19 @@ class TestMPILossyCavity:
-6.04105997e+01 ,-3.06532160e+01 ,-1.17749936e+01 ,-3.12574866e+00,
-7.35339521e-01 ,-1.13085658e-01 , 7.18247535e-01 , 8.73829036e-02])

gridLogs = {'use_mesh_refinement': False, 'Nx': 60, 'Ny': 60, 'Nz': 140, 'dx': 0.00866666634877522,
'dy': 0.00866666634877522, 'dz': 0.005714285799435207,
'xmin': -0.25999999046325684, 'xmax': 0.25999999046325684,
'ymin': -0.25999999046325684, 'ymax': 0.25999999046325684,
'zmin': -0.25, 'zmax': 0.550000011920929,
gridLogs = {'use_mesh_refinement': False, 'Nx': 60, 'Ny': 60, 'Nz': 140, 'dx': 0.00866666634877522,
'dy': 0.00866666634877522, 'dz': 0.005714285799435207,
'xmin': -0.25999999046325684, 'xmax': 0.25999999046325684,
'ymin': -0.25999999046325684, 'ymax': 0.25999999046325684,
'zmin': -0.25, 'zmax': 0.550000011920929,
'stl_solids': {'cavity': 'tests/stl/007_vacuum_cavity.stl', 'shell': 'tests/stl/007_lossymetal_shell.stl'},
'stl_materials': {'cavity': 'vacuum', 'shell': [30, 1.0, 30]},
'stl_materials': {'cavity': 'vacuum', 'shell': [30, 1.0, 30]},
'gridInitializationTime': 0}

solverLogs = {'use_gpu': False, 'use_mpi': False, 'background': 'pec',
'bc_low': ['pec', 'pec', 'pec'], 'bc_high': ['pec', 'pec', 'pec'],
'bc_low': ['pec', 'pec', 'pec'], 'bc_high': ['pec', 'pec', 'pec'],
'dt': 6.970326728398966e-12, 'solverInitializationTime': 0}

wakeSolverLogs = {'ti': 2.8516132094735135e-09, 'q': 1e-09, 'sigmaz': 0.1, 'beta': 1.0,
'xsource': 0.0, 'ysource': 0.0, 'xtest': 0.0, 'ytest': 0.0, 'chargedist': None,
'skip_cells': 10, 'results_folder': 'tests/007_results/', 'wakelength': 10.0, 'simulationTime': 0}
Expand Down Expand Up @@ -252,29 +252,6 @@ def test_mpi_plot1D(self):
xscale='linear', yscale='linear',
off_screen=True, title=self.img_folder+'Ez1d', n=3000)

@pytest.mark.skipif(not flag_plot_3D, reason="Requires interactive plotting")
def test_mpi_plot3D(self):
# Plot Abs Electric field on domain
# disabled when mpi = True
global solver
solver.plot3D('E', component='Abs',
cmap='rainbow', clim=[0, 500],
add_stl=['cavity', 'shell'], stl_opacity=0.1,
clip_interactive=True, clip_normal='-y')

@pytest.mark.skipif(not flag_plot_3D, reason="Requires interactive plotting")
def test_mpi_plot3DonSTL(self):
# Plot Abs Electric field on STL solid `cavity`
# disabled when mpi = True
global solver
solver.plot3DonSTL('E', component='Abs',
cmap='rainbow', clim=[0, 500],
stl_with_field='cavity', field_opacity=1.0,
stl_transparent='shell', stl_opacity=0.1, stl_colors='white',
clip_plane=True, clip_normal='-y', clip_origin=[0,0,0],
off_screen=False, zoom=1.2, title=self.img_folder+'Ez3d')


def test_mpi_wakefield(self):
# Reset fields
global solver
Expand Down Expand Up @@ -343,7 +320,7 @@ def test_long_impedance(self):
assert np.allclose(np.real(wake.Z)[::20], np.real(self.Z), rtol=0.1), "Real Impedance samples failed"
assert np.allclose(np.imag(wake.Z)[::20], np.imag(self.Z), rtol=0.1), "Imag Impedance samples failed"
assert np.cumsum(np.abs(wake.Z))[-1] == pytest.approx(250910.51090497518, 0.1), "Abs Impedance cumsum failed"

def test_log_file(self):
# Helper function to compare nested dicts with float tolerance
def assert_dict_allclose(d1, d2, rtol=1e-6, atol=1e-12, path=""):
Expand Down Expand Up @@ -379,7 +356,7 @@ def assert_dict_allclose(d1, d2, rtol=1e-6, atol=1e-12, path=""):

global solver
# Exclude timing info from comparison as they can vary between runs
solver.logger.grid["gridInitializationTime"] = 0
solver.logger.grid["gridInitializationTime"] = 0
solver.logger.solver["solverInitializationTime"] = 0
solver.logger.wakeSolver["simulationTime"] = 0
self.solverLogs['use_mpi'] = use_mpi
Expand Down
Loading
Loading