def fromProtoModel(cls, protomodel, nsteps=10000, strategy="aggressive", walkerid=0, dump_training=False, dbpath="<rundir>/database.pcl", expected=False, select="all", catch_exceptions=True, keep_meta=True, rundir=None, do_combine=False, seed=None, stopTeleportationAfter=-1): ret = cls( walkerid, nsteps=nsteps, dbpath = dbpath, expected=expected, select=select, catch_exceptions = catch_exceptions, rundir = rundir, do_combine = do_combine, seed = seed, stopTeleportationAfter = \ stopTeleportationAfter ) ret.manipulator.M = protomodel ret.manipulator.setWalkerId(walkerid) ret.manipulator.backupModel() if dump_training: ## we use the accelerator only to dump the training data from accelerator import Accelerator ret.accelerator = Accelerator(walkerid=walkerid, dump_training=True, is_trained=False) return ret
def main(): print("Test") acc = Accelerator() width = 0.4 height = 0.2 t0 = Transformator("T0", width, height) p1 = Pipe(width, height, 1.0) s0 = Screen("Screen", width, height, 0.2, 0.2) t1 = Transformator("T1", width, height) q1 = QuadrupoleMagnet("UN4QD11", width, height, 1.0, 0.8) q2 = QuadrupoleMagnet("UN4QD12", width, height, 1.0, -0.8) sl1 = Slit("Slit1", width, height) p2 = Pipe(width, height, 3.0) sl2 = Slit("Slit2", width, height) k1 = HorizontalKickerMagnet("kicker", width, height, 0.02) p3 = Pipe(width, height, 3.0) t2 = Transformator("T2", width, height) m1 = SectorBendingMagnet("UN4MU1", width, height, length=1.0, angle=0.5) t3 = Transformator("T3", width, height) s1 = Screen("Screen1", width, height, 0.2, 0.2) s2 = Screen("Screen2", width, height, 0.2, 0.2) # acc.append_devices([t0]) acc.append_devices([t0, s0, p1, t1, q1, sl1, q2, sl1, p2, sl2, s1, k1, p3, t2, m1, t3, s2]) sl2.set_positions(xpos_left=-0.01, xpos_right=0.01, ypos_bottom=-0.01, ypos_top=0.01) n = 80000 ''' acc.reset() simulate(accelerator=acc, num_of_particles=n, threaded=False, measure_time=True) print(t0.count.value, " particles in T0\n") print(s0.num_of_particles(), " particles in S0\n") ''' acc.reset() simulate(accelerator=acc, num_of_particles=n, threaded=True, measure_time=True) print(t0.count.value, " particles in T0\n") print(s0.num_of_particles(), " particles in S0\n") s1.show() s2.show()
def __init__(self, scene, args): self.shader = scene.shader(scene) self.scene = scene self._group_objects() self._init_lights() self.acc = Accelerator(args.choose_opencl_context) self._collect_tracer_data() self._init_misc() self._init_camera_and_image() self.ray_state = RayStateBuffers(self) self.shader.initialize_material_buffers(self.acc) program_code = Compiler(self).make_program() self.prog = self.acc.build_program(program_code, args.cl_build_options)
def __init__(self, walkerid=0, nsteps=10000, strategy="aggressive", dump_training=False, cheatcode=0, dbpath="./database.pcl", expected=False, select="all", catch_exceptions=True, rundir=None, nevents=100000, do_combine=False, record_history=False, seed=None, stopTeleportationAfter=-1): """ initialise the walker :param nsteps: maximum number of steps to perform, negative is infinity :param cheatcode: cheat mode. 0 is no cheating, 1 is with ranges, 2 is the Z323 model. :param expected: remove possible signals from database :param select: select only subset of results (all for all, em for efficiency maps only, ul for upper limits only, alternatively select for txnames via e.g. "txnames:T1,T2" :param catch_exceptions: should we catch exceptions :param nevents: number of MC events when computing cross-sections :param do_combine: if true, then also perform combinations, either via simplified likelihoods or via pyhf :param record_history: if true, attach a history recorder class :param seed: random seed, int or None :param stopTeleportationAfter: int or None. we stop teleportation after this step nr. If negative or None, we dont teleport at all """ if type(walkerid) != int or type(nsteps) != int or type( strategy) != str: self.pprint("Wrong call of constructor: %s, %s, %s" % (walkerid, nsteps, strategy)) sys.exit(-2) self.walkerid = walkerid ## walker id, for parallel runs self.rundir = rundir if rundir == None: self.rundir = "./" if seed is not None: from ptools import helpers helpers.seedRandomNumbers(seed + walkerid) self.pprint(f"setting random seed to {seed}") #Initialize Predictor self.predictor = Predictor(self.walkerid, dbpath=dbpath, expected=expected, select=select, do_combine=do_combine) #Initialize Hiscore (with access to the predictor) self.hiscoreList = Hiscore(walkerid, True, "%s/H%d.hi" % (self.rundir, walkerid), backup=False, predictor=self.predictor) self.hiscoreList.nkeep = 1 #Initialize ProtoModel and Manipulator: protomodel = ProtoModel( self.walkerid, keep_meta=True, nevents=nevents, dbversion=self.predictor.database.databaseVersion) self.manipulator = Manipulator(protomodel, strategy, do_record=record_history, seed=seed) self.catch_exceptions = catch_exceptions self.maxsteps = nsteps if stopTeleportationAfter == None: stopTeleportationAfter = -1 # stopTeleportationAfter = self.maxsteps/3. self.stopTeleportationAfter = stopTeleportationAfter self.accelerator = None if record_history: from ptools.history import History self.recorder = History(f"{self.rundir}/history{walkerid}.list") self.manipulator.do_record = True jobid = "unknown" if "SLURM_JOBID" in os.environ: jobid = os.environ["SLURM_JOBID"] self.pprint("Ramping up with slurm jobid %s" % jobid) if cheatcode <= 0: self.takeStep() # the first step should be considered as "taken" #Set current Z and K values to threshold values self.currentZ = -0.1 self.currentK = -20.0 else: self.manipulator.cheat(cheatcode) self.predictor.predict(self.protomodel) self.pprint ( "Cheat model gets Z=%.2f, K=%.2f" % \ ( self.manipulator.M.Z, self.manipulator.M.K ) ) # self.printStats ( substep=4 ) self.manipulator.backupModel() self.hiscoreList.newResult(self.manipulator) self.printStats(substep=5) self.currentK = self.manipulator.M.K self.currentZ = self.manipulator.M.Z if dump_training: from accelerator import Accelerator ## we use the accelerator only to dump the training data self.accelerator = Accelerator(walkerid=walkerid, dump_training=True, is_trained=False)
class Renderer: """ Main controller class that, when initialized with the Scene, generates and compiles the OpenCL code for rendering it and provides methods: * render_sample for sampling a new batch of rays and accumulating the results to an image * get_image for accessing the currently rendered result """ # TODO: refactor to better separated classes def get_image(self): imgdata = self.img.get().astype(np.float32) img = np.empty(self.img_shape + (3,)) img[self.image_order[:, 0], self.image_order[:, 1], :] = imgdata[..., 0:3] return img def rays_per_sample(self): return self.img_shape[0]*self.img_shape[1] def __init__(self, scene, args): self.shader = scene.shader(scene) self.scene = scene self._group_objects() self._init_lights() self.acc = Accelerator(args.choose_opencl_context) self._collect_tracer_data() self._init_misc() self._init_camera_and_image() self.ray_state = RayStateBuffers(self) self.shader.initialize_material_buffers(self.acc) program_code = Compiler(self).make_program() self.prog = self.acc.build_program(program_code, args.cl_build_options) def _group_objects(self): get_tracer_name = lambda obj: obj.tracer.tracer_kernel_name self.scene.objects.sort(key=get_tracer_name) groups = itertools.groupby(self.scene.objects, key=get_tracer_name) groups = [ (k,list(g)) for k,g in groups ] object_counts = { k : len(g) for k, g in groups } offset = 0 self.object_groups = [] for name in sorted([k for k,_ in groups]): count = object_counts[name] tracer = self.scene.objects[offset].tracer self.object_groups.append((tracer,count,offset)) offset += count # ------------- Find root container object self.root_object_id = 0 for i in range(len(self.scene.objects)): if self.scene.root_object == self.scene.objects[i]: self.root_object_id = i+1 def _init_misc(self): # TODO: bad self.max_broadcast_vecs = 6 self.vec_broadcast = self.acc.new_const_buffer(np.zeros((self.max_broadcast_vecs, 4))) self.vec_param_buf = np.zeros((self.max_broadcast_vecs, 4), dtype=np.float32) # Randomization init self.qdirs = camera.quasi_random_direction_sample(self.scene.samples_per_pixel) self.qdirs = np.random.permutation(self.qdirs) def _init_camera_and_image(self): scene = self.scene cam = self.scene.get_camera_rays() self.rotmat = scene.get_camera_rotmat() fovx_rad = scene.camera_fov / 180.0 * np.pi self.pixel_angle = fovx_rad / scene.image.size[0] self.img_shape = scene.image.size[::-1] self.n_pixels = self.img_shape[0] * self.img_shape[1] self.image_order = self.get_image_order() cam = cam[self.image_order[:, 0], self.image_order[:, 1], 0:3] # Device buffers self.cam = self.acc.make_vec3_array(cam) self.img = self.acc.new_vec3_array((self.n_pixels, )) def _init_lights(self): self.bidirectional_light_ids = [i for i in range(len(self.scene.objects)) if self.scene.objects[i].bidirectional_light] self.bidirectional = len(self.bidirectional_light_ids) > 0 def get_light_point(self): light_id = self.bidirectional_light_ids[np.random.randint(len(self.bidirectional_light_ids))] light = self.scene.objects[light_id] return (light_id, light.tracer.surface_area()) + \ light.tracer.random_surface_point_and_normal() + \ light.tracer.center_and_min_sampling_distance() def _collect_tracer_data(self): data_items = ['vector', 'integer', 'param_float3', 'param_int', 'param_float'] data = { k : [] for k in data_items } data_sizes = { k : 0 for k in data_items } object_data_pointer_buffer = [] const_data_buffers = True for obj in self.scene.objects: if obj.tracer.has_data(): cur_data = obj.tracer.get_data() else: cur_data = {} param_values_by_type = {} local_param_offsets = [] parameter_types = obj.tracer.parameter_types() param_values = obj.tracer.parameter_values() # two affine transformations -> (3+1)*2 3-vectors parameter_types += ['float3']*4 forward_affine = obj.tracer.global_to_tracer_coordinate_transform() inverse_affine = forward_affine.inverse() param_values += [ inverse_affine.linear[0,:], inverse_affine.linear[1,:], inverse_affine.linear[2,:], inverse_affine.translation ] for p_idx in range(len(parameter_types)): cl_type = parameter_types[p_idx] old = param_values_by_type.get(cl_type, []) local_param_offsets.append(len(old)) param_values_by_type[cl_type] = old + [param_values[p_idx]] obj.tracer.local_param_offsets = local_param_offsets for cl_type, params in param_values_by_type.items(): param_type = 'param_' + cl_type assert(param_type in data_items) cur_data[param_type] = np.array(params) offset_buffer = [] for dtype in data_items: cur = cur_data.get(dtype) n_data = data_sizes[dtype] offset_buffer.append(n_data) if cur is not None: if dtype in ['vector','param_float3']: if cur.shape[1] != 3: raise RuntimeError('invalid vector data shape') n_data += cur.shape[0] else: cur = np.ravel(cur) n_data += cur.size data[dtype].append(cur) data_sizes[dtype] = n_data object_data_pointer_buffer.append(offset_buffer) self.tracer_data_buffers = [] self.tracer_const_data_buffers = [] for dtype in data_items: values = data[dtype] if dtype == 'param_int': self.object_data_pointer_buffer_offset = data_sizes[dtype] values += object_data_pointer_buffer if len(values) == 0: values = None else: if dtype in ['vector', 'param_float3']: values = np.vstack(values) else: values = np.concatenate(values) if dtype == 'vector': if const_data_buffers: values = self.acc.make_const_vec3_buffer(values) else: values = self.acc.make_vec3_array(values) elif dtype == 'integer': if const_data_buffers: values = self.acc.new_const_buffer(values, dtype=np.int32) else: values = self.acc.to_device(values.astype(np.int32)) elif dtype == 'param_float3': values = self.acc.make_const_vec3_buffer(values) elif dtype == 'param_float': values = self.acc.new_const_buffer(values) elif dtype == 'param_int': values = self.acc.new_const_buffer(values, np.int32) else: assert(False) if dtype == 'vector': buffers = self.tracer_data_buffers elif dtype == 'integer': buffers = self.tracer_data_buffers elif dtype == 'param_float3': buffers = self.tracer_const_data_buffers elif dtype == 'param_float': buffers = self.tracer_const_data_buffers elif dtype == 'param_int': buffers = self.tracer_const_data_buffers else: assert(False) buffers.append(values) # helpers def _fill_vec(self, data, vec): hostbuf = np.float32(vec) self.acc.enqueue_copy(self.vec_broadcast, hostbuf) self.acc.call('fill_vec_broadcast', self.n_pixels, (data, ), \ value_args=(self.vec_broadcast, )) def new_camera_sample(self): scene = self.scene cam_origin = scene.camera_position # TODO: quasi random... sx = np.float32(np.random.rand()) sy = np.float32(np.random.rand()) # Tent filter as in smallpt if self.scene.tent_filter: def tent_filter_transformation(x): x *= 2 if x < 1: return np.sqrt(x)-1 else: return 1-np.sqrt(2-x) sx = tent_filter_transformation(sx) sy = tent_filter_transformation(sy) overlap = 0.0 thetax = (sx-0.5)*self.pixel_angle*(1.0+overlap) thetay = (sy-0.5)*self.pixel_angle*(1.0+overlap) dofx, dofy = camera.random_dof_sample() dof_pos = (dofx * self.rotmat[:, 0] + dofy * self.rotmat[:, 1]) * scene.camera_dof_fstop sharp_distance = scene.camera_sharp_distance tilt = camera.rotmat_tilt_camera(thetax, thetay) mat = np.dot(np.dot(self.rotmat, tilt), self.rotmat.transpose()) mat4 = np.zeros((4, 4)) mat4[0:3, 0:3] = mat mat4[3, 0:3] = dof_pos mat4[3, 3] = sharp_distance cam_origin = cam_origin + dof_pos return cam_origin, mat4 def render_sample(self, sample_index): scene = self.scene acc = self.acc cam_origin, mat4 = self.new_camera_sample() acc.enqueue_copy(self.vec_broadcast, mat4.astype(np.float32)) acc.call('subsample_transform_camera', self.n_pixels, \ (self.cam, self.ray_state.ray, self.ray_state.pixel), \ value_args=(self.vec_broadcast,)) self._fill_vec(self.ray_state.pos, cam_origin) self.ray_state.whichobject.fill(0) #self.ray_state.normal.fill(0) self.ray_state.raycolor.fill(1) self.ray_state.diffusions_left.fill(scene.min_bounces) self.ray_state.inside.fill(self.root_object_id) path_index = 0 self.shader.init_sample(self) self.cur_n_pixels = self.n_pixels for path_index in range(scene.max_bounces): if not self.compute_next_path_segment(sample_index, path_index, path_index == scene.max_bounces-1): break acc.finish() return path_index def compute_next_path_segment(self, sample_index, path_index, is_last): acc = self.acc self.ray_state.isec_dist[:self.cur_n_pixels].fill(self.scene.max_ray_length) self.ray_state.whichobject, self.ray_state.last_whichobject = \ (self.ray_state.last_whichobject, self.ray_state.whichobject) self.ray_state.which_subobject, self.ray_state.last_which_subobject = \ (self.ray_state.last_which_subobject, self.ray_state.which_subobject) for tracer, count, offset in self.object_groups: for object_index in range(offset, offset+count): acc.call(tracer.tracer_kernel_name, self.cur_n_pixels, \ self.ray_state.tracer_kernel_params() + \ tuple(self.tracer_data_buffers), value_args=tuple(self.tracer_const_data_buffers) + \ (np.int32(object_index+1),)) for tracer, count, offset in self.object_groups: acc.call(tracer.normal_kernel_name, self.cur_n_pixels, \ self.ray_state.normal_kernel_params() + \ tuple(self.tracer_data_buffers), value_args=tuple(self.tracer_const_data_buffers) + \ (np.int32(offset+1), np.int32(count))) if self.bidirectional: if path_index == 0: self.ray_state.suppress_emission.fill(0) light_id0, light_area, light_point, light_normal, \ light_center, min_light_sampling_distance = self.get_light_point() light_point = np.array(light_point).astype(np.float32) light_normal = np.array(light_normal).astype(np.float32) light_center = np.array(light_center).astype(np.float32) light_area = np.float32(light_area) min_light_sampling_distance = np.float32(min_light_sampling_distance) if is_last: light_id1 = np.int32(0) else: light_id1 = np.int32(light_id0+1) self.vec_param_buf[0, :3] = light_point acc.enqueue_copy(self.vec_broadcast, self.vec_param_buf) acc.call('init_shadow_mask', self.cur_n_pixels, (\ self.ray_state.pixel, self.ray_state.shadow_mask, self.ray_state.diffusions_left)) for tracer, count, offset in self.object_groups: acc.call(tracer.shadow_kernel_name, (self.cur_n_pixels, count), self.ray_state.shadow_kernel_params() + \ tuple(self.tracer_data_buffers), value_args=tuple(self.tracer_const_data_buffers) + \ (self.vec_broadcast, light_id1, np.int32(offset+1), np.int32(count))) if self.scene.quasirandom and path_index == 1: rand_vec = self.qdirs[sample_index, :] else: rand_vec = utils.normalize(np.random.normal(0, 1, (3, ))) rand_vec = np.array(rand_vec).astype(np.float32) rand_01 = np.float32(np.random.rand()) self.ray_state.prob[:self.cur_n_pixels].fill(rand_01) self.vec_param_buf[0, :3] = rand_vec self.vec_param_buf[1, :3] = np.random.normal(0, 1,( 3, )) # element 2 has color mask if self.bidirectional: self.vec_param_buf[3, :3] = light_point self.vec_param_buf[4, :3] = light_normal self.vec_param_buf[5, :3] = light_center acc.enqueue_copy(self.vec_broadcast, self.vec_param_buf) constant_params = self.shader.material_buffers + [self.vec_broadcast] if self.bidirectional: constant_params = [light_id1, light_area, min_light_sampling_distance] + constant_params pipeline = ['volumetric', 'emission'] if not is_last: pipeline += ['reflection', 'refraction', 'diffuse'] for shader_component in pipeline: acc.call('shader_'+shader_component, self.cur_n_pixels, \ (self.img, ) + self.ray_state.shader_kernel_params(), value_args=tuple(constant_params)) if not is_last: russian_roulette_prob = np.float32(np.random.rand()) acc.call('culler', self.cur_n_pixels, \ (self.ray_state.pixel, self.ray_state.raycolor), value_args=(russian_roulette_prob,), work_group_size=(self.warp_size,)) self.cur_n_pixels = acc.find_non_negative(self.ray_state.pixel, \ self.ray_state.new_pixel, self.cur_n_pixels) self.ray_state.pixel, self.ray_state.new_pixel = \ [self.ray_state.new_pixel, self.ray_state.pixel] if self.cur_n_pixels == 0: return False print '[', self.cur_n_pixels, ']', return True def get_image_order(self): order = [] width, height = self.img_shape block_w = 8 block_h = 4 if width % block_w == 0 and height % block_h == 0: for y_block in range(height / block_h): for x_block in range(width / block_w): for by in range(block_h): for bx in range(block_w): order.append([bx+x_block*block_w, by+y_block*block_h]) else: print "WARNING: image size should be (%d*x, %d*y)" % (block_w, block_h) for x in range(width): for y in range(height): order.append([x,y]) return np.array(order) @property def warp_size(self): return self.acc.warp_size @property def log_warp_size(self): return int(round(math.log(self.warp_size,2)))
from magnets import SectorBendingMagnet from magnets import HorizontalKickerMagnet from diagnostic import Transformator from diagnostic import Screen from diagnostic import Slit import xml.etree.ElementTree as ET ion = Ion(92, 146, 19, 1000) print(ion) ion = Ion(protons=6, neutrons=8, electrons=4, energy=1000) print(ion) acc = Accelerator() width = 0.4 height = 0.2 t0 = Transformator("T0", width, height) p1 = Pipe(width, height, 1.0) s0 = Screen("Screen", width, height, 0.2, 0.2) t1 = Transformator("T1", width, height) q1 = QuadrupoleMagnet("UN4QD11", width, height, 1.0, 0.8) q2 = QuadrupoleMagnet("UN4QD12", width, height, 1.0, -0.5) sl1 = Slit("Slit1", width, height) p2 = Pipe(width, height, 3.0) sl2 = Slit("Slit2", width, height) k1 = HorizontalKickerMagnet("kicker", width, height, 0.02) p3 = Pipe(width, height, 3.0)