forked from giadarol/PyParaSlice
-
Notifications
You must be signed in to change notification settings - Fork 3
How to define your simulation (single bunch)
giadarol edited this page Sep 18, 2018
·
1 revision
To define a simulation to run with the PyPARIS ring of CPUs, the user needs to write a simulation class. Each CPU will instantiate a separate instance of the class, and use it to preform the simulation according to the paradigm defined here.
PyPARIS will add to the object a member called ring_of_CPUs, which carries the information about the multiprocess structure and allows each process to identify itself.
A prototype simulation class is defined in the following, and examples can be found in the PyPARIS test folders.
class Simulation(object):
def __init__(self):
self.N_turns = 128
self.N_buffer_float_size = 500000
self.N_buffer_int_size = 450
def init_all(self):
# This function is executed by all nodes at the beginning of the simulation
# and it should be used to initialise the simulation.
# All the relevant data and code should be stored as members of this
# simulation object.
# Each CPU can identify itself and get information about the ring of CPUs
# through the object self.ring_of_CPUs that is automatically attached by
# PyPARIS (e.g. self.ring_of_CPUs.myid, self.ring_of_CPUs.N_nodes,
# self.ring_of_CPUs.I_am_the_master, self.ring_of_CPUs.I_am_a_worker).
def init_master(self):
# This function is executed by the master process only, after the
# init_all function. It must return a list of pieces object (e.g. bunch
# slices) to be fed to the ring of CPUs at the first turn.
return pieces_to_be_treated
def init_worker(self):
# This function is executed by all the worker processes (and not by the
# master), after the init_all function.
def treat_piece(self, piece):
# This function defines the task to be performed by each process when it
# receives a piece. (Most of the computational time of the simulation is
# most likely spent here).
def finalize_turn_on_master(self, pieces_treated):
# This function is executed on the master at the end of each turn, i.e.
# when all pieces have gone through the complete ring of CPUs and have
# been recollected by the master process.
# At this point you can re-merge the pieces on the master process (e.g.
# merge your slices) and perform operations that need to be performed
# collectively on your set of pieces (e.g. synchrotron motion).
# Then you can generate a new set of pieces to be treated (e.g. re-slice
# your bunch), which needs to be returned by this function.
# Through this function you can broadcast messages ("orders") from the
# master to all the other processes. These messages need to be in the
# form of a list of strings and will be passed to the function
# execute_orders_from_master, which is executed by all the processes
# (including the master).
return orders_to_pass, new_pieces_to_be_treated
def execute_orders_from_master(self, orders_from_master):
# This function is executed by all processes at the end of each turn and
# is supposed to execute the orders broadcasted by the master (see
# function: finalize_turn_on_master).
def finalize_simulation(self):
# This function is executed by the master process at the end of the
# simulation. It can be used to save the results of the simulation or
# for data post-processing.
def piece_to_buffer(self, piece):
# This function will be used to covert a piece object into a buffer (in
# the form of an array of floats), which is then sent to the
# destination process.
# In the case in which the object is a PyHEADTAIL beam, the converter
# is provided within PyPARIS in the communication_helpers module.
return buf
def buffer_to_piece(self, buf):
# This function will be used to covert a buffer (in
# the form of an array of floats) sent by another process into a piece
# object to be used in the computation.
# In the case in which the object is a PyHEADTAIL beam, the converter
# is provided within PyPARIS in the communication_helpers module.
return piece