Exemple #1
0
class NthOrderElasticTensor(Tensor):
    """
    An object representing an nth-order tensor expansion
    of the stress-strain constitutive equations
    """
    GPa_to_eV_A3 = Unit("GPa").get_conversion_factor(Unit("eV ang^-3"))
    symbol = "C"

    def __new__(cls, input_array, check_rank=None, tol=1e-4):
        obj = super(NthOrderElasticTensor, cls).__new__(cls,
                                                        input_array,
                                                        check_rank=check_rank)
        if obj.rank % 2 != 0:
            raise ValueError("ElasticTensor must have even rank")
        if not obj.is_voigt_symmetric(tol):
            warnings.warn("Input elastic tensor does not satisfy "
                          "standard voigt symmetries")
        return obj.view(cls)

    @property
    def order(self):
        """
        Order of the elastic tensor
        """
        return self.rank // 2

    def calculate_stress(self, strain):
        """
        Calculate's a given elastic tensor's contribution to the
        stress using Einstein summation

        Args:
            strain (3x3 array-like): matrix corresponding to strain
        """
        strain = np.array(strain)
        if strain.shape == (6, ):
            strain = Strain.from_voigt(strain)
        assert strain.shape == (3, 3), "Strain must be 3x3 or voigt-notation"
        stress_matrix = self.einsum_sequence([strain]*(self.order - 1)) \
                / factorial(self.order - 1)
        return Stress(stress_matrix)

    def energy_density(self, strain, convert_GPa_to_eV=True):
        """
        Calculates the elastic energy density due to a strain
        """
        e_density = np.sum(self.calculate_stress(strain) * strain) / self.order
        if convert_GPa_to_eV:
            e_density *= self.GPa_to_eV_A3  # Conversion factor for GPa to eV/A^3
        return e_density

    @classmethod
    def from_diff_fit(cls,
                      strains,
                      stresses,
                      eq_stress=None,
                      order=2,
                      tol=1e-10):
        return cls(
            diff_fit(strains, stresses, eq_stress, order, tol)[order - 2])
Exemple #2
0
    def __init__(self, symbol):
        self.symbol = "%s" % symbol
        d = _pt_data[symbol]

        # Store key variables for quick access
        self.Z = d["Atomic no"]
        self.X = d.get("X", 0)
        for a in ["mendeleev_no", "electrical_resistivity",
                  "velocity_of_sound", "reflectivity",
                  "refractive_index", "poissons_ratio", "molar_volume",
                  "electronic_structure", "thermal_conductivity",
                  "boiling_point", "melting_point",
                  "critical_temperature", "superconduction_temperature",
                  "liquid_range", "bulk_modulus", "youngs_modulus",
                  "brinell_hardness", "rigidity_modulus",
                  "mineral_hardness", "vickers_hardness",
                  "density_of_solid", "atomic_radius_calculated",
                  "van_der_waals_radius",
                  "coefficient_of_linear_thermal_expansion"]:
            kstr = a.capitalize().replace("_", " ")
            val = d.get(kstr, None)
            if str(val).startswith("no data"):
                val = None
            else:
                try:
                    val = float(val)
                except ValueError:
                    toks_nobracket = re.sub(r'\(.*\)', "", val)
                    toks = toks_nobracket.replace("about", "").strip().split(" ", 1)
                    if len(toks) == 2:
                        try:
                            if "10<sup>" in toks[1]:
                                base_power = re.findall(r'([+-]?\d+)', toks[1])
                                factor = "e" + base_power[1]
                                toks[0] += factor
                                if a == "electrical_resistivity":
                                    unit = "ohm m"
                                elif a == "coefficient_of_linear_thermal_expansion":
                                    unit = "K^-1"
                                else:
                                    unit = toks[1]
                                val = FloatWithUnit(toks[0], unit)
                            else:
                                unit = toks[1].replace("<sup>", "^").replace(
                                    "</sup>", "").replace("&Omega;",
                                                          "ohm")
                                units = Unit(unit)
                                if set(units.keys()).issubset(SUPPORTED_UNIT_NAMES):
                                    val = FloatWithUnit(toks[0], unit)
                        except ValueError as ex:
                            # Ignore error. val will just remain a string.
                            pass
            setattr(self, a, val)
        if str(d.get("Atomic radius", "no data")).startswith("no data"):
            self.atomic_radius = None
        else:
            self.atomic_radius = Length(d["Atomic radius"], "ang")
        self.atomic_mass = Mass(d["Atomic mass"], "amu")
        self._data = d
Exemple #3
0
    def __init__(self, symbol):
        self.symbol = "%s" % symbol
        d = _pt_data[symbol]

        # Store key variables for quick access
        self.Z = d["Atomic no"]
        self.X = d.get("X", 0)
        for a in [
                "mendeleev_no", "electrical_resistivity", "velocity_of_sound",
                "reflectivity", "refractive_index", "poissons_ratio",
                "molar_volume", "electronic_structure", "thermal_conductivity",
                "boiling_point", "melting_point", "critical_temperature",
                "superconduction_temperature", "liquid_range", "bulk_modulus",
                "youngs_modulus", "brinell_hardness", "rigidity_modulus",
                "mineral_hardness", "vickers_hardness", "density_of_solid",
                "atomic_radius_calculated", "van_der_waals_radius",
                "coefficient_of_linear_thermal_expansion"
        ]:
            kstr = a.capitalize().replace("_", " ")
            val = d.get(kstr, None)
            if str(val).startswith("no data"):
                val = None
            else:
                try:
                    val = float(val)
                except ValueError:
                    toks_nobracket = re.sub(r'\(.*\)', "", val)
                    toks = toks_nobracket.replace("about",
                                                  "").strip().split(" ", 1)
                    if len(toks) == 2:
                        try:
                            if "10<sup>" in toks[1]:
                                base_power = re.findall(r'([+-]?\d+)', toks[1])
                                factor = "e" + base_power[1]
                                toks[0] += factor
                                if a == "electrical_resistivity":
                                    unit = "ohm m"
                                elif a == "coefficient_of_linear_thermal_expansion":
                                    unit = "K^-1"
                                else:
                                    unit = toks[1]
                                val = FloatWithUnit(toks[0], unit)
                            else:
                                unit = toks[1].replace("<sup>", "^").replace(
                                    "</sup>", "").replace("&Omega;", "ohm")
                                units = Unit(unit)
                                if set(units.keys()).issubset(
                                        SUPPORTED_UNIT_NAMES):
                                    val = FloatWithUnit(toks[0], unit)
                        except ValueError as ex:
                            # Ignore error. val will just remain a string.
                            pass
            setattr(self, a, val)
        if str(d.get("Atomic radius", "no data")).startswith("no data"):
            self.atomic_radius = None
        else:
            self.atomic_radius = Length(d["Atomic radius"], "ang")
        self.atomic_mass = Mass(d["Atomic mass"], "amu")
        self._data = d
Exemple #4
0
 def __getattr__(self, item):
     if item in ["mendeleev_no", "electrical_resistivity",
                 "velocity_of_sound", "reflectivity",
                 "refractive_index", "poissons_ratio", "molar_volume",
                 "electronic_structure", "thermal_conductivity",
                 "boiling_point", "melting_point",
                 "critical_temperature", "superconduction_temperature",
                 "liquid_range", "bulk_modulus", "youngs_modulus",
                 "brinell_hardness", "rigidity_modulus",
                 "mineral_hardness", "vickers_hardness",
                 "density_of_solid", "atomic_radius_calculated",
                 "van_der_waals_radius", "atomic_orbitals",
                 "coefficient_of_linear_thermal_expansion",
                 "ground_state_term_symbol", "valence"]:
         kstr = item.capitalize().replace("_", " ")
         val = self._data.get(kstr, None)
         if str(val).startswith("no data"):
             val = None
         elif type(val) == dict:
             pass
         else:
             try:
                 val = float(val)
             except ValueError:
                 nobracket = re.sub(r'\(.*\)', "", val)
                 toks = nobracket.replace("about", "").strip().split(" ", 1)
                 if len(toks) == 2:
                     try:
                         if "10<sup>" in toks[1]:
                             base_power = re.findall(r'([+-]?\d+)', toks[1])
                             factor = "e" + base_power[1]
                             if toks[0] in ["&gt;", "high"]:
                                 toks[0] = "1"  # return the border value
                             toks[0] += factor
                             if item == "electrical_resistivity":
                                 unit = "ohm m"
                             elif (
                                     item ==
                                     "coefficient_of_linear_thermal_expansion"
                             ):
                                 unit = "K^-1"
                             else:
                                 unit = toks[1]
                             val = FloatWithUnit(toks[0], unit)
                         else:
                             unit = toks[1].replace("<sup>", "^").replace(
                                 "</sup>", "").replace("&Omega;",
                                                       "ohm")
                             units = Unit(unit)
                             if set(units.keys()).issubset(
                                     SUPPORTED_UNIT_NAMES):
                                 val = FloatWithUnit(toks[0], unit)
                     except ValueError as ex:
                         # Ignore error. val will just remain a string.
                         pass
         return val
     raise AttributeError
Exemple #5
0
 def __getattr__(self, item):
     if item in ["mendeleev_no", "electrical_resistivity",
                 "velocity_of_sound", "reflectivity",
                 "refractive_index", "poissons_ratio", "molar_volume",
                 "electronic_structure", "thermal_conductivity",
                 "boiling_point", "melting_point",
                 "critical_temperature", "superconduction_temperature",
                 "liquid_range", "bulk_modulus", "youngs_modulus",
                 "brinell_hardness", "rigidity_modulus",
                 "mineral_hardness", "vickers_hardness",
                 "density_of_solid", "atomic_radius_calculated",
                 "van_der_waals_radius", "atomic_orbitals",
                 "coefficient_of_linear_thermal_expansion"]:
         kstr = item.capitalize().replace("_", " ")
         val = self._data.get(kstr, None)
         if str(val).startswith("no data"):
             val = None
         elif type(val) == dict:
             pass
         else:
             try:
                 val = float(val)
             except ValueError:
                 nobracket = re.sub(r'\(.*\)', "", val)
                 toks = nobracket.replace("about", "").strip().split(" ", 1)
                 if len(toks) == 2:
                     try:
                         if "10<sup>" in toks[1]:
                             base_power = re.findall(r'([+-]?\d+)', toks[1])
                             factor = "e" + base_power[1]
                             if toks[0] in ["&gt;", "high"]:
                                 toks[0] = "1"  # return the border value
                             toks[0] += factor
                             if item == "electrical_resistivity":
                                 unit = "ohm m"
                             elif (
                                 item ==
                                 "coefficient_of_linear_thermal_expansion"
                             ):
                                 unit = "K^-1"
                             else:
                                 unit = toks[1]
                             val = FloatWithUnit(toks[0], unit)
                         else:
                             unit = toks[1].replace("<sup>", "^").replace(
                                 "</sup>", "").replace("&Omega;",
                                                       "ohm")
                             units = Unit(unit)
                             if set(units.keys()).issubset(
                                     SUPPORTED_UNIT_NAMES):
                                 val = FloatWithUnit(toks[0], unit)
                     except ValueError as ex:
                         # Ignore error. val will just remain a string.
                         pass
         return val
     raise AttributeError
Exemple #6
0
    def test_init(self):
        u1 = Unit((("m", 1), ("s", -1)))
        self.assertEqual(str(u1), "m s^-1")
        u2 = Unit("kg m ^ 2 s ^ -2")
        self.assertEqual(str(u2), "J")
        self.assertEqual(str(u1 * u2), "J m s^-1")
        self.assertEqual(str(u2 / u1), "J s m^-1")
        self.assertEqual(str(u1 / Unit("m")), "s^-1")
        self.assertEqual(str(u1 * Unit("s")), "m")

        acc = u1 / Unit("s")
        newton = Unit("kg") * acc
        self.assertEqual(str(newton * Unit("m")), "N m")
Exemple #7
0
    def test_unitized(self):

        @unitized("eV")
        def f():
            return [1, 2, 3]

        self.assertEqual(str(f()[0]), "1.0 eV")
        self.assertIsInstance(f(), list)

        @unitized("eV")
        def g():
            return 2, 3, 4

        self.assertEqual(str(g()[0]), "2.0 eV")
        self.assertIsInstance(g(), tuple)

        @unitized("pm")
        def h():
            d = collections.OrderedDict()
            for i in range(3):
                d[i] = i * 20
            return d

        self.assertEqual(str(h()[1]), "20.0 pm")
        self.assertIsInstance(h(), collections.OrderedDict)

        @unitized("kg")
        def i():
            return FloatWithUnit(5, "g")

        self.assertEqual(i(), FloatWithUnit(0.005, "kg"))

        @unitized("kg")
        def j():
            return ArrayWithUnit([5, 10], "g")

        j_out = j()
        self.assertEqual(j_out.unit, Unit("kg"))
        self.assertEqual(j_out[0], 0.005)
        self.assertEqual(j_out[1], 0.01)
def get_pymatgen_descriptor(composition, property_name):
    """
    Get descriptor data for elements in a compound from pymatgen.

    Args:
        composition (str/Composition): Either pymatgen Composition object or string formula,
            eg: "NaCl", "Na+1Cl-1", "Fe2+3O3-2" or "Fe2 +3 O3 -2"
            Notes:
                 - For 'ionic_radii' property, the Composition object must be made of oxidation
                    state decorated Specie objects not the plain Element objects.
                    eg.  fe2o3 = Composition({Specie("Fe", 3): 2, Specie("O", -2): 3})
                 - For string formula, the oxidation state sign(+ or -) must be specified explicitly.
                    eg.  "Fe2+3O3-2"

        property_name (str): pymatgen element attribute name, as defined in the Element class at
            http://pymatgen.org/_modules/pymatgen/core/periodic_table.html

    Returns:
        (list) of values containing descriptor floats for each atom in the compound(sorted by the
            electronegativity of the contituent atoms)

    """
    eldata = []
    # what are these named tuples for? not used or returned! -KM
    eldata_tup_lst = []
    eldata_tup = collections.namedtuple('eldata_tup', 'element propname propvalue propunit amt')

    oxidation_states = {}
    if isinstance(composition, Composition):
        # check whether the composition is composed of oxidation state decorates species (not just plain Elements)
        if hasattr(composition.elements[0], "oxi_state"):
            oxidation_states = dict([(str(sp.element), sp.oxi_state) for sp in composition.elements])
        el_amt_dict = composition.get_el_amt_dict()
    # string
    else:
        comp, oxidation_states = get_composition_oxidation_state(composition)
        el_amt_dict = comp.get_el_amt_dict()

    symbols = sorted(el_amt_dict.keys(), key=lambda sym: get_el_sp(sym).X)

    for el_sym in symbols:

        element = Element(el_sym)
        property_value = None
        property_units = None

        try:
            p = getattr(element, property_name)
        except AttributeError:
            print("{} attribute missing".format(property_name))
            raise

        if p is not None:
            if property_name in ['ionic_radii']:
                if oxidation_states:
                    property_value = element.ionic_radii[oxidation_states[el_sym]]
                    property_units = Unit("ang")
                else:
                    raise ValueError("oxidation state not given for {}; It does not yield a unique "
                                     "number per Element".format(property_name))
            else:
                property_value = float(p)

            # units are None for these pymatgen descriptors
            # todo: there seem to be a lot more unitless descriptors which are not listed here... -Alex D
            if property_name not in ['X', 'Z', 'group', 'row', 'number', 'mendeleev_no', 'ionic_radii']:
                property_units = p.unit

        # Make a named tuple out of all the available information
        eldata_tup_lst.append(eldata_tup(element=el_sym, propname=property_name, propvalue=property_value,
                                         propunit=property_units, amt=el_amt_dict[el_sym]))

        # Add descriptor values, one for each atom in the compound
        for i in range(int(el_amt_dict[el_sym])):
            eldata.append(property_value)

    return eldata