Skip to content

Commit d3c4192

Browse files
committed
Restructuring the simulation binary data, including an xboinc version check.
1 parent 19b9937 commit d3c4192

File tree

5 files changed

+122
-26
lines changed

5 files changed

+122
-26
lines changed

xboinc/generate_executable_source.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import xobjects as xo
22
from .default_tracker import get_default_tracker
3-
from .sim_data import SimState, SimConfig
3+
from .simulation_data import SimState, SimConfig
44
from .general import _pkg_root
55

66
from pathlib import Path

xboinc/simulation_data/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# copyright ############################### #
2+
# This file is part of the Xboinc Package. #
3+
# Copyright (c) CERN, 2023. #
4+
# ######################################### #
5+
6+
from .simulation_state import SimState
7+
from .simulation_data import build_input_file, SimConfig
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# copyright ############################### #
2+
# This file is part of the Xboinc Package. #
3+
# Copyright (c) CERN, 2023. #
4+
# ######################################### #
5+
6+
import xobjects as xo
7+
import xpart as xp
8+
9+
# As long as nothing changed in any of the C codes, this xboinc version is compatible
10+
11+
# If new versions have
12+
13+
# When updating xboinc, it checks all the versions that
Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,44 @@
1+
# copyright ############################### #
2+
# This file is part of the Xboinc Package. #
3+
# Copyright (c) CERN, 2023. #
4+
# ######################################### #
5+
16
import numpy as np
27

38
import xobjects as xo
49
import xpart as xp
510
import xtrack as xt
611

7-
from .default_tracker import get_default_tracker
12+
from ..default_tracker import get_default_tracker
13+
from .simulation_state import SimState
814

915
_default_tracker, _default_config_hash = get_default_tracker()
1016

1117

12-
class SimState(xo.HybridClass):
13-
_xofields = {
14-
'particles': xp.Particles._XoStruct,
15-
'i_turn': xo.Int64,
16-
'size': xo.Int64,
17-
}
18-
19-
2018
class SimConfig(xo.Struct):
21-
tracker_data = _default_tracker._tracker_data_cache[_default_config_hash]
22-
line_metadata = xo.Ref(tracker_data._element_ref_data.__class__)
23-
num_turns = xo.Int64
24-
num_elements = xo.Int64
19+
tracker_data = _default_tracker._tracker_data_cache[_default_config_hash]
20+
line_metadata = xo.Ref(tracker_data._element_ref_data.__class__)
21+
num_turns = xo.Int64
22+
num_elements = xo.Int64
2523
checkpoint_every = xo.Int64
26-
sim_state = xo.Ref(SimState._XoStruct)
24+
sim_state = xo.Ref(SimState)
2725

2826

2927
def build_input_file(name, num_turns, line, particles, checkpoint_every=-1):
3028
# Assemble data structure
3129
simbuf = xo.ContextCpu().new_buffer()
3230
sim_config = SimConfig(_buffer=simbuf)
3331
default_tracker = _default_tracker
32+
# TODO: need check if incompatible elements in line or so?
33+
# TODO: need to version tracker -> xboinc executable versions
3434
line.build_tracker(_context=simbuf.context, _buffer=simbuf,
3535
track_kernel=default_tracker.track_kernel)
36-
sim_state = SimState(_buffer=simbuf, particles=particles, i_turn=0)
3736
if _default_config_hash not in line.tracker._tracker_data_cache:
3837
raise RuntimeError('Tracker data for default config not found')
3938
tracker_data = line.tracker._tracker_data_cache[_default_config_hash]
39+
version, part = get_boinc_particles_from_particles(particles)
40+
sim_state = build_simulation_state(version=version, _buffer=simbuf,
41+
particles=part, i_turn=0)
4042
sim_config.line_metadata = tracker_data._element_ref_data
4143
sim_config.num_turns = num_turns
4244
sim_config.num_elements = len(line.element_names)
@@ -49,13 +51,3 @@ def build_input_file(name, num_turns, line, particles, checkpoint_every=-1):
4951
with open(name, 'wb') as fid:
5052
fid.write(simbuf.buffer.tobytes())
5153
return sim_config
52-
53-
54-
def read_output_file(filename):
55-
with open(filename, 'rb') as fid:
56-
state_bytes = fid.read()
57-
buffer_out = xo.ContextCpu().new_buffer(capacity=len(state_bytes))
58-
buffer_out.buffer[:] = np.frombuffer(state_bytes, dtype=np.int8)
59-
sim_state_xobject = SimState._XoStruct._from_buffer(buffer=buffer_out, offset=0)
60-
sim_state_out = SimState(_xobject=sim_state_xobject)
61-
return sim_state_out
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# copyright ############################### #
2+
# This file is part of the Xboinc Package. #
3+
# Copyright (c) CERN, 2023. #
4+
# ######################################### #
5+
6+
import sys
7+
from pathlib import Path
8+
import numpy as np
9+
10+
import xobjects as xo
11+
import xpart as xp
12+
13+
from ..general import __version__
14+
15+
16+
# XXX.YYY.ZZZ to XXXYYYZZZ
17+
def _version_to_int(version):
18+
vers = version.split('.')
19+
return int(vers[0])*1000000 + int(vers[1])*1000 + int(vers[2])
20+
21+
# XXXYYYZZZ to XXX.YYY.ZZZ
22+
def _int_to_version(verint):
23+
XXX = int(verint / 1000000)
24+
YYY = int((verint - XXX*1000000)/1000)
25+
ZZZ = int(verint - XXX*1000000 - YYY*1000)
26+
return f"{XXX}.{YYY}.{ZZZ}"
27+
28+
29+
# This class overloads the first field from the SimState,
30+
# in order to read the correct version from the binary
31+
class SimVersion(xo.HybridClass):
32+
_xofields = {
33+
'xboinc_version': xo.Int64, # version XXX.YYY.ZZZ as int
34+
}
35+
36+
def __init__(self, **kwargs):
37+
if '_xobject' not in kwargs:
38+
kwargs['xboinc'] = _version_to_int(version)
39+
super().__init__(**kwargs)
40+
41+
def assert_version(self):
42+
if _version_to_int(__version__) != self.xboinc_version:
43+
error += f"Incompatible xboinc version! Output file needs "
44+
error + f"{_int_to_version(self.xboinc_version)}, "
45+
error + f"but current version is {__version__}.\n"
46+
raise ValueError(error)
47+
48+
49+
class SimState(xo.HybridClass):
50+
_xofields = {
51+
'version': SimVersion, # This HAS to be the first field!
52+
'i_turn': xo.Int64,
53+
'size': xo.Int64,
54+
'particles': xp.Particles,
55+
}
56+
57+
def __init__(self, **kwargs):
58+
if '_xobject' not in kwargs:
59+
kwargs['version'] = SimVersion()
60+
super().__init__(**kwargs)
61+
62+
@classmethod
63+
def from_binary(filename, offset=0):
64+
# Read binary
65+
filename = Path(filename)
66+
with filename.open('rb') as fid:
67+
state_bytes = fid.read()
68+
buffer_data = xo.ContextCpu().new_buffer(capacity=len(state_bytes))
69+
buffer_data.buffer[:] = np.frombuffer(state_bytes, dtype=np.int8)
70+
# Cast to SimVersion to verify versions of xsuite packages
71+
version_offset = -1
72+
for field in cls._XoStruct._fields:
73+
if field.name == 'version':
74+
version_offset = field.offset
75+
if version_offset == -1:
76+
raise ValueError("No xofield 'version' found in SimState!")
77+
simver_xobject = SimVersion._XoStruct._from_buffer(buffer=buffer_data, offset=offset+version_offset)
78+
simver = SimVersion(_xobject=simver_xobject)
79+
simver.assert_version()
80+
# Retrieve simulation state
81+
simstate_xobject = cls._XoStruct._from_buffer(buffer=buffer_data, offset=offset)
82+
simstate_out = cls(_xobject=simstate_xobject)
83+
return simstate_out
84+

0 commit comments

Comments
 (0)