Skip to content
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
ddb2cbb
WIP: logfile
Antoniahuber Nov 10, 2025
37355f1
Merge branch 'main' of github.com:Antoniahuber/wakis
Antoniahuber Nov 10, 2025
28d4c74
Created Logfile and amended the test
Antoniahuber Nov 10, 2025
d04601b
Delete build/lib/wakis/__init__.py
Antoniahuber Nov 11, 2025
35f5090
Delete build/lib/wakis/_version.py
Antoniahuber Nov 11, 2025
70e5f61
Delete build/lib/wakis/conductors.py
Antoniahuber Nov 11, 2025
8ba80b5
Delete build/lib/wakis/conductors3d.py
Antoniahuber Nov 11, 2025
57d9695
Delete build/lib/wakis/field.py
Antoniahuber Nov 11, 2025
869fdb9
Delete build/lib/wakis/pmlBlock2D.py
Antoniahuber Nov 11, 2025
5d6afec
Delete build/lib/wakis/pmlBlock3D.py
Antoniahuber Nov 11, 2025
44df15c
Delete build/lib/wakis/routines.py
Antoniahuber Nov 11, 2025
2b2dbef
Delete build/lib/wakis/plotting.py
Antoniahuber Nov 11, 2025
8d1de64
Delete build/lib/wakis/geometry.py
Antoniahuber Nov 11, 2025
5f6b384
Delete build/lib/wakis/grid2D.py
Antoniahuber Nov 11, 2025
c8776ea
Delete build/lib/wakis/grid3D.py
Antoniahuber Nov 11, 2025
9865cd5
Delete build/lib/wakis/gridFIT3D.py
Antoniahuber Nov 11, 2025
8ea836f
Delete build/lib/wakis/materials.py
Antoniahuber Nov 11, 2025
7dfbf30
Delete build/lib/wakis/solver2D.py
Antoniahuber Nov 11, 2025
9807faf
Delete build/lib/wakis/solver3D.py
Antoniahuber Nov 11, 2025
17df67e
Delete build/lib/wakis/solverFIT3D.py
Antoniahuber Nov 11, 2025
a2dd44e
Delete build/lib/wakis/sources.py
Antoniahuber Nov 11, 2025
c4ee763
Delete build/lib/wakis/wakeSolver.py
Antoniahuber Nov 11, 2025
597c7e7
Merge pull request #2 from Antoniahuber/Antoniahuber-delete-unnecessa…
Antoniahuber Nov 11, 2025
57f2903
Refactor log variable names in test file
Antoniahuber Nov 11, 2025
baebebe
Refactor logger to use 'grid' instead of 'grid_logs'
Antoniahuber Nov 11, 2025
9a1e2da
Refactor Logger class to stick to camelCase
Antoniahuber Nov 11, 2025
e301c3d
Fix logger attribute assignment for wakeSolver
Antoniahuber Nov 11, 2025
c853b4b
Refactor logger attribute assignments in solverFIT3D
Antoniahuber Nov 11, 2025
b27588b
Change logger dictionary from wakeSolver_logs to wakeSolver
Antoniahuber Nov 11, 2025
796080a
Fix logger reference for wakeSolver
Antoniahuber Nov 11, 2025
c5a0ed5
Fix logger grid assignment in solverFIT3D.py
Antoniahuber Nov 11, 2025
c54d7f2
Rename bg_log to bgLog in solverFIT3D.py
Antoniahuber Nov 11, 2025
6bf3abf
Update logger attribute access in test case
Antoniahuber Nov 11, 2025
5583963
Fix logfile path in MPI lossy cavity test
Antoniahuber Nov 11, 2025
f016124
Merge branch 'ImpedanCEI:main' into main
Antoniahuber Nov 12, 2025
e198fb9
Exchanged function assign_logger by update_logger
Antoniahuber Nov 13, 2025
f22c209
Fixed bugs
Antoniahuber Nov 13, 2025
d7e3840
Fixed bug
Antoniahuber Nov 13, 2025
a19ab61
Exchange list by dictionary in comparison
Antoniahuber Nov 13, 2025
c1f59e0
Fix indentation in gridLogs dictionary
Antoniahuber Nov 13, 2025
9a68490
Fix indentation in solverLogs dictionary
Antoniahuber Nov 13, 2025
534792c
Separate changes from another pull request
Antoniahuber Nov 14, 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: 1 addition & 1 deletion tests/test_001_pec_cubic_cavity.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def test_simulation(self):
skip_cells = 12 # no. cells to skip in WP integration
wake = WakeSolver(q=q, sigmaz=sigmaz, beta=beta,
xsource=xs, ysource=ys, xtest=xt, ytest=yt,
save=False, logfile=False, Ez_file='tests/001_Ez.h5',
save=False, Ez_file='tests/001_Ez.h5',
skip_cells=skip_cells,
)

Expand Down
24 changes: 23 additions & 1 deletion tests/test_007_mpi_lossy_cavity.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ 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.008666666348775227, 'dy': 0.008666666348775227,
'dz': 0.005714285799435207, '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]}, 'gridInitializationTime': 0}

solverLogs = {'use_gpu': False, 'use_mpi': False, 'background': 'pec','bc_low': ['pec', 'pec', 'pec'],
'bc_high': ['pec', 'pec', 'pec'],
'dt': 6.970326728398968e-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}

img_folder = 'tests/007_img/'

def test_mpi_import(self):
Expand Down Expand Up @@ -314,4 +326,14 @@ 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):
global solver
solver.logger.grid["gridInitializationTime"] = 0 #times can vary
solver.logger.solver["solverInitializationTime"] = 0
solver.logger.wakeSolver["simulationTime"] = 0
logfile = os.path.join(solver.logger.wakeSolver["results_folder"], "wakis.log")
assert os.path.exists(logfile), "Log file not created"
assert solver.logger.grid == self.gridLogs, "Grid logs do not match expected values"
assert solver.logger.solver == self.solverLogs, "Solver logs do not match expected values"
assert solver.logger.wakeSolver == self.wakeSolverLogs, "WakeSolver logs do not match expected values"
2 changes: 2 additions & 0 deletions wakis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
from . import materials
from . import wakeSolver
from . import geometry
from . import logger
from . import field_monitors

from .field_monitors import FieldMonitor
from .field import Field
from .gridFIT3D import GridFIT3D
from .solverFIT3D import SolverFIT3D
from .wakeSolver import WakeSolver
from .logger import Logger

from ._version import __version__
26 changes: 25 additions & 1 deletion wakis/gridFIT3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import pyvista as pv
from functools import partial
from scipy.optimize import least_squares
import time

from .field import Field
from .logger import Logger

try:
from mpi4py import MPI
Expand Down Expand Up @@ -63,10 +65,13 @@ def __init__(self, xmin, xmax, ymin, ymax, zmin, zmax,
stl_rotate=[0., 0., 0.], stl_translate=[0., 0., 0.], stl_scale=1.0,
stl_colors=None, verbose=1, stl_tol=1e-3):

t0 = time.time()
self.logger = Logger()
if verbose: print('Generating grid...')
self.verbose = verbose
self.use_mpi = use_mpi
self.use_mesh_refinement = use_mesh_refinement
self.update_logger(['use_mesh_refinement'])

# domain limits
self.xmin = xmin
Expand All @@ -81,6 +86,7 @@ def __init__(self, xmin, xmax, ymin, ymax, zmin, zmax,
self.dx = (xmax - xmin) / Nx
self.dy = (ymax - ymin) / Ny
self.dz = (zmax - zmin) / Nz
self.update_logger(['Nx', 'Ny', 'Nz', 'dx', 'dy', 'dz'])

# stl info
self.stl_solids = stl_solids
Expand All @@ -89,6 +95,14 @@ def __init__(self, xmin, xmax, ymin, ymax, zmin, zmax,
self.stl_translate = stl_translate
self.stl_scale = stl_scale
self.stl_colors = stl_colors
self.update_logger(['stl_solids', 'stl_materials'])
if stl_rotate != [0., 0., 0.]:
self.update_logger(['stl_rotate'])
if stl_translate != [0., 0., 0.]:
self.update_logger(['stl_translate'])
if stl_scale != 1.0:
self.update_logger(['stl_scale'])

if stl_solids is not None:
self._prepare_stl_dicts()

Expand Down Expand Up @@ -143,6 +157,9 @@ def __init__(self, xmin, xmax, ymin, ymax, zmin, zmax,
if stl_colors is None:
self.assign_colors()

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as in SolverFIT3D

self.gridInitializationTime = time.time()-t0
self.update_logger(['gridInitializationTime'])

def compute_grid(self):
X, Y, Z = np.meshgrid(self.x, self.y, self.z, indexing='ij')
self.grid = pv.StructuredGrid(X.transpose(), Y.transpose(), Z.transpose())
Expand Down Expand Up @@ -838,4 +855,11 @@ def clip(widget):
if offscreen:
pl.export_html('grid_inspect.html')
else:
pl.show()
pl.show()

def update_logger(self, attrs):
"""
Assigns the parameters handed via attrs to the logger
"""
for atr in attrs:
self.logger.grid[atr] = getattr(self, atr)
67 changes: 67 additions & 0 deletions wakis/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# copyright ################################# #
# This file is part of the wakis Package. #
# Copyright (c) CERN, 2025. #
# ########################################### #

from tqdm import tqdm

import numpy as np
import time
import h5py
import os
import json

from scipy.constants import c as c_light, epsilon_0 as eps_0, mu_0 as mu_0
from scipy.sparse import csc_matrix as sparse_mat
from scipy.sparse import diags, hstack, vstack



class Logger():

def __init__(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to stick to camelCase convention, we should avoid using underscores _. Do you think it would be still legible if we remove the _logs? like this we keep the variable format a bit more uniform. In the end, you call it using logger.wakeSolver so the log is implicit? What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think that is fine. Should I remove them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

self.grid = {}
self.solver = {}
self.wakeSolver = {}

def save_logs(self):
"""
Save all logs (grid, solver, wakeSolver) into log-file inside the results folder.
"""
logfile = os.path.join(self.wakeSolver["results_folder"], "wakis.log")

# Write sections
if not os.path.exists(self.wakeSolver["results_folder"]):
os.mkdir(self.wakeSolver["results_folder"])

with open(logfile, "w", encoding="utf-8") as fh:
fh.write("Simulation Parameters\n")
fh.write("""=====================\n\n""")

sections = [
("WakeSolver Logs", self.wakeSolver),
("Solver Logs", self.solver),
("Grid Logs", self.grid),
]

for title, data in sections:
fh.write(f"\n## {title} ##\n")
if not data:
fh.write("(empty)\n")
continue

# convert non-serializable values to strings recursively
def _convert(obj):
if isinstance(obj, dict):
return {k: _convert(v) for k, v in obj.items()}
if isinstance(obj, (list, tuple)):
return [_convert(v) for v in obj]
try:
json.dumps(obj)
return obj
except Exception:
return str(obj)

clean = _convert(data)
fh.write(json.dumps(clean, indent=2, ensure_ascii=False))
fh.write("\n")
9 changes: 8 additions & 1 deletion wakis/routines.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import numpy as np
import h5py
import time
from tqdm import tqdm
from scipy.constants import c as c_light
from wakis.sources import Beam
Expand Down Expand Up @@ -297,6 +298,7 @@ def save_to_h5(self, hf, field, x, y, z, comp, n):
if plot_from is None: plot_from = int(self.ti/self.dt)

print('Running electromagnetic time-domain simulation...')
t0 = time.time()
for n in tqdm(range(Nt)):

# Initial condition
Expand Down Expand Up @@ -340,4 +342,9 @@ def save_to_h5(self, hf, field, x, y, z, comp, n):

# Compute wakefield magnitudes is done inside WakeSolver
self.wake.solve(compute_plane=compute_plane)


# Forward parameters to logger
self.logger.wakeSolver=self.wake.logger.wakeSolver
self.logger.wakeSolver["wakelength"]=wakelength
self.logger.wakeSolver["simulationTime"]=time.time()-t0
self.logger.save_logs()
26 changes: 23 additions & 3 deletions wakis/solverFIT3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from .materials import material_lib
from .plotting import PlotMixin
from .routines import RoutinesMixin
from .logger import Logger

try:
from cupyx.scipy.sparse import csc_matrix as gpu_sparse_mat
Expand Down Expand Up @@ -93,7 +94,8 @@ def __init__(self, grid, wake=None, cfln=0.5, dt=None,
'''

self.verbose = verbose
if verbose: t0 = time.time()
t0 = time.time()
self.logger = Logger()

# Flags
self.step_0 = True
Expand All @@ -110,10 +112,11 @@ def __init__(self, grid, wake=None, cfln=0.5, dt=None,
self.one_step = self._one_step
if use_stl:
self.use_conductors = False
self.update_logger(['use_gpu', 'use_mpi'])

# Grid
self.grid = grid

self.background = bg
self.Nx = self.grid.Nx
self.Ny = self.grid.Ny
self.Nz = self.grid.Nz
Expand All @@ -131,6 +134,7 @@ def __init__(self, grid, wake=None, cfln=0.5, dt=None,
self.iA = self.grid.iA
self.tL = self.grid.tL
self.itA = self.grid.itA
self.update_logger(['grid','background'])

# Wake computation
self.wake = wake
Expand Down Expand Up @@ -175,6 +179,7 @@ def __init__(self, grid, wake=None, cfln=0.5, dt=None,
if verbose: print('Applying boundary conditions...')
self.bc_low = bc_low
self.bc_high = bc_high
self.update_logger(['bc_low', 'bc_high'])
self.apply_bc_to_C()

# Materials
Expand Down Expand Up @@ -203,6 +208,7 @@ def __init__(self, grid, wake=None, cfln=0.5, dt=None,
self.pml_hi = 1.e-1
self.pml_func = np.geomspace
self.fill_pml_sigmas()
self.update_logger(['n_pml'])

# Timestep calculation
if verbose: print('Calculating maximal stable timestep...')
Expand All @@ -212,6 +218,7 @@ def __init__(self, grid, wake=None, cfln=0.5, dt=None,
else:
self.dt = dt
self.dt = dtype(self.dt)
self.update_logger(['dt'])

if self.use_conductivity: # relaxation time criterion tau

Expand Down Expand Up @@ -252,6 +259,9 @@ def __init__(self, grid, wake=None, cfln=0.5, dt=None,

if verbose: print(f'Total initialization time: {time.time() - t0} s')

self.solverInitializationTime = time.time() - t0
self.update_logger(['solverInitializationTime'])

def update_tensors(self, tensor='all'):
'''Update tensor matrices after
Field ieps, imu or sigma have been modified
Expand Down Expand Up @@ -1107,4 +1117,14 @@ def reset_fields(self):
for d in ['x', 'y', 'z']:
self.E[:, :, :, d] = 0.0
self.H[:, :, :, d] = 0.0
self.J[:, :, :, d] = 0.0
self.J[:, :, :, d] = 0.0

def update_logger(self, attrs):
"""
Assigns the parameters handed via attrs to the logger
"""
for atr in attrs:
if atr == 'grid':
self.logger.grid = self.grid.logger.grid
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grid is very heavy on memory, which information are we saving there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are giving the dictionary 'logger.grid' further to the logger object of the solver.
We are saving all the parameters assigned to the grid in Grid3DFit. It is whether mesh refinement is used, Nx, Ny, Nz, dx, dy, dz, stl_solids, stl_materials, stl_rotate, stl_translate, stl_scale and the gridInitializationTime

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see! You are just checking that, if the attribute is named "grid", then you pass only the logger and not the full grid class. Understood. Thanks!

else:
self.logger.solver[atr] = getattr(self, atr)
Loading
Loading