def test_from_voigt(self): with self.assertRaises(ValueError): ElasticTensor.from_voigt([[59.33, 28.08, 28.08, 0], [28.08, 59.31, 28.07, 0], [28.08, 28.07, 59.32, 0, 0], [0, 0, 0, 26.35, 0], [0, 0, 0, 0, 26.35]]) with warnings.catch_warnings(record=True) as w: ElasticTensor.from_voigt([[59.33, 28.08, 28.08, 0, 0, 0], [0.0, 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]]) self.assertEqual(len(w), 1)
def test_from_voigt(self): with self.assertRaises(ValueError): ElasticTensor.from_voigt([[59.33, 28.08, 28.08, 0], [28.08, 59.31, 28.07, 0], [28.08, 28.07, 59.32, 0, 0], [0, 0, 0, 26.35, 0], [0, 0, 0, 0, 26.35]]) with warnings.catch_warnings(record=True) as w: ElasticTensor.from_voigt([[59.33, 28.08, 28.08, 0, 0, 0], [0.0, 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]]) self.assertEqual(len(w), 1)
def plug_in(symbol_values): tensor = ElasticTensor.from_voigt(symbol_values["C_ij"]) structure = symbol_values["structure"] to_return = tensor.clarke_thermalcond(structure) if not isinstance(to_return, float): to_return = float(to_return) return {'t': to_return}
def test_init(self): # Film VO2 film = SpacegroupAnalyzer(self.get_structure("VO2"), symprec=0.1).get_conventional_standard_structure() # Substrate TiO2 substrate = SpacegroupAnalyzer(self.get_structure("TiO2"), symprec=0.1).get_conventional_standard_structure() film_elac = ElasticTensor.from_voigt( [ [324.32, 187.3, 170.92, 0.0, 0.0, 0.0], [187.3, 324.32, 170.92, 0.0, 0.0, 0.0], [170.92, 170.92, 408.41, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 150.73, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 150.73, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 238.74], ] ) s = SubstrateAnalyzer() matches = list(s.calculate(film, substrate, film_elac)) self.assertEqual(len(matches), 192) for match in matches: assert match is not None assert isinstance(match.match_area, float)
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 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 _evaluate(self, symbol_values): tensor = ElasticTensor.from_voigt(symbol_values["C_ij"]) structure = symbol_values["_structure"] return { 't': tensor.clarke_thermalcond(structure) }
def setUp(self): # Empty aggregated collection self.test_elasticity_agg = MongoStore("test_emmet", "elasticity_agg") self.test_elasticity_agg.connect() # Generate test materials collection self.test_materials = MongoStore("test_emmet", "materials") self.test_materials.connect() mat_docs = [] for n, formula in enumerate(['Si', 'BaNiO3', 'Li2O2', 'TiO2']): structure = PymatgenTest.get_structure(formula) structure.add_site_property("magmoms", [0.0] * len(structure)) mat_docs.append({ "task_id": "mp-{}".format(n), "structure": structure.as_dict(), "pretty_formula": formula }) self.test_materials.update(mat_docs, update_lu=False) # Create elasticity collection and add docs self.test_elasticity = MongoStore("test_emmet", "elasticity", key="optimization_task_id") self.test_elasticity.connect() si = PymatgenTest.get_structure("Si") si.add_site_property("magmoms", [0.0] * len(si)) et = ElasticTensor.from_voigt([[50, 25, 25, 0, 0, 0], [25, 50, 25, 0, 0, 0], [25, 25, 50, 0, 0, 0], [0, 0, 0, 75, 0, 0], [0, 0, 0, 0, 75, 0], [0, 0, 0, 0, 0, 75]]) doc = { "input_structure": si.copy().as_dict(), "order": 2, "magnetic_type": "non-magnetic", "optimization_task_id": "mp-1", "last_updated": datetime.utcnow(), "completed_at": datetime.utcnow(), "optimized_structure": si.copy().as_dict(), "pretty_formula": "Si", "state": "successful" } doc['elastic_tensor'] = et.voigt doc.update(et.property_dict) self.test_elasticity.update([doc]) # Insert second doc with diff params si.perturb(0.005) doc.update({ "optimized_structure": si.copy().as_dict(), "updated_at": datetime.utcnow(), "optimization_task_id": "mp-5" }) self.test_elasticity.update([doc]) self.builder = self.get_a_new_builder()
def get_et(elast_str=""): cij = np.empty((6, 6), dtype=float) elast = np.array(elast_str.split(","), dtype="float") count = 0 for ii in range(6): for jj in range(6): cij[ii][jj] = elast[count] count = count + 1 et = ElasticTensor.from_voigt(cij) return et
def get_et(elast_str=''): if elast_str == 'na': return 'na' else: cij = np.empty((6, 6), dtype=float) elast = np.array(elast_str.split(','), dtype='float') count = 0 for ii in range(6): for jj in range(6): cij[ii][jj] = elast[count] count = count + 1 et = ElasticTensor.from_voigt(cij) return et
def process_item(self, item): """ Process the tasks and materials into an elasticity collection Args: item: a dictionary of documents keyed by materials id Returns: an elasticity document """ all_docs = [] tasks, material_dict = item if not tasks: return all_docs grouped = group_by_task_id(material_dict, tasks) for mp_id, task_sets in grouped.items(): elastic_docs = [] for opt_task, defo_tasks in task_sets: elastic_doc = get_elastic_analysis(opt_task, defo_tasks) if elastic_doc: elastic_docs.append(elastic_doc) if not elastic_docs: logger.warning("No elastic doc for mp_id {}".format(mp_id)) continue # For now just do the most recent one that's not failed sorted(elastic_docs, key=lambda x: (x['state'], x['completed_at'])) final_doc = elastic_docs[-1] c_ijkl = ElasticTensor.from_voigt(final_doc['elastic_tensor']) structure = final_doc['optimized_structure'] formula = structure.composition.reduced_formula elements = [s.symbol for s in structure.composition.elements] chemsys = '-'.join(elements) final_doc.update(c_ijkl.property_dict) final_doc.update(c_ijkl.get_structure_property_dict(structure)) elastic_summary = { 'task_id': mp_id, 'all_elastic_fits': elastic_docs, 'elasticity': final_doc, 'pretty_formula': formula, 'chemsys': chemsys, 'elements': elements, 'last_updated': self.elasticity.lu_field } all_docs.append(elastic_summary) # elastic_summary.update(final_doc) return all_docs
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.000125664672793)
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 runTest(self): # Film VO2 film = SpacegroupAnalyzer(self.get_structure("VO2"), symprec=0.1).get_conventional_standard_structure() # Substrate TiO2 substrate = SpacegroupAnalyzer(self.get_structure("TiO2"), symprec=0.1).get_conventional_standard_structure() 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]]) s = SubstrateAnalyzer() matches = list(s.calculate(film,substrate,film_elac)) self.assertEqual(len(matches), 82)
def runTest(self): # Film VO2 film = SpacegroupAnalyzer( self.get_structure("VO2"), symprec=0.1).get_conventional_standard_structure() # Substrate TiO2 substrate = SpacegroupAnalyzer( self.get_structure("TiO2"), symprec=0.1).get_conventional_standard_structure() 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]]) s = SubstrateAnalyzer() matches = list(s.calculate(film, substrate, film_elac)) self.assertEqual(len(matches), 82)
def elastic_props(outcar="", vacuum=False): """ Obtain elastic tensor and calculate related properties Args: outcar: OUTCAR file path vacuum: whether the structure has vaccum such as 2D materials for vacuum structures bulk and shear mod. needs extra attenstion and elastic tensor are in Nm^-1 rather than GPa Returns: info: data for elastic tensor (in string and object representation), bulk, shear modulus, and phonon modes """ if vacuum == True: contcar = Structure.from_file(str(outcar).replace("OUTCAR", "POSCAR")) ratio_c = 0.1 * float(abs( contcar.lattice.matrix[2][2])) # *(10**9)*(10**-10) #N/m unit el_tens = "na" KV = "na" GV = "na" spin = "na" info = {} ratio_c = 1.0 v = open(outcar, "r") lines = v.read().splitlines() for i, line in enumerate(lines): if "TOTAL ELASTIC MODULI (kBar)" in line: c11 = lines[i + 3].split()[1] c12 = lines[i + 3].split()[2] c13 = lines[i + 3].split()[3] c14 = lines[i + 3].split()[4] c15 = lines[i + 3].split()[5] c16 = lines[i + 3].split()[6] c21 = lines[i + 4].split()[1] c22 = lines[i + 4].split()[2] c23 = lines[i + 4].split()[3] c24 = lines[i + 4].split()[4] c25 = lines[i + 4].split()[5] c26 = lines[i + 4].split()[6] c31 = lines[i + 5].split()[1] c32 = lines[i + 5].split()[2] c33 = lines[i + 5].split()[3] c34 = lines[i + 5].split()[4] c35 = lines[i + 5].split()[5] c36 = lines[i + 5].split()[6] c41 = lines[i + 6].split()[1] c42 = lines[i + 6].split()[2] c43 = lines[i + 6].split()[3] c44 = lines[i + 6].split()[4] c45 = lines[i + 6].split()[5] c46 = lines[i + 6].split()[6] c51 = lines[i + 7].split()[1] c52 = lines[i + 7].split()[2] c53 = lines[i + 7].split()[3] c54 = lines[i + 7].split()[4] c55 = lines[i + 7].split()[5] c56 = lines[i + 7].split()[6] c61 = lines[i + 8].split()[1] c62 = lines[i + 8].split()[2] c63 = lines[i + 8].split()[3] c64 = lines[i + 8].split()[4] c65 = lines[i + 8].split()[5] c66 = lines[i + 8].split()[6] c11 = round(ratio_c * float(c11) / float(10), 1) c12 = round(ratio_c * float(c12) / float(10), 1) c13 = round(ratio_c * float(c13) / float(10), 1) c14 = round(ratio_c * float(c14) / float(10), 1) c15 = round(ratio_c * float(c15) / float(10), 1) c16 = round(ratio_c * float(c16) / float(10), 1) c21 = round(ratio_c * float(c21) / float(10), 1) c22 = round(ratio_c * float(c22) / float(10), 1) c23 = round(ratio_c * float(c23) / float(10), 1) c24 = round(ratio_c * float(c24) / float(10), 1) c25 = round(ratio_c * float(c25) / float(10), 1) c26 = round(ratio_c * float(c26) / float(10), 1) c31 = round(float(c31) / float(10), 1) c32 = round(float(c32) / float(10), 1) c33 = round(float(c33) / float(10), 1) c34 = round(float(c34) / float(10), 1) c35 = round(float(c35) / float(10), 1) c36 = round(float(c36) / float(10), 1) c41 = round(float(c41) / float(10), 1) c42 = round(float(c42) / float(10), 1) c43 = round(float(c43) / float(10), 1) c44 = round(float(c44) / float(10), 1) c45 = round(float(c45) / float(10), 1) c46 = round(float(c46) / float(10), 1) c51 = round(float(c51) / float(10), 1) c52 = round(float(c52) / float(10), 1) c53 = round(float(c53) / float(10), 1) c54 = round(float(c54) / float(10), 1) c55 = round(float(c55) / float(10), 1) c56 = round(float(c56) / float(10), 1) c61 = round(float(c61) / float(10), 1) c62 = round(float(c62) / float(10), 1) c63 = round(float(c63) / float(10), 1) c64 = round(float(c64) / float(10), 1) c65 = round(float(c65) / float(10), 1) c66 = round(float(c66) / float(10), 1) KV = float((c11 + c22 + c33) + 2 * (c12 + c23 + c31)) / float(9) GV = float((c11 + c22 + c33) - (c12 + c23 + c31) + 3 * (c44 + c55 + c66)) / float(15) KV = round(KV, 3) GV = round(GV, 3) break v.close() # Convenient string representation for storage el_tens = (str(c11) + str(",") + str(c12) + str(",") + str(c13) + str(",") + str(c14) + str(",") + str(c15) + str(",") + str(c16) + str(",") + str(c21) + str(",") + str(c22) + str(",") + str(c23) + str(",") + str(c24) + str(",") + str(c25) + str(",") + str(c26) + str(",") + str(c31) + str(",") + str(c32) + str(",") + str(c33) + str(",") + str(c34) + str(",") + str(c35) + str(",") + str(c36) + str(",") + str(c41) + str(",") + str(c42) + str(",") + str(c43) + str(",") + str(c44) + str(",") + str(c45) + str(",") + str(c46) + str(",") + str(c51) + str(",") + str(c52) + str(",") + str(c53) + str(",") + str(c54) + str(",") + str(c55) + str(",") + str(c56) + str(",") + str(c61) + str(",") + str(c62) + str(",") + str(c63) + str(",") + str(c64) + str(",") + str(c65) + str(",") + str(c66)) cij = np.empty((6, 6), dtype=float) elast = np.array(el_tens.split(","), dtype="float") count = 0 for ii in range(6): for jj in range(6): cij[ii][jj] = elast[count] el_tens2 = ElasticTensor.from_voigt(cij) modes = [] try: for i in lines: if "cm-1" in i and "meV" in i: mod = float(i.split()[7]) if mod not in modes: modes.append(float(mod)) except: pass info["el_tens_str"] = el_tens info["el_tens_obj"] = el_tens2 info["KV"] = KV info["GV"] = GV info["modes"] = modes return info
def process_item(self, item): """ Calculates substrate matches for all given substrates Args: item (dict): a dict with a material_id and a structure Returns: dict: a diffraction dict """ substrates = self.__settings elastic_tensor = item.get("elastic_tensor", None) elastic_tensor = ElasticTensor.from_voigt( elastic_tensor) if elastic_tensor else None self.logger.debug("Calculating substrates for {}".format( item["task_id"])) film = Structure.from_dict(item["structure"]) all_matches = [] sa = SubstrateAnalyzer() for s in substrates: substrate = s["structure"] # Calculate lowest matches and group by substrate orientation matches_by_orient = groupby_itemkey( sa.calculate(film, substrate, elastic_tensor, lowest=True), "sub_miller") # Find the lowest area match for each substrate orientation lowest_matches = [ min(g, key=itemgetter("match_area")) for k, g in matches_by_orient ] for match in lowest_matches: db_entry = { "sub_id": s["task_id"], "orient": " ".join(map(str, match["sub_miller"])), "sub_form": substrate.composition.reduced_formula, "film_orient": " ".join(map(str, match["film_miller"])), "area": match["match_area"], } if "elastic_energy" in match: db_entry["energy"] = match["elastic_energy"] db_entry["strain"] = match["strain"] all_matches.append(db_entry) # Sort based on energy if an elastic tensor is present otherwise the area if elastic_tensor is not None: sort_key = itemgetter("energy") else: sort_key = itemgetter("area") all_matches = list(sorted(all_matches, key=sort_key)) d = {self.substrates.key: item["task_id"], "substrates": all_matches} return d
def get_pmg_elastic_tensor(self): """ Converts to a pymatgen ElasticTensor object. """ return ElasticTensor.from_voigt(self.elastic_tensor)