Beispiel #1
0
    def run_task(self, fw_spec):

        structures = self["structures"]
        energies = self["energies"]

        heisenberg_settings = self.get("heisenberg_settings", {})

        # Total energies
        energies = [e * len(s) for e, s in zip(energies, structures)]

        # Map system to a Heisenberg Model
        hmapper = HeisenbergMapper(structures, energies, **heisenberg_settings)

        # Get MSONable Heisenberg Model
        hmodel = hmapper.get_heisenberg_model()
        hmodel_dict = hmodel.as_dict()

        # Update FW spec with model
        name = "heisenberg_model_" + str(hmodel.cutoff).replace(".", "_")
        update_spec = {name: hmodel}

        # Write to file
        dumpfn(hmodel_dict, "heisenberg_model.json")

        return FWAction(update_spec=update_spec)
Beispiel #2
0
    def setUpClass(cls):
        cls.df = pd.read_json(os.path.join(test_dir, "mag_orderings_test_cases.json"))

        # Good tests
        cls.Mn3Al = pd.read_json(os.path.join(test_dir, "Mn3Al.json"))

        cls.compounds = [cls.Mn3Al]

        cls.hms = []
        for c in cls.compounds:
            ordered_structures = list(c["structure"])
            ordered_structures = [Structure.from_dict(d) for d in ordered_structures]
            epa = list(c["energy_per_atom"])
            energies = [e * len(s) for (e, s) in zip(epa, ordered_structures)]

            hm = HeisenbergMapper(ordered_structures, energies, cutoff=5.0, tol=0.02)
            cls.hms.append(hm)
Beispiel #3
0
    def __init__(
        self,
        ordered_structures=None,
        energies=None,
        mc_box_size=4.0,
        equil_timesteps=2000,
        mc_timesteps=4000,
        save_inputs=False,
        hm=None,
        avg=True,
        user_input_settings=None,
    ):
        """
        user_input_settings is a dictionary that can contain:
        * start_t (int): Start MC sim at this temp, defaults to 0 K.
        * end_t (int): End MC sim at this temp, defaults to 1500 K.
        * temp_increment (int): Temp step size, defaults to 25 K.

        Args:
            ordered_structures (list): Structure objects with magmoms.
            energies (list): Energies of each relaxed magnetic structure.
            mc_box_size (float): x=y=z dimensions (nm) of MC simulation box
            equil_timesteps (int): number of MC steps for equilibrating
            mc_timesteps (int): number of MC steps for averaging
            save_inputs (bool): if True, save scratch dir of vampire input files
            hm (HeisenbergModel): object already fit to low energy
                magnetic orderings.
            avg (bool): If True, simply use <J> exchange parameter estimate.
                If False, attempt to use NN, NNN, etc. interactions.
            user_input_settings (dict): optional commands for VAMPIRE Monte Carlo

        Parameters:
            sgraph (StructureGraph): Ground state graph.
            unique_site_ids (dict): Maps each site to its unique identifier
            nn_interacations (dict): {i: j} pairs of NN interactions
                between unique sites.
            ex_params (dict): Exchange parameter values (meV/atom)
            mft_t (float): Mean field theory estimate of critical T
            mat_name (str): Formula unit label for input files
            mat_id_dict (dict): Maps sites to material id # for vampire
                indexing.

        TODO:
            * Create input files in a temp folder that gets cleaned up after run terminates

        """

        self.mc_box_size = mc_box_size
        self.equil_timesteps = equil_timesteps
        self.mc_timesteps = mc_timesteps
        self.save_inputs = save_inputs
        self.avg = avg

        if not user_input_settings:  # set to empty dict
            self.user_input_settings = {}
        else:
            self.user_input_settings = user_input_settings

        # Get exchange parameters and set instance variables
        if not hm:
            hmapper = HeisenbergMapper(ordered_structures, energies, cutoff=3.0, tol=0.02)

            hm = hmapper.get_heisenberg_model()

        # Attributes from HeisenbergModel
        self.hm = hm
        self.structure = hm.structures[0]  # ground state
        self.sgraph = hm.sgraphs[0]  # ground state graph
        self.unique_site_ids = hm.unique_site_ids
        self.nn_interactions = hm.nn_interactions
        self.dists = hm.dists
        self.tol = hm.tol
        self.ex_params = hm.ex_params
        self.javg = hm.javg

        # Full structure name before reducing to only magnetic ions
        self.mat_name = hm.formula

        # Switch to scratch dir which automatically cleans up vampire inputs files unless user specifies to save them
        # with ScratchDir('/scratch', copy_from_current_on_enter=self.save_inputs,
        #                 copy_to_current_on_exit=self.save_inputs) as temp_dir:
        #     os.chdir(temp_dir)

        # Create input files
        self._create_mat()
        self._create_input()
        self._create_ucf()

        # Call Vampire
        with subprocess.Popen(["vampire-serial"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as process:
            stdout, stderr = process.communicate()
            stdout = stdout.decode()

        if stderr:
            vanhelsing = stderr.decode()
            if len(vanhelsing) > 27:  # Suppress blank warning msg
                logging.warning(vanhelsing)

        if process.returncode != 0:
            raise RuntimeError(f"Vampire exited with return code {process.returncode}.")

        self._stdout = stdout
        self._stderr = stderr

        # Process output
        nmats = max(self.mat_id_dict.values())
        parsed_out, critical_temp = VampireCaller.parse_stdout("output", nmats)
        self.output = VampireOutput(parsed_out, nmats, critical_temp)