Ejemplo n.º 1
0
    def write_results(self):
        # Save results from the Optimizer to HDF5 file if requested
        h5_group = get_h5_group(self.h5_fn, self.h5_group_name)

        # Some attributes never change and are only set in the first cycle
        if self.cur_cycle == 0:
            h5_group.attrs["is_cos"] = self.is_cos
            try:
                atoms = self.geometry.images[0].atoms
                coord_size = self.geometry.images[0].coords.size
            except AttributeError:
                atoms = self.geometry.atoms
                coord_size = self.geometry.coords.size
            h5_group.attrs["atoms"] = atoms
            h5_group.attrs["coord_type"] = self.geometry.coord_type
            h5_group.attrs["coord_size"] = coord_size

        # Update changing attributes
        h5_group.attrs["cur_cycle"] = self.cur_cycle
        h5_group.attrs["is_converged"] = self.is_converged

        for key, shape in self.data_model.items():
            value = getattr(self, key)
            # Don't try to set empty values, e.g. 'tangents' are only present
            # for COS methods. 'modified_forces' are only present for NCOptimizer.
            if not value:
                continue
            if len(shape) > 1:
                h5_group[key][self.cur_cycle, :len(value[-1])] = value[-1]
            else:
                h5_group[key][self.cur_cycle] = value[-1]

        h5_group.file.close()
Ejemplo n.º 2
0
 def init_h5_group(self, atoms, max_cycles=None):
     if max_cycles is None:
         max_cycles = self.h5_cycles
     self.data_model = get_data_model(atoms, max_cycles)
     self.h5_group = get_h5_group(self.h5_fn,
                                  self.h5_group_name,
                                  self.data_model,
                                  reset=True)
Ejemplo n.º 3
0
    def set_restart_info(self, restart_info):
        # Set restart information general to all optimizers
        self.last_cycle = restart_info["last_cycle"] + 1

        must_resize = self.last_cycle >= self.max_cycles
        if must_resize:
            self.max_cycles += restart_info["max_cycles"]
            # Resize HDF5
            if self.dump:
                h5_group = get_h5_group(self.h5_fn, self.h5_group_name)
                resize_h5_group(h5_group, self.max_cycles)
                h5_group.file.close()

        self.coords = [np.array(coords) for coords in restart_info["coords"]]
        self.energies = restart_info["energies"]
        self.forces = [np.array(forces) for forces in restart_info["forces"]]
        self.steps = [np.array(step) for step in restart_info["steps"]]

        # Set subclass specific information
        self._set_opt_restart_info(restart_info)

        # Propagate restart information downwards to the geometry
        self.geometry.set_restart_info(restart_info["geom_info"])
Ejemplo n.º 4
0
    def __init__(
        self,
        geometry,
        thresh="gau_loose",
        max_step=0.04,
        max_cycles=50,
        rms_force=None,
        rms_force_only=False,
        align=False,
        dump=False,
        dump_restart=None,
        prefix="",
        reparam_thresh=1e-3,
        overachieve_factor=0.0,
        restart_info=None,
        check_coord_diffs=True,
        coord_diff_thresh=0.01,
        h5_fn="optimization.h5",
        h5_group_name="opt",
    ):
        assert thresh in self.CONV_THRESHS.keys()

        self.geometry = geometry
        self.thresh = thresh
        self.max_step = max_step
        self.rms_force_only = rms_force_only
        self.align = align
        self.dump = dump
        self.dump_restart = dump_restart
        self.prefix = f"{prefix}_" if prefix else prefix
        self.reparam_thresh = reparam_thresh
        self.overachieve_factor = float(overachieve_factor)
        self.check_coord_diffs = check_coord_diffs
        self.coord_diff_thresh = float(coord_diff_thresh)

        self.is_cos = issubclass(type(self.geometry), ChainOfStates)
        self.convergence = self.make_conv_dict(thresh, rms_force)
        for key, value in self.convergence.items():
            setattr(self, key, value)

        # Setting some default values
        self.resetted = False
        self.max_cycles = max_cycles
        self.out_dir = os.getcwd()

        if self.is_cos:
            moving_image_num = len(self.geometry.moving_indices)
            print(f"Path with {moving_image_num} moving images.")

        self.out_dir = Path(self.out_dir)
        if not self.out_dir.exists():
            os.mkdir(self.out_dir)
        self.h5_fn = self.out_dir / h5_fn
        self.h5_group_name = h5_group_name

        current_fn = "current_geometries.trj" if self.is_cos else "current_geometry.xyz"
        self.current_fn = self.get_path_for_fn(current_fn)
        final_fn = "final_geometries.trj" if self.is_cos else "final_geometry.xyz"
        self.final_fn = self.get_path_for_fn(final_fn)
        self.hei_trj_fn = self.get_path_for_fn("cos_hei.trj")
        try:
            os.remove(self.hei_trj_fn)
        except FileNotFoundError:
            pass

        self.logger = logging.getLogger("optimizer")

        # Setting some empty lists as default. The actual shape of the respective
        # entries is not considered, which gives us some flexibility.
        self.data_model = get_data_model(self.geometry, self.is_cos,
                                         self.max_cycles)
        for la in self.data_model.keys():
            setattr(self, la, list())

        if self.dump:
            out_trj_fn = self.get_path_for_fn("optimization.trj")
            self.out_trj_handle = open(out_trj_fn, "w")
            # Call with reset=True to delete remnants of previous calculations, unless
            # the optimizer was restarted. Given a previous optimization with, e.g. 30
            # cycles and a second restarted optimization with 20 cycles the last 10 cycles
            # of the previous optimization would still be present.
            reset = restart_info is None
            h5_group = get_h5_group(self.h5_fn,
                                    self.h5_group_name,
                                    self.data_model,
                                    reset=reset)
            h5_group.file.close()
        if self.prefix:
            self.log(f"Created optimizer with prefix {self.prefix}")

        self.restarted = False
        self.last_cycle = 0
        self.cur_cycle = 0
        if restart_info is not None:
            if isinstance(restart_info, str):
                restart_info = yaml.load(restart_info, Loader=yaml.SafeLoader)
            self.set_restart_info(restart_info)
            self.restarted = True