Skip to content

Commit ec0f322

Browse files
authored
Add scanner_split to optimisation
Adds scanner split to optimisation which allows it to run each process of the scan on its own cpu, instead of splitting each run into many calculating cpus.
1 parent a88c990 commit ec0f322

1 file changed

Lines changed: 89 additions & 1 deletion

File tree

tools/Python/mcrun/optimisation.py

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from datetime import datetime
44
from decimal import Decimal
55
from os.path import join
6+
from multiprocessing import Pool
7+
import copy
68

79
try:
810
from scipy.optimize import minimize
@@ -218,9 +220,33 @@ def from_range(N, intervals):
218220
class InvalidInterval(McRunException):
219221
pass
220222

223+
def _simulate_point(args):
224+
i, point, intervals, mcstas_config, mcstas_dir = args
225+
226+
from shutil import copyfile
227+
from os.path import join
228+
229+
# Make a new instance of McStas and configure it
230+
mcstas = copy.deepcopy(mcstas_config) # You need to define a way to deepcopy or clone your mcstas object
231+
par_values = []
232+
233+
for key in intervals:
234+
mcstas.set_parameter(key, point[key])
235+
par_values.append(point[key])
236+
237+
current_dir = f'{mcstas_dir}/{i}'
238+
mcstas.run(pipe=False, extra_opts={'dir': current_dir})
239+
detectors = mcsimdetectors(current_dir)
240+
241+
result = {
242+
'index': i,
243+
'params': par_values,
244+
'detectors': detectors
245+
}
246+
return result
221247

222248
class Scanner:
223-
""" Perform a series of simulation steps along a given set of points """
249+
""" Perform a series of simulation steps along a given set of points"""
224250
def __init__(self, mcstas, intervals):
225251
self.mcstas = mcstas
226252
self.intervals = intervals
@@ -244,6 +270,7 @@ def run(self):
244270
mcstas_dir = self.mcstas.options.dir
245271
if mcstas_dir == '':
246272
mcstas_dir = '.'
273+
247274

248275
with open(self.outfile, 'w') as outfile:
249276
for i, point in enumerate(self.points):
@@ -278,6 +305,67 @@ def run(self):
278305
outfile.flush()
279306

280307

308+
class Scanner_split:
309+
""" Perform a series of simulation steps along a given set of points,
310+
Where each simulation is controlled by its own thread. """
311+
def __init__(self, mcstas, intervals, nb_cpu):
312+
self.mcstas = mcstas
313+
self.intervals = intervals
314+
self.points = None
315+
self.nb_cpu = nb_cpu
316+
self.outfile = mcstas.options.optimise_file
317+
self.simfile = join(mcstas.options.dir, 'mccode.sim')
318+
319+
def set_points(self, points):
320+
self.points = points
321+
322+
def set_outfile(self, path):
323+
self.outfile = path
324+
325+
def run(self):
326+
LOG.info('Running Scanner split, result file is "%s"' % self.outfile)
327+
328+
if len(self.intervals) == 0:
329+
raise InvalidInterval('No interval range specified')
330+
331+
mcstas_dir = self.mcstas.options.dir or '.'
332+
333+
# Prepare data to pass into processes
334+
args_list = [
335+
(i, point, self.intervals, self.mcstas, mcstas_dir)
336+
for i, point in enumerate(self.points)
337+
]
338+
339+
with Pool(processes=self.nb_cpu) as pool:
340+
results = pool.map(_simulate_point, args_list)
341+
342+
# Sort results to preserve order
343+
results.sort(key=lambda r: r['index'])
344+
345+
with open(self.outfile, 'w') as outfile:
346+
wrote_headers = False
347+
for result in results:
348+
if result['detectors'] is None:
349+
continue
350+
351+
if not wrote_headers:
352+
names = [d.name for d in result['detectors']]
353+
outfile.write(build_header(self.mcstas.options, self.intervals.keys(), self.intervals, names))
354+
with open(self.simfile, 'w') as simfile:
355+
simfile.write(build_mccodesim_header(
356+
self.mcstas.options,
357+
self.intervals,
358+
names,
359+
version=self.mcstas.version
360+
))
361+
wrote_headers = True
362+
363+
values = ['%s %s' % (d.intensity, d.error) for d in result['detectors']]
364+
line = '%s %s\n' % (' '.join(map(str, result['params'])), ' '.join(values))
365+
outfile.write(line)
366+
outfile.flush()
367+
368+
281369
class Optimizer:
282370
""" Optimize monitors by varying the parameters within interval """
283371

0 commit comments

Comments
 (0)