Exemple #1
0
 def set_potcar(self, mapping=None, functional='PBE'):
     """
     set the potcar: symbol to potcar type mapping
     """
     symbols = self.poscar.site_symbols
     mapped_symbols = []
     if mapping:
         for sym in symbols:
             mapped_symbols.append(mapping[sym])
     elif self.mappings_override:
         for sym in symbols:
             if sym in self.mappings_override.keys():
                 mapped_symbols.append(self.mappings_override[sym])
             else:
                 mapped_symbols.append(sym)     
     else:
         mapped_symbols = symbols
     if functional:
         func=functional
     else:
         func=self.functional
     self.potcar = Potcar(symbols=mapped_symbols,
                          functional=func)
            
     pass
 def setup(self):
     """
     setup static jobs for all the calibrate objects
     copies CONTCAR to POSCAR
     sets NSW = 0
     """
     for cal in self.cal_objs:
         for i, jdir in enumerate(cal.old_job_dir_list):
             job_dir = self.job_dir + os.sep \
                 + jdir.replace(os.sep, '_').replace('.', '_') \
                 + os.sep + 'STATIC'
             logger.info('setting up job in {}'.format(job_dir))
             cal.incar = Incar.from_file(jdir + os.sep + 'INCAR')
             cal.incar['EDIFF'] = '1E-6'
             cal.incar['NSW'] = 0
             cal.potcar = Potcar.from_file(jdir + os.sep + 'POTCAR')
             cal.kpoints = Kpoints.from_file(jdir + os.sep + 'KPOINTS')
             contcar_file = jdir + os.sep + 'CONTCAR'
             if os.path.isfile(contcar_file):
                 logger.info('setting poscar file from {}'
                             .format(contcar_file))
                 cal.poscar = Poscar.from_file(contcar_file)
                 cal.add_job(job_dir=job_dir)
             else:
                 logger.critical("""CONTCAR doesnt exist.
                 Setting up job using input set in the old
                 calibration directory""")
                 cal.poscar = Poscar.from_file(jdir + os.sep + 'POSCAR')
                 cal.add_job(job_dir=job_dir)
Exemple #3
0
 def __init__(self, name, incar, poscar, potcar, kpoints,
              qadapter=None, **kwargs ):
     """
     default INCAR from config_dict
     
     """
     self.name = name
     self.incar = Incar.from_dict(incar.as_dict())
     self.poscar = Poscar.from_dict(poscar.as_dict())
     self.potcar = Potcar.from_dict(potcar.as_dict())
     self.kpoints = Kpoints.from_dict(kpoints.as_dict())
     self.extra = kwargs
     if qadapter is not None:
         self.qadapter = qadapter.from_dict(qadapter.to_dict())
     else:
         self.qadapter = None        
     config_dict = {}
     config_dict['INCAR'] = self.incar.as_dict()
     config_dict['POSCAR'] = self.poscar.as_dict() 
     #caution the key and the value are not always the same        
     config_dict['POTCAR'] = self.potcar.as_dict() 
     #dict(zip(self.potcar.as_dict()['symbols'],
     #self.potcar.as_dict()['symbols']))
     config_dict['KPOINTS'] = self.kpoints.as_dict()
     #self.user_incar_settings = self.incar.as_dict()        
     DictVaspInputSet.__init__(self, name, config_dict,
                                ediff_per_atom=False, **kwargs)
Exemple #4
0
 def setUp(self):
     if "PMG_VASP_PSP_DIR" not in os.environ:
         test_potcar_dir = os.path.abspath(
             os.path.join(os.path.dirname(__file__), "..", "..", "..", "..",
                          "test_files"))
         os.environ["PMG_VASP_PSP_DIR"] = test_potcar_dir
     filepath = os.path.join(test_dir, 'POTCAR')
     self.potcar = Potcar.from_file(filepath)
Exemple #5
0
 def test_potcar_map(self):
     fe_potcar = zopen(PymatgenTest.TEST_FILES_DIR / "POT_GGA_PAW_PBE" /
                       "POTCAR.Fe_pv.gz").read().decode("utf-8")
     # specify V instead of Fe - this makes sure the test won't pass if the
     # code just grabs the POTCAR from the config file (the config file would
     # grab the V POTCAR)
     potcar = Potcar(["V"], sym_potcar_map={"V": fe_potcar})
     self.assertEqual(potcar.symbols, ["Fe_pv"],
                      "Wrong symbols read in for POTCAR")
Exemple #6
0
    def __init__(self,
                 name,
                 incar,
                 poscar,
                 kpoints,
                 potcar=None,
                 qadapter=None,
                 script_name='submit_script',
                 vis_logger=None,
                 reuse_path=None,
                 test=False,
                 **kwargs):
        """
        default INCAR from config_dict

        """
        self.name = name
        self.test = test
        #print (test)
        self.incar_init = Incar.from_dict(incar.as_dict())
        self.poscar_init = Poscar.from_dict(poscar.as_dict())
        if not self.test:
            self.potcar_init = Potcar.from_dict(potcar.as_dict())
        if not isinstance(kpoints, str):
            self.kpoints_init = Kpoints.from_dict(kpoints.as_dict())
            #print (kpoints)
        else:
            self.kpoints_init = kpoints
        self.reuse_path = reuse_path  # complete reuse paths
        self.extra = kwargs
        if qadapter is not None:
            self.qadapter = qadapter.from_dict(qadapter.to_dict())
        else:
            self.qadapter = None
        self.script_name = script_name
        config_dict = {}
        config_dict['INCAR'] = self.incar_init.as_dict()
        config_dict['POSCAR'] = self.poscar_init.as_dict()
        # caution the key and the value are not always the same
        if not self.test:
            config_dict['POTCAR'] = self.potcar_init.as_dict()
        # dict(zip(self.potcar.as_dict()['symbols'],
        # self.potcar.as_dict()['symbols']))
        if not isinstance(kpoints, str):
            #print (self.kpoints_init)
            config_dict['KPOINTS'] = self.kpoints_init.as_dict()
        else:
            # need to find a way to dictify this kpoints string more
            # appropriately
            config_dict['KPOINTS'] = {'kpts_hse': self.kpoints_init}
        # self.user_incar_settings = self.incar.as_dict()
        DictSet.__init__(self, poscar.structure, config_dict)
        #**kwargs)
        if vis_logger:
            self.logger = vis_logger
        else:
            self.logger = logger
Exemple #7
0
def generate_potcar(struct, dirname='.'):
    """
    Generate POTCAR according to input structure via pymatgen's POTCAR module
    """
    avail_pot = " ".join(Potcar.FUNCTIONAL_CHOICES)
    tip = """
    Available Pseudo-potentials are:
    """
    tip += avail_pot + '\n'
    warn_tip(1, tip)
    print('your choice ?')
    wait_sep()
    in_str = wait()
    assert in_str.upper() in avail_pot

    potcar = Potcar([el.value for el in struct.types_of_specie],
                    functional=in_str)
    potcar.write_file(os.path.join(dirname, "POTCAR"))
Exemple #8
0
 def collect_inputs(self, root_path="./"):
     incar = Incar.from_file(root_path + "/INCAR")
     kpoints = Kpoints.from_file(root_path + "/KPOINTS")
     potcar = Potcar.from_file(root_path + "/POTCAR")
     potcar_array = {}
     for atom in potcar:
         potcar_array[atom.keywords["TITEL"]] = atom.keywords["VRHFIN"]
     input_dict = {"INCAR": incar.as_dict(), "KPOINTS": kpoints.as_dict(), "Pseudos": potcar_array}
     return input_dict
Exemple #9
0
    def from_path(cls, path, suffix="", zpsp=None):
        """
        Convenience method to run critic2 analysis on a folder containing
        typical VASP output files.
        This method will:

        1. Look for files CHGCAR, AECAR0, AECAR2, POTCAR or their gzipped
        counterparts.

        2. If AECCAR* files are present, constructs a temporary reference
        file as AECCAR0 + AECCAR2.

        3. Runs critic2 analysis twice: once for charge, and a second time
        for the charge difference (magnetization density).

        :param path: path to folder to search in
        :param suffix: specific suffix to look for (e.g. '.relax1' for
            'CHGCAR.relax1.gz')
        :param zpsp: manually specify ZPSP if POTCAR not present
        :return:
        """

        chgcar_path = get_filepath("CHGCAR", "Could not find CHGCAR!", path,
                                   suffix)
        chgcar = Chgcar.from_file(chgcar_path)
        chgcar_ref = None

        if not zpsp:

            potcar_path = get_filepath(
                "POTCAR",
                "Could not find POTCAR, will not be able to calculate charge transfer.",
                path, suffix)

            if potcar_path:
                potcar = Potcar.from_file(potcar_path)
                zpsp = {p.element: p.zval for p in potcar}

        if not zpsp:
            # try and get reference "all-electron-like" charge density if zpsp not present
            aeccar0_path = get_filepath(
                "AECCAR0",
                "Could not find AECCAR0, interpret Bader results with caution.",
                path, suffix)
            aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

            aeccar2_path = get_filepath(
                "AECCAR2",
                "Could not find AECCAR2, interpret Bader results with caution.",
                path, suffix)
            aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

            chgcar_ref = aeccar0.linear_add(aeccar2) if (aeccar0
                                                         and aeccar2) else None

        return cls(chgcar.structure, chgcar, chgcar_ref, zpsp=zpsp)
Exemple #10
0
    def write_potcar(self):
        # NEED check if correct
        # TODO:
        # Every time when changing running environment, need uncomment the following two lines
        # os.system('pmg config --add PMG_VASP_PSP_DIR G:/pseudo-potential/')

        potcar_file_name = os.path.join(self._save_to_path, 'POTCAR')
        # Vasp functional set as potpaw_GGA
        Potcar(symbols=self.elements,
               functional='PW91').write_file(potcar_file_name)
Exemple #11
0
 def from_dict(cls, d):
     incar = Incar.from_dict(d["incar"])
     poscar = Poscar.from_dict(d["poscar"])
     potcar = Potcar.from_dict(d["potcar"])
     kpoints = Kpoints.from_dict(d["kpoints"])
     qadapter = None
     if d["qadapter"] is not None:
         qadapter = CommonAdapter.from_dict(d["qadapter"])
     return MPINTVaspInputSet(d["name"], incar, poscar, potcar,
                              kpoints, qadapter, **d["kwargs"])
Exemple #12
0
 def setUp(self):
     filepath = self.TEST_FILES_DIR / 'INCAR'
     incar = Incar.from_file(filepath)
     filepath = self.TEST_FILES_DIR / 'POSCAR'
     poscar = Poscar.from_file(filepath, check_for_POTCAR=False)
     if "PMG_VASP_PSP_DIR" not in os.environ:
         os.environ["PMG_VASP_PSP_DIR"] = str(self.TEST_FILES_DIR)
     filepath = self.TEST_FILES_DIR / 'POTCAR'
     potcar = Potcar.from_file(filepath)
     filepath = self.TEST_FILES_DIR / 'KPOINTS.auto'
     kpoints = Kpoints.from_file(filepath)
     self.vinput = VaspInput(incar, kpoints, poscar, potcar)
Exemple #13
0
 def setUp(self):
     filepath = self.TEST_FILES_DIR / 'INCAR'
     incar = Incar.from_file(filepath)
     filepath = self.TEST_FILES_DIR / 'POSCAR'
     poscar = Poscar.from_file(filepath,check_for_POTCAR=False)
     if "PMG_VASP_PSP_DIR" not in os.environ:
         os.environ["PMG_VASP_PSP_DIR"] = str(self.TEST_FILES_DIR)
     filepath = self.TEST_FILES_DIR / 'POTCAR'
     potcar = Potcar.from_file(filepath)
     filepath = self.TEST_FILES_DIR / 'KPOINTS.auto'
     kpoints = Kpoints.from_file(filepath)
     self.vinput = VaspInput(incar, kpoints, poscar, potcar)
Exemple #14
0
 def setUp(self):
     filepath = PymatgenTest.TEST_FILES_DIR / "INCAR"
     incar = Incar.from_file(filepath)
     filepath = PymatgenTest.TEST_FILES_DIR / "POSCAR"
     poscar = Poscar.from_file(filepath, check_for_POTCAR=False)
     if "PMG_VASP_PSP_DIR" not in os.environ:
         os.environ["PMG_VASP_PSP_DIR"] = str(PymatgenTest.TEST_FILES_DIR)
     filepath = PymatgenTest.TEST_FILES_DIR / "POTCAR"
     potcar = Potcar.from_file(filepath)
     filepath = PymatgenTest.TEST_FILES_DIR / "KPOINTS.auto"
     kpoints = Kpoints.from_file(filepath)
     self.vinput = VaspInput(incar, kpoints, poscar, potcar)
Exemple #15
0
def bader_analysis_from_path(path, suffix=""):
    """
    Convenience method to run Bader analysis on a folder containing
    typical VASP output files.

    This method will:

    1. Look for files CHGCAR, AECCAR0, AECCAR2, POTCAR or their gzipped
    counterparts.
    2. If AECCAR* files are present, constructs a temporary reference
    file as AECCAR0 + AECCAR2
    3. Runs Bader analysis twice: once for charge, and a second time
    for the charge difference (magnetization density).

    :param path: path to folder to search in
    :param suffix: specific suffix to look for (e.g. '.relax1' for 'CHGCAR.relax1.gz'
    :return: summary dict
    """
    def _get_filepath(filename, warning, path=path, suffix=suffix):
        paths = glob.glob(os.path.join(path, filename + suffix + "*"))
        if not paths:
            warnings.warn(warning)
            return None
        if len(paths) > 1:
            # using reverse=True because, if multiple files are present,
            # they likely have suffixes 'static', 'relax', 'relax2', etc.
            # and this would give 'static' over 'relax2' over 'relax'
            # however, better to use 'suffix' kwarg to avoid this!
            paths.sort(reverse=True)
            warnings.warn(
                f"Multiple files detected, using {os.path.basename(path)}")
        path = paths[0]
        return path

    chgcar_path = _get_filepath("CHGCAR", "Could not find CHGCAR!")
    chgcar = Chgcar.from_file(chgcar_path)

    aeccar0_path = _get_filepath(
        "AECCAR0",
        "Could not find AECCAR0, interpret Bader results with caution.")
    aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

    aeccar2_path = _get_filepath(
        "AECCAR2",
        "Could not find AECCAR2, interpret Bader results with caution.")
    aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

    potcar_path = _get_filepath(
        "POTCAR", "Could not find POTCAR, cannot calculate charge transfer.")
    potcar = Potcar.from_file(potcar_path) if potcar_path else None

    return bader_analysis_from_objects(chgcar, potcar, aeccar0, aeccar2)
Exemple #16
0
 def set_potcar(self, mapping=None, functional='PBE'):
     """
     set the potcar: symbol to potcar type mapping
     """
     symbols = self.poscar.site_symbols
     mapped_symbols = []
     if mapping:
         for sym in symbols:
             mapped_symbols.append(mapping[sym])
     elif self.mappings_override:
         for sym in symbols:
             if sym in self.mappings_override.keys():
                 mapped_symbols.append(self.mappings_override[sym])
             else:
                 mapped_symbols.append(sym)
     else:
         mapped_symbols = symbols
     if functional:
         func = functional
     else:
         func = self.functional
     self.potcar = Potcar(symbols=mapped_symbols, functional=func)
Exemple #17
0
 def from_dict(cls, d):
     incar = Incar.from_dict(d["incar"])
     poscar = Poscar.from_dict(d["poscar"])
     potcar = Potcar.from_dict(d["potcar"])
     kpoints = Kpoints.from_dict(d["kpoints"])
     qadapter = None
     if d["qadapter"] is not None:
         qadapter = CommonAdapter.from_dict(d["qadapter"])
     script_name = d["script_name"]
     return MPINTVaspInputSet(d["name"], incar, poscar, potcar,
                              kpoints, qadapter,
                              script_name=script_name,
                              vis_logger=logging.getLogger(d["logger"]),
                              **d["kwargs"])
Exemple #18
0
 def get_nelec_LHFCALC(self, dir):
     pos = Poscar.from_file(os.path.join(dir, 'POSCAR'))
     pot = Potcar.from_file(os.path.join(dir, 'POTCAR'))
     incar = Incar.from_file(os.path.join(dir, 'INCAR'))
     kpt = Kpoints.from_file(os.path.join(dir, 'KPOINTS'))
     if 'LHFCALC' in incar:
         LHFCALC = incar['LHFCALC']
     else:
         LHFCALC = False
     natoms = pos.natoms
     nelec_atom = [i.nelectrons for i in pot]
     nelec_elt = np.array(natoms) * np.array(nelec_atom)
     nelec_sum = nelec_elt.sum()
     return (nelec_sum, LHFCALC)
Exemple #19
0
    def potcar_from_linklist(cls, poscar_data, linklist):
        """
        Assemble pymatgen Potcar object from a list of VaspPotcarData instances

        Reads pseudo-potential from the passed list connecting each element
        with it's potential and creates the complete Potcar file according
        to the element ordering fodun in the passed poscar data object.

        :param poscar_data: input structure for VASP calculations
        :type poscar: :class:`aiida_cusp.data.inputs.VaspPoscarData`
        :param linklist: dictionary mapping element names to VaspPotcarData
            instances
        :type linklist: `dict`
        :returns: pymatgen Potcar data instance with containing the
            concatenated pseudo-potential information for all elements defined
            in the linklist
        :rtype: :class:`~pymatgen.io.vasp.inputs.Potcar`
        """
        # initialize empty Potcar object
        complete_potcar = Potcar()
        # file empty potcar with potential in order of elements found in the
        # passed structure data
        site_symbols = poscar_data.get_poscar().site_symbols
        for site_symbol in site_symbols:
            try:
                potential_pointer = linklist[site_symbol]
            except KeyError:
                raise VaspPotcarDataError(
                    "Found no potential in passed "
                    "potential-element map for "
                    "site symbol '{}'".format(site_symbol))
            potential_file = potential_pointer.load_potential_file_node()
            potential_contents = potential_file.get_content()
            potcar_single = PotcarSingle(potential_contents)
            complete_potcar.append(potcar_single)
        return complete_potcar
Exemple #20
0
 def from_dict(cls, d):
     incar = Incar.from_dict(d["incar"])
     poscar = Poscar.from_dict(d["poscar"])
     potcar = Potcar.from_dict(d["potcar"])
     kpoints = Kpoints.from_dict(d["kpoints"])
     cal =  Calibrate(incar, poscar, potcar, kpoints, 
                      system=d["system"], is_matrix = d["is_matrix"], 
                      Grid_type = d["Grid_type"], 
                      parent_job_dir=d["parent_job_dir"], 
                      job_dir=d["job_dir"], qadapter=d.get("qadapter"), 
                      job_cmd=d["job_cmd"], wait=d["wait"],
                      turn_knobs=d["turn_knobs"])
     cal.job_dir_list = d["job_dir_list"]
     cal.job_ids = d["job_ids"]
     return cal
Exemple #21
0
 def setUp(self):
     filepath = os.path.join(test_dir, 'INCAR')
     incar = Incar.from_file(filepath)
     filepath = os.path.join(test_dir, 'POSCAR')
     poscar = Poscar.from_file(filepath,check_for_POTCAR=False)
     if "PMG_VASP_PSP_DIR" not in os.environ:
         test_potcar_dir = os.path.abspath(
             os.path.join(os.path.dirname(__file__), "..", "..", "..", "..",
                          "test_files"))
         os.environ["PMG_VASP_PSP_DIR"] = test_potcar_dir
     filepath = os.path.join(test_dir, 'POTCAR')
     potcar = Potcar.from_file(filepath)
     filepath = os.path.join(test_dir, 'KPOINTS.auto')
     kpoints = Kpoints.from_file(filepath)
     self.vinput = VaspInput(incar, kpoints, poscar, potcar)
Exemple #22
0
 def from_dict(cls, d):
     incar = Incar.from_dict(d["incar"])
     poscar = Poscar.from_dict(d["poscar"])
     potcar = Potcar.from_dict(d["potcar"])
     kpoints = Kpoints.from_dict(d["kpoints"])
     cal = Calibrate(incar, poscar, potcar, kpoints,
                     system=d["system"], is_matrix=d["is_matrix"],
                     Grid_type=d["Grid_type"],
                     parent_job_dir=d["parent_job_dir"],
                     job_dir=d["job_dir"], qadapter=d.get("qadapter"),
                     job_cmd=d["job_cmd"], wait=d["wait"],
                     turn_knobs=d["turn_knobs"])
     cal.job_dir_list = d["job_dir_list"]
     cal.job_ids = d["job_ids"]
     return cal
Exemple #23
0
 def setUp(self):
     filepath = os.path.join(test_dir, "INCAR")
     incar = Incar.from_file(filepath)
     filepath = os.path.join(test_dir, "POSCAR")
     poscar = Poscar.from_file(filepath)
     if "VASP_PSP_DIR" not in os.environ:
         test_potcar_dir = os.path.abspath(
             os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "test_files")
         )
         os.environ["VASP_PSP_DIR"] = test_potcar_dir
     filepath = os.path.join(test_dir, "POTCAR")
     potcar = Potcar.from_file(filepath)
     filepath = os.path.join(test_dir, "KPOINTS.auto")
     kpoints = Kpoints.from_file(filepath)
     self.vinput = VaspInput(incar, kpoints, poscar, potcar)
Exemple #24
0
 def test_charged_defect_incar(self):
     with ScratchDir('.'):
         make_vasp_defect_files(self.defects, self.path)
         cr_def_path = glob.glob(os.path.join(self.path, 'vac*Cr'))[0]
         incar_loc = os.path.join(cr_def_path, 'charge_-1')
         try:
             potcar = Potcar.from_file(os.path.join(incar_loc, "POTCAR"))
         except:
             potcar = None
         if potcar:
             incar = Incar.from_file(os.path.join(incar_loc, "INCAR"))
             self.assertIsNotNone(incar.pop('NELECT', None))
             self.assertTrue(
                 self.neutral_def_incar_min.items() <= incar.items())
             self.assertTrue(set(self.def_keys).issubset(incar))
Exemple #25
0
 def test_sbt(self):
     from scipy.special import spherical_jn as jn
     cr = CoreRegion(Potcar.from_file("POTCAR"))
     r = cr.pps['Ga'].grid
     f = cr.pps['Ga'].aewaves[0] - cr.pps['Ga'].pswaves[0]
     ks, res = pawpyc.spherical_bessel_transform(1e6, 0, r, f)
     k = ks[180]
     vals = jn(0, r * k) * f * r
     integral = np.trapz(vals, r)
     print(integral)
     print(ks[180])
     print(res[180])
     assert_almost_equal(integral, res[180], decimal=3)
     perc = ks**2 * res**2
     perc = np.cumsum(perc)
     perc /= np.max(perc)
        def get_encut_from_potcar(fldr):
            potcar_file = os.path.join(fldr,"POTCAR")
            if not os.path.exists(potcar_file):
                logger.warning("Not POTCAR in {} to parse ENCUT".format(fldr))
                error_msg = ": Failure, No POTCAR file."
                return (None, error_msg) #Further processing is not useful

            try:
                potcar = Potcar.from_file(potcar_file)
            except:
                logger.warning("Couldn't parse {}".format(potcar_file))
                error_msg = ": Failure, couldn't read POTCAR file."
                return (None, error_msg)

            encut = max(ptcr_sngl.enmax for ptcr_sngl in potcar)
            return (encut, None)
Exemple #27
0
    def __init__(self, chgcar_filename, potcar_filename=None):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename: The filename of the CHGCAR.
            potcar_filename: Optional: the filename of the corresponding
                POTCAR file. Used for calculating the charge transfer. If
                None, the get_charge_transfer method will raise a ValueError.
        """
        self.chgcar = Chgcar.from_file(chgcar_filename)
        self.potcar = Potcar.from_file(potcar_filename) \
            if potcar_filename is not None else None
        self.natoms = self.chgcar.poscar.natoms
        chgcarpath = os.path.abspath(chgcar_filename)

        with ScratchDir(".") as temp_dir:
            shutil.copy(chgcarpath, os.path.join(temp_dir, "CHGCAR"))

            rs = subprocess.Popen(["bader", "CHGCAR"],
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE, close_fds=True)
            rs.communicate()
            if rs.returncode != 0:
                raise RuntimeError("bader exited with return code %d. "
                                   "Pls check your bader installation."
                                   % rs.returncode)
            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = [s.lower() for s in raw.pop(0).split()]
                raw.pop(0)
                while True:
                    l = raw.pop(0).strip()
                    if l.startswith("-"):
                        break
                    vals = map(float, l.split()[1:])
                    data.append(dict(zip(headers[1:], vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data
 def setup(self):
     """
     setup solvation jobs for the calibrate objects
     copies WAVECAR and sets the solvation params in the incar file
     also dumps system.json file in each directory for the database
     crawler
     mind: works only for cal objects that does only single
     calculations
     """
     for cal in self.cal_objs:
         jdir = cal.old_job_dir_list[0]
         cal.poscar = Poscar.from_file(jdir + os.sep + 'POSCAR')
         cal.potcar = Potcar.from_file(jdir + os.sep + 'POTCAR')
         cal.kpoints = Kpoints.from_file(jdir + os.sep + 'KPOINTS')
         cal.incar = Incar.from_file(jdir + os.sep + 'INCAR')
         cal.incar['LSOL'] = '.TRUE.'
         syms = [site.specie.symbol for site in cal.poscar.structure]
         zvals = {p.symbol: p.nelectrons for p in cal.potcar}
         nelectrons = sum([zvals[a[0]] * len(tuple(a[1]))
                           for a in itertools.groupby(syms)])
         keys = [k for k in self.sol_params.keys()
                 if self.sol_params[k]]
         prod_list = [self.sol_params.get(k) for k in keys]
         for params in itertools.product(*tuple(prod_list)):
             job_dir = self.job_dir + os.sep \
                 + cal.old_job_dir_list[0].replace(os.sep,
                                                   '_').replace('.',
                                                                '_') \
                 + os.sep + 'SOL'
             for i, k in enumerate(keys):
                 if k == 'NELECT':
                     cal.incar[k] = params[i] + nelectrons
                 else:
                     cal.incar[k] = params[i]
                 job_dir = job_dir + os.sep + k + os.sep + str(
                     cal.incar[k]).replace('.', '_')
             if not os.path.exists(job_dir):
                 os.makedirs(job_dir)
             with open(job_dir + os.sep + 'system.json', 'w') as f:
                 json.dump(dict(list(zip(keys, params))), f)
             wavecar_file = cal.old_job_dir_list[0] + os.sep + 'WAVECAR'
             if os.path.isfile(wavecar_file):
                 shutil.copy(wavecar_file, job_dir + os.sep + 'WAVECAR')
                 cal.add_job(job_dir=job_dir)
             else:
                 logger.critical('WAVECAR doesnt exist. Aborting ...')
                 sys.exit(0)
Exemple #29
0
 def setup(self):
     """
     setup solvation jobs for the calibrate objects
     copies WAVECAR and sets the solvation params in the incar file
     also dumps system.json file in each directory for the database
     crawler
     mind: works only for cal objects that does only single
     calculations
     """
     for cal in self.cal_objs:
         jdir = cal.old_job_dir_list[0]
         cal.poscar = Poscar.from_file(jdir + os.sep + 'POSCAR')
         cal.potcar = Potcar.from_file(jdir + os.sep + 'POTCAR')
         cal.kpoints = Kpoints.from_file(jdir + os.sep + 'KPOINTS')
         cal.incar = Incar.from_file(jdir + os.sep + 'INCAR')
         cal.incar['LSOL'] = '.TRUE.'
         syms = [site.specie.symbol for site in cal.poscar.structure]
         zvals = {p.symbol: p.nelectrons for p in cal.potcar}
         nelectrons = sum([
             zvals[a[0]] * len(tuple(a[1])) for a in itertools.groupby(syms)
         ])
         keys = [k for k in self.sol_params.keys() if self.sol_params[k]]
         prod_list = [self.sol_params.get(k) for k in keys]
         for params in itertools.product(*tuple(prod_list)):
             job_dir = self.job_dir + os.sep \
                 + cal.old_job_dir_list[0].replace(os.sep,
                                                   '_').replace('.',
                                                                '_') \
                 + os.sep + 'SOL'
             for i, k in enumerate(keys):
                 if k == 'NELECT':
                     cal.incar[k] = params[i] + nelectrons
                 else:
                     cal.incar[k] = params[i]
                 job_dir = job_dir + os.sep + k + os.sep + str(
                     cal.incar[k]).replace('.', '_')
             if not os.path.exists(job_dir):
                 os.makedirs(job_dir)
             with open(job_dir + os.sep + 'system.json', 'w') as f:
                 json.dump(dict(list(zip(keys, params))), f)
             wavecar_file = cal.old_job_dir_list[0] + os.sep + 'WAVECAR'
             if os.path.isfile(wavecar_file):
                 shutil.copy(wavecar_file, job_dir + os.sep + 'WAVECAR')
                 cal.add_job(job_dir=job_dir)
             else:
                 logger.critical('WAVECAR doesnt exist. Aborting ...')
                 sys.exit(0)
Exemple #30
0
def bader_analysis_from_path(path, suffix=''):
    """
    Convenience method to run Bader analysis on a folder containing
    typical VASP output files.

    This method will:

    1. Look for files CHGCAR, AECAR0, AECAR2, POTCAR or their gzipped
    counterparts.
    2. If AECCAR* files are present, constructs a temporary reference
    file as AECCAR0 + AECCAR2
    3. Runs Bader analysis twice: once for charge, and a second time
    for the charge difference (magnetization density).

    :param path: path to folder to search in
    :param suffix: specific suffix to look for (e.g. '.relax1' for 'CHGCAR.relax1.gz'
    :return: summary dict
    """

    def _get_filepath(filename, warning, path=path, suffix=suffix):
        paths = glob.glob(os.path.join(path, filename + suffix + '*'))
        if not paths:
            warnings.warn(warning)
            return None
        if len(paths) > 1:
            # using reverse=True because, if multiple files are present,
            # they likely have suffixes 'static', 'relax', 'relax2', etc.
            # and this would give 'static' over 'relax2' over 'relax'
            # however, better to use 'suffix' kwarg to avoid this!
            paths.sort(reverse=True)
            warnings.warn('Multiple files detected, using {}'.format(os.path.basename(path)))
        path = paths[0]
        return path

    chgcar_path = _get_filepath('CHGCAR', 'Could not find CHGCAR!')
    chgcar = Chgcar.from_file(chgcar_path)

    aeccar0_path = _get_filepath('AECCAR0', 'Could not find AECCAR0, interpret Bader results with caution.')
    aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

    aeccar2_path = _get_filepath('AECCAR2', 'Could not find AECCAR2, interpret Bader results with caution.')
    aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

    potcar_path = _get_filepath('POTCAR', 'Could not find POTCAR, cannot calculate charge transfer.')
    potcar = Potcar.from_file(potcar_path) if potcar_path else None

    return bader_analysis_from_objects(chgcar, potcar, aeccar0, aeccar2)
    def __init__(self, name, incar, poscar, kpoints, potcar=None,
                 qadapter=None, script_name='submit_script',
                 vis_logger=None, reuse_path=None, test=False,
                 **kwargs):
        """
        default INCAR from config_dict

        """
        self.name = name
        self.test = test
        self.incar_init = Incar.from_dict(incar.as_dict())
        self.poscar_init = Poscar.from_dict(poscar.as_dict())
        if not self.test:
            self.potcar_init = Potcar.from_dict(potcar.as_dict())
        if not isinstance(kpoints, str):
            self.kpoints_init = Kpoints.from_dict(kpoints.as_dict())
        else:
            self.kpoints_init = kpoints
        self.reuse_path = reuse_path  # complete reuse paths
        self.extra = kwargs
        if qadapter is not None:
            self.qadapter = qadapter.from_dict(qadapter.to_dict())
        else:
            self.qadapter = None
        self.script_name = script_name
        config_dict = {}
        config_dict['INCAR'] = self.incar_init.as_dict()
        config_dict['POSCAR'] = self.poscar_init.as_dict()
        # caution the key and the value are not always the same
        if not self.test:
            config_dict['POTCAR'] = self.potcar_init.as_dict()
        # dict(zip(self.potcar.as_dict()['symbols'],
        # self.potcar.as_dict()['symbols']))
        if not isinstance(kpoints, str):
            config_dict['KPOINTS'] = self.kpoints_init.as_dict()
        else:
            # need to find a way to dictify this kpoints string more
            # appropriately
            config_dict['KPOINTS'] = {'kpts_hse':self.kpoints_init}
        # self.user_incar_settings = self.incar.as_dict()
        DictSet.__init__(self, poscar.structure, config_dict)
                         #**kwargs)
        if vis_logger:
            self.logger = vis_logger
        else:
            self.logger = logger
 def setup(self):
     """
     setup static jobs for the calibrate objects
     copies CONTCAR to POSCAR
     sets NSW = 0
     write system.json file for database crawler
     """
     d = {}
     for cal in self.cal_objs:
         for i, jdir in enumerate(cal.old_job_dir_list):
             job_dir = self.job_dir + os.sep \
                 + jdir.replace(os.sep, '_').replace('.', '_') + \
                 os.sep + 'STATIC'
             cal.incar = Incar.from_file(jdir + os.sep + 'INCAR')
             cal.incar['EDIFF'] = '1E-6'
             cal.incar['NSW'] = 0
             cal.potcar = Potcar.from_file(jdir + os.sep + 'POTCAR')
             cal.kpoints = Kpoints.from_file(jdir + os.sep + 'KPOINTS')
             contcar_file = jdir + os.sep + 'CONTCAR'
             if os.path.isfile(contcar_file):
                 cal.poscar = Poscar.from_file(contcar_file)
                 if cal in self.cal_slabs or cal in self.cal_interfaces:
                     try:
                         d['hkl'] = cal.system['hkl']
                     except:
                         logger.critical("""the calibrate object
                         doesnt have a system set for calibrating""")
                 if cal in self.cal_interfaces:
                     try:
                         d['ligand'] = cal.system['ligand']['name']
                     except:
                         logger.critical("""the calibrate object
                         doesnt have a system set for calibrating""")
                 if not os.path.exists(job_dir):
                     os.makedirs(job_dir)
                 if d:
                     with open(job_dir + os.sep + 'system.json', 'w') as f:
                         json.dump(d, f)
                 cal.add_job(job_dir=job_dir)
             else:
                 logger.critical("""CONTCAR doesnt exist.
                 Setting up job using input set in the old
                 calibration directory""")
                 cal.poscar = Poscar.from_file(jdir + os.sep + 'POSCAR')
                 cal.add_job(job_dir=job_dir)
Exemple #33
0
 def setup(self):
     """
     setup static jobs for the calibrate objects
     copies CONTCAR to POSCAR
     sets NSW = 0
     write system.json file for database crawler
     """
     d = {}
     for cal in self.cal_objs:
         for i, jdir in enumerate(cal.old_job_dir_list):
             job_dir = self.job_dir + os.sep \
                 + jdir.replace(os.sep, '_').replace('.', '_') + \
                 os.sep + 'STATIC'
             cal.incar = Incar.from_file(jdir + os.sep + 'INCAR')
             cal.incar['EDIFF'] = '1E-6'
             cal.incar['NSW'] = 0
             cal.potcar = Potcar.from_file(jdir + os.sep + 'POTCAR')
             cal.kpoints = Kpoints.from_file(jdir + os.sep + 'KPOINTS')
             contcar_file = jdir + os.sep + 'CONTCAR'
             if os.path.isfile(contcar_file):
                 cal.poscar = Poscar.from_file(contcar_file)
                 if cal in self.cal_slabs or cal in self.cal_interfaces:
                     try:
                         d['hkl'] = cal.system['hkl']
                     except:
                         logger.critical("""the calibrate object
                         doesnt have a system set for calibrating""")
                 if cal in self.cal_interfaces:
                     try:
                         d['ligand'] = cal.system['ligand']['name']
                     except:
                         logger.critical("""the calibrate object
                         doesnt have a system set for calibrating""")
                 if not os.path.exists(job_dir):
                     os.makedirs(job_dir)
                 if d:
                     with open(job_dir + os.sep + 'system.json', 'w') as f:
                         json.dump(d, f)
                 cal.add_job(job_dir=job_dir)
             else:
                 logger.critical("""CONTCAR doesnt exist.
                 Setting up job using input set in the old
                 calibration directory""")
                 cal.poscar = Poscar.from_file(jdir + os.sep + 'POSCAR')
                 cal.add_job(job_dir=job_dir)
Exemple #34
0
    def __init__(self, chgcar_filename, potcar_filename=None):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename: The filename of the CHGCAR.
            potcar_filename: Optional: the filename of the corresponding
                POTCAR file. Used for calculating the charge transfer. If
                None, the get_charge_transfer method will raise a ValueError.
        """
        self.chgcar = Chgcar.from_file(chgcar_filename)
        self.potcar = Potcar.from_file(potcar_filename) \
            if potcar_filename is not None else None
        self.natoms = self.chgcar.poscar.natoms
        chgcarpath = os.path.abspath(chgcar_filename)

        with ScratchDir(".") as temp_dir:
            shutil.copy(chgcarpath, os.path.join(temp_dir, "CHGCAR"))

            rs = subprocess.Popen(["bader", "CHGCAR"],
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE,
                                  close_fds=True)
            rs.communicate()
            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = [s.lower() for s in raw.pop(0).split()]
                raw.pop(0)
                while True:
                    l = raw.pop(0).strip()
                    if l.startswith("-"):
                        break
                    vals = map(float, l.split()[1:])
                    data.append(dict(zip(headers[1:], vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data
Exemple #35
0
    def _get_potcar_symbols(POTCAR_input: str) -> list:
        """
        will return the name of the species in the POTCAR
        Args:
         POTCAR_input(str): string to potcar file
        Returns:
            list of the names of the species in string format
        """
        potcar = Potcar.from_file(POTCAR_input)
        for pot in potcar:
            if pot.potential_type != "PAW":
                raise IOError(
                    "Lobster only works with PAW! Use different POTCARs")

        if potcar.functional != "PBE":
            raise IOError("We only have BASIS options for PBE so far")

        Potcar_names = [name["symbol"] for name in potcar.spec]
        return Potcar_names
Exemple #36
0
 def __init__(self,
              name,
              incar,
              poscar,
              potcar,
              kpoints,
              qadapter=None,
              script_name='submit_script',
              vis_logger=None,
              **kwargs):
     """
     default INCAR from config_dict
     
     """
     self.name = name
     self.incar = Incar.from_dict(incar.as_dict())
     self.poscar = Poscar.from_dict(poscar.as_dict())
     self.potcar = Potcar.from_dict(potcar.as_dict())
     self.kpoints = Kpoints.from_dict(kpoints.as_dict())
     self.extra = kwargs
     if qadapter is not None:
         self.qadapter = qadapter.from_dict(qadapter.to_dict())
     else:
         self.qadapter = None
     self.script_name = script_name
     config_dict = {}
     config_dict['INCAR'] = self.incar.as_dict()
     config_dict['POSCAR'] = self.poscar.as_dict()
     # caution the key and the value are not always the same
     config_dict['POTCAR'] = self.potcar.as_dict()
     # dict(zip(self.potcar.as_dict()['symbols'],
     # self.potcar.as_dict()['symbols']))
     config_dict['KPOINTS'] = self.kpoints.as_dict()
     # self.user_incar_settings = self.incar.as_dict()
     DictVaspInputSet.__init__(self,
                               name,
                               config_dict,
                               ediff_per_atom=False,
                               **kwargs)
     if vis_logger:
         self.logger = vis_logger
     else:
         self.logger = logger
Exemple #37
0
    def from_files(
        struct="CONTCAR",
        wavecar="WAVECAR",
        cr="POTCAR",
        vr="vasprun.xml",
        setup_projectors=False,
    ):
        """
        Construct a Wavefunction object from file paths.

        Arguments:
                struct (str): VASP POSCAR or CONTCAR file path
                wavecar (str): VASP WAVECAR file path
                cr (str): VASP POTCAR file path
                vr (str): VASP vasprun file path
                outcar (str): VASP OUTCAR file path
                setup_projectors (bool, False): Whether to set up the core region
                        components of the wavefunctions. Pawpyseed will set up the projectors
                        automatically when they are first needed, so this generally
                        can be left as False.

        Returns:
                Wavefunction object
        """
        for fname in [struct, wavecar, cr, vr]:
            if not os.path.isfile(fname):
                raise FileNotFoundError(f"File {fname} does not exist.")
        vr = Vasprun(vr)
        dim = np.array(
            [vr.parameters["NGX"], vr.parameters["NGY"], vr.parameters["NGZ"]]
        )
        symprec = vr.parameters["SYMPREC"]
        pwf = pawpyc.PWFPointer(wavecar, vr)
        return Wavefunction(
            Poscar.from_file(struct).structure,
            pwf,
            CoreRegion(Potcar.from_file(cr)),
            dim,
            symprec,
            setup_projectors,
        )
Exemple #38
0
def bader_analysis_from_path(path, suffix=''):
    """
    Convenience method to run Bader analysis on a folder containing
    typical VASP output files.

    This method will:

    1. Look for files CHGCAR, AECAR0, AECAR2, POTCAR or their gzipped
    counterparts.
    2. If AECCAR* files are present, constructs a temporary reference
    file as AECCAR0 + AECCAR2
    3. Runs Bader analysis twice: once for charge, and a second time
    for the charge difference (magnetization density).

    :param path: path to folder to search in
    :param suffix: specific suffix to look for (e.g. '.relax1' for 'CHGCAR.relax1.gz'
    :return: summary dict
    """

    chgcar_path = get_filepath('CHGCAR', 'Could not find CHGCAR!', path,
                               suffix)
    chgcar = Chgcar.from_file(chgcar_path)

    aeccar0_path = get_filepath(
        'AECCAR0',
        'Could not find AECCAR0, interpret Bader results with caution.', path,
        suffix)
    aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

    aeccar2_path = get_filepath(
        'AECCAR2',
        'Could not find AECCAR2, interpret Bader results with caution.', path,
        suffix)
    aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

    potcar_path = get_filepath(
        'POTCAR', 'Could not find POTCAR, cannot calculate charge transfer.',
        path, suffix)
    potcar = Potcar.from_file(potcar_path) if potcar_path else None

    return bader_analysis_from_objects(chgcar, potcar, aeccar0, aeccar2)
Exemple #39
0
def generate(q=0,runtype='relax',functional='PBE',soc=False,relaxcell=False):

    """ 
    Generate INCAR file.
    
    Parameters
    ----------
    [optional] q (int): net charge of system. Default=0.
    [optional] runtype (str): type of calculation: relax(default)/dos/bands/dielectric
    [optional] functional (str): type of functional: PBE(default)/SCAN+rVV10
    [optional] soc (bool): to include spin-orbit coupling? Default=False.
    [optional] relaxcell (bool): to relax cell lattice parameters? Default=Fase.
    
    """
    
    dir_sub = os.getcwd()
    
    poscar = Poscar.from_file(os.path.join(dir_sub,"POSCAR"))
    potcar = Potcar.from_file(os.path.join(dir_sub,"POTCAR"))
    wavecar = os.path.exists(os.path.join(dir_sub,"WAVECAR"))  ## just a boolean (does file exist)
    chgcar = os.path.exists(os.path.join(dir_sub,"CHGCAR"))  ## just a boolean (does file exist)

    inc = IncarSettings(functional.split("+"),runtype,int(q),poscar,potcar,wavecar,chgcar)
    inc.setparams()
    if soc:
        inc.mag(ncl=True)
        inc.soc()
    if relaxcell:
        inc.ionicrelax(isif=3)
        inc.parallel(ncore=1)
        inc.output(lcharg=True)
    if runtype == 'dielectric':
        inc.dielectric()
        inc.startup(isym=None)
        inc.parallel(ncore=None)
        inc.output(lvtot=None,lvhar=None)
    inc.stripNone()      
    
    with open(os.path.join(dir_sub,"INCAR"),'w') as f:
        f.write(Incar.get_string(inc.params,sort_keys=False))
Exemple #40
0
 def test_init(self):
     self.assertEqual(self.potcar.symbols, ["Fe", "P", "O"],
                      "Wrong symbols read in for POTCAR")
     potcar = Potcar(["Fe_pv", "O"])
     self.assertEqual(potcar[0].enmax, 293.238)
Exemple #41
0
 def setUp(self):
     if "PMG_VASP_PSP_DIR" not in os.environ:
         os.environ["PMG_VASP_PSP_DIR"] = str(self.TEST_FILES_DIR)
     filepath = self.TEST_FILES_DIR / 'POTCAR'
     self.potcar = Potcar.from_file(filepath)
Exemple #42
0
    def __init__(self, chgcar_filename, potcar_filename=None,
                 chgref_filename=None, parse_atomic_densities=False):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename (str): The filename of the CHGCAR.
            potcar_filename (str): Optional: the filename of the corresponding
                POTCAR file. Used for calculating the charge transfer. If
                None, the get_charge_transfer method will raise a ValueError.
            chgref_filename (str): Optional. The filename of the reference
                CHGCAR, which calculated by AECCAR0 + AECCAR2. (See
                http://theory.cm.utexas.edu/henkelman/code/bader/ for details.)
            parse_atomic_densities (bool): Optional. turns on atomic partition of the charge density
                charge densities are atom centered

        """
        if not BADEREXE:
            raise RuntimeError(
                "BaderAnalysis requires the executable bader to be in the path."
                " Please download the library at http://theory.cm.utexas"
                ".edu/vasp/bader/ and compile the executable.")
        self.chgcar = Chgcar.from_file(chgcar_filename)
        self.potcar = Potcar.from_file(potcar_filename) \
            if potcar_filename is not None else None
        self.natoms = self.chgcar.poscar.natoms
        chgcarpath = os.path.abspath(chgcar_filename)
        chgrefpath = os.path.abspath(chgref_filename) if chgref_filename else None
        self.reference_used = True if chgref_filename else False
        self.parse_atomic_densities = parse_atomic_densities
        with ScratchDir(".") as temp_dir:
            with zopen(chgcarpath, 'rt') as f_in:
                with open("CHGCAR", "wt") as f_out:
                    shutil.copyfileobj(f_in, f_out)
            args = [BADEREXE, "CHGCAR"]
            if chgref_filename:
                with zopen(chgrefpath, 'rt') as f_in:
                    with open("CHGCAR_ref", "wt") as f_out:
                        shutil.copyfileobj(f_in, f_out)
                args += ['-ref', 'CHGCAR_ref']
            if parse_atomic_densities:
                args += ['-p', 'all_atom']
            rs = subprocess.Popen(args,
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE, close_fds=True)
            stdout, stderr = rs.communicate()
            if rs.returncode != 0:
                raise RuntimeError("bader exited with return code %d. "
                                   "Please check your bader installation."
                                   % rs.returncode)

            try:
                self.version = float(stdout.split()[5])
            except:
                self.version = -1  # Unknown
            if self.version < 1.0:
                warnings.warn('Your installed version of Bader is outdated, '
                              'calculation of vacuum charge may be incorrect.')

            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = ('x', 'y', 'z', 'charge', 'min_dist', 'atomic_vol')
                raw.pop(0)
                raw.pop(0)
                while True:
                    l = raw.pop(0).strip()
                    if l.startswith("-"):
                        break
                    vals = map(float, l.split()[1:])
                    data.append(dict(zip(headers, vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data

            if self.parse_atomic_densities:
                # convert the charge denisty for each atom spit out by Bader into Chgcar objects for easy parsing
                atom_chgcars = [Chgcar.from_file("BvAt{}.dat".format(str(i).zfill(4))) for i in
                                range(1, len(self.chgcar.structure) + 1)]

                atomic_densities = []
                # For each atom in the structure
                for atom, loc, chg in zip(self.chgcar.structure,
                                          self.chgcar.structure.frac_coords,
                                          atom_chgcars):
                    # Find the index of the atom in the charge density atom
                    index = np.round(np.multiply(loc, chg.dim))

                    data = chg.data['total']
                    # Find the shift vector in the array
                    shift = (np.divide(chg.dim, 2) - index).astype(int)

                    # Shift the data so that the atomic charge density to the center for easier manipulation
                    shifted_data = np.roll(data, shift, axis=(0, 1, 2))

                    # Slices a central window from the data array
                    def slice_from_center(data, xwidth, ywidth, zwidth):
                        x, y, z = data.shape
                        startx = x // 2 - (xwidth // 2)
                        starty = y // 2 - (ywidth // 2)
                        startz = z // 2 - (zwidth // 2)
                        return data[startx:startx + xwidth, starty:starty + ywidth, startz:startz + zwidth]

                    # Finds the central encompassing volume which holds all the data within a precision
                    def find_encompassing_vol(data,prec=1e-3):
                        total = np.sum(data)
                        for i in range(np.max(data.shape)):
                            sliced_data = slice_from_center(data,i,i,i)
                            if total - np.sum(sliced_data) < 0.1:
                                return sliced_data
                        return None

                    d = {
                        "data": find_encompassing_vol(shifted_data),
                        "shift": shift,
                        "dim": self.chgcar.dim
                    }
                    atomic_densities.append(d)
                self.atomic_densities = atomic_densities
Exemple #43
0
    def __init__(self, incar, poscar, potcar, kpoints, system=None,
                 is_matrix = False, Grid_type = 'A',
                 parent_job_dir='.',job_dir='Job',
                 qadapter=None, job_cmd='qsub', wait=True,
                 mappings_override = None, functional="PBE",
                 turn_knobs=OrderedDict( [ ('ENCUT',[]),
                                           ('KPOINTS',[])] ),
                 checkpoint_file=None, cal_logger=None):
        """
        Calibrate constructor

        Args:
            incar (Incar object): input INCAR
            poscar (Poscar object): input POSCAR
            potcar (Potcar object): input POTCAR
            kpoints: input KPOINTS
            system: system info as a dictionary,
                slab or interface example:
                system={'hkl':[1,1,1], 'ligand':None}, 
            is_matrix (bool): whether the jobs are dependent on each
                other
            Grid_type: kpoints grid_type
            parent_job_dir: the directory from which all the jobs are
                launched
            job_dir: job directory
            qadapter: adapter for the batch system
            job_cmd: command to be used for submitting the job. If 
                qadapter is specified then job_cmd is ignored
            wait: whther to wait for the job to finish. If the job is
                being submitted to the queue then there is no need for
                waiting
            turn_knobs: an ordered dictionary of parmaters and the 
                corresponding values
            mappings_override: override symbol mapping in potcar
                               eg:- {'S':'S_sv'}
            functional: exchange-correlation functional

        Note: input structure if needed will be obtained from the
            provided poscar object
        """
        self.name = datetime.datetime.now().isoformat()
        self.system = system
        self.parent_job_dir = os.path.abspath(parent_job_dir)
        self.job_dir = job_dir
        self.incar = incar               
        self.poscar = poscar
        self.potcar = potcar
        if poscar:
            self.potcar = Potcar(symbols=poscar.site_symbols,
                                 functional=functional)
        self.kpoints = kpoints
        if incar:
            self.incar_orig = incar.as_dict()
        if poscar:
            self.poscar_orig = poscar.as_dict()
        if self.potcar:
            self.potcar_orig = self.potcar.as_dict()
        if kpoints:
            self.kpoints_orig = kpoints.as_dict()
        self.qadapter = qadapter
        self.job_dir_list = []
        self.jobs = []
        self.job_ids = []        
        self.handlers = []
        self.job_cmd = job_cmd
        self.n_atoms = 0
        self.turn_knobs = turn_knobs
        self.response_to_knobs = {}
        self.sorted_response_to_knobs = {}        
        for k, v in turn_knobs.items():
            self.response_to_knobs[k] = {}
            self.sorted_response_to_knobs[k] = {}            
        self.is_matrix = is_matrix
        self.Grid_type = Grid_type
        self.wait = wait
        self.cal_log = []
        self.mappings_override = mappings_override
        self.functional = functional
        self.checkpoint_file = checkpoint_file
        if cal_logger:
            self.logger = cal_logger
        else:
            self.logger = logger
Exemple #44
0
 def test_write(self):
     tempfname = "POTCAR.testing"
     self.potcar.write_file(tempfname)
     p = Potcar.from_file(tempfname)
     self.assertEqual(p.symbols, self.potcar.symbols)
     os.remove(tempfname)
Exemple #45
0
 def test_to_from_dict(self):
     d = self.potcar.as_dict()
     potcar = Potcar.from_dict(d)
     self.assertEqual(potcar.symbols, ["Fe", "P", "O"])
Exemple #46
0
    def assimilate(self, path):
        files = os.listdir(path)
        try:
            files_to_parse = {}
            if "relax1" in files and "relax2" in files:
                for filename in ("INCAR", "POTCAR", "POSCAR"):
                    search_str = os.path.join(path, "relax1", filename + "*")
                    files_to_parse[filename] = glob.glob(search_str)[0]
                for filename in ("CONTCAR", "OSZICAR"):
                    search_str = os.path.join(path, "relax2", filename + "*")
                    files_to_parse[filename] = glob.glob(search_str)[-1]
            else:
                for filename in (
                    "INCAR", "POTCAR", "CONTCAR", "OSZICAR", "POSCAR", "DYNMAT"
                ):
                    files = glob.glob(os.path.join(path, filename + "*"))
                    if len(files) < 1:
                        continue
                    if len(files) == 1 or filename == "INCAR" or \
                       filename == "POTCAR" or filename == "DYNMAT":
                        files_to_parse[filename] = files[-1]\
                            if filename == "POTCAR" else files[0]
                    elif len(files) > 1:
                        """
                        This is a bit confusing, since there maybe be
                        multiple steps. By default, assimilate will try to find
                        a file simply named filename, filename.bz2, or
                        filename.gz.  Failing which it will try to get a relax2
                        from a custodian double relaxation style run if
                        possible. Or else, a random file is chosen.
                        """
                        for fname in files:
                            if fnmatch.fnmatch(os.path.basename(fname),
                                               "{}(\.gz|\.bz2)*"
                                               .format(filename)):
                                files_to_parse[filename] = fname
                                break
                            if fname == "POSCAR" and \
                                    re.search("relax1", fname):
                                files_to_parse[filename] = fname
                                break
                            if (fname in ("CONTCAR", "OSZICAR") and
                                    re.search("relax2", fname)):
                                files_to_parse[filename] = fname
                                break
                            files_to_parse[filename] = fname

            poscar, contcar, incar, potcar, oszicar, dynmat = [None]*6
            if 'POSCAR' in files_to_parse:
                poscar = Poscar.from_file(files_to_parse["POSCAR"])
            if 'CONTCAR' in files_to_parse:
                contcar = Poscar.from_file(files_to_parse["CONTCAR"])
            if 'INCAR' in files_to_parse:
                incar = Incar.from_file(files_to_parse["INCAR"])
            if 'POTCAR' in files_to_parse:
                potcar = Potcar.from_file(files_to_parse["POTCAR"])
            if 'OSZICAR' in files_to_parse:
                oszicar = Oszicar(files_to_parse["OSZICAR"])
            if 'DYNMAT' in files_to_parse:
                dynmat = Dynmat(files_to_parse["DYNMAT"])

            param = {"hubbards":{}}
            if poscar is not None and incar is not None and "LDAUU" in incar:
                param["hubbards"] = dict(zip(poscar.site_symbols,
                                             incar["LDAUU"]))
            param["is_hubbard"] = (
                incar.get("LDAU", False) and sum(param["hubbards"].values()) > 0
            ) if incar is not None else False
            param["run_type"] = None
            if incar is not None:
                param["run_type"] = "GGA+U" if param["is_hubbard"] else "GGA"
            param["history"] = _get_transformation_history(path)
            param["potcar_spec"] = potcar.spec if potcar is not None else None
            energy = oszicar.final_energy if oszicar is not None else 1e10
            structure = contcar.structure if contcar is not None\
                else poscar.structure
            initial_vol = poscar.structure.volume if poscar is not None else \
                None
            final_vol = contcar.structure.volume if contcar is not None else \
                None
            delta_volume = None
            if initial_vol is not None and final_vol is not None:
                delta_volume = (final_vol / initial_vol - 1)
            data = {"filename": path, "delta_volume": delta_volume}
            if dynmat is not None:
                data['phonon_frequencies'] = dynmat.get_phonon_frequencies()
            if self._inc_structure:
                entry = ComputedStructureEntry(
                    structure, energy, parameters=param, data=data
                )
            else:
                entry = ComputedEntry(
                  structure.composition, energy, parameters=param, data=data
                )
            return entry

        except Exception as ex:
            logger.debug("error in {}: {}".format(path, ex))
            return None
 def setUp(self):
     self.potcar = Potcar.from_file(test_dir+"/POTCAR")
     self.zval_dict = {'Ba': 10.0, 'Ti': 10.0, 'O': 6.0}
     self.ions = ions
     self.structures = structures
Exemple #48
0
    def __init__(self, incar, poscar, potcar, kpoints, system=None,
                 is_matrix=False, Grid_type='A',
                 parent_job_dir='.', job_dir='Job',
                 qadapter=None, job_cmd='qsub', wait=True,
                 mappings_override=None, functional="PBE",
                 database=None, magnetism=None, mag_init=None, reuse=None,
                 reuse_override=None, reuse_incar=None, solvation=None,
                 turn_knobs=OrderedDict([('ENCUT', []),
                                         ('KPOINTS', [])]),
                 checkpoint_file=None, finer_kpoint=None, cal_logger=None):
        """
        Calibrate constructor

        Args:
            incar (Incar object): input INCAR
            poscar (Poscar object): input POSCAR
            potcar (Potcar object): input POTCAR
            kpoints (Kpoints object): input KPOINTS
            system: system info as a dictionary,
                slab or interface example:
                system={'hkl':[1,1,1], 'ligand':None},
            is_matrix (bool): whether the jobs are dependent on each
                other
            Grid_type (str): kpoints grid_type
            parent_job_dir (str): the directory from which all the
                jobs are launched
            job_dir (str): job directory created for each job in the
                parent_job_dir
            qadapter (?): adapter for the batch system
            job_cmd (str): command to be used for submitting the job. If
                qadapter is specified then job_cmd is ignored
            wait (bool): whther to wait for the job to finish. If the job is
                being submitted to the queue then there is no need for
                waiting
            turn_knobs (dict): an ordered dictionary of parmaters and the
                corresponding values
            mappings_override (dict): override symbol mapping in potcar
                               eg:- {'S':'S_sv'}
            functional (str): exchange-correlation functional
            database (str): A work in progress, will be a database_name.yaml
                            file for defaults specific to a database workflow
                            that will have defaults for
                            INCAR: cutoff, convergence for relaxation and
                                   continuation jobs
                            KPOINTS: for relaxation, band structure jobs
                            POTCAR: database specific
                            For now defaults to None, if set to 'twod'
                            activates twod set of directives
            reuse (list or bool): list of filenames for reuse
                          Eg: ['CHGCAR', 'WAVECAR']
                          'CONTCAR' is copied by default and if found empty
                          warning is issued. Use the following flag for override
                          only if you know what you are doing
                          'True' for just copying the CONTCAR file
            reuse_override (bool): whether to override the missing CONTCAR for a
                          reuse calc
            magnetism (str): specifies magnetism calculation to be used
                           implemented are 'AntiFerroMagnetism' and
                           'Magntic Anisotropy Energy'
            solvation (bool): whether to activate a solvation job, sets LSOL=True
                           for now

        Calibrate jobs represent the engine configuration of mpinterfaces,
        where the fuel (input file sources) and driving method (kind of calculation)
        are decided . The Engine itself is instrument.py which creates the input set
        configured in Calibrate.

        Current fueling methods:
          1. simplest test case involving a single job:
               - specify the incar, kpoints, poscar, potcar (aka the VASP 4)
                 explicitly as pymatgen objects
               - turn_knobs = {} , is_matrix = False
          2. test case for calibration of parameters:
               - specify an initial configuration for the VASP 4
               - specify parameters to calibrate via turn_knobs,
                 set is_matrix = True only if number of parameters > 1
          3. Database production case: (possibly most used)
               - specify initial configuration for the VASP 4 based on
                 a database.yaml
               - specify an input.yaml that details the workflow

        Note: input structure if needed will be obtained from the
            provided poscar object
        """
        self.name = datetime.datetime.now().isoformat()
        self.system = system
        self.parent_job_dir = os.path.abspath(parent_job_dir)
        self.job_dir = job_dir
        self.incar = incar
        self.poscar = poscar
        self.potcar = potcar
        if poscar:
            self.potcar = Potcar(symbols=poscar.site_symbols,
                                 functional=functional)
        self.kpoints = kpoints
        if incar:
            self.incar_orig = incar.as_dict()
        if poscar:
            self.poscar_orig = poscar.as_dict()
        if self.potcar:
            self.potcar_orig = self.potcar.as_dict()
        if kpoints:
            self.kpoints_orig = kpoints.as_dict()
        self.qadapter = qadapter
        self.job_dir_list = []
        self.jobs = []
        self.job_ids = []
        self.handlers = []
        self.job_cmd = job_cmd
        self.n_atoms = 0
        self.turn_knobs = turn_knobs
        self.response_to_knobs = {}
        self.sorted_response_to_knobs = {}
        for k, v in turn_knobs.items():
            self.response_to_knobs[k] = {}
            self.sorted_response_to_knobs[k] = {}
        self.is_matrix = is_matrix
        self.Grid_type = Grid_type
        self.wait = wait
        self.cal_log = []
        self.mappings_override = mappings_override
        self.database = database
        self.magnetism = magnetism
        self.mag_init = mag_init
        self.solvation = solvation
        self.reuse = reuse
        self.reuse_incar = reuse_incar
        self.reuse_override = reuse_override
        self.reuse_paths = None  # list object communicated to instrument
        self.finer_kpoint = finer_kpoint
        self.functional = functional
        self.checkpoint_file = checkpoint_file
        if cal_logger:
            self.logger = cal_logger
        else:
            self.logger = logger
Exemple #49
0
class Calibrate(PMGSONable):    
    """
    The base class for creating vasp work flows for
    calibrating the input parameters for different systems

    A wrapper around Custodian
    """
    LOG_FILE = "calibrate.json"

    def __init__(self, incar, poscar, potcar, kpoints, system=None,
                 is_matrix = False, Grid_type = 'A',
                 parent_job_dir='.',job_dir='Job',
                 qadapter=None, job_cmd='qsub', wait=True,
                 mappings_override = None, functional="PBE",
                 turn_knobs=OrderedDict( [ ('ENCUT',[]),
                                           ('KPOINTS',[])] ),
                 checkpoint_file=None, cal_logger=None):
        """
        Calibrate constructor

        Args:
            incar (Incar object): input INCAR
            poscar (Poscar object): input POSCAR
            potcar (Potcar object): input POTCAR
            kpoints: input KPOINTS
            system: system info as a dictionary,
                slab or interface example:
                system={'hkl':[1,1,1], 'ligand':None}, 
            is_matrix (bool): whether the jobs are dependent on each
                other
            Grid_type: kpoints grid_type
            parent_job_dir: the directory from which all the jobs are
                launched
            job_dir: job directory
            qadapter: adapter for the batch system
            job_cmd: command to be used for submitting the job. If 
                qadapter is specified then job_cmd is ignored
            wait: whther to wait for the job to finish. If the job is
                being submitted to the queue then there is no need for
                waiting
            turn_knobs: an ordered dictionary of parmaters and the 
                corresponding values
            mappings_override: override symbol mapping in potcar
                               eg:- {'S':'S_sv'}
            functional: exchange-correlation functional

        Note: input structure if needed will be obtained from the
            provided poscar object
        """
        self.name = datetime.datetime.now().isoformat()
        self.system = system
        self.parent_job_dir = os.path.abspath(parent_job_dir)
        self.job_dir = job_dir
        self.incar = incar               
        self.poscar = poscar
        self.potcar = potcar
        if poscar:
            self.potcar = Potcar(symbols=poscar.site_symbols,
                                 functional=functional)
        self.kpoints = kpoints
        if incar:
            self.incar_orig = incar.as_dict()
        if poscar:
            self.poscar_orig = poscar.as_dict()
        if self.potcar:
            self.potcar_orig = self.potcar.as_dict()
        if kpoints:
            self.kpoints_orig = kpoints.as_dict()
        self.qadapter = qadapter
        self.job_dir_list = []
        self.jobs = []
        self.job_ids = []        
        self.handlers = []
        self.job_cmd = job_cmd
        self.n_atoms = 0
        self.turn_knobs = turn_knobs
        self.response_to_knobs = {}
        self.sorted_response_to_knobs = {}        
        for k, v in turn_knobs.items():
            self.response_to_knobs[k] = {}
            self.sorted_response_to_knobs[k] = {}            
        self.is_matrix = is_matrix
        self.Grid_type = Grid_type
        self.wait = wait
        self.cal_log = []
        self.mappings_override = mappings_override
        self.functional = functional
        self.checkpoint_file = checkpoint_file
        if cal_logger:
            self.logger = cal_logger
        else:
            self.logger = logger
    
    def setup(self):
        """
        set up the jobs for the given turn_knobs dict
        is_matrix = True implies that the params in the dict are 
        interrelated. Otherwise calcs corresponding to each dict key
        is independent
        """
        if self.is_matrix: 
            self.setup_matrix_job()	
        else:
            self._setup()

    def _setup(self, turn_knobs=None):
        """
        invoke the set up methods corresponding to the dict keys
        any key other than KPOINTS, VOLUME and POTCAR are treated
        as INCAR parameters
        
        Args:
            turn_knobs: knobs aka paramters to be tuned

        Note: poscar jobs setup through the VOLUME is only for
              backward compatibility, use POSCAR key in the
              turn_knobs to tune poscars
        """
        if turn_knobs is None:
            turn_knobs = self.turn_knobs
        if any(turn_knobs.values()):
            for k, v in turn_knobs.items():
                if k == 'KPOINTS' and v:
                    self.setup_kpoints_jobs(kpoints_list = v)
                elif k == 'VOLUME' and v:
                    self.setup_poscar_jobs(scale_list = v)
                elif k == 'POTCAR' and v:
                    self.setup_potcar_jobs(mappings = v)
                elif k == 'POSCAR' and v:
                    self.setup_poscar_jobs(poscar_list=v)
                else:
                    self.setup_incar_jobs(k, v)
        else:
            self.logger.warn('knobs not set, running a single job')
            self.add_job(name='single_job', job_dir=self.job_dir)

    def setup_matrix_job(self):
        """
        set up jobs where the dict keys are interrelated
        mind: its an ordered dict, the order in which the keys
        are specified determines the nested directory structure
        """
        orig_job_dir = self.job_dir
        job_dir = self.job_dir
        n_items = len(self.turn_knobs.items())
        keys = self.turn_knobs.keys()
        self._setup(turn_knobs=dict([(keys[0], 
                                      self.turn_knobs[keys[0]])]))
        self.recursive_jobs(n_items, keys, 0)
        #restore
        self.job_dir = orig_job_dir

    def recursive_jobs(self,n, keys, i):
        """
        recursively setup the jobs: used by setup_matrix_job
        
        Args:
            n: total number of knobs aka parameters to be tuned
            keys: list of knobs i.e parameter names
            i: ith knob
            
        """
        job_dir = self.job_dir + os.sep + self.key_to_name(keys[i])
        if i == n-1 and i != 0:
            for val in self.turn_knobs[keys[i]]:
                self.job_dir = job_dir + os.sep + self.val_to_name(val)
                self.logger.info('setting jobs in the directory: '+self.job_dir)
                self._setup(turn_knobs=dict([(keys[i], [val])]))
                self.add_job(name=job_dir, job_dir=self.job_dir)
        else:
            for val in self.turn_knobs[keys[i]]:
                self.job_dir = job_dir + os.sep + self.val_to_name(val)
                self.logger.info('setting jobs in the directory: '+self.job_dir)
                self._setup(turn_knobs=dict([(keys[i], [val])]))
                self.recursive_jobs(n,keys,i+1)

    def key_to_name(self, key):
        """
        convenient string mapping for the keys in the turn_knobs dict
        
        Args:
            key: key to the knob dict
            
        Returns:
            an appropriate string representation of the key so that
            the name doesnt clash with the filenames
        """
        if key == 'KPOINTS':
            return 'KPTS'
        elif key == 'POTCAR_map' or key == 'POTCAR_functional':
            return 'POT'
        elif key == 'POSCAR':
            return 'POS'        
        else:
            return key

    def val_to_name(self, val):
        """
        convert a value to a string so that it can be used for naming
        the job directory
        the decimal points in floats are replaced with underscore 
        character
        if the value is of type list, kpoint_to_name method is used 
        since
        only kpoint values are expected to be of type list
        if the values is of type dict then potcar_to_name method is 
        invoked
        
        Args:
            val: knob value to be converted into an appropriate string
                representation
            
        Returns:
            a string filename for the value 
        """
        if type(val) == float:
            return re.sub('\.','_',str(val))
        elif type(val) == list:
            return self.kpoint_to_name(val, 'M')
        elif type(val) == dict:
            return self.potcar_to_name(val)
        elif isinstance(val, Poscar):
            return val.comment        
        else:
            return str(val)
                
    def kpoint_to_name(self, kpoint, grid_type):
        """
        get a string representation for the given kpoint
        
        Args:
            kpoint: an iterable
            grid_type: grid_type used for the KPOINTS
        
        Returns:    
            string representation for kpoint eg: Monkhorst Pack
	    2 2 2 will be named 2x2x2
        """
        if grid_type == 'M' or grid_type == 'G':
            return str(kpoint[0]) + 'x' + str(kpoint[1]) + 'x' \
                + str(kpoint[2])
        else:    
            return str(kpoint)

    def potcar_to_name(self, mapping,functional):
        """
        convert a symbol mapping and functional to a name that 
        can be used for setting up the potcar jobs
         
         Args:
             mapping: example:- if mapping = {'Pt':'Pt_pv', 
                 'Si':'Si_GW'} then the name will be PBE_Pt_pv_Si_GW
                  with self.functional="PBE"
                 
        Returns:
            string 
        """
        if mapping:
            l = [v for k,v in mapping.items()]
            return '_'.join(self.functional, l)
        elif functional:
            return '_'.join(functional)
        else:
            return '_'.join(functional,l)
        

    def set_incar(self, param, val):
        """
        set the incar paramter, param = val
        """
        self.incar[param] = val

    def set_poscar(self, scale=None, poscar=None):
        """
        perturbs given structure by volume scaling factor 
	or takes user defined variants of Poscar 
	
	Args:
	   scale : Volume Scaling parameter

	   poscar : Poscar object of user defined structure

	   set the poscar: volume scaled by the scale factor
        """
        if scale is not None:
            structure = Poscar.from_dict(self.poscar_orig).structure
            volume = structure.volume
            structure.scale_lattice(scale *volume)
            self.poscar = Poscar(structure)
        elif poscar is not None:
            self.poscar = poscar

    def set_potcar(self, mapping=None, functional='PBE'):
        """
        set the potcar: symbol to potcar type mapping
        """
        symbols = self.poscar.site_symbols
        mapped_symbols = []
        if mapping:
            for sym in symbols:
                mapped_symbols.append(mapping[sym])
        elif self.mappings_override:
            for sym in symbols:
                if sym in self.mappings_override.keys():
                    mapped_symbols.append(self.mappings_override[sym])
                else:
                    mapped_symbols.append(sym)     
        else:
            mapped_symbols = symbols
        if functional:
            func=functional
        else:
            func=self.functional
        self.potcar = Potcar(symbols=mapped_symbols,
                             functional=func)

    def set_kpoints(self, kpoint):
        """
        set the kpoint
        """
        if self.Grid_type == 'M':
            self.kpoints = Kpoints.monkhorst_automatic(kpts = kpoint)
        elif self.Grid_type == 'A':
            self.kpoints = Kpoints.automatic(subdivisions = kpoint)
        elif self.Grid_type == 'G': 
            self.kpoints = Kpoints.gamma_automatic(kpts = kpoint)
        elif self.Grid_type == '3DD':
            self.kpoints = Kpoints.automatic_density_by_vol(structure=\
                           self.poscar.structure, kppvol=kpoint)
        elif self.Grid_type == 'band':
            self.kpoints = Kpoints.automatic_linemode(divisions=kpoint,\
                           ibz=HighSymmKpath(self.poscar.structure))
        name = self.kpoint_to_name(kpoint, self.Grid_type)
        job_dir = self.job_dir +os.sep+ self.key_to_name('KPOINTS') \
          + os.sep + name
        return job_dir
                                        
    def setup_incar_jobs(self, param, val_list):
        """
        set up incar jobs,, calls set_incar to set the value to param

	Args:
	    param: Name of INCAR parameter
	    val_list: List of values to vary for the param
        """
        if val_list:
            for val in val_list:
                self.logger.info('setting INCAR parameter ' + param + ' = '\
                            + str(val))
                self.set_incar(param, val)
                if not self.is_matrix:
                    job_dir  = self.job_dir+ os.sep + \
                        param + os.sep +  self.val_to_name(val)
                    self.add_job(name=job_dir, job_dir=job_dir)
        else:
            self.logger.warn('incar list empty')
                    
            
    def setup_kpoints_jobs(self, kpoints_list = None):
        """
        setup the kpoint jobs
        
        """
        if kpoints_list:
            for kpoint in kpoints_list:
                job_dir = self.set_kpoints(kpoint)
                if not self.is_matrix:                     
                    self.add_job(name=job_dir, job_dir=job_dir)
        else:
            self.logger.warn('kpoints_list empty')
            
    def setup_poscar_jobs(self, scale_list=None, poscar_list=None):
        """
        for scaling the latice vectors of the original structure,
        scale_list is volume scaling factor list
        """
        if scale_list:
            for scale in scale_list:
                self.set_poscar(scale=scale)
                self.set_potcar()
                job_dir  = self.job_dir+ os.sep + 'POS' +\
                        os.sep + 'VOLUME_'+str(scale)
                if not self.is_matrix:
                    self.add_job(name=job_dir, job_dir=job_dir)
        elif poscar_list:
            for poscar in poscar_list:
                self.set_poscar(poscar=poscar)
                self.set_potcar()
                poskey = str(poscar.structure.composition.reduced_formula) \
                                 + '_'+ str(int(poscar.structure.lattice.volume)) \
                                 + '_' + ''.join((poscar.comment).split())
                
                job_dir  = self.job_dir+ os.sep +'POS' +\
                  os.sep + poskey
                if not self.is_matrix:
                    self.add_job(name=job_dir, job_dir=job_dir)
                    

    def setup_potcar_jobs(self, mappings,functional_list):
        """
        take a list of symbol mappings and setup the potcar jobs
        """
        if functional_list:
            for func in functional_list:
                self.set_potcar(functional=func)
                if not self.is_matrix:
                    job_dir  = self.job_dir+ os.sep \
                        + self.key_to_name('POTCAR') \
                        + os.sep + self.potcar_to_name(func)
                    self.add_job(name=job_dir, job_dir=job_dir)
        
        elif mappings:
            for mapping in mappings:
                self.set_potcar(mapping)
                if not self.is_matrix:
                    job_dir  = self.job_dir+ os.sep \
                        + self.key_to_name('POTCAR') \
                        + os.sep + self.potcar_to_name(mapping)
                    self.add_job(name=job_dir, job_dir=job_dir)
                

    def add_job(self, name='noname', job_dir='.'):
        """
        add a single job using the current incar, poscar, potcar and 
        kpoints
        """
        vis = MPINTVaspInputSet(name, self.incar, self.poscar,
                                self.potcar, self.kpoints,
                                self.qadapter, vis_logger=self.logger)
        #the job command can be overrridden in the run method
        job = MPINTVaspJob(self.job_cmd, name=name, final = True,
                           parent_job_dir=self.parent_job_dir,
                           job_dir=job_dir, vis=vis, wait=self.wait,
                           vjob_logger = self.logger)
        self.job_dir_list.append(os.path.abspath(job_dir))
        self.jobs.append(job)
    
    def run(self, job_cmd=None):
        """
        run the vasp jobs through custodian
        if the job list is empty,
        run a single job with the initial input set
        """
        for j in self.jobs:
            if job_cmd is not None:            
                j.job_cmd = job_cmd
            else:
                j.job_cmd = self.job_cmd
        c_params = {'jobs': [j.as_dict() for j in self.jobs],
                'handlers': [h.as_dict() for h in self.handlers],
                'max_errors': 5}
        c = Custodian(self.handlers, self.jobs, max_errors=5)
        c.run()
        for j in self.jobs:
            self.cal_log.append({"job": j.as_dict(), 
                                 'job_id': j.job_id, 
                                 "corrections": [], 
                                 'final_energy': None})
            self.job_ids.append(j.job_id)
        if self.checkpoint_file:
            dumpfn(self.cal_log, self.checkpoint_file,
                   cls=MontyEncoder, indent=4)
        else:
            dumpfn(self.cal_log, Calibrate.LOG_FILE, cls=MontyEncoder,
                   indent=4)
            
    def as_dict(self):
        qadapter = None
        system = None
        if self.qadapter:
            qadapter = self.qadapter.to_dict()
        if self.system is not None:
            system = self.system
        d = dict(incar=self.incar.as_dict(),
                 poscar=self.poscar.as_dict(), 
                 potcar=self.potcar.as_dict(),
                 kpoints=self.kpoints.as_dict(), 
                 system=system, is_matrix = self.is_matrix, 
                 Grid_type = self.Grid_type,
                 parent_job_dir=self.parent_job_dir,
                 job_dir=self.job_dir,
                 qadapter=qadapter, job_cmd=self.job_cmd,
                 wait=self.wait,
                 turn_knobs=self.turn_knobs,
                 job_dir_list=self.job_dir_list,
                 job_ids = self.job_ids)
        d["@module"] = self.__class__.__module__
        d["@class"] = self.__class__.__name__
        #d['calibrate'] = self.__class__.__name__
        return d
        
    @classmethod
    def from_dict(cls, d):
        incar = Incar.from_dict(d["incar"])
        poscar = Poscar.from_dict(d["poscar"])
        potcar = Potcar.from_dict(d["potcar"])
        kpoints = Kpoints.from_dict(d["kpoints"])
        cal =  Calibrate(incar, poscar, potcar, kpoints, 
                         system=d["system"], is_matrix = d["is_matrix"], 
                         Grid_type = d["Grid_type"], 
                         parent_job_dir=d["parent_job_dir"], 
                         job_dir=d["job_dir"], qadapter=d.get("qadapter"), 
                         job_cmd=d["job_cmd"], wait=d["wait"],
                         turn_knobs=d["turn_knobs"])
        cal.job_dir_list = d["job_dir_list"]
        cal.job_ids = d["job_ids"]
        return cal
Exemple #50
0
    def assimilate(self, path):
        files = os.listdir(path)
        try:
            files_to_parse = {}
            if "relax1" in files and "relax2" in files:
                for filename in ("INCAR", "POTCAR", "POSCAR"):
                    search_str = os.path.join(path, "relax1", filename + "*")
                    files_to_parse[filename] = glob.glob(search_str)[0]
                for filename in ("CONTCAR", "OSZICAR"):
                    search_str = os.path.join(path, "relax2", filename + "*")
                    files_to_parse[filename] = glob.glob(search_str)[-1]
            else:
                for filename in (
                    "INCAR", "POTCAR", "CONTCAR", "OSZICAR", "POSCAR", "DYNMAT"
                ):
                    files = sorted(glob.glob(os.path.join(path, filename + "*")))
                    if len(files) < 1:
                        continue
                    if len(files) == 1 or filename == "INCAR" or \
                       filename == "POTCAR" or filename == "DYNMAT":
                        files_to_parse[filename] = files[-1]\
                            if filename == "POTCAR" else files[0]
                    elif len(files) > 1:
                        # Since multiple files are ambiguous, we will always
                        # use the first one for POSCAR and the last one
                        # alphabetically for CONTCAR and OSZICAR.

                        if filename == "POSCAR":
                            files_to_parse[filename] = files[0]
                        else:
                            files_to_parse[filename] = files[-1]
                        warnings.warn(
                            "%d files found. %s is being parsed." %
                            (len(files), files_to_parse[filename]))

            poscar, contcar, incar, potcar, oszicar, dynmat = [None]*6
            if 'POSCAR' in files_to_parse:
                poscar = Poscar.from_file(files_to_parse["POSCAR"])
            if 'CONTCAR' in files_to_parse:
                contcar = Poscar.from_file(files_to_parse["CONTCAR"])
            if 'INCAR' in files_to_parse:
                incar = Incar.from_file(files_to_parse["INCAR"])
            if 'POTCAR' in files_to_parse:
                potcar = Potcar.from_file(files_to_parse["POTCAR"])
            if 'OSZICAR' in files_to_parse:
                oszicar = Oszicar(files_to_parse["OSZICAR"])
            if 'DYNMAT' in files_to_parse:
                dynmat = Dynmat(files_to_parse["DYNMAT"])

            param = {"hubbards":{}}
            if poscar is not None and incar is not None and "LDAUU" in incar:
                param["hubbards"] = dict(zip(poscar.site_symbols,
                                             incar["LDAUU"]))
            param["is_hubbard"] = (
                incar.get("LDAU", False) and sum(param["hubbards"].values()) > 0
            ) if incar is not None else False
            param["run_type"] = None
            if incar is not None:
                param["run_type"] = "GGA+U" if param["is_hubbard"] else "GGA"
            # param["history"] = _get_transformation_history(path)
            param["potcar_spec"] = potcar.spec if potcar is not None else None
            energy = oszicar.final_energy if oszicar is not None else 1e10
            structure = contcar.structure if contcar is not None\
                else poscar.structure
            initial_vol = poscar.structure.volume if poscar is not None else \
                None
            final_vol = contcar.structure.volume if contcar is not None else \
                None
            delta_volume = None
            if initial_vol is not None and final_vol is not None:
                delta_volume = (final_vol / initial_vol - 1)
            data = {"filename": path, "delta_volume": delta_volume}
            if dynmat is not None:
                data['phonon_frequencies'] = dynmat.get_phonon_frequencies()
            if self._inc_structure:
                entry = ComputedStructureEntry(
                    structure, energy, parameters=param, data=data
                )
            else:
                entry = ComputedEntry(
                  structure.composition, energy, parameters=param, data=data
                )
            return entry

        except Exception as ex:
            logger.debug("error in {}: {}".format(path, ex))
            return None
Exemple #51
0
 def setUp(self):
     if "PMG_VASP_PSP_DIR" not in os.environ:
         os.environ["PMG_VASP_PSP_DIR"] = str(self.TEST_FILES_DIR)
     filepath = self.TEST_FILES_DIR / 'POTCAR'
     self.potcar = Potcar.from_file(filepath)
Exemple #52
0
 def test_write(self):
     tempfname = Path("POTCAR.testing")
     self.potcar.write_file(tempfname)
     p = Potcar.from_file(tempfname)
     self.assertEqual(p.symbols, self.potcar.symbols)
     tempfname.unlink()
Exemple #53
0
 def test_to_from_dict(self):
     d = self.potcar.as_dict()
     potcar = Potcar.from_dict(d)
     self.assertEqual(potcar.symbols, ["Fe", "P", "O"])
Exemple #54
0
 def test_write(self):
     tempfname = Path("POTCAR.testing")
     self.potcar.write_file(tempfname)
     p = Potcar.from_file(tempfname)
     self.assertEqual(p.symbols, self.potcar.symbols)
     tempfname.unlink()
Exemple #55
0
class Calibrate(MSONable):
    """
    The base class for creating vasp work flows for
    calibrating the input parameters for different systems

    A wrapper around Custodian
    """
    LOG_FILE = "calibrate.json"

    def __init__(self, incar, poscar, potcar, kpoints, system=None,
                 is_matrix=False, Grid_type='A',
                 parent_job_dir='.', job_dir='Job',
                 qadapter=None, job_cmd='qsub', wait=True,
                 mappings_override=None, functional="PBE",
                 database=None, magnetism=None, mag_init=None, reuse=None,
                 reuse_override=None, reuse_incar=None, solvation=None,
                 turn_knobs=OrderedDict([('ENCUT', []),
                                         ('KPOINTS', [])]),
                 checkpoint_file=None, finer_kpoint=None, cal_logger=None):
        """
        Calibrate constructor

        Args:
            incar (Incar object): input INCAR
            poscar (Poscar object): input POSCAR
            potcar (Potcar object): input POTCAR
            kpoints (Kpoints object): input KPOINTS
            system: system info as a dictionary,
                slab or interface example:
                system={'hkl':[1,1,1], 'ligand':None},
            is_matrix (bool): whether the jobs are dependent on each
                other
            Grid_type (str): kpoints grid_type
            parent_job_dir (str): the directory from which all the
                jobs are launched
            job_dir (str): job directory created for each job in the
                parent_job_dir
            qadapter (?): adapter for the batch system
            job_cmd (str): command to be used for submitting the job. If
                qadapter is specified then job_cmd is ignored
            wait (bool): whther to wait for the job to finish. If the job is
                being submitted to the queue then there is no need for
                waiting
            turn_knobs (dict): an ordered dictionary of parmaters and the
                corresponding values
            mappings_override (dict): override symbol mapping in potcar
                               eg:- {'S':'S_sv'}
            functional (str): exchange-correlation functional
            database (str): A work in progress, will be a database_name.yaml
                            file for defaults specific to a database workflow
                            that will have defaults for
                            INCAR: cutoff, convergence for relaxation and
                                   continuation jobs
                            KPOINTS: for relaxation, band structure jobs
                            POTCAR: database specific
                            For now defaults to None, if set to 'twod'
                            activates twod set of directives
            reuse (list or bool): list of filenames for reuse
                          Eg: ['CHGCAR', 'WAVECAR']
                          'CONTCAR' is copied by default and if found empty
                          warning is issued. Use the following flag for override
                          only if you know what you are doing
                          'True' for just copying the CONTCAR file
            reuse_override (bool): whether to override the missing CONTCAR for a
                          reuse calc
            magnetism (str): specifies magnetism calculation to be used
                           implemented are 'AntiFerroMagnetism' and
                           'Magntic Anisotropy Energy'
            solvation (bool): whether to activate a solvation job, sets LSOL=True
                           for now

        Calibrate jobs represent the engine configuration of mpinterfaces,
        where the fuel (input file sources) and driving method (kind of calculation)
        are decided . The Engine itself is instrument.py which creates the input set
        configured in Calibrate.

        Current fueling methods:
          1. simplest test case involving a single job:
               - specify the incar, kpoints, poscar, potcar (aka the VASP 4)
                 explicitly as pymatgen objects
               - turn_knobs = {} , is_matrix = False
          2. test case for calibration of parameters:
               - specify an initial configuration for the VASP 4
               - specify parameters to calibrate via turn_knobs,
                 set is_matrix = True only if number of parameters > 1
          3. Database production case: (possibly most used)
               - specify initial configuration for the VASP 4 based on
                 a database.yaml
               - specify an input.yaml that details the workflow

        Note: input structure if needed will be obtained from the
            provided poscar object
        """
        self.name = datetime.datetime.now().isoformat()
        self.system = system
        self.parent_job_dir = os.path.abspath(parent_job_dir)
        self.job_dir = job_dir
        self.incar = incar
        self.poscar = poscar
        self.potcar = potcar
        if poscar:
            self.potcar = Potcar(symbols=poscar.site_symbols,
                                 functional=functional)
        self.kpoints = kpoints
        if incar:
            self.incar_orig = incar.as_dict()
        if poscar:
            self.poscar_orig = poscar.as_dict()
        if self.potcar:
            self.potcar_orig = self.potcar.as_dict()
        if kpoints:
            self.kpoints_orig = kpoints.as_dict()
        self.qadapter = qadapter
        self.job_dir_list = []
        self.jobs = []
        self.job_ids = []
        self.handlers = []
        self.job_cmd = job_cmd
        self.n_atoms = 0
        self.turn_knobs = turn_knobs
        self.response_to_knobs = {}
        self.sorted_response_to_knobs = {}
        for k, v in turn_knobs.items():
            self.response_to_knobs[k] = {}
            self.sorted_response_to_knobs[k] = {}
        self.is_matrix = is_matrix
        self.Grid_type = Grid_type
        self.wait = wait
        self.cal_log = []
        self.mappings_override = mappings_override
        self.database = database
        self.magnetism = magnetism
        self.mag_init = mag_init
        self.solvation = solvation
        self.reuse = reuse
        self.reuse_incar = reuse_incar
        self.reuse_override = reuse_override
        self.reuse_paths = None  # list object communicated to instrument
        self.finer_kpoint = finer_kpoint
        self.functional = functional
        self.checkpoint_file = checkpoint_file
        if cal_logger:
            self.logger = cal_logger
        else:
            self.logger = logger

    def setup(self):
        """
        set up the jobs for the given turn_knobs dict
        is_matrix = True implies that the params in the dict are
        interrelated. Otherwise calcs corresponding to each dict key
        is independent
        """
        if self.is_matrix:
            self.setup_matrix_job()
        else:
            self._setup()

    def _setup(self, turn_knobs=None):
        """
        invoke the set up methods corresponding to the dict keys
        any key other than KPOINTS, VOLUME and POTCAR are treated
        as INCAR parameters

        Args:
            turn_knobs: knobs aka paramters to be tuned

        Note: poscar jobs setup through the VOLUME is only for
              backward compatibility, use POSCAR key in the
              turn_knobs to tune poscars
        """
        if turn_knobs is None:
            turn_knobs = self.turn_knobs
        if any(turn_knobs.values()):
            for k, v in turn_knobs.items():
                if k == 'KPOINTS' and v:
                    self.setup_kpoints_jobs(kpoints_list=v)
                elif k == 'VOLUME' and v:
                    self.setup_poscar_jobs(scale_list=v)
                elif k == 'POTCAR' and v:
                    self.setup_potcar_jobs(mappings=v, functional_list=None)
                elif k == 'POTCAR_functional' and v:
                    self.setup_potcar_jobs(mappings=None, functional_list=v)
                elif k == 'POSCAR' and v:
                    self.setup_poscar_jobs(poscar_list=v)
                else:
                    self.setup_incar_jobs(k, v)
        else:
            self.logger.warn('knobs not set, running a single job')
            self.add_job(name='single_job', job_dir=self.job_dir)

    def setup_matrix_job(self):
        """
        set up jobs where the dict keys are interrelated
        mind: its an ordered dict, the order in which the keys
        are specified determines the nested directory structure
        """
        orig_job_dir = self.job_dir
        job_dir = self.job_dir
        n_items = len(list(self.turn_knobs.items()))
        keys = list(self.turn_knobs.keys())
        self._setup(turn_knobs=dict([(keys[0],
                                      self.turn_knobs[keys[0]])]))
        self.recursive_jobs(n_items, keys, 0)
        # restore
        self.job_dir = orig_job_dir

    def recursive_jobs(self, n, keys, i):
        """
        recursively setup the jobs: used by setup_matrix_job

        Args:
            n: total number of knobs aka parameters to be tuned
            keys: list of knobs i.e parameter names
            i: ith knob

        """
        #### Testing ####
        # Orig
        # job_dir = self.job_dir + os.sep + self.key_to_name(keys[i])
        job_dir = '__'.join(
            [self.job_dir.split('/')[-1], self.key_to_name(keys[i])])
        #### Testing ####
        if i == n - 1 and i != 0:
            for val in self.turn_knobs[keys[i]]:
                ##
                ## self.job_dir = job_dir + os.sep + self.val_to_name(val)
                self.job_dir = '__'.join([job_dir, self.val_to_name(val)])
                self.logger.info(
                    'setting jobs in the directory: ' + self.job_dir)
                self._setup(turn_knobs=dict([(keys[i], [val])]))
                self.add_job(name=job_dir, job_dir=self.job_dir)
        else:
            for val in self.turn_knobs[keys[i]]:
                ##
                ## self.job_dir = job_dir + os.sep + self.val_to_name(val)
                self.job_dir = '__'.join([job_dir, self.val_to_name(val)])
                self.logger.info(
                    'setting jobs in the directory: ' + self.job_dir)
                self._setup(turn_knobs=dict([(keys[i], [val])]))
                self.recursive_jobs(n, keys, i + 1)

    def key_to_name(self, key):
        """
        convenient string mapping for the keys in the turn_knobs dict

        Args:
            key: key to the knob dict

        Returns:
            an appropriate string representation of the key so that
            the name doesnt clash with the filenames
        """
        if key == 'KPOINTS':
            return 'KPTS'
        elif key == 'POTCAR_map' or key == 'POTCAR_functional':
            return 'POT'
        elif key == 'POSCAR':
            return 'POS'
        else:
            return key

    def val_to_name(self, val):
        """
        convert a value to a string so that it can be used for naming
        the job directory
        the decimal points in floats are replaced with underscore
        character
        if the value is of type list, kpoint_to_name method is used
        since
        only kpoint values are expected to be of type list
        if the values is of type dict then potcar_to_name method is
        invoked

        Args:
            val: knob value to be converted into an appropriate string
                representation

        Returns:
            a string filename for the value
        """
        if isinstance(val, float):
            return re.sub('\.', '_', str(val))
        elif isinstance(val, list):
            return self.kpoint_to_name(val, 'M')
        elif isinstance(val, dict):
            return self.potcar_to_name(mapping=val)
        elif isinstance(val, Poscar):
            name = str(val.structure.composition.reduced_formula) \
                + '_' + str(int(val.structure.lattice.volume)) \
                + '_' + ''.join((val.comment).split())
            return name.replace('\\', '_').replace('(', '_').replace(')', '_')
        else:
            return str(val)

    def kpoint_to_name(self, kpoint, grid_type):
        """
        get a string representation for the given kpoint

        Args:
            kpoint: an iterable
            grid_type: grid_type used for the KPOINTS

        Returns:
            string representation for kpoint eg: Monkhorst Pack
            2 2 2 will be named 2x2x2
        """
        if grid_type == 'M' or grid_type == 'G':
            kpoint = [str(k).replace('.', '_') for k in kpoint]
            return 'x'.join(kpoint)
        else:
            return str(kpoint)

    def potcar_to_name(self, mapping=None, functional=None):
        """
        convert a symbol mapping and functional to a name that
        can be used for setting up the potcar jobs

         Args:
             mapping: example:- if mapping = {'Pt':'Pt_pv',
                 'Si':'Si_GW'} then the name will be PBE_Pt_pv_Si_GW
                  with self.functional="PBE"

        Returns:
            string
        """
        if mapping:
            l = [v for k, v in mapping.items()]
            return '_'.join(l)
        elif functional:
            return '_'.join(functional)
        else:
            return '_'.join(self.functional)

    def set_incar(self, param, val):
        """
        set the incar paramter, param = val
        """
        self.incar[param] = val

    def set_poscar(self, scale=None, poscar=None):
        """
        perturbs given structure by volume scaling factor
        or takes user defined variants of Poscar

        Args:
           scale : Volume Scaling parameter

           poscar : Poscar object of user defined structure

           set the poscar: volume scaled by the scale factor
        """
        if scale is not None:
            structure = Poscar.from_dict(self.poscar_orig).structure
            volume = structure.volume
            structure.scale_lattice(scale * volume)
            self.poscar = Poscar(structure)
        elif poscar is not None:
            self.poscar = poscar

    def set_potcar(self, mapping=None, functional='PBE'):
        """
        set the potcar: symbol to potcar type mapping
        """
        symbols = self.poscar.site_symbols
        mapped_symbols = []
        if mapping:
            for sym in symbols:
                mapped_symbols.append(mapping[sym])
        elif self.mappings_override:
            for sym in symbols:
                if sym in list(self.mappings_override.keys()):
                    mapped_symbols.append(self.mappings_override[sym])
                else:
                    mapped_symbols.append(sym)
        else:
            mapped_symbols = symbols
        if functional:
            func = functional
        else:
            func = self.functional
        self.potcar = Potcar(symbols=mapped_symbols,
                             functional=func)

    def set_kpoints(self, kpoint=None, poscar=None, ibzkpth=None):
        """
        set the kpoint
        """
        # useful to check if a poscar is supplied from setup_poscar_jobs (most often the case)
        # or this is a single poscar use case
        if not poscar:
            poscar = self.poscar

        # splitting into two if elif branches means fewer if statements to check on
        # a run

        # Most general method of setting the k-points for
        # different grid types
        # NOTE: requires that at least one k-points value be passed
        # as a turn - knobs list value
        # this is not true for values that may be caculated out of
        # a database
        # use this part only if this is a non-database run for example
        # for k-points calibration

        if not self.database:

            if self.Grid_type == 'M':
                self.kpoints = Kpoints.monkhorst_automatic(kpts=kpoint)
            elif self.Grid_type == 'A':
                self.kpoints = Kpoints.automatic(subdivisions=kpoint)
            elif self.Grid_type == 'G':
                self.kpoints = Kpoints.gamma_automatic(kpts=kpoint)
            elif self.Grid_type == '3D_vol':
                self.kpoints = Kpoints.automatic_density_by_vol(structure=poscar.structure,
                                                                kppvol=kpoint)
            elif self.Grid_type == 'bulk_bands_pbe':
                self.kpoints = Kpoints.automatic_linemode(divisions=kpoint,
                                                          ibz=HighSymmKpath(
                                                              poscar.structure))

            elif self.Grid_type == 'D':
                self.kpoints = Kpoints.automatic_density(structure=poscar.structure,kppa=kpoint)

            elif self.Grid_type == 'Finer_G_Mesh':
                # kpoint is the scaling factor and self.kpoints is the old kpoint mesh
                self.logger.info('Setting Finer G Mesh for {0} by scale {1}'.format(kpoint, self.finer_kpoint))
                self.kpoints = Kpoints.gamma_automatic(kpts = \
                   [i * self.finer_kpoint for i in kpoint])
                self.logger.info('Finished scaling operation of k-mesh')

        # applicable for database runs
        # future constructs or settinsg can be activated via a yaml file
        # database yaml file or better still the input deck from its speification
        # decides what combination of input calibrate constructor settings to use
        # one of them being the grid_type tag

        elif self.database == 'twod':

            # set of kpoints settings according to the 2D database profile
            # the actual settings of k-points density
            # will in future come from any database input file set

            if self.Grid_type == 'hse_bands_2D_prep':
                kpoint_dict = Kpoints.automatic_gamma_density(poscar.structure,
                                                              200).as_dict()
                kpoint_dict['kpoints'][0][2] = 1  # remove z kpoints
                self.kpoints = Kpoints.from_dict(kpoint_dict)

            elif self.Grid_type == 'hse_bands_2D':
                # can at most return the path to the correct kpoints file
                # needs kpoints to be written out in instrument in a different way
                # not using the Kpoints object
                self.kpoints = get_2D_hse_kpoints(poscar.structure, ibzkpth)

            elif self.Grid_type == 'bands_2D':
                kpoint_dict = Kpoints.automatic_linemode(divisions=20,
                                                         ibz=HighSymmKpath(poscar.structure)).as_dict()
                self.kpoints = Kpoints.from_dict(kpoint_dict)

            elif self.Grid_type == 'relax_2D':
                # general relaxation settings for 2D
                kpoint_dict = Kpoints.automatic_gamma_density(poscar.structure,
                                                              1000).as_dict()
                kpoint_dict['kpoints'][0][2] = 1
                self.kpoints = Kpoints.from_dict(kpoint_dict)

            elif self.Grid_type == 'relax_3D':
                # general relaxation settings for 3D
                kpoint_dict = Kpoints.automatic_gamma_density(
                    poscar.structure, 1000)
                self.kpoints = Kpoints.from_dict(kpoint_dict)

    def setup_incar_jobs(self, param, val_list):
        """
        set up incar jobs,, calls set_incar to set the value to param

        Args:
            param: Name of INCAR parameter
            val_list: List of values to vary for the param
        """

        if val_list != ['2D_default']:
            for val in val_list:
                self.logger.info('setting INCAR parameter ' + param + ' = '
                                 + str(val))
                self.set_incar(param, val)
                if not self.is_matrix:
                    job_dir = self.job_dir + os.sep + \
                        param + os.sep + self.val_to_name(val)
                    self.add_job(name=job_dir, job_dir=job_dir)
        else:
            self.logger.warn('incar list empty')

    def setup_kpoints_jobs(self, kpoints_list=None):
        """
        setup the kpoint jobs

        """
        if kpoints_list:
            for kpoint in kpoints_list:
                self.set_kpoints(kpoint)
                if not self.is_matrix:
                    job_dir = self.job_dir + os.sep + self.key_to_name(
                        'KPOINTS') \
                        + os.sep + self.kpoint_to_name(kpoint,
                                                       self.Grid_type)
                    self.add_job(name=job_dir, job_dir=job_dir)
        else:
            self.logger.warn('kpoints_list empty')

    def setup_poscar_jobs(self, scale_list=None, poscar_list=None):
        """
        for scaling the latice vectors of the original structure,
        scale_list is volume scaling factor list
        """
        if scale_list:
            for scale in scale_list:
                self.set_poscar(scale=scale)
                self.set_potcar()
                if not self.is_matrix:
                    job_dir = self.job_dir + os.sep + 'POS' + \
                        os.sep + 'VOLUME_' + str(scale)
                    self.add_job(name=job_dir, job_dir=job_dir)
        elif poscar_list:
            for pos in poscar_list:
                # if it is a twod_database run or any general standard database run,
                # the incar, kpoints and potcar follow a standard input set
                # which will be activated by the twod_database tag set to true
                # NOTE: this implementation means that the first turn_knobs tag
                # needs to be the poscar objects list
                # the database tag will be set to the name of the yaml file with the
                # standard input deck definition for that database
                # this incar dict provided as the init can be general format
                # based on the chosen functional, cutoff
                # so self.incar is a vdW incar for re-relaxation in vdW, gga for every
                # other calculation or LDA+U for LSDA+U calculations
                incar_dict = self.incar.as_dict()
                if self.reuse:
                    # if this is a true list minimally, ['CONTCAR']
                    # it is to be ensured that the poscar list is a
                    # list of paths as opposed to list of poscar objects by the turn knobs
                    # values
                    # Here pos is the path and r in each self.reuse is the name of the file(s)
                    # to be reused
                    # in a reuse calculation the following are possible:
                    # update incar (Solvation calculations) or reset incar (HSE calculations)
                    # reset kpoints file with IBZKPT
                    # copy a CHGCAR or WAVECAR or both perhaps
                    try:
                        # first setup of POSCAR initial, INCAR, KPOINTS
                        poscar = Poscar.from_file(pos + os.sep + 'CONTCAR')
                        self.logger.info('Read previous relaxed CONTCAR file from {}'.
                                         format(pos))
                        # check if it is KPOINTS altering job like HSE
                        if self.Grid_type == 'hse_bands_2D_prep':
                            # HSE prep calcualtions
                            # reset the INCAR file with a magmom only if exists
                            try:
                                incar_dict = {
                                    'MAGMOM': get_magmom_string(poscar)}
                            except:
                                incar_dict = {}
                            incar_dict = get_2D_incar_hse_prep(incar_dict)
                            self.set_kpoints(poscar=poscar)
                            self.logger.info(
                                'updated input set for HSE 2D prep calcaultion')

                        elif self.Grid_type == 'hse_bands_2D':
                            # HSE calculation
                            # reset the incar and kpoints file builds
                            # on the preceding calculations (prep calculation)
                            # IBZKPT
                            try:
                                incar_dict = {
                                    'MAGMOM': get_magmom_string(poscar)}
                            except:
                                incar_dict = {}
                            incar_dict = get_2D_incar_hse(incar_dict)
                            self.set_kpoints(poscar=poscar,
                                             ibzkpth=pos + os.sep + 'IBZKPT')
                            self.logger.info('updated input set for HSE calcaultion\
                                             using IBZKPT from {0}'.format(pos + os.sep + 'IBZKPT'))

                        elif self.Grid_type == 'hse_bands':
                            # general HSE bands
                            pass

                        elif self.Grid_type == 'Finer_G_Mesh':
                            self.logger.info('updating to Finer G Mesh')
                            kpoint = Kpoints.from_file(pos+os.sep+'KPOINTS')
                            self.set_kpoints(kpoint=kpoint.kpts[0])

                        else:
                            # use the same kpoints file and build from the old
                            # incar
                            self.kpoints = Kpoints.from_file(
                                pos + os.sep + 'KPOINTS')
                            # decide on how to use incar, use same one or
                            # update or afresh
                            if self.reuse_incar == 'old':
                                incar_dict = Incar.from_file(
                                    pos + os.sep + 'INCAR').as_dict()
                            elif self.reuse_incar == 'update':
                                # way to go for cutoff updates, convergence, etc.
                                # but retain the old functional
                                incar_dict.update(Incar.from_file(pos + os.sep + 'INCAR').
                                                  as_dict())
                            else:
                                # use a fresh incar as specified by the init
                                # way to go for example for LDAU or other
                                # major removals done to INCAR
                                # but always retain the MAGMOM if present
                                old_incar_dict = Incar.from_file(
                                    pos + os.sep + 'INCAR').as_dict()
                                if 'MAGMOM' in old_incar_dict.keys():
                                    incar_dict['MAGMOM'] = old_incar_dict[
                                        'MAGMOM']
                                else:
                                    incar_dict = incar_dict

                        if isinstance(self.reuse, list):
                            reuse_paths = [
                                pos + os.sep + r for r in self.reuse]
                            self.reuse_paths = reuse_paths
                        # Magnetism use cases, updates to be made to the INCAR (MAE)
                        # and poscar (AFM)
                        # MAE and AFM

                        if self.magnetism == 'MAE':

                            # remove vdW tags for MAE calculations
                            vdW_tags = ('GGA', 'AGGAC', 'LUSE_VDW',
                                        'PARAM1', 'PARAM2')
                            for key in vdW_tags:
                                if key in incar_dict:
                                    del incar_dict[key]

                            self.logger.info(
                                'updating input set for MAE calculation')
                            self.mag_init = Outcar(
                                pos + os.sep + 'OUTCAR').total_mag
                            nbands = 2 * \
                                Vasprun(pos + os.sep +
                                        'vasprun.xml').parameters['NBANDS']
                            # u_value = Vasprun(pos+os.sep+'vasprun.xml').incar['LDAUU']
                            # u_value = 4.0
                            self.logger.info(
                                "updating mag mom with value {0}".format(self.mag_init))
                            self.logger.info(
                                "updating NBANDS with {0}".format(nbands))
                            incar_dict.update({'NBANDS': nbands,
                                               'LSORBIT': True,
                                               'EDIFF': 1e-08,
                                               'ICHARG': 11,
                                               'LMAXMIX': 4,
                                               'LCHARG': False,
                                               'ISYM': 0,
                                               'NSW': 0,
                                               'ISPIN': 2,
                                               'IBRION': -1,
                                               'LORBIT': 11,
                                               'MAGMOM': get_magmom_mae(poscar, self.mag_init)
                                               })
                            # incar_dict.update({'LDAUU': u_value})

                        elif self.magnetism == 'AFM':
                            self.logger.info(
                                'updating INCAR and POSCAR for AFM calculation')
                            afm, poscar = get_magmom_afm(poscar, self.database)
                            incar_dict.update({'MAGMOM': afm})
                    except:
                        # check what to do if the previous calculation being reused is not
                        # actuall done .. system exit or adopt a user override
                        # with POSCAR
                        self.logger.warn(
                            'Empty relaxed CONTCAR file .. Probably job not done')
                        if not self.reuse_override:
                            self.logger.warn(
                                'You can set reuse_override to continue with POSCAR file, exiting now ..')
                            sys.exit(0)
                        else:
                            self.logger.info('Using old Poscar for rerun')
                            poscar = Poscar.from_file(pos + os.sep + 'POSCAR')

                # case for non - reuse
                else:
                    poscar = pos
                    # temporary: magnetism only set if twod flag is activated
                    if self.database == 'twod':
                        incar_dict.update(
                            {'MAGMOM': get_magmom_string(poscar)})
                        self.set_kpoints(poscar=poscar)
                    self.incar = Incar.from_dict(incar_dict)

                self.set_poscar(poscar=poscar)
                self.set_potcar()
                if not self.is_matrix:
                    job_dir = self.job_dir + os.sep + 'POS' + \
                        os.sep + self.val_to_name(poscar)
                    self.add_job(name=job_dir, job_dir=job_dir)

    def setup_potcar_jobs(self, mappings, functional_list):
        """
        take a list of symbol mappings and setup the potcar jobs
        """
        if functional_list:
            for func in functional_list:
                self.set_potcar(functional=func)
                if not self.is_matrix:
                    job_dir = self.job_dir + os.sep \
                        + self.key_to_name('POTCAR') \
                        + os.sep + self.potcar_to_name(func)
                    self.add_job(name=job_dir, job_dir=job_dir)

        elif mappings:
            for mapping in mappings:
                self.set_potcar(mapping)
                if not self.is_matrix:
                    job_dir = self.job_dir + os.sep \
                        + self.key_to_name('POTCAR') \
                        + os.sep + self.potcar_to_name(mapping)
                    self.add_job(name=job_dir, job_dir=job_dir)

    def add_job(self, name='noname', job_dir='.'):
        """
        add a single job using the current incar, poscar, potcar and
        kpoints
        """
        vis = MPINTVaspInputSet(name, self.incar, self.poscar,
                                self.potcar, self.kpoints,
                                self.qadapter, vis_logger=self.logger,
                                reuse_path=self.reuse_paths)
        # the job command can be overrridden in the run method
        job = MPINTVaspJob(self.job_cmd, name=name, final=True,
                           parent_job_dir=self.parent_job_dir,
                           job_dir=job_dir, vis=vis, wait=self.wait,
                           vjob_logger=self.logger)
        self.job_dir_list.append(os.path.abspath(job_dir))
        self.jobs.append(job)

    def run(self, job_cmd=None):
        """
        run the vasp jobs through custodian
        if the job list is empty,
        run a single job with the initial input set
        """
        for j in self.jobs:
            if job_cmd is not None:
                j.job_cmd = job_cmd
            else:
                j.job_cmd = self.job_cmd
        c_params = {'jobs': [j.as_dict() for j in self.jobs],
                    'handlers': [h.as_dict() for h in self.handlers],
                    'max_errors': 5}
        c = Custodian(self.handlers, self.jobs, max_errors=5)
        c.run()
        for j in self.jobs:
            self.cal_log.append({"job": j.as_dict(),
                                 'job_id': j.job_id,
                                 "corrections": [],
                                 'final_energy': None})
            self.job_ids.append(j.job_id)
        if self.checkpoint_file:
            dumpfn(self.cal_log, self.checkpoint_file,
                   cls=MontyEncoder, indent=4)
        else:
            dumpfn(self.cal_log, Calibrate.LOG_FILE, cls=MontyEncoder,
                   indent=4)

    def as_dict(self):
        qadapter = None
        system = None
        if self.qadapter:
            qadapter = self.qadapter.to_dict()
        if self.system is not None:
            system = self.system
        d = dict(incar=self.incar.as_dict(),
                 poscar=self.poscar.as_dict(),
                 potcar=self.potcar.as_dict(),
                 kpoints=self.kpoints.as_dict(),
                 system=system, is_matrix=self.is_matrix,
                 Grid_type=self.Grid_type,
                 parent_job_dir=self.parent_job_dir,
                 job_dir=self.job_dir,
                 qadapter=qadapter, job_cmd=self.job_cmd,
                 wait=self.wait,
                 turn_knobs=self.turn_knobs,
                 job_dir_list=self.job_dir_list,
                 job_ids=self.job_ids)
        d["@module"] = self.__class__.__module__
        d["@class"] = self.__class__.__name__
        # d['calibrate'] = self.__class__.__name__
        return d

    @classmethod
    def from_dict(cls, d):
        incar = Incar.from_dict(d["incar"])
        poscar = Poscar.from_dict(d["poscar"])
        potcar = Potcar.from_dict(d["potcar"])
        kpoints = Kpoints.from_dict(d["kpoints"])
        cal = Calibrate(incar, poscar, potcar, kpoints,
                        system=d["system"], is_matrix=d["is_matrix"],
                        Grid_type=d["Grid_type"],
                        parent_job_dir=d["parent_job_dir"],
                        job_dir=d["job_dir"], qadapter=d.get("qadapter"),
                        job_cmd=d["job_cmd"], wait=d["wait"],
                        turn_knobs=d["turn_knobs"])
        cal.job_dir_list = d["job_dir_list"]
        cal.job_ids = d["job_ids"]
        return cal