class ElasticTensorTest(PymatgenTest): def setUp(self): self.voigt_1 = [[59.33, 28.08, 28.08, 0, 0, 0], [28.08, 59.31, 28.07, 0, 0, 0], [28.08, 28.07, 59.32, 0, 0, 0], [0, 0, 0, 26.35, 0, 0], [0, 0, 0, 0, 26.35, 0], [0, 0, 0, 0, 0, 26.35]] mat = np.random.randn(6, 6) mat = mat + np.transpose(mat) self.rand_elastic_tensor = ElasticTensor.from_voigt(mat) self.ft = np.array([[[[59.33, 0, 0], [0, 28.08, 0], [0, 0, 28.08]], [[0, 26.35, 0], [26.35, 0, 0], [0, 0, 0]], [[0, 0, 26.35], [0, 0, 0], [26.35, 0, 0]]], [[[0, 26.35, 0], [26.35, 0, 0], [0, 0, 0]], [[28.08, 0, 0], [0, 59.31, 0], [0, 0, 28.07]], [[0, 0, 0], [0, 0, 26.35], [0, 26.35, 0]]], [[[0, 0, 26.35], [0, 0, 0], [26.35, 0, 0]], [[0, 0, 0], [0, 0, 26.35], [0, 26.35, 0]], [[28.08, 0, 0], [0, 28.07, 0], [0, 0, 59.32]]]]) self.elastic_tensor_1 = ElasticTensor(self.ft) filepath = os.path.join(test_dir, 'Sn_def_stress.json') with open(filepath) as f: self.def_stress_dict = json.load(f) with open(os.path.join(test_dir, 'test_toec_data.json')) as f: self.toec_dict = json.load(f) self.structure = self.get_structure("Sn") warnings.simplefilter("always") def test_properties(self): # compliance tensor ct = ComplianceTensor.from_voigt( np.linalg.inv(self.elastic_tensor_1.voigt)) self.assertArrayAlmostEqual(ct, self.elastic_tensor_1.compliance_tensor) # KG average properties self.assertAlmostEqual(38.49111111111, self.elastic_tensor_1.k_voigt) self.assertAlmostEqual(22.05866666666, self.elastic_tensor_1.g_voigt) self.assertAlmostEqual(38.49110945133, self.elastic_tensor_1.k_reuss) self.assertAlmostEqual(20.67146635306, self.elastic_tensor_1.g_reuss) self.assertAlmostEqual(38.49111028122, self.elastic_tensor_1.k_vrh) self.assertAlmostEqual(21.36506650986, self.elastic_tensor_1.g_vrh) # universal anisotropy self.assertAlmostEqual(0.33553509658699, self.elastic_tensor_1.universal_anisotropy) # homogeneous poisson self.assertAlmostEqual(0.26579965576472, self.elastic_tensor_1.homogeneous_poisson) # voigt notation tensor self.assertArrayAlmostEqual(self.elastic_tensor_1.voigt, self.voigt_1) # young's modulus self.assertAlmostEqual(54087787667.160583, self.elastic_tensor_1.y_mod) # prop dict prop_dict = self.elastic_tensor_1.property_dict self.assertAlmostEqual(prop_dict["homogeneous_poisson"], 0.26579965576) for k, v in prop_dict.items(): self.assertAlmostEqual(getattr(self.elastic_tensor_1, k), v) def test_directional_elastic_mod(self): self.assertAlmostEqual( self.elastic_tensor_1.directional_elastic_mod([1, 0, 0]), self.elastic_tensor_1.voigt[0, 0]) self.assertAlmostEqual( self.elastic_tensor_1.directional_elastic_mod([1, 1, 1]), 73.624444444) def test_compliance_tensor(self): stress = self.elastic_tensor_1.calculate_stress([0.01] + [0] * 5) comp = self.elastic_tensor_1.compliance_tensor strain = Strain(comp.einsum_sequence([stress])) self.assertArrayAlmostEqual(strain.voigt, [0.01] + [0] * 5) def test_directional_poisson_ratio(self): v_12 = self.elastic_tensor_1.directional_poisson_ratio([1, 0, 0], [0, 1, 0]) self.assertAlmostEqual(v_12, 0.321, places=3) def test_structure_based_methods(self): # trans_velocity self.assertAlmostEqual(1996.35019877, self.elastic_tensor_1.trans_v(self.structure)) # long_velocity self.assertAlmostEqual(3534.68123832, self.elastic_tensor_1.long_v(self.structure)) # Snyder properties self.assertAlmostEqual(18.06127074, self.elastic_tensor_1.snyder_ac(self.structure)) self.assertAlmostEqual( 0.18937465, self.elastic_tensor_1.snyder_opt(self.structure)) self.assertAlmostEqual( 18.25064540, self.elastic_tensor_1.snyder_total(self.structure)) # Clarke self.assertAlmostEqual( 0.3450307, self.elastic_tensor_1.clarke_thermalcond(self.structure)) # Cahill self.assertAlmostEqual( 0.37896275, self.elastic_tensor_1.cahill_thermalcond(self.structure)) # Debye self.assertAlmostEqual( 198.8037985019, self.elastic_tensor_1.debye_temperature(self.structure)) # structure-property dict sprop_dict = self.elastic_tensor_1.get_structure_property_dict( self.structure) self.assertAlmostEqual(sprop_dict["long_v"], 3534.68123832) for val in sprop_dict.values(): self.assertFalse(isinstance(val, FloatWithUnit)) for k, v in sprop_dict.items(): if k == "structure": self.assertEqual(v, self.structure) else: f = getattr(self.elastic_tensor_1, k) if callable(f): self.assertAlmostEqual( getattr(self.elastic_tensor_1, k)(self.structure), v) else: self.assertAlmostEqual(getattr(self.elastic_tensor_1, k), v) # Test other sprop dict modes sprop_dict = self.elastic_tensor_1.get_structure_property_dict( self.structure, include_base_props=False) self.assertFalse("k_vrh" in sprop_dict) # Test ValueError being raised for structure properties test_et = deepcopy(self.elastic_tensor_1) test_et[0][0][0][0] = -100000 prop_dict = test_et.property_dict for attr_name in sprop_dict: if not attr_name in (list(prop_dict.keys()) + ['structure']): self.assertRaises(ValueError, getattr(test_et, attr_name), self.structure) self.assertRaises(ValueError, test_et.get_structure_property_dict, self.structure) noval_sprop_dict = test_et.get_structure_property_dict( self.structure, ignore_errors=True) self.assertIsNone(noval_sprop_dict['snyder_ac']) def test_new(self): self.assertArrayAlmostEqual(self.elastic_tensor_1, ElasticTensor(self.ft)) nonsymm = self.ft nonsymm[0, 1, 2, 2] += 1.0 with warnings.catch_warnings(record=True) as w: ElasticTensor(nonsymm) self.assertEqual(len(w), 1) badtensor1 = np.zeros((3, 3, 3)) badtensor2 = np.zeros((3, 3, 3, 2)) self.assertRaises(ValueError, ElasticTensor, badtensor1) self.assertRaises(ValueError, ElasticTensor, badtensor2) def test_from_pseudoinverse(self): strain_list = [ Strain.from_deformation(def_matrix) for def_matrix in self.def_stress_dict['deformations'] ] stress_list = [stress for stress in self.def_stress_dict['stresses']] with warnings.catch_warnings(record=True): et_fl = -0.1 * ElasticTensor.from_pseudoinverse( strain_list, stress_list).voigt self.assertArrayAlmostEqual( et_fl.round(2), [[59.29, 24.36, 22.46, 0, 0, 0], [ 28.06, 56.91, 22.46, 0, 0, 0 ], [28.06, 25.98, 54.67, 0, 0, 0], [0, 0, 0, 26.35, 0, 0], [0, 0, 0, 0, 26.35, 0], [0, 0, 0, 0, 0, 26.35]]) def test_from_independent_strains(self): strains = self.toec_dict["strains"] stresses = self.toec_dict["stresses"] with warnings.catch_warnings(record=True) as w: et = ElasticTensor.from_independent_strains(strains, stresses) self.assertArrayAlmostEqual(et.voigt, self.toec_dict["C2_raw"], decimal=-1) def test_energy_density(self): film_elac = ElasticTensor.from_voigt( [[324.32, 187.3, 170.92, 0., 0., 0.], [187.3, 324.32, 170.92, 0., 0., 0.], [170.92, 170.92, 408.41, 0., 0., 0.], [0., 0., 0., 150.73, 0., 0.], [0., 0., 0., 0., 150.73, 0.], [0., 0., 0., 0., 0., 238.74]]) dfm = Deformation([[-9.86004855e-01, 2.27539582e-01, -4.64426035e-17], [-2.47802121e-01, -9.91208483e-01, -7.58675185e-17], [-6.12323400e-17, -6.12323400e-17, 1.00000000e+00]]) self.assertAlmostEqual( film_elac.energy_density(dfm.green_lagrange_strain), 0.00125664672793) film_elac.energy_density( Strain.from_deformation([[0.99774738, 0.11520994, -0.], [-0.11520994, 0.99774738, 0.], [ -0., -0., 1., ]]))
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()
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()
class ElasticTensorTest(PymatgenTest): def setUp(self): self.voigt_1 = [[59.33, 28.08, 28.08, 0, 0, 0], [28.08, 59.31, 28.07, 0, 0, 0], [28.08, 28.07, 59.32, 0, 0, 0], [0, 0, 0, 26.35, 0, 0], [0, 0, 0, 0, 26.35, 0], [0, 0, 0, 0, 0, 26.35]] mat = np.random.randn(6, 6) mat = mat + np.transpose(mat) self.rand_elastic_tensor = ElasticTensor.from_voigt(mat) self.ft = np.array([[[[59.33, 0, 0], [0, 28.08, 0], [0, 0, 28.08]], [[0, 26.35, 0], [26.35, 0, 0], [0, 0, 0]], [[0, 0, 26.35], [0, 0, 0], [26.35, 0, 0]]], [[[0, 26.35, 0], [26.35, 0, 0], [0, 0, 0]], [[28.08, 0, 0], [0, 59.31, 0], [0, 0, 28.07]], [[0, 0, 0], [0, 0, 26.35], [0, 26.35, 0]]], [[[0, 0, 26.35], [0, 0, 0], [26.35, 0, 0]], [[0, 0, 0], [0, 0, 26.35], [0, 26.35, 0]], [[28.08, 0, 0], [0, 28.07, 0], [0, 0, 59.32]]]]) self.elastic_tensor_1 = ElasticTensor(self.ft) filepath = os.path.join(test_dir, 'Sn_def_stress.json') with open(filepath) as f: self.def_stress_dict = json.load(f) with open(os.path.join(test_dir, 'test_toec_data.json')) as f: self.toec_dict = json.load(f) self.structure = self.get_structure("Sn") warnings.simplefilter("always") def test_properties(self): # compliance tensor ct = ComplianceTensor.from_voigt(np.linalg.inv(self.elastic_tensor_1.voigt)) self.assertArrayAlmostEqual(ct, self.elastic_tensor_1.compliance_tensor) # KG average properties self.assertAlmostEqual(38.49111111111, self.elastic_tensor_1.k_voigt) self.assertAlmostEqual(22.05866666666, self.elastic_tensor_1.g_voigt) self.assertAlmostEqual(38.49110945133, self.elastic_tensor_1.k_reuss) self.assertAlmostEqual(20.67146635306, self.elastic_tensor_1.g_reuss) self.assertAlmostEqual(38.49111028122, self.elastic_tensor_1.k_vrh) self.assertAlmostEqual(21.36506650986, self.elastic_tensor_1.g_vrh) # universal anisotropy self.assertAlmostEqual(0.33553509658699, self.elastic_tensor_1.universal_anisotropy) # homogeneous poisson self.assertAlmostEqual(0.26579965576472, self.elastic_tensor_1.homogeneous_poisson) # voigt notation tensor self.assertArrayAlmostEqual(self.elastic_tensor_1.voigt, self.voigt_1) # young's modulus self.assertAlmostEqual(54087787667.160583, self.elastic_tensor_1.y_mod) # prop dict prop_dict = self.elastic_tensor_1.property_dict self.assertAlmostEqual(prop_dict["homogeneous_poisson"], 0.26579965576) for k, v in prop_dict.items(): self.assertAlmostEqual(getattr(self.elastic_tensor_1, k), v) def test_directional_elastic_mod(self): self.assertAlmostEqual(self.elastic_tensor_1.directional_elastic_mod([1, 0, 0]), self.elastic_tensor_1.voigt[0, 0]) self.assertAlmostEqual(self.elastic_tensor_1.directional_elastic_mod([1, 1, 1]), 73.624444444) def test_compliance_tensor(self): stress = self.elastic_tensor_1.calculate_stress([0.01] + [0]*5) comp = self.elastic_tensor_1.compliance_tensor strain = Strain(comp.einsum_sequence([stress])) self.assertArrayAlmostEqual(strain.voigt, [0.01] + [0]*5) def test_directional_poisson_ratio(self): v_12 = self.elastic_tensor_1.directional_poisson_ratio([1, 0, 0], [0, 1, 0]) self.assertAlmostEqual(v_12, 0.321, places=3) def test_structure_based_methods(self): # trans_velocity self.assertAlmostEqual(1996.35019877, self.elastic_tensor_1.trans_v(self.structure)) # long_velocity self.assertAlmostEqual(3534.68123832, self.elastic_tensor_1.long_v(self.structure)) # Snyder properties self.assertAlmostEqual(18.06127074, self.elastic_tensor_1.snyder_ac(self.structure)) self.assertAlmostEqual(0.18937465, self.elastic_tensor_1.snyder_opt(self.structure)) self.assertAlmostEqual(18.25064540, self.elastic_tensor_1.snyder_total(self.structure)) # Clarke self.assertAlmostEqual(0.3450307, self.elastic_tensor_1.clarke_thermalcond(self.structure)) # Cahill self.assertAlmostEqual(0.37896275, self.elastic_tensor_1.cahill_thermalcond(self.structure)) # Debye self.assertAlmostEqual(198.8037985019, self.elastic_tensor_1.debye_temperature(self.structure)) # structure-property dict sprop_dict = self.elastic_tensor_1.get_structure_property_dict(self.structure) self.assertAlmostEqual(sprop_dict["long_v"], 3534.68123832) for val in sprop_dict.values(): self.assertFalse(isinstance(val, FloatWithUnit)) for k, v in sprop_dict.items(): if k=="structure": self.assertEqual(v, self.structure) else: f = getattr(self.elastic_tensor_1, k) if callable(f): self.assertAlmostEqual(getattr(self.elastic_tensor_1, k)(self.structure), v) else: self.assertAlmostEqual(getattr(self.elastic_tensor_1, k), v) # Test other sprop dict modes sprop_dict = self.elastic_tensor_1.get_structure_property_dict( self.structure, include_base_props=False) self.assertFalse("k_vrh" in sprop_dict) # Test ValueError being raised for structure properties test_et = deepcopy(self.elastic_tensor_1) test_et[0][0][0][0] = -100000 prop_dict = test_et.property_dict for attr_name in sprop_dict: if not attr_name in (list(prop_dict.keys()) + ['structure']): self.assertRaises(ValueError, getattr(test_et, attr_name), self.structure) self.assertRaises(ValueError, test_et.get_structure_property_dict, self.structure) noval_sprop_dict = test_et.get_structure_property_dict(self.structure, ignore_errors=True) self.assertIsNone(noval_sprop_dict['snyder_ac']) def test_new(self): self.assertArrayAlmostEqual(self.elastic_tensor_1, ElasticTensor(self.ft)) nonsymm = self.ft nonsymm[0, 1, 2, 2] += 1.0 with warnings.catch_warnings(record=True) as w: ElasticTensor(nonsymm) self.assertEqual(len(w), 1) badtensor1 = np.zeros((3, 3, 3)) badtensor2 = np.zeros((3, 3, 3, 2)) self.assertRaises(ValueError, ElasticTensor, badtensor1) self.assertRaises(ValueError, ElasticTensor, badtensor2) def test_from_pseudoinverse(self): strain_list = [Strain.from_deformation(def_matrix) for def_matrix in self.def_stress_dict['deformations']] stress_list = [stress for stress in self.def_stress_dict['stresses']] with warnings.catch_warnings(record=True): et_fl = -0.1*ElasticTensor.from_pseudoinverse(strain_list, stress_list).voigt self.assertArrayAlmostEqual(et_fl.round(2), [[59.29, 24.36, 22.46, 0, 0, 0], [28.06, 56.91, 22.46, 0, 0, 0], [28.06, 25.98, 54.67, 0, 0, 0], [0, 0, 0, 26.35, 0, 0], [0, 0, 0, 0, 26.35, 0], [0, 0, 0, 0, 0, 26.35]]) def test_from_independent_strains(self): strains = self.toec_dict["strains"] stresses = self.toec_dict["stresses"] with warnings.catch_warnings(record=True) as w: et = ElasticTensor.from_independent_strains(strains, stresses) self.assertArrayAlmostEqual(et.voigt, self.toec_dict["C2_raw"], decimal=-1) def test_energy_density(self): film_elac = ElasticTensor.from_voigt([ [324.32, 187.3, 170.92, 0., 0., 0.], [187.3, 324.32, 170.92, 0., 0., 0.], [170.92, 170.92, 408.41, 0., 0., 0.], [0., 0., 0., 150.73, 0., 0.], [0., 0., 0., 0., 150.73, 0.], [0., 0., 0., 0., 0., 238.74]]) dfm = Deformation([[ -9.86004855e-01,2.27539582e-01,-4.64426035e-17], [ -2.47802121e-01,-9.91208483e-01,-7.58675185e-17], [ -6.12323400e-17,-6.12323400e-17,1.00000000e+00]]) self.assertAlmostEqual(film_elac.energy_density(dfm.green_lagrange_strain), 0.00125664672793) film_elac.energy_density(Strain.from_deformation([[ 0.99774738, 0.11520994, -0. ], [-0.11520994, 0.99774738, 0. ], [-0., -0., 1., ]]))