def run_task(self, fw_spec): mpr = MPRester(env_chk(self.get("MAPI_KEY"), fw_spec)) vasprun, outcar = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=False) my_entry = vasprun.get_computed_entry(inc_structure=False) stored_data = mpr.get_stability([my_entry])[0] if stored_data["e_above_hull"] > self.get("ehull_cutoff", 0.05): return FWAction(stored_data=stored_data, exit=True, defuse_workflow=True) else: return FWAction(stored_data=stored_data)
def run_task(self, fw_spec): mpr = MPRester(env_chk(self.get("MAPI_KEY"), fw_spec)) vasprun, outcar = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=False) my_entry = vasprun.get_computed_entry(inc_structure=False) stored_data = mpr.get_stability([my_entry])[0] if stored_data["e_above_hull"] > self.get("ehull_cutoff", 0.05): logger.info("CheckStability: failed test!") return FWAction(stored_data=stored_data, exit=True, defuse_workflow=True) else: return FWAction(stored_data=stored_data)
class MaterialsEhullBuilder(AbstractBuilder): def __init__(self, materials_write, mapi_key=None, update_all=False): """ Starting with an existing materials collection, adds stability information and The Materials Project ID. Args: materials_write: mongodb collection for materials (write access needed) mapi_key: (str) Materials API key (if MAPI_KEY env. var. not set) update_all: (bool) - if true, updates all docs. If false, only updates docs w/o a stability key """ self._materials = materials_write self.mpr = MPRester(api_key=mapi_key) self.update_all = update_all def run(self): logger.info("MaterialsEhullBuilder starting...") self._build_indexes() q = {"thermo.energy": {"$exists": True}} if not self.update_all: q["stability"] = {"$exists": False} mats = [ m for m in self._materials.find( q, { "calc_settings": 1, "structure": 1, "thermo.energy": 1, "material_id": 1 }) ] pbar = tqdm(mats) for m in pbar: pbar.set_description("Processing materials_id: {}".format( m['material_id'])) try: params = {} for x in ["is_hubbard", "hubbards", "potcar_spec"]: params[x] = m["calc_settings"][x] structure = Structure.from_dict(m["structure"]) energy = m["thermo"]["energy"] my_entry = ComputedEntry(structure.composition, energy, parameters=params) # TODO: @computron This only calculates Ehull with respect to Materials Project. # It should also account for the current database's results. -computron self._materials.update_one({"material_id": m["material_id"]}, { "$set": { "stability": self.mpr.get_stability([my_entry])[0] } }) # TODO: @computron: also add additional properties like inverse hull energy? # TODO: @computron it's better to use PD tool or reaction energy calculator # Otherwise the compatibility schemes might have issues...one strategy might be # use MP only to retrieve entries but compute the PD locally -computron for el, elx in my_entry.composition.items(): entries = self.mpr.get_entries(el.symbol, compatible_only=True) min_e = min( entries, key=lambda x: x.energy_per_atom).energy_per_atom energy -= elx * min_e self._materials.update_one({"material_id": m["material_id"]}, { "$set": { "thermo.formation_energy_per_atom": energy / structure.num_sites } }) mpids = self.mpr.find_structure(structure) self._materials.update_one({"material_id": m["material_id"]}, {"$set": { "mpids": mpids }}) except: import traceback logger.exception("<---") logger.exception( "There was an error processing material_id: {}".format(m)) logger.exception(traceback.format_exc()) logger.exception("--->") logger.info("MaterialsEhullBuilder finished processing.") def reset(self): logger.info("Resetting MaterialsEhullBuilder") self._materials.update_many({}, {"$unset": {"stability": 1}}) self._build_indexes() logger.info("Finished resetting MaterialsEhullBuilder") def _build_indexes(self): self._materials.create_index("stability.e_above_hull") @classmethod def from_file(cls, db_file, m="materials", **kwargs): """ Get a MaterialsEhullBuilder using only a db file Args: db_file: (str) path to db file m: (str) name of "materials" collection **kwargs: other parameters to feed into the builder, e.g. mapi_key """ db_write = get_database(db_file, admin=True) return cls(db_write[m], **kwargs)
class MaterialsEhullBuilder(AbstractBuilder): def __init__(self, materials_write, mapi_key=None, update_all=False): """ Starting with an existing materials collection, adds stability information and The Materials Project ID. Args: materials_write: mongodb collection for materials (write access needed) mapi_key: (str) Materials API key (if MAPI_KEY env. var. not set) update_all: (bool) - if true, updates all docs. If false, only updates docs w/o a stability key """ self._materials = materials_write self.mpr = MPRester(api_key=mapi_key) self.update_all = update_all def run(self): print("MaterialsEhullBuilder starting...") self._build_indexes() q = {"thermo.energy": {"$exists": True}} if not self.update_all: q["stability"] = {"$exists": False} mats = [ m for m in self._materials.find( q, { "calc_settings": 1, "structure": 1, "thermo.energy": 1, "material_id": 1 }) ] pbar = tqdm(mats) for m in pbar: pbar.set_description("Processing materials_id: {}".format( m['material_id'])) try: params = {} for x in ["is_hubbard", "hubbards", "potcar_spec"]: params[x] = m["calc_settings"][x] structure = Structure.from_dict(m["structure"]) energy = m["thermo"]["energy"] my_entry = ComputedEntry(structure.composition, energy, parameters=params) self._materials.update_one({"material_id": m["material_id"]}, { "$set": { "stability": self.mpr.get_stability([my_entry])[0] } }) mpids = self.mpr.find_structure(structure) self._materials.update_one({"material_id": m["material_id"]}, {"$set": { "mpids": mpids }}) except: import traceback print("<---") print( "There was an error processing material_id: {}".format(m)) traceback.print_exc() print("--->") print("MaterialsEhullBuilder finished processing.") def reset(self): self._materials.update_many({}, {"$unset": {"stability": 1}}) self._build_indexes() def _build_indexes(self): self._materials.create_index("stability.e_above_hull") @classmethod def from_file(cls, db_file, m="materials", **kwargs): """ Get a MaterialsEhullBuilder using only a db file Args: db_file: (str) path to db file m: (str) name of "materials" collection **kwargs: other parameters to feed into the builder, e.g. mapi_key """ db_write = get_database(db_file, admin=True) return cls(db_write[m], **kwargs)
class MaterialsEhullBuilder: def __init__(self, materials_write, mapi_key=None, update_all=False): """ Starting with an existing materials collection, adds stability information and The Materials Project ID. Args: materials_write: mongodb collection for materials (write access needed) mapi_key: (str) Materials API key (if MAPI_KEY env. var. not set) update_all: (bool) - if true, updates all docs. If false, only updates docs w/o a stability key """ self._materials = materials_write self.mpr = MPRester(api_key=mapi_key) self.update_all = update_all def run(self): print("MaterialsEhullBuilder starting...") self._build_indexes() q = {"thermo.energy": {"$exists": True}} if not self.update_all: q["stability"] = {"$exists": False} mats = [m for m in self._materials.find(q, {"calc_settings": 1, "structure": 1, "thermo.energy": 1, "material_id": 1})] pbar = tqdm(mats) for m in pbar: pbar.set_description("Processing materials_id: {}".format(m['material_id'])) try: params = {} for x in ["is_hubbard", "hubbards", "potcar_spec"]: params[x] = m["calc_settings"][x] structure = Structure.from_dict(m["structure"]) energy = m["thermo"]["energy"] my_entry = ComputedEntry(structure.composition, energy, parameters=params) self._materials.update_one({"material_id": m["material_id"]}, {"$set": {"stability": self.mpr.get_stability([my_entry])[0]}}) mpids = self.mpr.find_structure(structure) self._materials.update_one({"material_id": m["material_id"]}, {"$set": {"mpids": mpids}}) except: import traceback print("<---") print("There was an error processing material_id: {}".format(m)) traceback.print_exc() print("--->") print("MaterialsEhullBuilder finished processing.") def reset(self): self._materials.update_many({}, {"$unset": {"stability": 1}}) self._build_indexes() def _build_indexes(self): self._materials.create_index("stability.e_above_hull") @staticmethod def from_db_file(db_file, m="materials", **kwargs): """ Get a MaterialsEhullBuilder using only a db file Args: db_file: (str) path to db file m: (str) name of "materials" collection **kwargs: other parameters to feed into the builder, e.g. mapi_key """ db_write = get_database(db_file, admin=True) return MaterialsEhullBuilder(db_write[m], **kwargs)
class MaterialsEhullBuilder(AbstractBuilder): def __init__(self, materials_write, mapi_key=None, update_all=False): """ Starting with an existing materials collection, adds stability information and The Materials Project ID. Args: materials_write: mongodb collection for materials (write access needed) mapi_key: (str) Materials API key (if MAPI_KEY env. var. not set) update_all: (bool) - if true, updates all docs. If false, only updates docs w/o a stability key """ self._materials = materials_write self.mpr = MPRester(api_key=mapi_key) self.update_all = update_all def run(self): logger.info("MaterialsEhullBuilder starting...") self._build_indexes() q = {"thermo.energy": {"$exists": True}} if not self.update_all: q["stability"] = {"$exists": False} mats = [m for m in self._materials.find(q, {"calc_settings": 1, "structure": 1, "thermo.energy": 1, "material_id": 1})] pbar = tqdm(mats) for m in pbar: pbar.set_description("Processing materials_id: {}".format(m['material_id'])) try: params = {} for x in ["is_hubbard", "hubbards", "potcar_spec"]: params[x] = m["calc_settings"][x] structure = Structure.from_dict(m["structure"]) energy = m["thermo"]["energy"] my_entry = ComputedEntry(structure.composition, energy, parameters=params) # TODO: @computron This only calculates Ehull with respect to Materials Project. # It should also account for the current database's results. -computron self._materials.update_one({"material_id": m["material_id"]}, {"$set": {"stability": self.mpr.get_stability([my_entry])[0]}}) # TODO: @computron: also add additional properties like inverse hull energy? # TODO: @computron it's better to use PD tool or reaction energy calculator # Otherwise the compatibility schemes might have issues...one strategy might be # use MP only to retrieve entries but compute the PD locally -computron for el, elx in my_entry.composition.items(): entries = self.mpr.get_entries(el.symbol, compatible_only=True) min_e = min(entries, key=lambda x: x.energy_per_atom).energy_per_atom energy -= elx * min_e self._materials.update_one({"material_id": m["material_id"]}, {"$set": {"thermo.formation_energy_per_atom": energy / structure.num_sites}}) mpids = self.mpr.find_structure(structure) self._materials.update_one({"material_id": m["material_id"]}, {"$set": {"mpids": mpids}}) except: import traceback logger.exception("<---") logger.exception("There was an error processing material_id: {}".format(m)) logger.exception(traceback.format_exc()) logger.exception("--->") logger.info("MaterialsEhullBuilder finished processing.") def reset(self): logger.info("Resetting MaterialsEhullBuilder") self._materials.update_many({}, {"$unset": {"stability": 1}}) self._build_indexes() logger.info("Finished resetting MaterialsEhullBuilder") def _build_indexes(self): self._materials.create_index("stability.e_above_hull") @classmethod def from_file(cls, db_file, m="materials", **kwargs): """ Get a MaterialsEhullBuilder using only a db file Args: db_file: (str) path to db file m: (str) name of "materials" collection **kwargs: other parameters to feed into the builder, e.g. mapi_key """ db_write = get_database(db_file, admin=True) return cls(db_write[m], **kwargs)