Ejemplo n.º 1
0
    def from_symbol_and_functional(symbol, functional=None):
        if functional is None:
            functional = SETTINGS.get("PMG_DEFAULT_FUNCTIONAL", "PBE")
        funcdir = PotcarSingle.functional_dir[functional]

        if not os.path.isdir(os.path.join(
                SETTINGS.get("PMG_VASP_PSP_DIR"), funcdir)):
            functional_dir = {"LDA_US": "pot",
                              "PW91_US": "pot_GGA", 
                              "LDA": "potpaw", 
                              "PW91": "potpaw_GGA", 
                              "LDA_52": "potpaw_LDA.52",
                              "LDA_54": "potpaw_LDA.54",
                              "PBE": "potpaw_PBE", 
                              "PBE_52": "potpaw_PBE.52",
                              "PBE_54": "potpaw_PBE.54",
                              }
            funcdir = functional_dir[functional]

        d = SETTINGS.get("PMG_VASP_PSP_DIR")
        if d is None:
            raise ValueError("No POTCAR directory found. Please set "
                             "the VASP_PSP_DIR environment variable")

        paths_to_try = [os.path.join(d, funcdir, "POTCAR.{}".format(symbol)),
                        os.path.join(d, funcdir, symbol, "POTCAR.Z"),
                        os.path.join(d, funcdir, symbol, "POTCAR")]
        for p in paths_to_try:
            p = os.path.expanduser(p)
            p = zpath(p)
            if os.path.exists(p):
                return PotcarSingleMod.from_file(p)
        raise IOError("You do not have the right POTCAR with functional " +
                      "{} and label {} in your VASP_PSP_DIR".format(functional,
                                                                    symbol))
Ejemplo n.º 2
0
    def __init__(self, package_options=None):
        if SETTINGS.get("PMG_MAPI_KEY", "") != "": 
            self.materials_project_configuration = SETTINGS.get("PMG_MAPI_KEY", "")
        else:
            self.materials_project_configuration = None


        if package_options is None:
            self.package_options = self.DEFAULT_PACKAGE_OPTIONS
        else:
            self.package_options = package_options
Ejemplo n.º 3
0
    def __init__(self, package_options=None):
        if SETTINGS.get("PMG_MAPI_KEY", "") != "":
            self.materials_project_configuration = SETTINGS.get(
                "PMG_MAPI_KEY", "")
        else:
            self.materials_project_configuration = None

        if package_options is None:
            self.package_options = self.DEFAULT_PACKAGE_OPTIONS
        else:
            self.package_options = package_options
Ejemplo n.º 4
0
    def setUp(self, lpad=True):
        """
        Create scratch directory(removes the old one if there is one) and change to it.
        Also initialize launchpad.
        """
        if not SETTINGS.get("PMG_VASP_PSP_DIR"):
            SETTINGS["PMG_VASP_PSP_DIR"] = os.path.abspath(
                os.path.join(MODULE_DIR, "..", "vasp", "test_files"))
            print(
                'This system is not set up to run VASP jobs. '
                'Please set PMG_VASP_PSP_DIR variable in your ~/.pmgrc.yaml file.'
            )

        self.scratch_dir = os.path.join(MODULE_DIR, "scratch")
        if os.path.exists(self.scratch_dir):
            shutil.rmtree(self.scratch_dir)
        os.makedirs(self.scratch_dir)
        os.chdir(self.scratch_dir)
        if lpad:
            try:
                self.lp = LaunchPad.from_file(
                    os.path.join(DB_DIR, "my_launchpad.yaml"))
                self.lp.reset("", require_password=False)
            except:
                raise unittest.SkipTest(
                    'Cannot connect to MongoDB! Is the database server running? '
                    'Are the credentials correct?')
Ejemplo n.º 5
0
    def test_chemenv_config(self):
        with ScratchDir("."):
            config = ChemEnvConfig()

            if SETTINGS.get("PMG_MAPI_KEY", "") != "":
                 self.assertTrue(config.has_materials_project_access)
            else:
                 self.assertFalse(config.has_materials_project_access)

            package_options = ChemEnvConfig.DEFAULT_PACKAGE_OPTIONS
            package_options['default_max_distance_factor'] = 1.8

            config = ChemEnvConfig(package_options=package_options)

            self.assertEqual(config.package_options_description(),
                             'Package options :\n'
                             ' - Maximum distance factor : 1.8000\n'
                             ' - Default strategy is "SimplestChemenvStrategy" :\n'
                             '    Simplest ChemenvStrategy using fixed angle and distance parameters \n'
                             '    for the definition of neighbors in the Voronoi approach. \n'
                             '    The coordination environment is then given as the one with the \n'
                             '    lowest continuous symmetry measure.\n'
                             '   with options :\n'
                             '     - distance_cutoff : 1.4\n'
                             '     - angle_cutoff : 0.3\n'
                             '     - additional_condition : 1\n'
                             '     - continuous_symmetry_measure_cutoff : 10.0\n')

            config.save(root_dir='tmp_dir')

            config = config.auto_load(root_dir='tmp_dir')

            self.assertEqual(config.package_options, package_options)
Ejemplo n.º 6
0
class SettingsTestCase(unittest.TestCase):

    # def test_something(self):
    #     SETTINGS = _load_pmg_settings()
    #     if os.path.exists(SETTINGS_FILE):
    #         with open(SETTINGS_FILE, "rt") as f:
    #             d = yaml.safe_load(f)
    #             for k, v in d.items():
    #                 self.assertEqual(v, SETTINGS[k])
    #     else:
    #         for k, v in SETTINGS.items():
    #             self.assertEqual(v, os.environ.get(k))

    @unittest.skipIf(not SETTINGS.get("PMG_MAPI_KEY"),
                     "PMG_MAPI_KEY environment variable not set.")
    def test_get_structure_from_mp(self):
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            self.assertEqual(get_structure_from_mp("Li2O").formula, "Li2 O1")
            self.assertRaises(ValueError, get_structure_from_mp, "LiNaKCs")

    def test_loadfn(self):
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            obj = loadfn(os.path.join(test_dir, "Li2O.cif"))
            self.assertIsInstance(obj, Structure)
            obj = loadfn(os.path.join(test_dir, "POSCAR"))
            self.assertIsInstance(obj, Structure)
            obj = loadfn(os.path.join(test_dir, "LiFePO4.vasp"))
            self.assertIsInstance(obj, Structure)
            obj = loadfn(os.path.join(test_dir, "vasprun.xml"))
            self.assertIsInstance(obj, Vasprun)
Ejemplo n.º 7
0
 def test_get(self):
     mp = MaterialsProject(SETTINGS.get("PMG_MAPI_KEY"))
     features = ["pretty_formula", "band_gap", "formation_energy_per_atom", "e_above_hull", "elasticity.K_VRH"]
     df = mp.get(criteria={"nelements": 1}, properties=features)
     assert df.shape[0] > 700
     assert df.shape[1] == len(features)
     assert set(df.columns) == set(features)
Ejemplo n.º 8
0
def set_PMG_VASP_PSP_DIR(abspath):
    """
    一. abspath 文件夹产生方式为:

    # 初始potcar, 位置为 EXTRACTED_VASP_POTCAR (初始poscar数据源在华为盘,百度盘,240)
    # 1.`pmg config - p <EXTRACTED_VASP_POTCAR>  ../../poscar_pmg  ` 产生 poscar_pmg 文件夹。
    # 2.`pmg config --add PMG_VASP_PSP_DIR <MY_PSP> ` 设置 poscar_pmg 文件夹。

    二. 如果直接有 poscar_pmg 文件夹,可使用此函数设置 poscar_pmg 路径,也可以直接用第二步。
    """
    d = SETTINGS.get("PMG_VASP_PSP_DIR")
    SETTINGS_FILE = os.path.join(os.path.expanduser("~"), ".pmgrc.yaml")
    if d is None:
        if os.path.isfile(SETTINGS_FILE):
            with open(SETTINGS_FILE, "a+") as f:
                f.write("\nPMG_VASP_PSP_DIR: {}}".format(abspath))
    else:
        if os.path.isfile(SETTINGS_FILE):
            with open(SETTINGS_FILE, "r") as f:
                lines = f.readlines()
            lines = [i for i in lines if "VASP_PSP_DIR" not in i]
            with open(SETTINGS_FILE, "w+") as f:
                f.writelines(lines)
                f.write("\nPMG_VASP_PSP_DIR: {}".format(abspath))
        print("PMG_VASP_PSP_DIR is refreshed to `{}`".format(abspath))
Ejemplo n.º 9
0
 def __init__(self, api_key=None,
              endpoint="https://www.materialsproject.org/rest/v2"):
     if api_key is not None:
         self.api_key = api_key
     else:
         self.api_key = SETTINGS.get("MAPI_KEY", "")
     self.preamble = endpoint
     self.session = requests.Session()
     self.session.headers = {"x-api-key": self.api_key}
Ejemplo n.º 10
0
 def test_something(self):
     if SETTINGS_FILE.exists():
         with SETTINGS_FILE.open("rt") as f:
             d = yaml.load(f)
             for k, v in d.items():
                 self.assertEqual(v, SETTINGS[k])
     else:
         for k, v in SETTINGS.items():
             self.assertEqual(v, os.environ.get(k))
Ejemplo n.º 11
0
def check_PMG_VASP_PSP_DIR():
    d = SETTINGS.get("PMG_VASP_PSP_DIR")
    if d is None:
        warnings.warn(
            "No POTCAR found. Please set the PMG_VASP_PSP_DIR environment in .pmgrc.yaml "
            "by `set_PMG_VASP_PSP_DIR function` or manually", ValueError)
        return False
    else:
        return True
Ejemplo n.º 12
0
 def test_something(self):
     SETTINGS = _load_pmg_settings()
     if os.path.exists(SETTINGS_FILE):
         with open(SETTINGS_FILE, "rt") as f:
             d = yaml.safe_load(f)
             for k, v in d.items():
                 self.assertEqual(v, SETTINGS[k])
     else:
         for k, v in SETTINGS.items():
             self.assertEqual(v, os.environ.get(k))
Ejemplo n.º 13
0
 def __init__(self, api_key=None,
              endpoint="https://www.materialsproject.org/rest/v2"):
     if api_key is not None:
         self.api_key = api_key
     else:
         self.api_key = SETTINGS.get("PMG_MAPI_KEY", "")
     self.preamble = endpoint
     import requests
     self.session = requests.Session()
     self.session.headers = {"x-api-key": self.api_key}
Ejemplo n.º 14
0
 def test_something(self):
     SETTINGS = _load_pmg_settings()
     if os.path.exists(SETTINGS_FILE):
         with open(SETTINGS_FILE, "rt") as f:
             d = yaml.safe_load(f)
             for k, v in d.items():
                 self.assertEqual(v, SETTINGS[k])
     else:
         for k, v in SETTINGS.items():
             self.assertEqual(v, os.environ.get(k))
    def setUpClass(cls):
        # TODO: update this for the latest pymatgen...
        if not SETTINGS.get("VASP_PSP_DIR"):
            SETTINGS["VASP_PSP_DIR"] = os.path.join(module_dir, "reference_files")
            print('This system is not set up to run VASP jobs. '
                  'Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file.')

        cls.struct_si = PymatgenTest.get_structure("Si")

        cls.scratch_dir = os.path.join(module_dir, "scratch")
Ejemplo n.º 16
0
    def setUpClass(cls):
        if not SETTINGS.get("VASP_PSP_DIR"):
            SETTINGS["VASP_PSP_DIR"] = os.path.join(module_dir, "..", "..", "tests", "reference_files")
            print('This system is not set up to run VASP jobs. '
                  'Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file.')

        cls.struct_si = PymatgenTest.get_structure("Si")
        cls.scratch_dir = os.path.join(module_dir, "scratch")
        cls.raman_config = {"modes": [0, 1], "step_size": 0.005,
                            "vasp_cmd": ">>vasp_cmd<<", "db_file": ">>db_file<<"}
        cls.wf = wf_raman_spectra(cls.struct_si, cls.raman_config)
    def setUpClass(cls):
        if not SETTINGS.get("VASP_PSP_DIR"):
            SETTINGS["VASP_PSP_DIR"] = os.path.join(module_dir, "..", "..", "tests", "reference_files")
            print(
                "This system is not set up to run VASP jobs. "
                "Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file."
            )

        cls.struct_si = PymatgenTest.get_structure("Si")
        cls.scratch_dir = os.path.join(module_dir, "scratch")
        cls.raman_config = {"modes": [0, 1], "step_size": 0.005, "vasp_cmd": ">>vasp_cmd<<", "db_file": ">>db_file<<"}
        cls.wf = wf_raman_spectra(cls.struct_si, cls.raman_config)
Ejemplo n.º 18
0
    def setUpClass(cls):
        # TODO: update this for the latest pymatgen...
        if not SETTINGS.get("VASP_PSP_DIR"):
            SETTINGS["VASP_PSP_DIR"] = os.path.join(module_dir,
                                                    "reference_files")
            print(
                'This system is not set up to run VASP jobs. '
                'Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file.')

        cls.struct_si = PymatgenTest.get_structure("Si")

        cls.scratch_dir = os.path.join(module_dir, "scratch")
    def setUpClass(cls):
        if not SETTINGS.get("VASP_PSP_DIR"):
            SETTINGS["VASP_PSP_DIR"] = os.path.join(module_dir, "..", "..", "tests", "reference_files")
            print('This system is not set up to run VASP jobs. '
                  'Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file.')

        cls.struct_si = SpacegroupAnalyzer(
                PymatgenTest.get_structure("Si")).get_conventional_standard_structure()
        cls.scratch_dir = os.path.join(module_dir, "scratch")
        cls.elastic_config = {"norm_deformations":[0.01],
                              "shear_deformations":[0.03],
                              "vasp_cmd": ">>vasp_cmd<<", "db_file": ">>db_file<<"}
        cls.wf = wf_elastic_constant(cls.struct_si, cls.elastic_config)
Ejemplo n.º 20
0
    def setUpClass(cls):
        if not SETTINGS.get("VASP_PSP_DIR"):
            SETTINGS["VASP_PSP_DIR"] = os.path.join(module_dir, "reference_files")
            print(
                "This system is not set up to run VASP jobs. "
                "Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file."
            )

        cls.struct_si = PymatgenTest.get_structure("Si")

        cls.ref_incar = Incar.from_file(os.path.join(module_dir, "reference_files", "setup_test", "INCAR"))
        cls.ref_poscar = Poscar.from_file(os.path.join(module_dir, "reference_files", "setup_test", "POSCAR"))
        cls.ref_potcar = Potcar.from_file(os.path.join(module_dir, "reference_files", "setup_test", "POTCAR"))
        cls.ref_kpoints = Kpoints.from_file(os.path.join(module_dir, "reference_files", "setup_test", "KPOINTS"))
        cls.ref_incar_preserve = Incar.from_file(os.path.join(module_dir, "reference_files", "preserve_incar", "INCAR"))
Ejemplo n.º 21
0
    def setUpClass(cls):
        if not SETTINGS.get("VASP_PSP_DIR"):
            raise unittest.SkipTest(
                "This system is not set up to run VASP jobs. "
                "Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file."
            )

        coords = [[0, 0, 0], [0.75, 0.5, 0.75]]
        lattice = Lattice(
            [[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]]
        )
        cls.struct_si = IStructure(lattice, ["Si"] * 2, coords)

        cls.ref_incar = Incar.from_file(os.path.join(module_dir, "reference_files", "setup_test", "INCAR"))
        cls.ref_poscar = Poscar.from_file(os.path.join(module_dir, "reference_files", "setup_test", "POSCAR"))
        cls.ref_potcar = Potcar.from_file(os.path.join(module_dir, "reference_files", "setup_test", "POTCAR"))
        cls.ref_kpoints = Kpoints.from_file(os.path.join(module_dir, "reference_files", "setup_test", "KPOINTS"))
Ejemplo n.º 22
0
 def __init__(self, api_key=None,
              endpoint="https://www.materialsproject.org/rest/v2"):
     if api_key is not None:
         self.api_key = api_key
     else:
         self.api_key = SETTINGS.get("PMG_MAPI_KEY", "")
     self.preamble = endpoint
     import requests
     try:
         from pybtex import __version__
     except ImportError:
         warnings.warn("If you query for structure data encoded using MP's "
                       "Structure Notation Language (SNL) format and you use "
                       "`mp_decode=True` (the default) for MPRester queries, "
                       "you should install dependencies via "
                       "`pip install pymatgen[matproj.snl]`.")
     self.session = requests.Session()
     self.session.headers = {"x-api-key": self.api_key}
Ejemplo n.º 23
0
def index(request):
    ctx = RequestContext(request)
    if request.user.is_authenticated():
        from pymatgen import SETTINGS
        API_KEY = SETTINGS.get(
            "PMG_MAPI_KEY", request.user.api_key)  # jupyterhub vs alpha page
        with MPResterBase(API_KEY) as mpr:  # falls back on MAPI endpoint
            try:
                criteria = {"snl.about.authors.email": "*****@*****.**"}
                properties = [
                    "task_id", "pretty_formula", "spacegroup.symbol",
                    "formation_energy_per_atom", "e_above_hull", "band_gap",
                    "nsites", "density", "volume"
                ]
                payload = {
                    "criteria": json.dumps(criteria),
                    "properties": json.dumps(properties)
                }
                docs = mpr._make_request("/query",
                                         payload=payload,
                                         method="POST")
                if not docs:
                    raise Exception(
                        'No contributions found for Defect Genome PCFC Materials!'
                    )

                columns = [
                    'MP Id', 'Formula', 'Spacegroup', 'Formation Energy (eV)',
                    'E above Hull (eV)', 'Band Gap (eV)', 'Nsites',
                    'Density (gm/cc)', 'Volume'
                ]
                df = DataFrame(columns=columns)
                for doc in docs:
                    row = dict(
                        (columns[i], doc[k]) for i, k in enumerate(properties))
                    df = df.append(row, ignore_index=True)

                table = render_dataframe(df, webapp=True)
            except Exception as ex:
                ctx.update({'alert': str(ex)})
    else:
        ctx.update({'alert': 'Please log in!'})
    return render_to_response(
        "defect_genome_pcfc_materials_explorer_index.html", locals(), ctx)
Ejemplo n.º 24
0
class SettingsTestCase(unittest.TestCase):
    def test_something(self):
        SETTINGS = _load_pmg_settings()
        if os.path.exists(SETTINGS_FILE):
            with open(SETTINGS_FILE, "rt") as f:
                d = yaml.safe_load(f)
                for k, v in d.items():
                    self.assertEqual(v, SETTINGS[k])
        else:
            for k, v in SETTINGS.items():
                self.assertEqual(v, os.environ.get(k))

    @unittest.skipIf(not SETTINGS.get("PMG_MAPI_KEY"),
                     "PMG_MAPI_KEY environment variable not set.")
    def test_get_structure_from_mp(self):
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            self.assertEqual(get_structure_from_mp("Li2O").formula, "Li2 O1")
            self.assertRaises(ValueError, get_structure_from_mp, "LiNaKCs")
Ejemplo n.º 25
0
 def __init__(self, api_key=None,
              endpoint="https://www.materialsproject.org/rest/v2"):
     if api_key is not None:
         self.api_key = api_key
     else:
         self.api_key = SETTINGS.get("PMG_MAPI_KEY", "")
     self.preamble = endpoint
     import requests
     if sys.version_info[0] < 3:
         try:
             from pybtex import __version__
         except ImportError:
             warnings.warn("If you query for structure data encoded using MP's "
                         "Structure Notation Language (SNL) format and you use "
                         "`mp_decode=True` (the default) for MPRester queries, "
                         "you should install dependencies via "
                         "`pip install pymatgen[matproj.snl]`.")
     self.session = requests.Session()
     self.session.headers = {"x-api-key": self.api_key}
Ejemplo n.º 26
0
def get_mprester(api_key=None, endpoint=None):
    """
    Args:
        api_key (str): A String API key for accessing the MaterialsProject
            REST interface. Please apply on the Materials Project website for one.
            If this is None, the code will check if there is a `PMG_MAPI_KEY` in
            your .pmgrc.yaml. If so, it will use that environment
            This makes easier for heavy users to simply add
            this environment variable to their setups and MPRester can
            then be called without any arguments.
        endpoint (str): Url of endpoint to access the MaterialsProject REST interface.
            Defaults to the standard Materials Project REST address, but
            can be changed to other urls implementing a similar interface.
    """
    if api_key is None:
        api_key = SETTINGS.get("PMG_MAPI_KEY")
        if api_key is None:
            raise RuntimeError("Cannot find PMG_MAPI_KEY in pymatgen settings. Add it to $HOME/.pmgrc.yaml")

    if endpoint is None: endpoint = MP_DEFAULT_ENDPOINT
    return MyMPRester(api_key=api_key, endpoint=endpoint)
Ejemplo n.º 27
0
def get_mprester(api_key=None, endpoint=None):
    """
    Args:
        api_key (str): A String API key for accessing the MaterialsProject
            REST interface. Please apply on the Materials Project website for one.
            If this is None, the code will check if there is a `PMG_MAPI_KEY` in
            your .pmgrc.yaml. If so, it will use that environment
            This makes easier for heavy users to simply add
            this environment variable to their setups and MPRester can
            then be called without any arguments.
        endpoint (str): Url of endpoint to access the MaterialsProject REST interface.
            Defaults to the standard Materials Project REST address, but
            can be changed to other urls implementing a similar interface.
    """
    if api_key is None:
        api_key = SETTINGS.get("PMG_MAPI_KEY")
        if api_key is None:
            raise RuntimeError("Cannot find PMG_MAPI_KEY in pymatgen settings. Add it to $HOME/.pmgrc.yaml")

    if endpoint is None: endpoint = MP_DEFAULT_ENDPOINT
    return MyMPRester(api_key=api_key, endpoint=endpoint)
Ejemplo n.º 28
0
def get_aux_basis(basis_type, default_basis_type='cFIT'):
    """
    Get auxiliary basis info for a list of species.

    Args:
        basis_type (dict): dict of auxiliary basis sets to use. i.e:
            basis_type = {'Si': 'cFIT', 'O': 'cpFIT'}. Basis type needs to
            exist for that species.

            Basis types:
                FIT
                cFIT
                pFIT
                cpFIT
                GTH-def2
                aug-{FIT,cFIT,pFIT,cpFIT, GTH-def2}

        default_basis_type (str) default basis type if n

    """
    default_basis_type = default_basis_type or SETTINGS.get(
        "PMG_CP2K_DEFAULT_AUX_BASIS_TYPE")
    basis_type = {
        k: basis_type[k] if basis_type[k] else default_basis_type
        for k in basis_type
    }
    basis = {k: {} for k in basis_type}
    aux_bases = loadfn(os.path.join(MODULE_DIR, 'aux_basis.yaml'))
    for k in basis_type:
        for i in aux_bases[k]:
            if i.startswith(basis_type[k]):
                basis[k] = i
                break
    for k in basis:
        if not basis[k]:
            if aux_bases[k]:
                basis[k] = aux_bases[k][0]
            else:
                raise LookupError("NO BASIS OF THAT TYPE")
    return basis
Ejemplo n.º 29
0
    def setUp(self, lpad=True):
        """
        Create scratch directory(removes the old one if there is one) and change to it.
        Also initialize launchpad.
        """
        if not SETTINGS.get("PMG_VASP_PSP_DIR"):
            SETTINGS["PMG_VASP_PSP_DIR"] = os.path.abspath(os.path.join(MODULE_DIR, "..", "vasp", "test_files"))
            print('This system is not set up to run VASP jobs. '
                  'Please set PMG_VASP_PSP_DIR variable in your ~/.pmgrc.yaml file.')

        self.scratch_dir = os.path.join(MODULE_DIR, "scratch")
        if os.path.exists(self.scratch_dir):
            shutil.rmtree(self.scratch_dir)
        os.makedirs(self.scratch_dir)
        os.chdir(self.scratch_dir)
        if lpad:
            try:
                self.lp = LaunchPad.from_file(os.path.join(DB_DIR, "my_launchpad.yaml"))
                self.lp.reset("", require_password=False)
            except:
                raise unittest.SkipTest('Cannot connect to MongoDB! Is the database server running? '
                                        'Are the credentials correct?')
Ejemplo n.º 30
0
    def setUpClass(cls):
        if not SETTINGS.get("VASP_PSP_DIR"):
            raise unittest.SkipTest(
                'This system is not set up to run VASP jobs. '
                'Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file.')

        coords = [[0, 0, 0], [0.75, 0.5, 0.75]]
        lattice = Lattice([[3.8401979337, 0.00, 0.00],
                           [1.9200989668, 3.3257101909, 0.00],
                           [0.00, -2.2171384943, 3.1355090603]])
        cls.struct_si = IStructure(lattice, ["Si"] * 2, coords)

        cls.ref_incar = Incar.from_file(
            os.path.join(module_dir, "reference_files", "setup_test", "INCAR"))
        cls.ref_poscar = Poscar.from_file(
            os.path.join(module_dir, "reference_files", "setup_test",
                         "POSCAR"))
        cls.ref_potcar = Potcar.from_file(
            os.path.join(module_dir, "reference_files", "setup_test",
                         "POTCAR"))
        cls.ref_kpoints = Kpoints.from_file(
            os.path.join(module_dir, "reference_files", "setup_test",
                         "KPOINTS"))
Ejemplo n.º 31
0
    def setUpClass(cls):
        if not SETTINGS.get("VASP_PSP_DIR"):
            SETTINGS["VASP_PSP_DIR"] = os.path.join(module_dir,
                                                    "reference_files")
            print(
                'This system is not set up to run VASP jobs. '
                'Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file.')

        cls.struct_si = PymatgenTest.get_structure("Si")

        cls.ref_incar = Incar.from_file(
            os.path.join(module_dir, "reference_files", "setup_test", "INCAR"))
        cls.ref_poscar = Poscar.from_file(
            os.path.join(module_dir, "reference_files", "setup_test",
                         "POSCAR"))
        cls.ref_potcar = Potcar.from_file(
            os.path.join(module_dir, "reference_files", "setup_test",
                         "POTCAR"))
        cls.ref_kpoints = Kpoints.from_file(
            os.path.join(module_dir, "reference_files", "setup_test",
                         "KPOINTS"))
        cls.ref_incar_preserve = Incar.from_file(
            os.path.join(module_dir, "reference_files", "preserve_incar",
                         "INCAR"))
Ejemplo n.º 32
0
def main():
    """
    Handle main.
    """
    parser = argparse.ArgumentParser(
        description="""
    pmg is a convenient script that uses pymatgen to perform many
    analyses, plotting and format conversions. This script works based on
    several sub-commands with their own options. To see the options for the
    sub-commands, type "pmg sub-command -h".""",
        epilog="""Version: {}""".format(__version__),
    )

    subparsers = parser.add_subparsers()

    parser_config = subparsers.add_parser(
        "config",
        help="Tools for configuring pymatgen, e.g., "
        "potcar setup, modifying .pmgrc.yaml "
        "configuration file.",
    )
    groups = parser_config.add_mutually_exclusive_group(required=True)
    groups.add_argument(
        "-p",
        "--potcar",
        dest="potcar_dirs",
        metavar="dir_name",
        nargs=2,
        help="Initial directory where downloaded VASP "
        "POTCARs are extracted to, and the "
        "output directory where the reorganized "
        "potcars will be stored. The input "
        "directory should be "
        "the parent directory that contains the "
        "POT_GGA_PAW_PBE or potpaw_PBE type "
        "subdirectories.",
    )
    groups.add_argument(
        "-i",
        "--install",
        dest="install",
        metavar="package_name",
        choices=["enumlib", "bader"],
        help="Install various optional command line "
        "tools needed for full functionality.",
    )

    groups.add_argument(
        "-a",
        "--add",
        dest="var_spec",
        nargs="+",
        help="Variables to add in the form of space "
        "separated key value pairs. E.g., "
        "PMG_VASP_PSP_DIR ~/psps",
    )
    parser_config.set_defaults(func=configure_pmg)

    parser_analyze = subparsers.add_parser(
        "analyze", help="Vasp calculation analysis tools."
    )
    parser_analyze.add_argument(
        "directories",
        metavar="dir",
        default=".",
        type=str,
        nargs="*",
        help="directory to process (default to .)",
    )
    parser_analyze.add_argument(
        "-e",
        "--energies",
        dest="get_energies",
        action="store_true",
        help="Print energies",
    )
    parser_analyze.add_argument(
        "-m",
        "--mag",
        dest="ion_list",
        type=str,
        nargs=1,
        help="Print magmoms. ION LIST can be a range "
        "(e.g., 1-2) or the string 'All' for all ions.",
    )
    parser_analyze.add_argument(
        "-r",
        "--reanalyze",
        dest="reanalyze",
        action="store_true",
        help="Force reanalysis. Typically, vasp_analyzer"
        " will just reuse a vasp_analyzer_data.gz if "
        "present. This forces the analyzer to reanalyze "
        "the data.",
    )
    parser_analyze.add_argument(
        "-f",
        "--format",
        dest="format",
        choices=tabulate_formats,
        default="simple",
        help="Format for table. Supports all options in tabulate package.",
    )
    parser_analyze.add_argument(
        "-v",
        "--verbose",
        dest="verbose",
        action="store_true",
        help="Verbose mode. Provides detailed output on progress.",
    )
    parser_analyze.add_argument(
        "-q",
        "--quick",
        dest="quick",
        action="store_true",
        help="Faster mode, but less detailed information. Parses individual vasp files.",
    )
    parser_analyze.add_argument(
        "-s",
        "--sort",
        dest="sort",
        choices=["energy_per_atom", "filename"],
        default="energy_per_atom",
        help="Sort criteria. Defaults to energy / atom.",
    )
    parser_analyze.set_defaults(func=analyze)

    parser_query = subparsers.add_parser(
        "query", help="Search for structures and data from the Materials Project."
    )
    parser_query.add_argument(
        "criteria",
        metavar="criteria",
        help="Search criteria. Supported formats in formulas, chemical "
        "systems, Materials Project ids, etc.",
    )
    group = parser_query.add_mutually_exclusive_group(required=True)
    group.add_argument(
        "-s",
        "--structure",
        dest="structure",
        metavar="format",
        choices=["poscar", "cif", "cssr"],
        type=str.lower,
        help="Get structures from Materials Project and write them to a "
        "specified format.",
    )
    group.add_argument(
        "-e",
        "--entries",
        dest="entries",
        metavar="filename",
        help="Get entries from Materials Project and write them to "
        "serialization file. JSON and YAML supported.",
    )
    group.add_argument(
        "-d",
        "--data",
        dest="data",
        metavar="fields",
        nargs="*",
        help="Print a summary of entries in the Materials Project satisfying "
        "the criteria. Supply field names to include additional data. "
        "By default, the Materials Project id, formula, spacegroup, "
        "energy per atom, energy above hull are shown.",
    )
    parser_query.set_defaults(func=do_query)

    parser_plot = subparsers.add_parser(
        "plot", help="Plotting tool for " "DOS, CHGCAR, XRD, etc."
    )
    group = parser_plot.add_mutually_exclusive_group(required=True)
    group.add_argument(
        "-d",
        "--dos",
        dest="dos_file",
        metavar="vasprun.xml",
        help="Plot DOS from a vasprun.xml",
    )
    group.add_argument(
        "-c",
        "--chgint",
        dest="chgcar_file",
        metavar="CHGCAR",
        help="Generate charge integration plots from any " "CHGCAR",
    )
    group.add_argument(
        "-x",
        "--xrd",
        dest="xrd_structure_file",
        metavar="structure_file",
        help="Generate XRD plots from any supported structure "
        "file, e.g., CIF, POSCAR, vasprun.xml, etc.",
    )

    parser_plot.add_argument(
        "-s",
        "--site",
        dest="site",
        action="store_const",
        const=True,
        help="Plot site projected DOS",
    )
    parser_plot.add_argument(
        "-e",
        "--element",
        dest="element",
        type=str,
        nargs=1,
        help="List of elements to plot as comma-separated" " values e.g., Fe,Mn",
    )
    parser_plot.add_argument(
        "-o",
        "--orbital",
        dest="orbital",
        action="store_const",
        const=True,
        help="Plot orbital projected DOS",
    )

    parser_plot.add_argument(
        "-i",
        "--indices",
        dest="inds",
        type=str,
        nargs=1,
        help="Comma-separated list of indices to plot "
        "charge integration, e.g., 1,2,3,4. If not "
        "provided, the code will plot the chgint "
        "for all symmetrically distinct atoms "
        "detected.",
    )
    parser_plot.add_argument(
        "-r",
        "--radius",
        dest="radius",
        type=float,
        default=3,
        help="Radius of integration for charge " "integration plot.",
    )
    parser_plot.add_argument(
        "--out_file",
        dest="out_file",
        type=str,
        help="Save plot to file instead of displaying.",
    )
    parser_plot.set_defaults(func=plot)

    parser_structure = subparsers.add_parser(
        "structure", help="Structure conversion and analysis tools."
    )

    parser_structure.add_argument(
        "-f",
        "--filenames",
        dest="filenames",
        metavar="filename",
        nargs="+",
        help="List of structure files.",
    )

    groups = parser_structure.add_mutually_exclusive_group(required=True)
    groups.add_argument(
        "-c",
        "--convert",
        dest="convert",
        action="store_true",
        help="Convert from structure file 1 to structure "
        "file 2. Format determined from filename. "
        "Supported formats include POSCAR/CONTCAR, "
        "CIF, CSSR, etc. If the keyword'prim' is within "
        "the filename, the code will automatically attempt "
        "to find a primitive cell.",
    )
    groups.add_argument(
        "-s",
        "--symmetry",
        dest="symmetry",
        metavar="tolerance",
        type=float,
        help="Determine the spacegroup using the "
        "specified tolerance. 0.1 is usually a good "
        "value for DFT calculations.",
    )
    groups.add_argument(
        "-g",
        "--group",
        dest="group",
        choices=["element", "species"],
        metavar="mode",
        help="Compare a set of structures for similarity. "
        "Element mode does not compare oxidation states. "
        "Species mode will take into account oxidations "
        "states.",
    )
    groups.add_argument(
        "-l",
        "--localenv",
        dest="localenv",
        nargs="+",
        help="Local environment analysis. Provide bonds in the format of"
        "Center Species-Ligand Species=max_dist, e.g., H-O=0.5.",
    )

    parser_structure.set_defaults(func=analyze_structures)

    parser_view = subparsers.add_parser("view", help="Visualize structures")
    parser_view.add_argument(
        "filename", metavar="filename", type=str, nargs=1, help="Filename"
    )
    parser_view.add_argument(
        "-e",
        "--exclude_bonding",
        dest="exclude_bonding",
        type=str,
        nargs=1,
        help="List of elements to exclude from bonding " "analysis. E.g., Li,Na",
    )
    parser_view.set_defaults(func=parse_view)

    parser_diff = subparsers.add_parser(
        "diff", help="Diffing tool. For now, only INCAR supported."
    )
    parser_diff.add_argument(
        "-i",
        "--incar",
        dest="incars",
        metavar="INCAR",
        required=True,
        nargs=2,
        help="List of INCARs to compare.",
    )
    parser_diff.set_defaults(func=diff_incar)

    parser_potcar = subparsers.add_parser("potcar", help="Generate POTCARs")
    parser_potcar.add_argument(
        "-f",
        "--functional",
        dest="functional",
        type=str,
        choices=sorted(Potcar.FUNCTIONAL_CHOICES),
        default=SETTINGS.get("PMG_DEFAULT_FUNCTIONAL", "PBE"),
        help="Functional to use. Unless otherwise "
        "stated (e.g., US), "
        "refers to PAW psuedopotential.",
    )
    group = parser_potcar.add_mutually_exclusive_group(required=True)

    group.add_argument(
        "-s",
        "--symbols",
        dest="symbols",
        type=str,
        nargs="+",
        help="List of POTCAR symbols. Use -f to set " "functional. Defaults to PBE.",
    )
    group.add_argument(
        "-r",
        "--recursive",
        dest="recursive",
        type=str,
        help="Dirname to find and generate from POTCAR.spec.",
    )
    parser_potcar.set_defaults(func=generate_potcar)

    try:
        import argcomplete

        argcomplete.autocomplete(parser)
    except ImportError:
        # argcomplete not present.
        pass

    args = parser.parse_args()

    try:
        getattr(args, "func")
    except AttributeError:
        parser.print_help()
        sys.exit(-1)
    return args.func(args)
Ejemplo n.º 33
0
def get_basis_and_potential(species, d, cardinality='DZVP', functional='PBE'):
    """
    Given a specie and a potential/basis type, this function accesses the available basis sets and potentials.
    Generally, the GTH potentials are used with the GTH basis sets.

    Args:
        species: (list) list of species for which to get the potential/basis strings
        d: (dict) a dictionary specifying how bases and/or potentials should be assigned to species
            E.g. {'Si': {'cardinality': 'DZVP', 'sr': True}, 'O': {'cardinality': 'TZVP'}}
        functional: (str) functional type. Default: 'PBE'
        basis_type: (str) the basis set type. Default: 'MOLOPT'
        cardinality: (str) basis set cardinality. Default: 'DZVP'

    Returns:
        (dict) of the form {'specie': {'potential': potential, 'basis': basis}...}
    """

    potential_filename = SETTINGS.get("PMG_DEFAULT_CP2K_POTENTIAL_FILE",
                                      "GTH_POTENTIALS")
    basis_filenames = ['BASIS_MOLOPT', 'BASIS_MOLOPT_UCL']

    functional = functional or SETTINGS.get("PMG_DEFAULT_FUNCTIONAL", "PBE")
    cardinality = cardinality or SETTINGS.get("PMG_DEFAULT_BASIS_CARDINALITY",
                                              "DZVP")
    basis_and_potential = {
        "basis_filenames": basis_filenames,
        "potential_filename": potential_filename,
    }
    for s in species:
        if s not in d:
            d[s] = {}
        if 'sr' not in d[s]:
            d[s]['sr'] = True
        if 'cardinality' not in d[s]:
            d[s]['cardinality'] = cardinality

    with open(os.path.join(MODULE_DIR, 'basis_molopt.yaml'), 'rt') as f:
        data_b = yaml.load(f, Loader=yaml.Loader)
    with open(os.path.join(MODULE_DIR, 'gth_potentials.yaml'), 'rt') as f:
        data_p = yaml.load(f, Loader=yaml.Loader)

    for s in species:
        basis_and_potential[s] = {}
        b = [_ for _ in data_b[s] if d[s]['cardinality'] in _.split('-')]
        if d[s]['sr'] and any(['SR' in _ for _ in b]):
            b = [_ for _ in b if 'SR' in _]
        else:
            b = [_ for _ in b if 'SR' not in _]
        if 'q' in d[s]:
            b = [_ for _ in b if d[s]['q'] in _]
        else:

            def srt(x):
                return int(x.split('q')[-1])

            b = sorted(b, key=srt)[-1:]
        if len(b) == 0:
            raise LookupError('NO BASIS OF THAT TYPE AVAILABLE')
        elif len(b) > 1:
            raise LookupError('AMBIGUITY IN BASIS. PLEASE SPECIFY FURTHER')

        basis_and_potential[s]['basis'] = b[0]
        p = [_ for _ in data_p[s] if functional in _.split('-')]
        if len(p) == 0:
            raise LookupError('NO PSEUDOPOTENTIAL OF THAT TYPE AVAILABLE')
        if len(p) > 1:
            raise LookupError('AMBIGUITY IN POTENTIAL. PLEASE SPECIFY FURTHER')

        basis_and_potential[s]['potential'] = p[0]

    return basis_and_potential
Ejemplo n.º 34
0
)
from pymatgen.electronic_structure.dos import CompleteDos
from pymatgen.entries.compatibility import MaterialsProjectCompatibility
from pymatgen.entries.computed_entries import ComputedEntry
from pymatgen.ext.matproj import MPRester, MPRestError, TaskType
from pymatgen.io.cif import CifParser
from pymatgen.phonon.bandstructure import PhononBandStructureSymmLine
from pymatgen.phonon.dos import CompletePhononDos
from pymatgen.util.testing import PymatgenTest

website_is_up = requests.get(
    "https://www.materialsproject.org").status_code == 200


@unittest.skipIf(
    (not SETTINGS.get("PMG_MAPI_KEY")) or (not website_is_up),
    "PMG_MAPI_KEY environment variable not set or MP is down.",
)
class MPResterTest(PymatgenTest):
    _multiprocess_shared_ = True

    def setUp(self):
        self.rester = MPRester()
        warnings.simplefilter("ignore")

    def tearDown(self):
        warnings.simplefilter("default")
        self.rester.session.close()

    def test_get_all_materials_ids_doc(self):
        mids = self.rester.get_materials_ids("Al2O3")
Ejemplo n.º 35
0
class PourbaixDiagramTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.test_data = loadfn(os.path.join(test_dir, 'pourbaix_test_data.json'))
        cls.pbx = PourbaixDiagram(cls.test_data['Zn'], filter_solids=True)
        cls.pbx_nofilter = PourbaixDiagram(cls.test_data['Zn'],
                                           filter_solids=False)

    def test_pourbaix_diagram(self):
        self.assertEqual(set([e.name for e in self.pbx.stable_entries]),
                         {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
                         "List of stable entries does not match")

        self.assertEqual(set([e.name for e in self.pbx_nofilter.stable_entries]),
                         {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)",
                          "ZnO2(s)", "ZnH(s)"},
                         "List of stable entries for unfiltered pbx does not match")

        pbx_lowconc = PourbaixDiagram(self.test_data['Zn'], conc_dict={"Zn": 1e-8},
                                      filter_solids=True)
        self.assertEqual(set([e.name for e in pbx_lowconc.stable_entries]),
                         {"Zn(HO)2(aq)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"})

    def test_multicomponent(self):
        # Binary system
        pd_binary = PourbaixDiagram(self.test_data['Ag-Te'], filter_solids=True,
                                    comp_dict={"Ag": 0.5, "Te": 0.5},
                                    conc_dict={"Ag": 1e-8, "Te": 1e-8})
        self.assertEqual(len(pd_binary.stable_entries), 30)
        test_entry = pd_binary.find_stable_entry(8, 2)
        self.assertTrue("mp-499" in test_entry.entry_id)

        # Find a specific multientry to test
        self.assertEqual(pd_binary.get_decomposition_energy(test_entry, 8, 2), 0)
        self.assertEqual(pd_binary.get_decomposition_energy(
            test_entry.entry_list[0], 8, 2), 0)

        pd_ternary = PourbaixDiagram(self.test_data['Ag-Te-N'], filter_solids=True)
        self.assertEqual(len(pd_ternary.stable_entries), 49)

        ag = self.test_data['Ag-Te-N'][30]
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 2, -1), 0)
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 10, -2), 0)

    def test_get_pourbaix_domains(self):
        domains = PourbaixDiagram.get_pourbaix_domains(self.test_data['Zn'])
        self.assertEqual(len(domains[0]), 7)

    def test_get_decomposition(self):
        # Test a stable entry to ensure that it's zero in the stable region
        entry = self.test_data['Zn'][12] # Should correspond to mp-2133
        self.assertAlmostEqual(self.pbx.get_decomposition_energy(entry, 10, 1),
                               0.0, 5, "Decomposition energy of ZnO is not 0.")

        # Test an unstable entry to ensure that it's never zero
        entry = self.test_data['Zn'][11]
        ph, v = np.meshgrid(np.linspace(0, 14), np.linspace(-2, 4))
        result = self.pbx_nofilter.get_decomposition_energy(entry, ph, v)
        self.assertTrue((result >= 0).all(),
                        "Unstable energy has hull energy of 0 or less")

        # Test an unstable hydride to ensure HER correction works
        self.assertAlmostEqual(self.pbx.get_decomposition_energy(entry, -3, -2),
                               11.093744395)
        # Test a list of pHs
        self.pbx.get_decomposition_energy(entry, np.linspace(0, 2, 5), 2)

        # Test a list of Vs
        self.pbx.get_decomposition_energy(entry, 4, np.linspace(-3, 3, 10))

        # Test a set of matching arrays
        ph, v = np.meshgrid(np.linspace(0, 14), np.linspace(-3, 3))
        self.pbx.get_decomposition_energy(entry, ph, v)

    @unittest.skipIf(not SETTINGS.get("PMG_MAPI_KEY"),
                     "PMG_MAPI_KEY environment variable not set.")
    def test_mpr_pipeline(self):
        from pymatgen import MPRester
        mpr = MPRester()
        data = mpr.get_pourbaix_entries(["Zn"])
        pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8})
        pbx.find_stable_entry(10, 0)

        data = mpr.get_pourbaix_entries(["Ag", "Te"])
        pbx = PourbaixDiagram(data, filter_solids=True,
                              conc_dict={"Ag": 1e-8, "Te": 1e-8})
        self.assertEqual(len(pbx.stable_entries), 30)
        test_entry = pbx.find_stable_entry(8, 2)
        self.assertAlmostEqual(test_entry.energy, 2.393900378500001)

        # Test custom ions
        entries = mpr.get_pourbaix_entries(["Sn", "C", "Na"])
        ion = IonEntry(Ion.from_formula("NaO28H80Sn12C24+"), -161.676)
        custom_ion_entry = PourbaixEntry(ion, entry_id='my_ion')
        pbx = PourbaixDiagram(entries + [custom_ion_entry], filter_solids=True,
                              comp_dict={"Na": 1, "Sn": 12, "C": 24})
        self.assertAlmostEqual(pbx.get_decomposition_energy(custom_ion_entry, 5, 2),
                               8.31082110278154)
Ejemplo n.º 36
0
from __future__ import division, print_function, unicode_literals

from abipy.core.testing import AbipyTest
from pymatgen import SETTINGS
from HTGW.flows.GWtasks import VaspGWTask, VaspGWExecuteTask, VaspGWInputTask, SingleVaspGWWork
from HTGW.flows.datastructures import GWSpecs
from HTGW.flows.tests.test_helpers import structure
from HTGW.flows.GWworks import VaspGWFWWorkFlow
from HTGW.flows.helpers import add_gg_gap, s_name
import os

POTCAR_DIR = SETTINGS.get("VASP_PSP_DIR")

# TODO: These tests produce several files. The execution of the test should be done in a temp directory.

__author__ = 'setten'


class GWVaspTest(AbipyTest):
    def test_VaspGWTasks(self):
        """
        testing the vasp GW task
        """
        spec = GWSpecs()
        struct = add_gg_gap(structure)
        structure_dict = struct.as_dict()
        band_structure_dict = {
            'vbm_l': structure.vbm_l,
            'cbm_l': structure.cbm_l,
            'vbm_a': structure.vbm[0],
            'vbm_b': structure.vbm[1],
Ejemplo n.º 37
0
class PourbaixDiagramTest(unittest.TestCase):
    _multiprocess_shared_ = True

    @classmethod
    def setUpClass(cls):
        cls.test_data = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "pourbaix_test_data.json"))
        cls.pbx = PourbaixDiagram(cls.test_data["Zn"], filter_solids=True)
        cls.pbx_nofilter = PourbaixDiagram(cls.test_data["Zn"], filter_solids=False)

    def test_pourbaix_diagram(self):
        self.assertEqual(
            set([e.name for e in self.pbx.stable_entries]),
            {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
            "List of stable entries does not match",
        )

        self.assertEqual(
            set([e.name for e in self.pbx_nofilter.stable_entries]),
            {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)", "ZnO2(s)", "ZnH(s)"},
            "List of stable entries for unfiltered pbx does not match",
        )

        pbx_lowconc = PourbaixDiagram(
            self.test_data["Zn"], conc_dict={"Zn": 1e-8}, filter_solids=True
        )
        self.assertEqual(
            set([e.name for e in pbx_lowconc.stable_entries]),
            {"Zn(HO)2(aq)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
        )

    def test_properties(self):
        self.assertEqual(len(self.pbx.unstable_entries), 2)

    def test_multicomponent(self):
        # Assure no ions get filtered at high concentration
        ag_n = [e for e in self.test_data["Ag-Te-N"] if "Te" not in e.composition]
        highconc = PourbaixDiagram(
            ag_n, filter_solids=True, conc_dict={"Ag": 1e-5, "N": 1}
        )
        entry_sets = [set(e.entry_id) for e in highconc.stable_entries]
        self.assertIn({"mp-124", "ion-17"}, entry_sets)

        # Binary system
        pd_binary = PourbaixDiagram(
            self.test_data["Ag-Te"],
            filter_solids=True,
            comp_dict={"Ag": 0.5, "Te": 0.5},
            conc_dict={"Ag": 1e-8, "Te": 1e-8},
        )
        self.assertEqual(len(pd_binary.stable_entries), 30)
        test_entry = pd_binary.find_stable_entry(8, 2)
        self.assertTrue("mp-499" in test_entry.entry_id)

        # Find a specific multientry to test
        self.assertEqual(pd_binary.get_decomposition_energy(test_entry, 8, 2), 0)

        pd_ternary = PourbaixDiagram(self.test_data["Ag-Te-N"], filter_solids=True)
        self.assertEqual(len(pd_ternary.stable_entries), 49)

        # Fetch a solid entry and a ground state entry mixture
        ag_te_n = self.test_data["Ag-Te-N"][-1]
        ground_state_ag_with_ions = MultiEntry(
            [self.test_data["Ag-Te-N"][i] for i in [4, 18, 30]],
            weights=[1 / 3, 1 / 3, 1 / 3],
        )
        self.assertAlmostEqual(
            pd_ternary.get_decomposition_energy(ag_te_n, 2, -1), 2.767822855765
        )
        self.assertAlmostEqual(
            pd_ternary.get_decomposition_energy(ag_te_n, 10, -2), 3.756840056890625
        )
        self.assertAlmostEqual(
            pd_ternary.get_decomposition_energy(ground_state_ag_with_ions, 2, -1), 0
        )

        # Test invocation of pourbaix diagram from ternary data
        new_ternary = PourbaixDiagram(pd_ternary.all_entries)
        self.assertEqual(len(new_ternary.stable_entries), 49)
        self.assertAlmostEqual(
            new_ternary.get_decomposition_energy(ag_te_n, 2, -1), 2.767822855765
        )
        self.assertAlmostEqual(
            new_ternary.get_decomposition_energy(ag_te_n, 10, -2), 3.756840056890625
        )
        self.assertAlmostEqual(
            new_ternary.get_decomposition_energy(ground_state_ag_with_ions, 2, -1), 0
        )

    def test_get_pourbaix_domains(self):
        domains = PourbaixDiagram.get_pourbaix_domains(self.test_data["Zn"])
        self.assertEqual(len(domains[0]), 7)

    def test_get_decomposition(self):
        # Test a stable entry to ensure that it's zero in the stable region
        entry = self.test_data["Zn"][12]  # Should correspond to mp-2133
        self.assertAlmostEqual(
            self.pbx.get_decomposition_energy(entry, 10, 1),
            0.0,
            5,
            "Decomposition energy of ZnO is not 0.",
        )

        # Test an unstable entry to ensure that it's never zero
        entry = self.test_data["Zn"][11]
        ph, v = np.meshgrid(np.linspace(0, 14), np.linspace(-2, 4))
        result = self.pbx_nofilter.get_decomposition_energy(entry, ph, v)
        self.assertTrue(
            (result >= 0).all(), "Unstable energy has hull energy of 0 or less"
        )

        # Test an unstable hydride to ensure HER correction works
        self.assertAlmostEqual(
            self.pbx.get_decomposition_energy(entry, -3, -2), 3.6979147983333
        )
        # Test a list of pHs
        self.pbx.get_decomposition_energy(entry, np.linspace(0, 2, 5), 2)

        # Test a list of Vs
        self.pbx.get_decomposition_energy(entry, 4, np.linspace(-3, 3, 10))

        # Test a set of matching arrays
        ph, v = np.meshgrid(np.linspace(0, 14), np.linspace(-3, 3))
        self.pbx.get_decomposition_energy(entry, ph, v)

    def test_get_stable_entry(self):
        entry = self.pbx.get_stable_entry(0, 0)
        self.assertEqual(entry.entry_id, "ion-0")

    def test_multielement_parallel(self):
        # Simple test to ensure that multiprocessing is working
        test_entries = self.test_data["Ag-Te-N"]
        nproc = multiprocessing.cpu_count()
        pbx = PourbaixDiagram(test_entries, filter_solids=True, nproc=nproc)
        self.assertEqual(len(pbx.stable_entries), 49)

    def test_solid_filter(self):
        entries = self.test_data["Zn"]
        pbx = PourbaixDiagram(entries, filter_solids=False)
        oxidized_phase = pbx.find_stable_entry(10, 2)
        self.assertEqual(oxidized_phase.name, "ZnO2(s)")

        entries = self.test_data["Zn"]
        pbx = PourbaixDiagram(entries, filter_solids=True)
        oxidized_phase = pbx.find_stable_entry(10, 2)
        self.assertEqual(oxidized_phase.name, "ZnO(s)")

    def test_serialization(self):
        d = self.pbx.as_dict()
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(
            set([e.name for e in new.stable_entries]),
            {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
            "List of stable entries does not match",
        )

        # Test with unprocessed entries included, this should result in the
        # previously filtered entries being included
        d = self.pbx.as_dict(include_unprocessed_entries=True)
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(
            set([e.name for e in new.stable_entries]),
            {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)", "ZnO2(s)", "ZnH(s)"},
            "List of stable entries for unfiltered pbx does not match",
        )

        pd_binary = PourbaixDiagram(
            self.test_data["Ag-Te"],
            filter_solids=True,
            comp_dict={"Ag": 0.5, "Te": 0.5},
            conc_dict={"Ag": 1e-8, "Te": 1e-8},
        )
        new_binary = PourbaixDiagram.from_dict(pd_binary.as_dict())
        self.assertEqual(len(pd_binary.stable_entries), len(new_binary.stable_entries))

    # The two tests below rely on the MP Rest interface.
    @unittest.skipIf(
        not SETTINGS.get("PMG_MAPI_KEY"), "PMG_MAPI_KEY environment variable not set."
    )
    def test_heavy(self):
        from pymatgen import MPRester

        mpr = MPRester()
        entries = mpr.get_pourbaix_entries(["Li", "Mg", "Sn", "Pd"])
        pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
        entries = mpr.get_pourbaix_entries(["Ba", "Ca", "V", "Cu", "F"])
        pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
        entries = mpr.get_pourbaix_entries(["Ba", "Ca", "V", "Cu", "F", "Fe"])
        pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
        entries = mpr.get_pourbaix_entries(["Na", "Ca", "Nd", "Y", "Ho", "F"])
        pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)

    @unittest.skipIf(
        not SETTINGS.get("PMG_MAPI_KEY"), "PMG_MAPI_KEY environment variable not set."
    )
    def test_mpr_pipeline(self):
        from pymatgen import MPRester

        mpr = MPRester()
        data = mpr.get_pourbaix_entries(["Zn"])
        pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8})
        pbx.find_stable_entry(10, 0)

        data = mpr.get_pourbaix_entries(["Ag", "Te"])
        pbx = PourbaixDiagram(
            data, filter_solids=True, conc_dict={"Ag": 1e-8, "Te": 1e-8}
        )
        self.assertEqual(len(pbx.stable_entries), 30)
        test_entry = pbx.find_stable_entry(8, 2)
        self.assertAlmostEqual(test_entry.energy, 2.3894017960000009, 1)

        # Test custom ions
        entries = mpr.get_pourbaix_entries(["Sn", "C", "Na"])
        ion = IonEntry(Ion.from_formula("NaO28H80Sn12C24+"), -161.676)
        custom_ion_entry = PourbaixEntry(ion, entry_id="my_ion")
        pbx = PourbaixDiagram(
            entries + [custom_ion_entry],
            filter_solids=True,
            comp_dict={"Na": 1, "Sn": 12, "C": 24},
        )
        self.assertAlmostEqual(
            pbx.get_decomposition_energy(custom_ion_entry, 5, 2), 2.1209002582, 1
        )

        # Test against ion sets with multiple equivalent ions (Bi-V regression)
        entries = mpr.get_pourbaix_entries(["Bi", "V"])
        pbx = PourbaixDiagram(
            entries, filter_solids=True, conc_dict={"Bi": 1e-8, "V": 1e-8}
        )
        self.assertTrue(
            all(
                [
                    "Bi" in entry.composition and "V" in entry.composition
                    for entry in pbx.all_entries
                ]
            )
        )
Ejemplo n.º 38
0
class TestConversions(TestCase):

    def test_conversion_overwrite(self):
        # Test with overwrite
        d = {'comp_str': ["Fe2", "MnO2"]}
        df = DataFrame(data=d)

        stc = StrToComposition(target_col_id='comp_str', overwrite_data=False)
        with self.assertRaises(ValueError):
            df = stc.featurize_dataframe(df, 'comp_str', inplace=True)

        with self.assertRaises(ValueError):
            df = stc.featurize_dataframe(df, 'comp_str', inplace=False)

        stc = StrToComposition(target_col_id='comp_str', overwrite_data=True)

        dfres_ipt = df.copy()
        stc.featurize_dataframe(dfres_ipt, 'comp_str', inplace=True)
        self.assertListEqual(dfres_ipt.columns.tolist(), ["comp_str"])

        dfres_ipf = stc.featurize_dataframe(df, 'comp_str', inplace=False)
        self.assertListEqual(dfres_ipf.columns.tolist(), ["comp_str"])

    def test_str_to_composition(self):
        d = {'comp_str': ["Fe2", "MnO2"]}

        df = DataFrame(data=d)
        df = StrToComposition().featurize_dataframe(df, 'comp_str')

        self.assertEqual(df["composition"].tolist(),
                         [Composition("Fe2"), Composition("MnO2")])

        stc = StrToComposition(reduce=True, target_col_id='composition_red')
        df = stc.featurize_dataframe(df, 'comp_str')

        self.assertEqual(df["composition_red"].tolist(),
                         [Composition("Fe"), Composition("MnO2")])

    def test_structure_to_composition(self):
        coords = [[0, 0, 0], [0.75, 0.5, 0.75]]
        lattice = Lattice([[3.8401979337, 0.00, 0.00],
                           [1.9200989668, 3.3257101909, 0.00],
                           [0.00, -2.2171384943, 3.1355090603]])
        struct = Structure(lattice, ["Si"] * 2, coords)
        df = DataFrame(data={'structure': [struct]})

        stc = StructureToComposition()
        df = stc.featurize_dataframe(df, 'structure')
        self.assertEqual(df["composition"].tolist()[0], Composition("Si2"))

        stc = StructureToComposition(reduce=True,
                                     target_col_id='composition_red')
        df = stc.featurize_dataframe(df, 'structure')
        self.assertEqual(df["composition_red"].tolist()[0], Composition("Si"))

    def test_dict_to_object(self):
        coords = [[0, 0, 0], [0.75, 0.5, 0.75]]
        lattice = Lattice([[3.8401979337, 0.00, 0.00],
                           [1.9200989668, 3.3257101909, 0.00],
                           [0.00, -2.2171384943, 3.1355090603]])
        struct = Structure(lattice, ["Si"] * 2, coords)
        d = {'structure_dict': [struct.as_dict(), struct.as_dict()]}
        df = DataFrame(data=d)

        dto = DictToObject(target_col_id='structure')
        df = dto.featurize_dataframe(df, 'structure_dict')
        self.assertEqual(df["structure"].tolist()[0], struct)
        self.assertEqual(df["structure"].tolist()[1], struct)

        # test dynamic target_col_id setting
        df = DataFrame(data=d)
        dto = DictToObject()
        df = dto.featurize_dataframe(df, 'structure_dict')
        self.assertEqual(df["structure_dict_object"].tolist()[0], struct)
        self.assertEqual(df["structure_dict_object"].tolist()[1], struct)

    def test_json_to_object(self):
        coords = [[0, 0, 0], [0.75, 0.5, 0.75]]
        lattice = Lattice([[3.8401979337, 0.00, 0.00],
                           [1.9200989668, 3.3257101909, 0.00],
                           [0.00, -2.2171384943, 3.1355090603]])
        struct = Structure(lattice, ["Si"] * 2, coords)
        struct_json = json.dumps(struct, cls=MontyEncoder)

        d = {'structure_json': [struct_json]}
        df = DataFrame(data=d)

        jto = JsonToObject(target_col_id='structure')
        df = jto.featurize_dataframe(df, 'structure_json')
        self.assertEqual(df["structure"].tolist()[0], struct)

        # test dynamic target_col_id setting
        df = DataFrame(data=d)
        jto = JsonToObject()
        df = jto.featurize_dataframe(df, 'structure_json')
        self.assertEqual(df["structure_json_object"].tolist()[0], struct)

    def test_structure_to_oxidstructure(self):
        cscl = Structure(Lattice([[4.209, 0, 0], [0, 4.209, 0], [0, 0, 4.209]]),
                         ["Cl", "Cs"], [[0.45, 0.5, 0.5], [0, 0, 0]])
        d = {'structure': [cscl]}
        df = DataFrame(data=d)

        sto = StructureToOxidStructure()
        df = sto.featurize_dataframe(df, 'structure')
        self.assertEqual(df["structure_oxid"].tolist()[0][0].specie.oxi_state,
                         -1)
        self.assertEqual(df["structure_oxid"].tolist()[0][1].specie.oxi_state,
                         +1)

        sto = StructureToOxidStructure(target_col_id='structure_oxid2',
                                       oxi_states_override={"Cl": [-2],
                                                            "Cs": [+2]})
        df = sto.featurize_dataframe(df, 'structure')
        self.assertEqual(df["structure_oxid2"].tolist()[0][0].specie.oxi_state,
                         -2)
        self.assertEqual(df["structure_oxid2"].tolist()[0][1].specie.oxi_state,
                         +2)

        # original is preserved
        self.assertEqual(df["structure"].tolist()[0][0].specie, Element("Cl"))

        # test in-place
        sto = StructureToOxidStructure(target_col_id=None, overwrite_data=True)
        df = sto.featurize_dataframe(df, 'structure')
        self.assertEqual(df["structure"].tolist()[0][0].specie.oxi_state, -1)

        # test error handling
        test_struct = Structure([5, 0, 0, 0, 5, 0, 0, 0, 5], ['Sb', 'F', 'O'],
                                [[0, 0, 0], [0.2, 0.2, 0.2], [0.5, 0.5, 0.5]])
        df = DataFrame(data={'structure': [test_struct]})
        sto = StructureToOxidStructure(return_original_on_error=False,
                                       max_sites=2)
        self.assertRaises(ValueError, sto.featurize_dataframe, df,
                          'structure')

        # check non oxi state structure returned correctly
        sto = StructureToOxidStructure(return_original_on_error=True,
                                       max_sites=2)
        df = sto.featurize_dataframe(df, 'structure')
        self.assertEqual(df["structure_oxid"].tolist()[0][0].specie,
                         Element("Sb"))

    def test_composition_to_oxidcomposition(self):
        df = DataFrame(data={"composition": [Composition("Fe2O3")]})
        cto = CompositionToOxidComposition()
        df = cto.featurize_dataframe(df, 'composition')
        self.assertEqual(df["composition_oxid"].tolist()[0],
                         Composition({"Fe3+": 2, "O2-": 3}))

        # test error handling
        df = DataFrame(data={"composition": [Composition("Fe2O3")]})
        cto = CompositionToOxidComposition(
            return_original_on_error=False, max_sites=2)
        self.assertRaises(ValueError, cto.featurize_dataframe, df,
                          'composition')

        # check non oxi state structure returned correctly
        cto = CompositionToOxidComposition(
            return_original_on_error=True, max_sites=2)
        df = cto.featurize_dataframe(df, 'composition')
        self.assertEqual(df["composition_oxid"].tolist()[0],
                         Composition({"Fe": 2, "O": 3}))

    def test_to_istructure(self):
        cscl = Structure(Lattice([[4.209, 0, 0], [0, 4.209, 0], [0, 0, 4.209]]),
                         ["Cl", "Cs"], [[0.45, 0.5, 0.5], [0, 0, 0]])
        df = DataFrame({"structure": [cscl]})

        # Run the conversion
        sti = StructureToIStructure()
        df = sti.featurize_dataframe(df, 'structure')

        # Make sure the new structure is an IStructure, and equal
        # to the original structure
        self.assertIsInstance(df["istructure"][0], IStructure)
        self.assertEqual(df["istructure"][0], df["structure"][0])

    def test_conversion_multiindex(self):
        d = {'comp_str': ["Fe2", "MnO2"]}

        df_1lvl = DataFrame(data=d)

        df_1lvl = StrToComposition().featurize_dataframe(
            df_1lvl, 'comp_str', multiindex=True)
        self.assertEqual(df_1lvl[("StrToComposition", "composition")].tolist(),
                         [Composition("Fe2"), Composition("MnO2")])

        df_2lvl = DataFrame(data=d)
        df_2lvl.columns = MultiIndex.from_product((["custom"],
                                                   df_2lvl.columns.values))

        df_2lvl = StrToComposition().featurize_dataframe(
            df_2lvl, ("custom", "comp_str"), multiindex=True)
        self.assertEqual(df_2lvl[("StrToComposition", "composition")].tolist(),
                         [Composition("Fe2"), Composition("MnO2")])

        df_2lvl = DataFrame(data=d)
        df_2lvl.columns = MultiIndex.from_product((["custom"],
                                                   df_2lvl.columns.values))

        sto = StrToComposition(target_col_id='test')
        df_2lvl = sto.featurize_dataframe(
            df_2lvl, ("custom", "comp_str"), multiindex=True)
        self.assertEqual(df_2lvl[("StrToComposition", "test")].tolist(),
                         [Composition("Fe2"), Composition("MnO2")])

        # if two level multiindex provided as target, it should be written there
        # here we test converting multiindex in place
        df_2lvl = DataFrame(data=d)
        df_2lvl.columns = MultiIndex.from_product((["custom"],
                                                   df_2lvl.columns.values))

        sto = StrToComposition(target_col_id=None, overwrite_data=True)

        df_2lvl = sto.featurize_dataframe(
            df_2lvl, ("custom", "comp_str"), multiindex=True, inplace=False)
        self.assertEqual(df_2lvl[("custom", "comp_str")].tolist(),
                         [Composition("Fe2"), Composition("MnO2")])

        # Try inplace multiindex conversion with return errors
        df_2lvl = DataFrame(data=d)
        df_2lvl.columns = MultiIndex.from_product((["custom"],
                                                   df_2lvl.columns.values))

        sto = StrToComposition(target_col_id=None, overwrite_data=True)
        df_2lvl = sto.featurize_dataframe(
            df_2lvl, ("custom", "comp_str"), multiindex=True,
            return_errors=True, ignore_errors=True)

        self.assertTrue(
            all(df_2lvl[("custom", "StrToComposition Exceptions")].isnull()))

    def test_conversion_multiindex_dynamic(self):
        # test dynamic target_col_id setting with multiindex

        coords = [[0, 0, 0], [0.75, 0.5, 0.75]]
        lattice = Lattice([[3.8401979337, 0.00, 0.00],
                           [1.9200989668, 3.3257101909, 0.00],
                           [0.00, -2.2171384943, 3.1355090603]])
        struct = Structure(lattice, ["Si"] * 2, coords)
        d = {'structure_dict': [struct.as_dict(), struct.as_dict()]}
        df_2lvl = DataFrame(data=d)
        df_2lvl.columns = MultiIndex.from_product((["custom"],
                                                   df_2lvl.columns.values))

        dto = DictToObject()
        df_2lvl = dto.featurize_dataframe(df_2lvl, ('custom', 'structure_dict'),
                                          multiindex=True)
        new_col_id = ('DictToObject', 'structure_dict_object')
        self.assertEqual(df_2lvl[new_col_id].tolist()[0], struct)
        self.assertEqual(df_2lvl[new_col_id].tolist()[1], struct)

    @unittest.skipIf(not SETTINGS.get("PMG_MAPI_KEY", ""),
                     "PMG_MAPI_KEY not in environment variables.")
    def test_composition_to_structurefromMP(self):
        df = DataFrame(data={"composition": [Composition("Fe2O3"),
                                             Composition("N9Al34Fe234")]})

        cto = CompositionToStructureFromMP()
        df = cto.featurize_dataframe(df, 'composition')
        structures = df["structure"].tolist()
        self.assertTrue(isinstance(structures[0], Structure))
        self.assertGreaterEqual(len(structures[0]), 5)  # has at least 5 sites
        self.assertTrue(math.isnan(structures[1]))
Ejemplo n.º 39
0
from matplotlib import rc
from monty.json import MontyDecoder, MontyEncoder
from pymatgen import Composition, SETTINGS, Element, MPRester
from pymatgen.analysis.phase_diagram import PhaseDiagram, GrandPotentialPhaseDiagram
from pymatgen.analysis.reaction_calculator import ComputedReaction
from pymatgen.entries.computed_entries import ComputedEntry

__author__ = "Yizhou Zhu"
__copyright__ = ""
__version__ = "2.2"
__maintainer__ = "Yizhou Zhu"
__email__ = "*****@*****.**"
__status__ = "Production"
__date__ = "Jun 10, 2018"

PD_PRELOAD_PATH = SETTINGS.get("PMG_PD_PRELOAD_PATH")
# if PD_PRELOAD_PATH is None:
#     trypreload = False

plt.rcParams['mathtext.default'] = 'regular'
rc('font', **{'family': 'sans-serif', 'sans-serif': ['Helvetica'], 'size': 15})


class VirtualEntry(ComputedEntry):
    def __init__(self, composition, energy, name=None):
        super(VirtualEntry, self).__init__(Composition(composition), energy)
        if name:
            self.name = name

    @classmethod
    def from_composition(cls, comp, energy=0, name=None):
Ejemplo n.º 40
0
class PymatgenTest(unittest.TestCase):
    """
    Extends unittest.TestCase with functions (taken from numpy.testing.utils)
    that support the comparison of arrays.
    """
    MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
    STRUCTURES_DIR = os.path.join(MODULE_DIR, "structures")
    """
    Dict for test structures to aid testing.
    """
    TEST_STRUCTURES = {}
    for fn in os.listdir(STRUCTURES_DIR):
        TEST_STRUCTURES[fn.rsplit(".", 1)[0]] = loadfn(os.path.join(
            STRUCTURES_DIR, fn),
                                                       cls=MontyDecoder)

    @classmethod
    def get_structure(cls, name):
        return cls.TEST_STRUCTURES[name].copy()

    @classmethod
    @requires(SETTINGS.get("PMG_MAPI_KEY"), "PMG_MAPI_KEY needs to be set.")
    def get_mp_structure(cls, mpid):
        m = MPRester()
        return m.get_structure_by_material_id(mpid)

    @staticmethod
    def assert_almost_equal(actual,
                            desired,
                            decimal=7,
                            err_msg='',
                            verbose=True):
        """
        Alternative naming for assertArrayAlmostEqual.
        """
        return PymatgenTest.assertArrayAlmostEqual(actual, desired, decimal,
                                                   err_msg, verbose)

    @staticmethod
    def assert_equal(actual, desired, err_msg='', verbose=True):
        """
        Alternative naming for assertArrayEqual.
        """
        return PymatgenTest.assertArrayEqual(actual,
                                             desired,
                                             err_msg=err_msg,
                                             verbose=verbose)

    @staticmethod
    def assertArrayAlmostEqual(actual,
                               desired,
                               decimal=7,
                               err_msg='',
                               verbose=True):
        """
        Tests if two arrays are almost equal to a tolerance. The CamelCase
        naming is so that it is consistent with standard unittest methods.
        """
        return nptu.assert_almost_equal(actual, desired, decimal, err_msg,
                                        verbose)

    @staticmethod
    def assertArrayEqual(actual, desired, err_msg='', verbose=True):
        """
        Tests if two arrays are equal. The CamelCase naming is so that it is
         consistent with standard unittest methods.
        """
        return nptu.assert_equal(actual,
                                 desired,
                                 err_msg=err_msg,
                                 verbose=verbose)

    def serialize_with_pickle(self, objects, protocols=None, test_eq=True):
        """
        Test whether the object(s) can be serialized and deserialized with pickle.
        This method tries to serialize the objects with pickle and the protocols
        specified in input. Then it deserializes the pickle format and compares
        the two objects with the __eq__ operator if test_eq == True.

        Args:
            objects: Object or list of objects.
            protocols: List of pickle protocols to test. If protocols is None, HIGHEST_PROTOCOL is tested.

        Returns:
            Nested list with the objects deserialized with the specified protocols.
        """
        # Use the python version so that we get the traceback in case of errors
        import pickle as pickle
        from pymatgen.serializers.pickle_coders import pmg_pickle_load, pmg_pickle_dump

        # Build a list even when we receive a single object.
        got_single_object = False
        if not isinstance(objects, (list, tuple)):
            got_single_object = True
            objects = [objects]

        if protocols is None:
            #protocols = set([0, 1, 2] + [pickle.HIGHEST_PROTOCOL])
            protocols = [pickle.HIGHEST_PROTOCOL]

        # This list will contains the object deserialized with the different protocols.
        objects_by_protocol, errors = [], []

        for protocol in protocols:
            # Serialize and deserialize the object.
            mode = "wb"
            fd, tmpfile = tempfile.mkstemp(text="b" not in mode)

            try:
                with open(tmpfile, mode) as fh:
                    #pickle.dump(objects, fh, protocol=protocol)
                    pmg_pickle_dump(objects, fh, protocol=protocol)
            except Exception as exc:
                errors.append("pickle.dump with protocol %s raised:\n%s" %
                              (protocol, str(exc)))
                continue

            try:
                with open(tmpfile, "rb") as fh:
                    #new_objects = pickle.load(fh)
                    new_objects = pmg_pickle_load(fh)
            except Exception as exc:
                errors.append("pickle.load with protocol %s raised:\n%s" %
                              (protocol, str(exc)))
                continue

            # Test for equality
            if test_eq:
                for old_obj, new_obj in zip(objects, new_objects):
                    #print("old_obj:", type(old_obj))
                    #print(old_obj)
                    #print("new_obj:", type(new_obj))
                    #print(new_obj)
                    self.assertEqual(old_obj, new_obj)

            # Save the deserialized objects and test for equality.
            objects_by_protocol.append(new_objects)

        if errors:
            raise ValueError("\n".join(errors))

        # Return nested list so that client code can perform additional tests.
        if got_single_object:
            return [o[0] for o in objects_by_protocol]
        else:
            return objects_by_protocol

    def tmpfile_write(self, string):
        """
        Write string to a temporary file. Returns the name of the temporary file.
        """
        fd, tmpfile = tempfile.mkstemp(text=True)

        with open(tmpfile, "w") as fh:
            fh.write(string)

        return tmpfile

    def assertMSONable(self, obj, test_if_subclass=True):
        """
        Tests if obj is MSONable and tries to verify whether the contract is fullfilled.

        By default, the method tests whether obj is an instance of MSONable. 
        This check can be deactivated by setting test_if_subclass to False.
        """
        if test_if_subclass:
            self.assertIsInstance(obj, MSONable)
        self.assertDictEqual(obj.as_dict(),
                             obj.__class__.from_dict(obj.as_dict()).as_dict())
        json.loads(obj.to_json(), cls=MontyDecoder)
Ejemplo n.º 41
0
def main():
    parser = argparse.ArgumentParser(description="""
    pmg is a convenient script that uses pymatgen to perform many
    analyses, plotting and format conversions. This script works based on
    several sub-commands with their own options. To see the options for the
    sub-commands, type "pmg sub-command -h".""",
                                     epilog="""
    Author: Shyue Ping Ong
    Version: {}
    Last updated: {}""".format(__version__, __date__))

    subparsers = parser.add_subparsers()

    parser_config = subparsers.add_parser(
        "config", help="Tools for configuring pymatgen, e.g., "
                       "potcar setup, modifying .pmgrc.yaml "
                       "configuration file.")
    groups = parser_config.add_mutually_exclusive_group(required=True)
    groups.add_argument("-p", "--potcar", dest="potcar_dirs",
                        metavar="dir_name",
                        nargs=2,
                        help="Initial directory where downloaded VASP "
                             "POTCARs are extracted to, and the "
                             "output directory where the reorganized "
                             "potcars will be stored. The input "
                             "directory should be "
                             "the parent directory that contains the "
                             "POT_GGA_PAW_PBE or potpaw_PBE type "
                             "subdirectories.")
    groups.add_argument("-i", "--install", dest="install",
                        metavar="package_name",
                        choices=["enumlib", "bader"],
                        help="Install various optional command line "
                             "tools needed for full functionality.")

    groups.add_argument("-a", "--add", dest="var_spec", nargs="+",
                        help="Variables to add in the form of space "
                             "separated key value pairs. E.g., "
                             "VASP_PSP_DIR ~/psps")
    parser_config.set_defaults(func=configure_pmg)

    parser_analyze = subparsers.add_parser(
        "analyze", help="Vasp calculation analysis tools.")
    parser_analyze.add_argument("directories", metavar="dir", default=".",
                                type=str, nargs="*",
                                help="directory to process (default to .)")
    parser_analyze.add_argument("-e", "--energies", dest="get_energies",
                                action="store_true", help="Print energies")
    parser_analyze.add_argument(
        "-m", "--mag", dest="ion_list", type=str, nargs=1,
        help="Print magmoms. ION LIST can be a range "
             "(e.g., 1-2) or the string 'All' for all ions.")
    parser_analyze.add_argument(
        "-r", "--reanalyze", dest="reanalyze", action="store_true",
        help="Force reanalysis. Typically, vasp_analyzer"
             " will just reuse a vasp_analyzer_data.gz if "
             "present. This forces the analyzer to reanalyze "
             "the data.")
    parser_analyze.add_argument(
        "-f", "--format", dest="format", choices=tabulate_formats,
        default="simple",
        help="Format for table. Supports all options in tabulate package.")
    parser_analyze.add_argument(
        "-v", "--verbose", dest="verbose", action="store_true",
        help="Verbose mode. Provides detailed output on progress.")
    parser_analyze.add_argument(
        "-d", "--detailed", dest="detailed", action="store_true",
        help="Detailed, but slower mode. Parses vasprun.xml instead of "
             "separate vasp outputs.")
    parser_analyze.add_argument(
        "-s", "--sort", dest="sort", choices=["energy_per_atom", "filename"],
        default="energy_per_atom",
        help="Sort criteria. Defaults to energy / atom.")
    parser_analyze.set_defaults(func=analyze)

    parser_query = subparsers.add_parser(
        "query",
        help="Search for structures and data from the Materials Project.")
    parser_query.add_argument(
        "criteria", metavar="criteria",
        help="Search criteria. Supported formats in formulas, chemical "
             "systems, Materials Project ids, etc.")
    group = parser_query.add_mutually_exclusive_group(required=True)
    group.add_argument(
        "-s", "--structure", dest="structure", metavar="format",
        choices=["poscar", "cif", "cssr"], type=str.lower,
        help="Get structures from Materials Project and write them to a "
             "specified format.")
    group.add_argument(
        "-e", "--entries", dest="entries", metavar="filename",
        help="Get entries from Materials Project and write them to "
             "serialization file. JSON and YAML supported.")
    group.add_argument(
        "-d", "--data", dest="data", metavar="fields", nargs="*",
        help="Print a summary of entries in the Materials Project satisfying "
             "the criteria. Supply field names to include additional data. "
             "By default, the Materials Project id, formula, spacegroup, "
             "energy per atom, energy above hull are shown.")
    parser_query.set_defaults(func=do_query)

    parser_plot = subparsers.add_parser("plot", help="Plotting tool for "
                                                     "DOS, CHGCAR, XRD, etc.")
    group = parser_plot.add_mutually_exclusive_group(required=True)
    group.add_argument('-d', '--dos', dest="dos_file", metavar="vasprun.xml",
                       help="Plot DOS from a vasprun.xml")
    group.add_argument('-c', '--chgint', dest="chgcar_file", metavar="CHGCAR",
                       help="Generate charge integration plots from any "
                            "CHGCAR")
    group.add_argument('-x', '--xrd', dest="xrd_structure_file",
                       metavar="structure_file",
                       help="Generate XRD plots from any supported structure "
                            "file, e.g., CIF, POSCAR, vasprun.xml, etc.")

    parser_plot.add_argument("-s", "--site", dest="site", action="store_const",
                             const=True, help="Plot site projected DOS")
    parser_plot.add_argument("-e", "--element", dest="element", type=str,
                             nargs=1,
                             help="List of elements to plot as comma-separated"
                                  " values e.g., Fe,Mn")
    parser_plot.add_argument("-o", "--orbital", dest="orbital",
                             action="store_const", const=True,
                             help="Plot orbital projected DOS")

    parser_plot.add_argument("-i", "--indices", dest="inds", type=str,
                             nargs=1,
                             help="Comma-separated list of indices to plot "
                                  "charge integration, e.g., 1,2,3,4. If not "
                                  "provided, the code will plot the chgint "
                                  "for all symmetrically distinct atoms "
                                  "detected.")
    parser_plot.add_argument("-r", "--radius", dest="radius", type=float,
                             default=3,
                             help="Radius of integration for charge "
                                  "integration plot.")
    parser_plot.add_argument("--out_file", dest="out_file", type=str,
                             help="Save plot to file instead of displaying.")
    parser_plot.set_defaults(func=plot)

    parser_structure = subparsers.add_parser(
        "structure",
        help="Structure conversion and analysis tools.")

    parser_structure.add_argument(
        "-f", "--filenames", dest="filenames",
        metavar="filename", nargs="+",
        help="List of structure files.")

    groups = parser_structure.add_mutually_exclusive_group(required=True)
    groups.add_argument("-c", "--convert", dest="convert", action="store_true",
                        help="Convert from structure file 1 to structure "
                             "file 2. Format determined from filename. "
                             "Supported formats include POSCAR/CONTCAR, "
                             "CIF, CSSR, etc. If the keyword'prim' is within "
                             "the filename, the code will automatically attempt "
                             "to find a primitive cell.")
    groups.add_argument("-s", "--symmetry", dest="symmetry",
                        metavar="tolerance", type=float,
                        help="Determine the spacegroup using the "
                             "specified tolerance. 0.1 is usually a good "
                             "value for DFT calculations.")
    groups.add_argument("-g", "--group", dest="group",
                        choices=["element", "species"],
                        metavar="mode",
                        help="Compare a set of structures for similarity. "
                             "Element mode does not compare oxidation states. "
                             "Species mode will take into account oxidations "
                             "states.")
    groups.add_argument(
        "-l", "--localenv", dest="localenv", nargs="+",
        help="Local environment analysis. Provide bonds in the format of"
             "Center Species-Ligand Species=max_dist, e.g., H-O=0.5.")

    parser_structure.set_defaults(func=analyze_structures)

    parser_view = subparsers.add_parser("view", help="Visualize structures")
    parser_view.add_argument("filename", metavar="filename", type=str,
                             nargs=1, help="Filename")
    parser_view.add_argument("-e", "--exclude_bonding", dest="exclude_bonding",
                             type=str, nargs=1,
                             help="List of elements to exclude from bonding "
                                  "analysis. E.g., Li,Na")
    parser_view.set_defaults(func=parse_view)

    parser_diff = subparsers.add_parser(
        "diff", help="Diffing tool. For now, only INCAR supported.")
    parser_diff.add_argument("-i", "--incar", dest="incars",
                             metavar="INCAR", required=True,
                             nargs=2, help="List of INCARs to compare.")
    parser_diff.set_defaults(func=diff_incar)

    parser_potcar = subparsers.add_parser("potcar",
                                          help="Generate POTCARs")
    parser_potcar.add_argument("-f", "--functional", dest="functional",
                               type=str,
                               choices=sorted(Potcar.FUNCTIONAL_CHOICES),
                               default=SETTINGS.get("DEFAULT_FUNCTIONAL",
                                                    "PBE"),
                               help="Functional to use. Unless otherwise "
                                    "stated (e.g., US), "
                                    "refers to PAW psuedopotential.")
    group = parser_potcar.add_mutually_exclusive_group(required=True)

    group.add_argument("-s", "--symbols", dest="symbols",
                       type=str, nargs="+",
                       help="List of POTCAR symbols. Use -f to set "
                            "functional. Defaults to PBE.")
    group.add_argument("-r", "--recursive", dest="recursive",
                       type=str, nargs="+",
                       help="Dirname to find and generate from POTCAR.spec.")
    parser_potcar.set_defaults(func=generate_potcar)

    args = parser.parse_args()

    try:
        getattr(args, "func")
    except AttributeError:
        parser.print_help()
        sys.exit(0)
    args.func(args)
Ejemplo n.º 42
0
"""


__author__ = "Shyue Ping Ong"
__copyright__ = "Copyright 2012, The Materials Project"
__version__ = "0.1"
__maintainer__ = "Shyue Ping Ong"
__email__ = "*****@*****.**"
__date__ = "Jun 9, 2012"


test_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..",
                        'test_files')


@unittest.skipIf(not SETTINGS.get("PMG_MAPI_KEY"), "PMG_MAPI_KEY environment variable not set.")
class MPResterTest(unittest.TestCase):

    def setUp(self):
        self.rester = MPRester()
        warnings.simplefilter("ignore")

    def tearDown(self):
        warnings.resetwarnings()

    def test_get_all_materials_ids_doc(self):
        mids = self.rester.get_materials_ids("Al2O3")
        random.shuffle(mids)
        doc = self.rester.get_doc(mids.pop(0))
        self.assertEqual(doc["pretty_formula"], "Al2O3")
Ejemplo n.º 43
0
class PourbaixDiagramTest(unittest.TestCase):
    _multiprocess_shared_ = True

    @classmethod
    def setUpClass(cls):
        cls.test_data = loadfn(
            os.path.join(test_dir, 'pourbaix_test_data.json'))
        cls.pbx = PourbaixDiagram(cls.test_data['Zn'], filter_solids=True)
        cls.pbx_nofilter = PourbaixDiagram(cls.test_data['Zn'],
                                           filter_solids=False)

    def test_pourbaix_diagram(self):
        self.assertEqual(set([e.name for e in self.pbx.stable_entries]),
                         {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
                         "List of stable entries does not match")

        self.assertEqual(
            set([e.name for e in self.pbx_nofilter.stable_entries]), {
                "ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)", "ZnO2(s)",
                "ZnH(s)"
            }, "List of stable entries for unfiltered pbx does not match")

        pbx_lowconc = PourbaixDiagram(self.test_data['Zn'],
                                      conc_dict={"Zn": 1e-8},
                                      filter_solids=True)
        self.assertEqual(
            set([e.name for e in pbx_lowconc.stable_entries]),
            {"Zn(HO)2(aq)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"})

    def test_properties(self):
        self.assertEqual(len(self.pbx.unstable_entries), 2)

    def test_multicomponent(self):
        # Assure no ions get filtered at high concentration
        ag_n = [
            e for e in self.test_data['Ag-Te-N'] if not "Te" in e.composition
        ]
        highconc = PourbaixDiagram(ag_n,
                                   filter_solids=True,
                                   conc_dict={
                                       "Ag": 1e-5,
                                       "N": 1
                                   })
        entry_sets = [set(e.entry_id) for e in highconc.stable_entries]
        self.assertIn({"mp-124", "ion-17"}, entry_sets)

        # Binary system
        pd_binary = PourbaixDiagram(self.test_data['Ag-Te'],
                                    filter_solids=True,
                                    comp_dict={
                                        "Ag": 0.5,
                                        "Te": 0.5
                                    },
                                    conc_dict={
                                        "Ag": 1e-8,
                                        "Te": 1e-8
                                    })
        self.assertEqual(len(pd_binary.stable_entries), 30)
        test_entry = pd_binary.find_stable_entry(8, 2)
        self.assertTrue("mp-499" in test_entry.entry_id)

        # Find a specific multientry to test
        self.assertEqual(pd_binary.get_decomposition_energy(test_entry, 8, 2),
                         0)
        self.assertEqual(
            pd_binary.get_decomposition_energy(test_entry.entry_list[0], 8, 2),
            0)

        pd_ternary = PourbaixDiagram(self.test_data['Ag-Te-N'],
                                     filter_solids=True)
        self.assertEqual(len(pd_ternary.stable_entries), 49)

        ag = self.test_data['Ag-Te-N'][30]
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 2, -1),
                               0)
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 10, -2),
                               0)

        # Test invocation of pourbaix diagram from ternary data
        new_ternary = PourbaixDiagram(pd_ternary.all_entries)
        self.assertEqual(len(new_ternary.stable_entries), 49)
        self.assertAlmostEqual(new_ternary.get_decomposition_energy(ag, 2, -1),
                               0)
        self.assertAlmostEqual(
            new_ternary.get_decomposition_energy(ag, 10, -2), 0)

    def test_get_pourbaix_domains(self):
        domains = PourbaixDiagram.get_pourbaix_domains(self.test_data['Zn'])
        self.assertEqual(len(domains[0]), 7)

    def test_get_decomposition(self):
        # Test a stable entry to ensure that it's zero in the stable region
        entry = self.test_data['Zn'][12]  # Should correspond to mp-2133
        self.assertAlmostEqual(self.pbx.get_decomposition_energy(entry, 10, 1),
                               0.0, 5, "Decomposition energy of ZnO is not 0.")

        # Test an unstable entry to ensure that it's never zero
        entry = self.test_data['Zn'][11]
        ph, v = np.meshgrid(np.linspace(0, 14), np.linspace(-2, 4))
        result = self.pbx_nofilter.get_decomposition_energy(entry, ph, v)
        self.assertTrue((result >= 0).all(),
                        "Unstable energy has hull energy of 0 or less")

        # Test an unstable hydride to ensure HER correction works
        self.assertAlmostEqual(
            self.pbx.get_decomposition_energy(entry, -3, -2), 11.093744395)
        # Test a list of pHs
        self.pbx.get_decomposition_energy(entry, np.linspace(0, 2, 5), 2)

        # Test a list of Vs
        self.pbx.get_decomposition_energy(entry, 4, np.linspace(-3, 3, 10))

        # Test a set of matching arrays
        ph, v = np.meshgrid(np.linspace(0, 14), np.linspace(-3, 3))
        self.pbx.get_decomposition_energy(entry, ph, v)

    def test_multielement_parallel(self):
        # Simple test to ensure that multiprocessing is working
        test_entries = self.test_data["Ag-Te-N"]
        nproc = multiprocessing.cpu_count()
        pbx = PourbaixDiagram(test_entries, filter_solids=True, nproc=nproc)
        self.assertEqual(len(pbx.stable_entries), 49)

    @unittest.skipIf(not SETTINGS.get("PMG_MAPI_KEY"),
                     "PMG_MAPI_KEY environment variable not set.")
    def test_mpr_pipeline(self):
        from pymatgen import MPRester
        mpr = MPRester()
        data = mpr.get_pourbaix_entries(["Zn"])
        pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8})
        pbx.find_stable_entry(10, 0)

        data = mpr.get_pourbaix_entries(["Ag", "Te"])
        pbx = PourbaixDiagram(data,
                              filter_solids=True,
                              conc_dict={
                                  "Ag": 1e-8,
                                  "Te": 1e-8
                              })
        self.assertEqual(len(pbx.stable_entries), 30)
        test_entry = pbx.find_stable_entry(8, 2)
        self.assertAlmostEqual(test_entry.energy, 2.3894017960000009, 3)

        # Test custom ions
        entries = mpr.get_pourbaix_entries(["Sn", "C", "Na"])
        ion = IonEntry(Ion.from_formula("NaO28H80Sn12C24+"), -161.676)
        custom_ion_entry = PourbaixEntry(ion, entry_id='my_ion')
        pbx = PourbaixDiagram(entries + [custom_ion_entry],
                              filter_solids=True,
                              comp_dict={
                                  "Na": 1,
                                  "Sn": 12,
                                  "C": 24
                              })
        self.assertAlmostEqual(
            pbx.get_decomposition_energy(custom_ion_entry, 5, 2),
            8.31202738629504, 1)

    def test_nofilter(self):
        entries = self.test_data['Ag-Te']
        pbx = PourbaixDiagram(entries)
        pbx.get_decomposition_energy(entries[0], 0, 0)

    def test_solid_filter(self):
        entries = self.test_data['Ag-Te-N']
        pbx = PourbaixDiagram(entries, filter_solids=True)
        pbx.get_decomposition_energy(entries[0], 0, 0)

    def test_serialization(self):
        d = self.pbx.as_dict()
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(set([e.name for e in new.stable_entries]),
                         {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
                         "List of stable entries does not match")

        # Test with unprocessed entries included, this should result in the
        # previously filtered entries being included
        d = self.pbx.as_dict(include_unprocessed_entries=True)
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(
            set([e.name for e in new.stable_entries]), {
                "ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)", "ZnO2(s)",
                "ZnH(s)"
            }, "List of stable entries for unfiltered pbx does not match")

        pd_binary = PourbaixDiagram(self.test_data['Ag-Te'],
                                    filter_solids=True,
                                    comp_dict={
                                        "Ag": 0.5,
                                        "Te": 0.5
                                    },
                                    conc_dict={
                                        "Ag": 1e-8,
                                        "Te": 1e-8
                                    })
        new_binary = PourbaixDiagram.from_dict(pd_binary.as_dict())
        self.assertEqual(len(pd_binary.stable_entries),
                         len(new_binary.stable_entries))
Ejemplo n.º 44
0
from pymatgen.util.testing import PymatgenTest

"""
Created on Jun 9, 2012
"""


__author__ = "Shyue Ping Ong"
__copyright__ = "Copyright 2012, The Materials Project"
__version__ = "0.1"
__maintainer__ = "Shyue Ping Ong"
__email__ = "*****@*****.**"
__date__ = "Jun 9, 2012"


@unittest.skipIf(not SETTINGS.get("PMG_MAPI_KEY"),
                 "PMG_MAPI_KEY environment variable not set.")
class MPResterTest(PymatgenTest):
    _multiprocess_shared_ = True

    def setUp(self):
        self.rester = MPRester()
        warnings.simplefilter("ignore")

    def tearDown(self):
        warnings.simplefilter("default")
        self.rester.session.close()

    def test_get_all_materials_ids_doc(self):
        mids = self.rester.get_materials_ids("Al2O3")
        random.shuffle(mids)
Ejemplo n.º 45
0
from pymatgen.util.testing import PymatgenTest

"""
Created on Jun 9, 2012
"""


__author__ = "Shyue Ping Ong"
__copyright__ = "Copyright 2012, The Materials Project"
__version__ = "0.1"
__maintainer__ = "Shyue Ping Ong"
__email__ = "*****@*****.**"
__date__ = "Jun 9, 2012"


@unittest.skipIf(not SETTINGS.get("PMG_MAPI_KEY"),
                 "PMG_MAPI_KEY environment variable not set.")
class MPResterTest(PymatgenTest):
    _multiprocess_shared_ = True

    def setUp(self):
        self.rester = MPRester()
        warnings.simplefilter("ignore")

    def tearDown(self):
        warnings.simplefilter("default")

    def test_get_all_materials_ids_doc(self):
        mids = self.rester.get_materials_ids("Al2O3")
        random.shuffle(mids)
        doc = self.rester.get_doc(mids.pop(0))