コード例 #1
0
 def test_get_compliance_expansion(self):
     ce_exp = self.exp_cu.get_compliance_expansion()
     et_comp = ElasticTensorExpansion(ce_exp)
     strain_orig = Strain.from_voigt([0.01, 0, 0, 0, 0, 0])
     stress = self.exp_cu.calculate_stress(strain_orig)
     strain_revert = et_comp.calculate_stress(stress)
     self.assertArrayAlmostEqual(strain_orig, strain_revert, decimal=4)
コード例 #2
0
 def test_get_compliance_expansion(self):
     ce_exp = self.exp_cu.get_compliance_expansion()
     et_comp = ElasticTensorExpansion(ce_exp)
     strain_orig = Strain.from_voigt([0.01, 0, 0, 0, 0, 0])
     stress = self.exp_cu.calculate_stress(strain_orig)
     strain_revert = et_comp.calculate_stress(stress)
     self.assertArrayAlmostEqual(strain_orig, strain_revert, decimal=4)
コード例 #3
0
 def setUp(self):
     with open(os.path.join(test_dir, 'test_toec_data.json')) as f:
         self.data_dict = json.load(f)
     self.strains = [Strain(sm) for sm in self.data_dict['strains']]
     self.pk_stresses = [Stress(d) for d in self.data_dict['pk_stresses']]
     self.c2 = self.data_dict["C2_raw"]
     self.c3 = self.data_dict["C3_raw"]
     self.exp = ElasticTensorExpansion.from_voigt([self.c2, self.c3])
     self.cu = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3.623),
                                         ["Cu"], [[0] * 3])
     indices = [(0, 0), (0, 1), (3, 3)]
     values = [167.8, 113.5, 74.5]
     cu_c2 = ElasticTensor.from_values_indices(values,
                                               indices,
                                               structure=self.cu,
                                               populate=True)
     indices = [(0, 0, 0), (0, 0, 1), (0, 1, 2), (0, 3, 3), (0, 5, 5),
                (3, 4, 5)]
     values = [-1507., -965., -71., -7., -901., 45.]
     cu_c3 = Tensor.from_values_indices(values,
                                        indices,
                                        structure=self.cu,
                                        populate=True)
     self.exp_cu = ElasticTensorExpansion([cu_c2, cu_c3])
     cu_c4 = Tensor.from_voigt(self.data_dict["Cu_fourth_order"])
     self.exp_cu_4 = ElasticTensorExpansion([cu_c2, cu_c3, cu_c4])
     warnings.simplefilter("ignore")
コード例 #4
0
 def setUp(self):
     with open(os.path.join(test_dir, 'test_toec_data.json')) as f:
         self.data_dict = json.load(f)
     self.strains = [Strain(sm) for sm in self.data_dict['strains']]
     self.pk_stresses = [Stress(d) for d in self.data_dict['pk_stresses']]
     self.c2 = self.data_dict["C2_raw"]
     self.c3 = self.data_dict["C3_raw"]
     self.exp = ElasticTensorExpansion.from_voigt([self.c2, self.c3])
     self.cu = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3.623),
                                         ["Cu"], [[0]*3])
     indices = [(0, 0), (0, 1), (3, 3)]
     values = [167.8, 113.5, 74.5]
     cu_c2 = ElasticTensor.from_values_indices(values, indices, structure=self.cu,
                                               populate=True)
     indices = [(0, 0, 0), (0, 0, 1), (0, 1, 2),
                (0, 3, 3), (0, 5, 5), (3, 4, 5)]
     values = [-1507., -965., -71., -7., -901., 45.]
     cu_c3 = Tensor.from_values_indices(values, indices, structure=self.cu,
                                        populate=True)
     self.exp_cu = ElasticTensorExpansion([cu_c2, cu_c3])
     cu_c4 = Tensor.from_voigt(self.data_dict["Cu_fourth_order"])
     self.exp_cu_4 = ElasticTensorExpansion([cu_c2, cu_c3, cu_c4])
     warnings.simplefilter("ignore")
コード例 #5
0
 def test_from_diff_fit(self):
     exp = ElasticTensorExpansion.from_diff_fit(self.strains,
                                                self.pk_stresses)
コード例 #6
0
 def test_init(self):
     cijkl = Tensor.from_voigt(self.c2)
     cijklmn = Tensor.from_voigt(self.c3)
     exp = ElasticTensorExpansion([cijkl, cijklmn])
     from_voigt = ElasticTensorExpansion.from_voigt([self.c2, self.c3])
     self.assertEqual(exp.order, 3)
コード例 #7
0
class ElasticTensorExpansionTest(PymatgenTest):
    def setUp(self):
        with open(os.path.join(test_dir, 'test_toec_data.json')) as f:
            self.data_dict = json.load(f)
        self.strains = [Strain(sm) for sm in self.data_dict['strains']]
        self.pk_stresses = [Stress(d) for d in self.data_dict['pk_stresses']]
        self.c2 = self.data_dict["C2_raw"]
        self.c3 = self.data_dict["C3_raw"]
        self.exp = ElasticTensorExpansion.from_voigt([self.c2, self.c3])
        self.cu = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3.623),
                                            ["Cu"], [[0] * 3])
        indices = [(0, 0), (0, 1), (3, 3)]
        values = [167.8, 113.5, 74.5]
        cu_c2 = ElasticTensor.from_values_indices(values,
                                                  indices,
                                                  structure=self.cu,
                                                  populate=True)
        indices = [(0, 0, 0), (0, 0, 1), (0, 1, 2), (0, 3, 3), (0, 5, 5),
                   (3, 4, 5)]
        values = [-1507., -965., -71., -7., -901., 45.]
        cu_c3 = Tensor.from_values_indices(values,
                                           indices,
                                           structure=self.cu,
                                           populate=True)
        self.exp_cu = ElasticTensorExpansion([cu_c2, cu_c3])
        cu_c4 = Tensor.from_voigt(self.data_dict["Cu_fourth_order"])
        self.exp_cu_4 = ElasticTensorExpansion([cu_c2, cu_c3, cu_c4])
        warnings.simplefilter("ignore")

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

    def test_init(self):
        cijkl = Tensor.from_voigt(self.c2)
        cijklmn = Tensor.from_voigt(self.c3)
        exp = ElasticTensorExpansion([cijkl, cijklmn])
        from_voigt = ElasticTensorExpansion.from_voigt([self.c2, self.c3])
        self.assertEqual(exp.order, 3)

    def test_from_diff_fit(self):
        exp = ElasticTensorExpansion.from_diff_fit(self.strains,
                                                   self.pk_stresses)

    def test_calculate_stress(self):
        calc_stress = self.exp.calculate_stress(self.strains[0])
        self.assertArrayAlmostEqual(self.pk_stresses[0],
                                    calc_stress,
                                    decimal=2)

    def test_energy_density(self):
        edensity = self.exp.energy_density(self.strains[0])
        self.assertAlmostEqual(edensity, 1.36363099e-4)

    def test_gruneisen(self):
        # Get GGT
        ggt = self.exp_cu.get_ggt([1, 0, 0], [0, 1, 0])
        self.assertArrayAlmostEqual(
            np.eye(3) * np.array([4.92080537, 4.2852349, -0.7147651]), ggt)
        # Get TGT
        tgt = self.exp_cu.get_tgt()
        self.assertArrayAlmostEqual(tgt, np.eye(3) * 2.59631832)

        # Get heat capacity
        c0 = self.exp_cu.get_heat_capacity(0, self.cu, [1, 0, 0], [0, 1, 0])
        self.assertEqual(c0, 0.0)
        c = self.exp_cu.get_heat_capacity(300, self.cu, [1, 0, 0], [0, 1, 0])
        self.assertAlmostEqual(c, 8.285611958)

        # Get Gruneisen parameter
        gp = self.exp_cu.get_gruneisen_parameter()
        self.assertAlmostEqual(gp, 2.59631832)
        gpt = self.exp_cu.get_gruneisen_parameter(temperature=200,
                                                  structure=self.cu)

    def test_thermal_expansion_coeff(self):
        #TODO get rid of duplicates
        alpha_dp = self.exp_cu.thermal_expansion_coeff(self.cu,
                                                       300,
                                                       mode="dulong-petit")
        alpha_debye = self.exp_cu.thermal_expansion_coeff(self.cu,
                                                          300,
                                                          mode="debye")
        alpha_comp = 5.9435148e-7 * np.ones((3, 3))
        alpha_comp[np.diag_indices(3)] = 21.4533472e-06
        self.assertArrayAlmostEqual(alpha_comp, alpha_debye)

    def test_get_compliance_expansion(self):
        ce_exp = self.exp_cu.get_compliance_expansion()
        et_comp = ElasticTensorExpansion(ce_exp)
        strain_orig = Strain.from_voigt([0.01, 0, 0, 0, 0, 0])
        stress = self.exp_cu.calculate_stress(strain_orig)
        strain_revert = et_comp.calculate_stress(stress)
        self.assertArrayAlmostEqual(strain_orig, strain_revert, decimal=4)

    def test_get_effective_ecs(self):
        # Ensure zero strain is same as SOEC
        test_zero = self.exp_cu.get_effective_ecs(np.zeros((3, 3)))
        self.assertArrayAlmostEqual(test_zero, self.exp_cu[0])
        s = np.zeros((3, 3))
        s[0, 0] = 0.02
        test_2percent = self.exp_cu.get_effective_ecs(s)
        diff = test_2percent - test_zero
        self.assertArrayAlmostEqual(self.exp_cu[1].einsum_sequence([s]), diff)

    def test_get_strain_from_stress(self):
        strain = Strain.from_voigt([0.05, 0, 0, 0, 0, 0])
        stress3 = self.exp_cu.calculate_stress(strain)
        strain_revert3 = self.exp_cu.get_strain_from_stress(stress3)
        self.assertArrayAlmostEqual(strain, strain_revert3, decimal=2)
        # fourth order
        stress4 = self.exp_cu_4.calculate_stress(strain)
        strain_revert4 = self.exp_cu_4.get_strain_from_stress(stress4)
        self.assertArrayAlmostEqual(strain, strain_revert4, decimal=2)

    def test_get_yield_stress(self):
        ys = self.exp_cu_4.get_yield_stress([1, 0, 0])
コード例 #8
0
ファイル: parse_outputs.py プロジェクト: lingtikong/atomate
    def run_task(self, fw_spec):
        ref_struct = self['structure']
        d = {"analysis": {}, "initial_structure": self['structure'].as_dict()}

        # Get optimized structure
        calc_locs_opt = [
            cl for cl in fw_spec.get('calc_locs', [])
            if 'optimiz' in cl['name']
        ]
        if calc_locs_opt:
            optimize_loc = calc_locs_opt[-1]['path']
            logger.info("Parsing initial optimization directory: {}".format(
                optimize_loc))
            drone = VaspDrone()
            optimize_doc = drone.assimilate(optimize_loc)
            opt_struct = Structure.from_dict(
                optimize_doc["calcs_reversed"][0]["output"]["structure"])
            d.update({"optimized_structure": opt_struct.as_dict()})
            ref_struct = opt_struct
            eq_stress = -0.1 * Stress(optimize_doc["calcs_reversed"][0]
                                      ["output"]["ionic_steps"][-1]["stress"])
        else:
            eq_stress = None

        if self.get("fw_spec_field"):
            d.update({
                self.get("fw_spec_field"):
                fw_spec.get(self.get("fw_spec_field"))
            })

        # Get the stresses, strains, deformations from deformation tasks
        defo_dicts = fw_spec["deformation_tasks"].values()
        stresses, strains, deformations = [], [], []
        for defo_dict in defo_dicts:
            stresses.append(Stress(defo_dict["stress"]))
            strains.append(Strain(defo_dict["strain"]))
            deformations.append(Deformation(defo_dict["deformation_matrix"]))
            # Add derived stresses and strains if symmops is present
            for symmop in defo_dict.get("symmops", []):
                stresses.append(Stress(defo_dict["stress"]).transform(symmop))
                strains.append(Strain(defo_dict["strain"]).transform(symmop))
                deformations.append(
                    Deformation(
                        defo_dict["deformation_matrix"]).transform(symmop))

        stresses = [-0.1 * s for s in stresses]
        pk_stresses = [
            stress.piola_kirchoff_2(deformation)
            for stress, deformation in zip(stresses, deformations)
        ]

        d['fitting_data'] = {
            'cauchy_stresses': stresses,
            'eq_stress': eq_stress,
            'strains': strains,
            'pk_stresses': pk_stresses,
            'deformations': deformations
        }

        logger.info("Analyzing stress/strain data")
        # TODO: @montoyjh: what if it's a cubic system? don't need 6. -computron
        # TODO: Can add population method but want to think about how it should
        #           be done. -montoyjh
        order = self.get('order', 2)
        if order > 2:
            method = 'finite_difference'
        else:
            method = self.get('fitting_method', 'finite_difference')

        if method == 'finite_difference':
            result = ElasticTensorExpansion.from_diff_fit(strains,
                                                          pk_stresses,
                                                          eq_stress=eq_stress,
                                                          order=order)
            if order == 2:
                result = ElasticTensor(result[0])
        elif method == 'pseudoinverse':
            result = ElasticTensor.from_pseudoinverse(strains, pk_stresses)
        elif method == 'independent':
            result = ElasticTensor.from_independent_strains(
                strains, pk_stresses, eq_stress=eq_stress)
        else:
            raise ValueError(
                "Unsupported method, method must be finite_difference, "
                "pseudoinverse, or independent")

        ieee = result.convert_to_ieee(ref_struct)
        d.update({
            "elastic_tensor": {
                "raw": result.voigt,
                "ieee_format": ieee.voigt
            }
        })
        if order == 2:
            d.update({
                "derived_properties":
                ieee.get_structure_property_dict(ref_struct)
            })
        else:
            soec = ElasticTensor(ieee[0])
            d.update({
                "derived_properties":
                soec.get_structure_property_dict(ref_struct)
            })

        d["formula_pretty"] = ref_struct.composition.reduced_formula
        d["fitting_method"] = method
        d["order"] = order

        d = jsanitize(d)

        # Save analysis results in json or db
        db_file = env_chk(self.get('db_file'), fw_spec)
        if not db_file:
            with open("elasticity.json", "w") as f:
                f.write(json.dumps(d, default=DATETIME_HANDLER))
        else:
            db = VaspCalcDb.from_db_file(db_file, admin=True)
            db.collection = db.db["elasticity"]
            db.collection.insert_one(d)
            logger.info("Elastic analysis complete.")

        return FWAction()
コード例 #9
0
def get_elastic_analysis(opt_task, defo_tasks):
    """
    Performs the analysis of opt_tasks and defo_tasks necessary for
    an elastic analysis

    Args:
        opt_task: task doc corresponding to optimization
        defo_tasks: task_doc corresponding to deformations

    Returns:
        elastic document with fitted elastic tensor and analysis

    """
    elastic_doc = {"warnings": []}
    opt_struct = Structure.from_dict(opt_task['output']['structure'])
    input_struct = Structure.from_dict(opt_task['input']['structure'])
    # For now, discern order (i.e. TOEC) using parameters from optimization
    # TODO: figure this out more intelligently
    diff = get(opt_task, "input.incar.EDIFFG", 0)
    order = 3 if np.isclose(diff, -0.001) else 2
    explicit, derived = process_elastic_calcs(opt_task, defo_tasks)
    all_calcs = explicit + derived
    stresses = [c.get("cauchy_stress") for c in all_calcs]
    pk_stresses = [c.get("pk_stress") for c in all_calcs]
    strains = [c.get("strain") for c in all_calcs]
    elastic_doc['calculations'] = all_calcs
    vstrains = [s.zeroed(0.002).voigt for s in strains]
    if np.linalg.matrix_rank(vstrains) == 6:
        if order == 2:
            et_fit = legacy_fit(strains, stresses)
        elif order == 3:
            # Test for TOEC
            if len(strains) < 70:
                logger.info("insufficient valid strains for {} TOEC".format(
                    opt_task['formula_pretty']))
                return None
            eq_stress = -0.1 * Stress(opt_task['output']['stress'])
            # strains = [s.zeroed(0.0001) for s in strains]
            # et_expansion = pdb_function(ElasticTensorExpansion.from_diff_fit,
            #     strains, pk_stresses, eq_stress=eq_stress, tol=1e-5)
            et_exp_raw = ElasticTensorExpansion.from_diff_fit(
                strains, pk_stresses, eq_stress=eq_stress, tol=1e-6)
            et_exp = et_exp_raw.voigt_symmetrized.convert_to_ieee(opt_struct)
            et_exp = et_exp.round(1)
            et_fit = ElasticTensor(et_exp[0])
            # Update elastic doc with TOEC stuff
            tec = et_exp.thermal_expansion_coeff(opt_struct, 300)
            elastic_doc.update({
                "elastic_tensor_expansion":
                elastic_sanitize(et_exp),
                "elastic_tensor_expansion_original":
                elastic_sanitize(et_exp_raw),
                "thermal_expansion_tensor":
                tec,
                "average_linear_thermal_expansion":
                np.trace(tec) / 3
            })
        et = et_fit.voigt_symmetrized.convert_to_ieee(opt_struct)
        vasp_input = opt_task['input']
        if 'structure' in vasp_input:
            vasp_input.pop('structure')
        completed_at = max([d['completed_at'] for d in defo_tasks])
        elastic_doc.update({
            "optimization_task_id":
            opt_task['task_id'],
            "optimization_dir_name":
            opt_task['dir_name'],
            "cauchy_stresses":
            stresses,
            "strains":
            strains,
            "elastic_tensor":
            elastic_sanitize(et.zeroed(0.01).round(0)),
            # Convert compliance to 10^-12 Pa
            "compliance_tensor":
            elastic_sanitize(et.compliance_tensor * 1000),
            "elastic_tensor_original":
            elastic_sanitize(et_fit),
            "optimized_structure":
            opt_struct,
            "spacegroup":
            input_struct.get_space_group_info()[0],
            "input_structure":
            input_struct,
            "completed_at":
            completed_at,
            "optimization_input":
            vasp_input,
            "order":
            order,
            "pretty_formula":
            opt_struct.composition.reduced_formula
        })
        # Add magnetic type
        mag = CollinearMagneticStructureAnalyzer(opt_struct).ordering.value
        elastic_doc['magnetic_type'] = mag_types[mag]
        try:
            prop_dict = et.get_structure_property_dict(opt_struct)
            prop_dict.pop('structure')
        except ValueError:
            logger.debug("Negative K or G found, structure property "
                         "dict not computed")
            prop_dict = et.property_dict
        for k, v in prop_dict.items():
            if k in ['homogeneous_poisson', 'universal_anisotropy']:
                prop_dict[k] = np.round(v, 2)
            else:
                prop_dict[k] = np.round(v, 0)
        elastic_doc.update(prop_dict)
        # Update with state and warnings
        state, warnings = get_state_and_warnings(elastic_doc)
        elastic_doc.update({"state": state, "warnings": warnings})
        # TODO: add kpoints params?
        return elastic_doc
    else:
        logger.info("insufficient valid strains for {}".format(
            opt_task['formula_pretty']))
        return None
コード例 #10
0
    def process_item(self, item):
        docs, material_dict = item
        grouped = group_by_material_id(material_dict, docs, 'input_structure')
        formula = docs[0]['pretty_formula']
        if not grouped:
            formula = Structure.from_dict(list(
                material_dict.values())[0]).composition.reduced_formula
            logger.debug("No material match for {}".format(formula))

        # For now just do the most recent one that's not failed
        # TODO: better sorting of docs
        all_docs = []
        for task_id, elastic_docs in grouped.items():
            elastic_docs = sorted(elastic_docs,
                                  key=lambda x:
                                  (x['order'], x['state'], x['completed_at']))
            grouped_by_order = {
                k: list(v)
                for k, v in groupby(elastic_docs, key=lambda x: x['order'])
            }
            soec_docs = grouped_by_order.get(2)
            toec_docs = grouped_by_order.get(3)
            if soec_docs:
                final_doc = soec_docs[-1]
            else:
                final_doc = toec_docs[-1]
            structure = Structure.from_dict(final_doc['optimized_structure'])
            formula = structure.composition.reduced_formula
            elements = [s.symbol for s in structure.composition.elements]
            chemsys = '-'.join(elements)

            # Issue warning if relaxed structure differs
            warnings = final_doc.get('warnings') or []
            opt = Structure.from_dict(final_doc['optimized_structure'])
            init = Structure.from_dict(final_doc['input_structure'])
            # TODO: are these the right params?
            if not StructureMatcher().fit(init, opt):
                warnings.append("Inequivalent optimization structure")
            material_mag = CollinearMagneticStructureAnalyzer(
                opt).ordering.value
            material_mag = mag_types[material_mag]
            if final_doc['magnetic_type'] != material_mag:
                warnings.append("Elastic magnetic phase is {}".format(
                    final_doc['magnetic_type']))
            warnings = warnings or None

            # Filter for failure and warnings
            k_vrh = final_doc['k_vrh']
            if k_vrh < 0 or k_vrh > 600:
                state = 'failed'
            elif warnings is not None:
                state = 'warning'
            else:
                state = 'successful'
            final_doc.update({"warnings": warnings})
            elastic_summary = {
                'task_id': task_id,
                'all_elastic_fits': elastic_docs,
                'elasticity': final_doc,
                'spacegroup': init.get_space_group_info()[0],
                'magnetic_type': final_doc['magnetic_type'],
                'pretty_formula': formula,
                'chemsys': chemsys,
                'elements': elements,
                'last_updated': self.elasticity.lu_field,
                'state': state
            }
            if toec_docs:
                # TODO: this should be a bit more refined
                final_toec_doc = deepcopy(toec_docs[-1])
                et_exp = ElasticTensorExpansion.from_voigt(
                    final_toec_doc['elastic_tensor_expansion'])
                symbol_dict = et_exp[1].zeroed(1e-2).get_symbol_dict()
                final_toec_doc.update({"symbol_dict": symbol_dict})
                set_(elastic_summary, "elasticity.third_order", final_toec_doc)
            all_docs.append(jsanitize(elastic_summary))
            # elastic_summary.update(final_doc)
        return all_docs
コード例 #11
0
ファイル: parse_outputs.py プロジェクト: shyamd/MatMethods
    def run_task(self, fw_spec):
        ref_struct = self['structure']
        d = {
            "analysis": {},
            "initial_structure": self['structure'].as_dict()
        }

        # Get optimized structure
        calc_locs_opt = [cl for cl in fw_spec.get('calc_locs', []) if 'optimiz' in cl['name']]
        if calc_locs_opt:
            optimize_loc = calc_locs_opt[-1]['path']
            logger.info("Parsing initial optimization directory: {}".format(optimize_loc))
            drone = VaspDrone()
            optimize_doc = drone.assimilate(optimize_loc)
            opt_struct = Structure.from_dict(optimize_doc["calcs_reversed"][0]["output"]["structure"])
            d.update({"optimized_structure": opt_struct.as_dict()})
            ref_struct = opt_struct
            eq_stress = -0.1*Stress(optimize_doc["calcs_reversed"][0]["output"]["ionic_steps"][-1]["stress"])
        else:
            eq_stress = None

        if self.get("fw_spec_field"):
            d.update({self.get("fw_spec_field"): fw_spec.get(self.get("fw_spec_field"))})

        # Get the stresses, strains, deformations from deformation tasks
        defo_dicts = fw_spec["deformation_tasks"].values()
        stresses, strains, deformations = [], [], []
        for defo_dict in defo_dicts:
            stresses.append(Stress(defo_dict["stress"]))
            strains.append(Strain(defo_dict["strain"]))
            deformations.append(Deformation(defo_dict["deformation_matrix"]))
            # Add derived stresses and strains if symmops is present
            for symmop in defo_dict.get("symmops", []):
                stresses.append(Stress(defo_dict["stress"]).transform(symmop))
                strains.append(Strain(defo_dict["strain"]).transform(symmop))
                deformations.append(Deformation(defo_dict["deformation_matrix"]).transform(symmop))

        stresses = [-0.1*s for s in stresses]
        pk_stresses = [stress.piola_kirchoff_2(deformation)
                       for stress, deformation in zip(stresses, deformations)]

        d['fitting_data'] = {'cauchy_stresses': stresses,
                             'eq_stress': eq_stress,
                             'strains': strains,
                             'pk_stresses': pk_stresses,
                             'deformations': deformations
                             }

        logger.info("Analyzing stress/strain data")
        # TODO: @montoyjh: what if it's a cubic system? don't need 6. -computron
        # TODO: Can add population method but want to think about how it should
        #           be done. -montoyjh
        order = self.get('order', 2)
        if order > 2:
            method = 'finite_difference'
        else:
            method = self.get('fitting_method', 'finite_difference')

        if method == 'finite_difference':
            result = ElasticTensorExpansion.from_diff_fit(
                    strains, pk_stresses, eq_stress=eq_stress, order=order)
            if order == 2:
                result = ElasticTensor(result[0])
        elif method == 'pseudoinverse':
            result = ElasticTensor.from_pseudoinverse(strains, pk_stresses)
        elif method == 'independent':
            result = ElasticTensor.from_independent_strains(strains, pk_stresses, eq_stress=eq_stress)
        else:
            raise ValueError("Unsupported method, method must be finite_difference, "
                             "pseudoinverse, or independent")

        ieee = result.convert_to_ieee(ref_struct)
        d.update({
            "elastic_tensor": {
                "raw": result.voigt,
                "ieee_format": ieee.voigt
            }
        })
        if order == 2:
            d.update({"derived_properties": ieee.get_structure_property_dict(ref_struct)})
        else:
            soec = ElasticTensor(ieee[0])
            d.update({"derived_properties": soec.get_structure_property_dict(ref_struct)})

        d["formula_pretty"] = ref_struct.composition.reduced_formula
        d["fitting_method"] = method
        d["order"] = order

        d = jsanitize(d)

        # Save analysis results in json or db
        db_file = env_chk(self.get('db_file'), fw_spec)
        if not db_file:
            with open("elasticity.json", "w") as f:
                f.write(json.dumps(d, default=DATETIME_HANDLER))
        else:
            db = VaspCalcDb.from_db_file(db_file, admin=True)
            db.collection = db.db["elasticity"]
            db.collection.insert_one(d)
            logger.info("Elastic analysis complete.")
        
        return FWAction()
コード例 #12
0
 def test_from_diff_fit(self):
     exp = ElasticTensorExpansion.from_diff_fit(self.strains, self.pk_stresses)
コード例 #13
0
 def test_init(self):
     cijkl = Tensor.from_voigt(self.c2)
     cijklmn = Tensor.from_voigt(self.c3)
     exp = ElasticTensorExpansion([cijkl, cijklmn])
     from_voigt = ElasticTensorExpansion.from_voigt([self.c2, self.c3])
     self.assertEqual(exp.order, 3)
コード例 #14
0
class ElasticTensorExpansionTest(PymatgenTest):
    def setUp(self):
        with open(os.path.join(test_dir, 'test_toec_data.json')) as f:
            self.data_dict = json.load(f)
        self.strains = [Strain(sm) for sm in self.data_dict['strains']]
        self.pk_stresses = [Stress(d) for d in self.data_dict['pk_stresses']]
        self.c2 = self.data_dict["C2_raw"]
        self.c3 = self.data_dict["C3_raw"]
        self.exp = ElasticTensorExpansion.from_voigt([self.c2, self.c3])
        self.cu = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3.623),
                                            ["Cu"], [[0]*3])
        indices = [(0, 0), (0, 1), (3, 3)]
        values = [167.8, 113.5, 74.5]
        cu_c2 = ElasticTensor.from_values_indices(values, indices, structure=self.cu,
                                                  populate=True)
        indices = [(0, 0, 0), (0, 0, 1), (0, 1, 2),
                   (0, 3, 3), (0, 5, 5), (3, 4, 5)]
        values = [-1507., -965., -71., -7., -901., 45.]
        cu_c3 = Tensor.from_values_indices(values, indices, structure=self.cu,
                                           populate=True)
        self.exp_cu = ElasticTensorExpansion([cu_c2, cu_c3])
        cu_c4 = Tensor.from_voigt(self.data_dict["Cu_fourth_order"])
        self.exp_cu_4 = ElasticTensorExpansion([cu_c2, cu_c3, cu_c4])
        warnings.simplefilter("ignore")

    def tearDown(self):
        warnings.resetwarnings()

    def test_init(self):
        cijkl = Tensor.from_voigt(self.c2)
        cijklmn = Tensor.from_voigt(self.c3)
        exp = ElasticTensorExpansion([cijkl, cijklmn])
        from_voigt = ElasticTensorExpansion.from_voigt([self.c2, self.c3])
        self.assertEqual(exp.order, 3)

    def test_from_diff_fit(self):
        exp = ElasticTensorExpansion.from_diff_fit(self.strains, self.pk_stresses)

    def test_calculate_stress(self):
        calc_stress = self.exp.calculate_stress(self.strains[0])
        self.assertArrayAlmostEqual(self.pk_stresses[0], calc_stress, decimal=2)

    def test_energy_density(self):
        edensity = self.exp.energy_density(self.strains[0])
        self.assertAlmostEqual(edensity, 1.36363099e-4)

    def test_gruneisen(self):
        # Get GGT
        ggt = self.exp_cu.get_ggt([1, 0, 0], [0, 1, 0])
        self.assertArrayAlmostEqual(
                np.eye(3)*np.array([4.92080537, 4.2852349, -0.7147651]), ggt)
        # Get TGT
        tgt = self.exp_cu.get_tgt()
        self.assertArrayAlmostEqual(tgt, np.eye(3)*2.59631832)

        # Get heat capacity
        c0 = self.exp_cu.get_heat_capacity(0, self.cu, [1, 0, 0], [0, 1, 0])
        self.assertEqual(c0, 0.0)
        c = self.exp_cu.get_heat_capacity(300, self.cu, [1, 0, 0], [0, 1, 0])
        self.assertAlmostEqual(c, 8.285611958)

        # Get Gruneisen parameter
        gp = self.exp_cu.get_gruneisen_parameter()
        self.assertAlmostEqual(gp, 2.59631832)
        gpt = self.exp_cu.get_gruneisen_parameter(temperature=200, structure=self.cu)

    def test_thermal_expansion_coeff(self):
        #TODO get rid of duplicates
        alpha_dp = self.exp_cu.thermal_expansion_coeff(self.cu, 300,
                                                       mode="dulong-petit")
        alpha_debye = self.exp_cu.thermal_expansion_coeff(self.cu, 300,
                                                          mode="debye")
        alpha_comp = 5.9435148e-7 * np.ones((3, 3))
        alpha_comp[np.diag_indices(3)] = 21.4533472e-06
        self.assertArrayAlmostEqual(alpha_comp, alpha_debye)

    def test_get_compliance_expansion(self):
        ce_exp = self.exp_cu.get_compliance_expansion()
        et_comp = ElasticTensorExpansion(ce_exp)
        strain_orig = Strain.from_voigt([0.01, 0, 0, 0, 0, 0])
        stress = self.exp_cu.calculate_stress(strain_orig)
        strain_revert = et_comp.calculate_stress(stress)
        self.assertArrayAlmostEqual(strain_orig, strain_revert, decimal=4)

    def test_get_effective_ecs(self):
        # Ensure zero strain is same as SOEC
        test_zero = self.exp_cu.get_effective_ecs(np.zeros((3, 3)))
        self.assertArrayAlmostEqual(test_zero, self.exp_cu[0])
        s = np.zeros((3, 3))
        s[0, 0] = 0.02
        test_2percent = self.exp_cu.get_effective_ecs(s)
        diff = test_2percent - test_zero
        self.assertArrayAlmostEqual(self.exp_cu[1].einsum_sequence([s]), diff)

    def test_get_strain_from_stress(self):
        strain = Strain.from_voigt([0.05, 0, 0, 0, 0, 0])
        stress3 = self.exp_cu.calculate_stress(strain)
        strain_revert3 = self.exp_cu.get_strain_from_stress(stress3)
        self.assertArrayAlmostEqual(strain, strain_revert3, decimal=2)
        # fourth order
        stress4 = self.exp_cu_4.calculate_stress(strain)
        strain_revert4 = self.exp_cu_4.get_strain_from_stress(stress4)
        self.assertArrayAlmostEqual(strain, strain_revert4, decimal=2)

    def test_get_yield_stress(self):
        ys = self.exp_cu_4.get_yield_stress([1, 0, 0])