diff --git a/config/default.in b/config/default.in index c799905683d6d316ea5934d38e4d2dcc1eb4a495..418732a319d2e84c3b7d7342ab26bcc0b30aa638 100644 --- a/config/default.in +++ b/config/default.in @@ -4,9 +4,12 @@ report_file = True [Simulation parameters] sim_type = ase_sim -kT = 300 -n_exchanges = 10000 -n_frames = 100 +kT_high = 500 +kT_low = 100 +n_steps_high = 10000 +n_steps_fall = 10000 +n_steps_low = 10000 +n_frames = 200 rand_ox = True [Lattice parameters] @@ -31,3 +34,4 @@ Cr = o,#8a99c7 Al = ^,#bfa6a6 O = D,#ff0d0d X = x,#000000 + diff --git a/ovito_overlay.py b/ovito_overlay.py new file mode 100644 index 0000000000000000000000000000000000000000..865ce5aff64ac396a56552f2d571aef5214a4ff0 --- /dev/null +++ b/ovito_overlay.py @@ -0,0 +1,30 @@ +import ovito + +# This user-defined function is called by OVITO to let it draw arbitrary graphics on top of the viewport. +# It is passed a QPainter (see http://qt-project.org/doc/qt-5/qpainter.html). +def render(painter, **args): + + # This demo code prints the current animation frame into the upper left corner of the viewport. + text1 = "Frame {}".format(ovito.dataset.anim.current_frame) + y = 10 + painter.fontMetrics().ascent() + painter.drawText(10, y, text1) + + node = ovito.dataset.selected_node + y += 10 + painter.fontMetrics().ascent() + text2 = "Temperature: {}".format(node.source.attributes['T']) + painter.drawText(10, y, text2) + + y += 10 + painter.fontMetrics().ascent() + text3 = "Energy: {}".format(node.source.attributes['energy']) + painter.drawText(10, y, text3) + + # Also print the current number of particles into the lower left corner of the viewport. + num_particles = (node.compute().number_of_particles if node else 0) + text4 = "{} particles".format(num_particles) + painter.drawText(10, painter.window().height() - 10, text4) + + # Print to the log window: + print(text1) + print(text2) + print(text3) + print(text4) diff --git a/sajuhak_dyn.py b/sajuhak_dyn.py index 0e59b994c8025bd3ed6b08e3f6bb3872fe6a9aaa..55574f162034df61a4ae31f3806e8cffb2cd747f 100644 --- a/sajuhak_dyn.py +++ b/sajuhak_dyn.py @@ -101,7 +101,10 @@ class SajuhakDynamics(Dynamics): def run(self, kT, n_steps=100): for i in range(n_steps): - self.step(kT) + if type(kT) is np.ndarray: + self.step(kT[i]) + else: + self.step(kT) def step(self, kT): # choose a random point and one of its neighbors diff --git a/sim_controller.py b/sim_controller.py index f979b775a602fedcef768d1abd09c1548206f0f1..85cfdd9a0d29508a63334cbe568f8b99c6e0b311 100644 --- a/sim_controller.py +++ b/sim_controller.py @@ -26,8 +26,8 @@ class SimController(object): "{lattice_counts}" "Particles created in {particles_time}.\n" "\n" - "Metropolis steps: {n_exchanges}\n" - "kT: {kT}\n" + "{kT_str}\n" + "{exchanges_str}\n" "Frames: {n_frames}\n" "Random (de)oxidation: {rand_ox}\n" "Simulation took {sim_time}.\n") @@ -58,11 +58,30 @@ class SimController(object): sim_params = default_reader['Simulation parameters'] if sim_params['sim_type'] == 'ase_sim': self.sim = ase_sim.AseSim() - self.n_exchanges = int(sim_params['n_exchanges']) self.n_frames = int(sim_params['n_frames']) - self.n_steps = int(self.n_exchanges / self.n_frames) - self.kT = int(sim_params['kT']) - if 'rand_ox' in sim_params.keys() and sim_params['rand_ox'] != False: + self.n_exchanges = None + self.kT = None + if 'n_exchanges' in sim_params.keys() and 'kT' in sim_params.keys(): + self.n_exchanges = int(sim_params['n_exchanges']) + self.n_steps_per_frame = int(self.n_exchanges / self.n_frames) + self.kT = int(sim_params['kT']) + self.last_kT = self.kT + elif 'n_steps_high' in sim_params.keys() \ + and 'n_steps_fall' in sim_params.keys() \ + and 'n_steps_low' in sim_params.keys()\ + and 'kT_high' in sim_params.keys()\ + and 'kT_low' in sim_params.keys(): + self.n_exchanges = [int(sim_params['n_steps_high']), + int(sim_params['n_steps_fall']), + int(sim_params['n_steps_low'])] + self.n_steps_per_frame = int(sum(self.n_exchanges) / self.n_frames) + self.kT = [int(sim_params['kT_high']), + int(sim_params['kT_low'])] + self.last_kT = self.kT[0] + else: + print('Could not determine the amount of steps.') + exit(1) + if 'rand_ox' in sim_params.keys() and sim_params['rand_ox'] is not False: self.rand_ox = True else: self.rand_ox = False @@ -102,6 +121,8 @@ class SimController(object): else: self.figure_params = None + self.i_step = 0 + self.lattice_time = "" self.n_sites = 0 self.bulk_counts = None @@ -115,9 +136,19 @@ class SimController(object): self.vacuum_counts = self.sim.dope(self.empty_space_dopants, 'X') def run(self): - self.sim.run(self.kT, self.n_steps) + if type(self.kT) is list: + step_list = range(self.i_step, self.i_step + self.n_steps_per_frame) + exchanges_cumulative = [self.n_exchanges[0], self.n_exchanges[0] + self.n_exchanges[1]] + kT = np.interp(step_list, exchanges_cumulative, self.kT) + self.last_kT = np.average(kT) + else: + kT = self.kT + self.last_kT = kT + self.sim.run(kT, self.n_steps_per_frame) + self.i_step += self.n_steps_per_frame def write_frame(self, frames_path): + self.sim.lattice.info['T'] = self.last_kT self.sim.write(frames_path) def make_report_file(self, out_folder): @@ -137,14 +168,26 @@ class SimController(object): count=int(count), perc=float(count)/sum_bulk*100) - vacuum_counts_string = "" + vacuum_counts_str = "" sum_vacuum = self.vacuum_counts[1].sum() for symbol, count in np.transpose(self.vacuum_counts): - vacuum_counts_string += elements_line.format(symbol=symbol, + vacuum_counts_str += elements_line.format(symbol=symbol, count=int(count), perc=float(count)/sum_vacuum*100) - lattice_counts = bulk_counts_header + bulk_counts_string + vacuum_counts_header + vacuum_counts_string + lattice_counts = bulk_counts_header + bulk_counts_string + vacuum_counts_header + vacuum_counts_str + + if type(self.kT) is list: + kT_header_str = "kT [high, low]: " + else: + kT_header_str = "kT: " + kT_str = kT_header_str + str(self.kT) + + if type(self.n_exchanges) is list: + exchanges_header_str = "Metropolis steps [high, fall, low]: " + else: + exchanges_header_str = "Metropolis steps: " + exchanges_str = exchanges_header_str + str(self.n_exchanges) report_filename = "sim_report.txt" report_path = os.path.join(out_folder, report_filename) @@ -156,13 +199,11 @@ class SimController(object): cell_x=cell_dimensions[0], cell_y=cell_dimensions[1], cell_z=cell_dimensions[2], - lattice_counts=lattice_counts, - particles_time=self.lattice_time, - n_exchanges=self.n_exchanges, - kT=self.kT, + kT_str=kT_str, + exchanges_str=exchanges_str, n_frames=self.n_frames, rand_ox=self.rand_ox, sim_time=self.sim_time) @@ -226,9 +267,12 @@ def make_config_file(conf_filename='default.in'): conf_writer['Job parameters'] = OrderedDict((('job_name', 'default'), ('report_file', 'True'))) conf_writer['Simulation parameters'] = OrderedDict((('sim_type', 'ase_sim'), - ('kT', '300'), - ('n_exchanges', '10000'), - ('n_frames', '100'), + ('kT_high', '500'), + ('kT_low', '100'), + ('n_steps_high', '10000'), + ('n_steps_fall', '10000'), + ('n_steps_low', '10000'), + ('n_frames', '200'), ('rand_ox', 'True'))) conf_writer['Lattice parameters'] = OrderedDict((('bounds_scale', '10'), ('x_scale', '1'), @@ -353,20 +397,20 @@ for sim_ctrl in sim_controllers: start_time = time.time() print_time = time.time() # write first frame - idx = '1'.zfill(n_frames_width) - sim_frames_path = os.path.join(sim_frames_folder, sim_frames_filename.format(i=idx)) + i_str = '1'.zfill(n_frames_width) + sim_frames_path = os.path.join(sim_frames_folder, sim_frames_filename.format(i=i_str)) sim_ctrl.write_frame(sim_frames_path) for i in range(2, sim_ctrl.n_frames + 1): # simulate sim_ctrl.run() # write frame - idx = str(i).zfill(n_frames_width) - sim_frames_path = os.path.join(sim_frames_folder, sim_frames_filename.format(i=idx)) + i_str = str(i).zfill(n_frames_width) + sim_frames_path = os.path.join(sim_frames_folder, sim_frames_filename.format(i=i_str)) sim_ctrl.write_frame(sim_frames_path) # update console two times per second if time.time() - print_time >= 0.5: - print("\rWrote frame {i}/{n}".format(i=idx, n=str(sim_ctrl.n_frames)), end="") + print("\rWrote frame {i}/{n}".format(i=i_str, n=str(sim_ctrl.n_frames)), end="") print_time = time.time() print("\rWrote frame {}/{}".format(str(sim_ctrl.n_frames), str(sim_ctrl.n_frames)), flush=True)