コード例 #1
0
    def from_abivars(cls, *args, **kwargs):
        """
        Returns a new instance from a dictionary with the variables
        used in ABINIT to define the unit cell.
        """
        kwargs.update(dict(*args))
        d = kwargs
        rprim = d.get("rprim", None)
        angdeg = d.get("angdeg", None)
        acell = d["acell"]

        # Call pymatgen constructors (note that pymatgen uses Angstrom instead of Bohr).
        if rprim is not None:
            assert angdeg is None
            rprim = np.reshape(rprim, (3, 3))
            rprimd = [float(acell[i]) * rprim[i] for i in range(3)]
            return cls(ArrayWithUnit(rprimd, "bohr").to("ang"))

        elif angdeg is not None:
            # angdeg(0) is the angle between the 2nd and 3rd vectors,
            # angdeg(1) is the angle between the 1st and 3rd vectors,
            # angdeg(2) is the angle between the 1st and 2nd vectors,
            raise NotImplementedError("angdeg convention should be tested")
            angles = angdeg
            angles[1] = -angles[1]
            l = ArrayWithUnit(acell, "bohr").to("ang")
            return cls.from_lengths_and_angles(l, angdeg)

        else:
            raise ValueError(
                "Don't know how to construct a Lattice from dict: %s" % str(d))
コード例 #2
0
ファイル: gsr.py プロジェクト: xue-smile/abipy
 def read_cart_forces(self, unit="eV ang^-1"):
     """
     Read and return a |numpy-array| with the cartesian forces in unit ``unit``.
     Shape (natom, 3)
     """
     return ArrayWithUnit(self.read_value("cartesian_forces"),
                          "Ha bohr^-1").to(unit)
コード例 #3
0
 def test_factors(self):
     e = EnergyArray([27.21138386, 1], "eV").to("Ha")
     self.assertTrue(str(e).endswith("Ha"))
     l = LengthArray([1.0], "ang").to("bohr")
     self.assertTrue(str(l).endswith(" bohr"))
     v = ArrayWithUnit([1, 2, 3], "bohr^3").to("ang^3")
     self.assertTrue(str(v).endswith(' ang^3'))
コード例 #4
0
 def test_factors(self):
     e = EnergyArray([27.21138386, 1], "eV").to("Ha")
     self.assertTrue(str(e) == "[ 0.99999996  0.03674932] Ha")
     l = LengthArray([1.0], "ang").to("bohr")
     self.assertTrue(str(l) == "[ 1.88972612] bohr")
     v = ArrayWithUnit([1, 2, 3], "bohr^3").to("ang^3")
     self.assertTrue(str(v) == '[ 0.14818471  0.29636942  0.44455413] ang^3')
コード例 #5
0
    def to_abivars(self):
        "Returns a dictionary with the abinit variables."
        types_of_specie = self.types_of_specie
        natom = self.num_sites

        znucl_type = [specie.number for specie in types_of_specie]

        znucl_atoms = self.atomic_numbers

        typat = np.zeros(natom, np.int)
        for (atm_idx, site) in enumerate(self):
            typat[atm_idx] = types_of_specie.index(site.specie) + 1

        rprim = ArrayWithUnit(self.lattice.matrix, "ang").to("bohr")
        xred = np.reshape([site.frac_coords for site in self], (-1,3))

        return {
            "acell" : 3 * [1.0],
            "rprim" : rprim,
            "natom" : natom,
            "ntypat": len(types_of_specie),
            "typat" : typat,
            "xred"  : xred,
            "znucl" : znucl_type,
        }
コード例 #6
0
ファイル: lattice.py プロジェクト: yanguang21/pymatgen
    def from_dict(cls, d, fmt=None, **kwargs):
        """
        Create a Lattice from a dictionary containing the a, b, c, alpha, beta,
        and gamma parameters.

        """
        if fmt == "abivars":
            kwargs.update(d)
            d = kwargs
            rprim = d.get("rprim", None)
            angdeg = d.get("angdeg", None)
            acell = d["acell"]

            # Call pymatgen constructors (note that pymatgen uses Angstrom instead of Bohr).
            if rprim is not None:
                assert angdeg is None
                rprim = np.reshape(rprim, (3, 3))
                rprimd = [float(acell[i]) * rprim[i] for i in range(3)]
                return cls(ArrayWithUnit(rprimd, "bohr").to("ang"))

            elif angdeg is not None:
                # angdeg(0) is the angle between the 2nd and 3rd vectors,
                # angdeg(1) is the angle between the 1st and 3rd vectors,
                # angdeg(2) is the angle between the 1st and 2nd vectors,
                raise NotImplementedError("angdeg convention should be tested")
                angles = angdeg
                angles[1] = -angles[1]
                l = ArrayWithUnit(acell, "bohr").to("ang")
                return cls.from_lengths_and_angles(l, angdeg)

            else:
                raise ValueError(
                    "Don't know how to construct a Lattice from dict: %s" %
                    str(d))

        if "matrix" in d:
            return cls(d["matrix"])
        else:
            return cls.from_parameters(d["a"], d["b"], d["c"], d["alpha"],
                                       d["beta"], d["gamma"])
コード例 #7
0
def structure_from_etsf_file(ncdata, site_properties=None):
    """
    Reads and returns a pymatgen structure from a NetCDF file
    containing crystallographic data in the ETSF-IO format.

    Args:
        ncdata:
            filename or NetcdfReader instance.
        site_properties:
            Dictionary with site properties.
    """
    ncdata, closeit = as_ncreader(ncdata)

    # TODO check whether atomic units are used
    lattice = ArrayWithUnit(ncdata.read_value("primitive_vectors"),
                            "bohr").to("ang")

    red_coords = ncdata.read_value("reduced_atom_positions")
    natom = len(red_coords)

    znucl_type = ncdata.read_value("atomic_numbers")

    # type_atom[0:natom] --> index Between 1 and number of atom species
    type_atom = ncdata.read_value("atom_species")

    # Fortran to C index and float --> int conversion.
    species = natom * [None]
    for atom in range(natom):
        type_idx = type_atom[atom] - 1
        species[atom] = int(znucl_type[type_idx])

    d = {}
    if site_properties is not None:
        for prop in site_properties:
            d[property] = ncdata.read_value(prop)

    structure = Structure(lattice, species, red_coords, site_properties=d)

    # Quick and dirty hack.
    # I need an abipy structure since I need to_abivars and other methods.
    #from pymatgen.io.abinitio.abiobjects import AbiStructure
    #structure.__class__ = AbiStructure
    try:
        from abipy.core.structure import Structure as AbipyStructure
        structure.__class__ = AbipyStructure
    except ImportError:
        pass

    if closeit:
        ncdata.close()

    return structure
コード例 #8
0
def structure_to_abivars(structure, **kwargs):
    """
    Receives a structure and returns a dictionary with the ABINIT variables.
    """
    types_of_specie = structure.types_of_specie
    natom = structure.num_sites

    znucl_type = [specie.number for specie in types_of_specie]

    znucl_atoms = structure.atomic_numbers

    typat = np.zeros(natom, np.int)
    for atm_idx, site in enumerate(structure):
        typat[atm_idx] = types_of_specie.index(site.specie) + 1

    rprim = ArrayWithUnit(structure.lattice.matrix, "ang").to("bohr")
    xred = np.reshape([site.frac_coords for site in structure], (-1,3))

    # Set small values to zero. This usually happens when the CIF file
    # does not give structure parameters with enough digits.
    rprim = np.where(np.abs(rprim) > 1e-8, rprim, 0.0)
    xred = np.where(np.abs(xred) > 1e-8, xred, 0.0)

    # Info on atoms.
    d = dict(
        natom=natom,
        ntypat=len(types_of_specie),
        typat=typat,
        znucl=znucl_type,
        xred=xred,
    )

    # Add info on the lattice.
    # Should we use (rprim, acell) or (angdeg, acell) to specify the lattice?
    geomode = kwargs.pop("geomode", "rprim")
    #latt_dict = structure.lattice.to_abivars(geomode=geomode)

    if geomode == "rprim":
        d.update(dict(
            acell=3 * [1.0],
            rprim=rprim))

    elif geomode == "angdeg":
        d.update(dict(
            acell=3 * [1.0],
            angdeg=angdeg))
    else:
        raise ValueError("Wrong value for geomode: %s" % geomode)

    return d
コード例 #9
0
    def boxed_molecule(cls, pseudos, cart_coords, acell=3 * (10, )):
        """
        Creates a molecule in a periodic box of lengths acell [Bohr]

        Args:
            pseudos: List of pseudopotentials
            cart_coords: Cartesian coordinates
            acell: Lengths of the box in *Bohr*
        """
        cart_coords = np.atleast_2d(cart_coords)

        molecule = pymatgen.Molecule([p.symbol for p in pseudos], cart_coords)

        l = ArrayWithUnit(acell, "bohr").to("ang")

        structure = molecule.get_boxed_structure(l[0], l[1], l[2])

        return cls(structure)
コード例 #10
0
 def test_as_base_units(self):
     x = ArrayWithUnit([5, 10], "MPa")
     self.assertArrayEqual(ArrayWithUnit([5000000, 10000000], "Pa"),
                           x.as_base_units)
コード例 #11
0
 def j():
     return ArrayWithUnit([5, 10], "g")
コード例 #12
0
ファイル: abiobjects.py プロジェクト: cespejo79/pymatgen
def structure_from_abivars(cls=None, *args, **kwargs):
    """
    Build a :class:`Structure` object from a dictionary with ABINIT variables.

    Args:
        cls: Structure class to be instantiated. pymatgen.core.structure.Structure if cls is None

    example:

        al_structure = structure_from_abivars(
            acell=3*[7.5],
            rprim=[0.0, 0.5, 0.5,
                   0.5, 0.0, 0.5,
                   0.5, 0.5, 0.0],
            typat=1,
            xred=[0.0, 0.0, 0.0],
            ntypat=1,
            znucl=13,
        )

    `xred` can be replaced with `xcart` or `xangst`.
    """
    kwargs.update(dict(*args))
    d = kwargs

    cls = Structure if cls is None else cls

    #lattice = Lattice.from_dict(d, fmt="abivars")
    lattice = lattice_from_abivars(**d)
    coords, coords_are_cartesian = d.get("xred", None), False

    if coords is None:
        coords = d.get("xcart", None)
        if coords is not None:
            if "xangst" in d:
                raise ValueError("xangst and xcart are mutually exclusive")
            coords = ArrayWithUnit(coords, "bohr").to("ang")
        else:
            coords = d.get("xangst", None)
        coords_are_cartesian = True

    if coords is None:
        raise ValueError("Cannot extract coordinates from:\n %s" % str(d))

    coords = np.reshape(coords, (-1,3))

    znucl_type, typat = d["znucl"], d["typat"]

    if not isinstance(znucl_type, collections.Iterable):
        znucl_type = [znucl_type]

    if not isinstance(typat, collections.Iterable):
        typat = [typat]

    if len(typat) != len(coords):
        raise ValueError("len(typat) != len(coords):\ntypat: %s\ncoords: %s" % (typat, coords))

    # Note Fortran --> C indexing
    #znucl_type = np.rint(znucl_type)
    species = [znucl_type[typ-1] for typ in typat]

    return cls(lattice, species, coords, validate_proximity=False,
               to_unit_cell=False, coords_are_cartesian=coords_are_cartesian)
コード例 #13
0
ファイル: abiobjects.py プロジェクト: cespejo79/pymatgen
def lattice_from_abivars(cls=None, *args, **kwargs):
    """
    Returns a `Lattice` object from a dictionary
    with the Abinit variables `acell` and either `rprim` in Bohr or `angdeg`
    If acell is not given, the Abinit default is used i.e. [1,1,1] Bohr

    Args:
        cls: Lattice class to be instantiated. pymatgen.core.lattice.Lattice if cls is None

    Example:

    lattice_from_abivars(acell=3*[10], rprim=np.eye(3))
    """
    cls = Lattice if cls is None else cls
    kwargs.update(dict(*args))
    d = kwargs

    rprim = d.get("rprim", None)
    angdeg = d.get("angdeg", None)
    acell = d["acell"]

    if rprim is not None:
        if angdeg is not None:
            raise ValueError("angdeg and rprimd are mutually exclusive")
        rprim = np.reshape(rprim, (3,3))
        rprimd = [float(acell[i]) * rprim[i] for i in range(3)]
        # Call pymatgen constructors (note that pymatgen uses Angstrom instead of Bohr).
        return cls(ArrayWithUnit(rprimd, "bohr").to("ang"))

    elif angdeg is not None:
        angdeg = np.reshape(angdeg, 3)

        if np.any(angdeg <= 0.):
            raise ValueError("Angles must be > 0 but got %s" % str(angdeg))
        if angdeg.sum() >= 360.:
            raise ValueError("The sum of angdeg must be lower that 360, angdeg %s" % str(angdeg))

        # This code follows the implementation in ingeo.F90
        # See also http://www.abinit.org/doc/helpfiles/for-v7.8/input_variables/varbas.html#angdeg
        tol12 = 1e-12
        pi, sin, cos, sqrt = np.pi, np.sin, np.cos, np.sqrt
        rprim = np.zeros((3,3))
        if (abs(angdeg[0] -angdeg[1]) < tol12 and abs(angdeg[1] - angdeg[2]) < tol12 and
            abs(angdeg[0]-90.) + abs(angdeg[1]-90.) + abs(angdeg[2] -90) > tol12):
            # Treat the case of equal angles (except all right angles):
            # generates trigonal symmetry wrt third axis
            cosang = cos(pi * angdeg[0]/180.0)
            a2 = 2.0/3.0*(1.0 - cosang)
            aa = sqrt(a2)
            cc = sqrt(1.0-a2)
            rprim[0,0] = aa     ; rprim[0,1] = 0.0              ; rprim[0,2] = cc
            rprim[1,0] = -0.5*aa; rprim[1,1] = sqrt(3.0)*0.5*aa ; rprim[1,2] = cc
            rprim[2,0] = -0.5*aa; rprim[2,1] = -sqrt(3.0)*0.5*aa; rprim[2,2] = cc
        else:
            # Treat all the other cases
            rprim[0,0] = 1.0
            rprim[1,0] = cos(pi*angdeg[2]/180.)
            rprim[1,1] = sin(pi*angdeg[2]/180.)
            rprim[2,0] = cos(pi*angdeg[1]/180.)
            rprim[2,1] = (cos(pi*angdeg[0]/180.0)-rprim[1,0]*rprim[2,0])/rprim[1,1]
            rprim[2,2] = sqrt(1.0-rprim[2,0]**2-rprim[2,1]**2)

        # Call pymatgen constructors (note that pymatgen uses Angstrom instead of Bohr).
        rprimd = [float(acell[i]) * rprim[i] for i in range(3)]
        return cls(ArrayWithUnit(rprimd, "bohr").to("ang"))

    raise ValueError("Don't know how to construct a Lattice from dict: %s" % str(d))
コード例 #14
0
ファイル: hist.py プロジェクト: gmrigna/abipy
 def read_cart_forces(self, unit="eV ang^-1"):
     """Read and return a numpy array with the cartesian forces. Shape (num_steps, natom, 3)"""
     return ArrayWithUnit(self.read_value("fcart"), "Ha bohr^-1").to(unit)
コード例 #15
0
ファイル: abiobjects.py プロジェクト: JMPriest/test_matminer
def structure_to_abivars(structure, **kwargs):
    """
    Receives a structure and returns a dictionary with the ABINIT variables.
    """
    if not structure.is_ordered:
        raise ValueError("""\
Received disordered structure with partial occupancies that cannot be converted into an Abinit input
Please use OrderDisorderedStructureTransformation or EnumerateStructureTransformation
to build an appropriate supercell from partial occupancies or alternatively use the Virtual Crystal Approximation.""")

    types_of_specie = structure.types_of_specie
    natom = structure.num_sites

    znucl_type = [specie.number for specie in types_of_specie]
    znucl_atoms = structure.atomic_numbers

    typat = np.zeros(natom, np.int)
    for atm_idx, site in enumerate(structure):
        typat[atm_idx] = types_of_specie.index(site.specie) + 1

    rprim = ArrayWithUnit(structure.lattice.matrix, "ang").to("bohr")
    angdeg = structure.lattice.angles
    xred = np.reshape([site.frac_coords for site in structure], (-1, 3))

    # Set small values to zero. This usually happens when the CIF file
    # does not give structure parameters with enough digits.
    rprim = np.where(np.abs(rprim) > 1e-8, rprim, 0.0)
    xred = np.where(np.abs(xred) > 1e-8, xred, 0.0)

    # Info on atoms.
    d = dict(
        natom=natom,
        ntypat=len(types_of_specie),
        typat=typat,
        znucl=znucl_type,
        xred=xred,
    )

    # Add info on the lattice.
    # Should we use (rprim, acell) or (angdeg, acell) to specify the lattice?
    geomode = kwargs.pop("geomode", "rprim")
    if geomode == "automatic":
        geomode = "rprim"
        if structure.lattice.is_hexagonal: # or structure.lattice.is_rhombohedral
            geomode = "angdeg"
            angdeg = structure.lattice.angles
            # Here one could polish a bit the numerical values if they are not exact.
            # Note that in pmg the angles are 12, 20, 01 while in Abinit 12, 02, 01
            # One should make sure that the orientation is preserved (see Curtarolo's settings)

    if geomode == "rprim":
        d.update(
            acell=3 * [1.0],
            rprim=rprim,
        )

    elif geomode == "angdeg":
        d.update(
            acell=ArrayWithUnit(structure.lattice.abc, "ang").to("bohr"),
            angdeg=angdeg,
        )
    else:
        raise ValueError("Wrong value for geomode: %s" % geomode)

    return d