def setUp(self): self.norm_defo = Deformation.from_index_amount((0, 0), 0.02) self.ind_defo = Deformation.from_index_amount((0, 1), 0.02) self.non_ind_defo = Deformation([[1.0, 0.02, 0.02], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) lattice = Lattice( [[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]] ) self.structure = Structure(lattice, ["Si", "Si"], [[0, 0, 0], [0.75, 0.5, 0.75]])
def setUp(self): self.norm_defo = Deformation.from_index_amount((0, 0), 0.02) self.ind_defo = Deformation.from_index_amount((0, 1), 0.02) self.non_ind_defo = Deformation([[1.0, 0.02, 0.02], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) lattice = Lattice([[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]]) self.structure = Structure(lattice, ["Si", "Si"], [[0, 0, 0], [0.75, 0.5, 0.75]])
def test_properties(self): # mean_stress self.assertEqual( self.rand_stress.mean_stress, 1. / 3. * (self.rand_stress[0, 0] + self.rand_stress[1, 1] + self.rand_stress[2, 2])) self.assertAlmostEqual(self.symm_stress.mean_stress, 3.66) # deviator_stress self.assertArrayAlmostEqual( self.symm_stress.deviator_stress, Stress([[-3.15, 2.29, 2.42], [2.29, 1.48, 5.07], [2.42, 5.07, 1.67]])) self.assertArrayAlmostEqual( self.non_symm.deviator_stress, [[-0.2666666667, 0.2, 0.3], [0.4, 0.133333333, 0.6], [0.2, 0.5, 0.133333333]]) # deviator_principal_invariants self.assertArrayAlmostEqual(self.symm_stress.dev_principal_invariants, [0, 44.2563, 111.953628]) # von_mises self.assertAlmostEqual(self.symm_stress.von_mises, 11.52253878275) # piola_kirchoff 1, 2 f = Deformation.from_index_amount((0, 1), 0.03) self.assertArrayAlmostEqual( self.symm_stress.piola_kirchoff_1(f), [[0.4413, 2.29, 2.42], [2.1358, 5.14, 5.07], [2.2679, 5.07, 5.33]]) self.assertArrayAlmostEqual( self.symm_stress.piola_kirchoff_2(f), [[0.377226, 2.1358, 2.2679], [2.1358, 5.14, 5.07], [2.2679, 5.07, 5.33]]) # voigt self.assertArrayEqual(self.symm_stress.voigt, [0.51, 5.14, 5.33, 5.07, 2.42, 2.29]) with self.assertRaises(ValueError): self.non_symm.voigt
def test_properties(self): # mean_stress self.assertEqual(self.rand_stress.mean_stress, 1. / 3. * (self.rand_stress[0, 0] + self.rand_stress[1, 1] + self.rand_stress[2, 2])) self.assertAlmostEqual(self.symm_stress.mean_stress, 3.66) # deviator_stress self.assertArrayAlmostEqual(self.symm_stress.deviator_stress, Stress([[-3.15, 2.29, 2.42], [2.29, 1.48, 5.07], [2.42, 5.07, 1.67]])) self.assertArrayAlmostEqual(self.non_symm.deviator_stress, [[-0.2666666667, 0.2, 0.3], [0.4, 0.133333333, 0.6], [0.2, 0.5, 0.133333333]]) # deviator_principal_invariants self.assertArrayAlmostEqual(self.symm_stress.dev_principal_invariants, [0, 44.2563, 111.953628]) # von_mises self.assertAlmostEqual(self.symm_stress.von_mises, 11.52253878275) # piola_kirchoff 1, 2 f = Deformation.from_index_amount((0, 1), 0.03) self.assertArrayAlmostEqual(self.symm_stress.piola_kirchoff_1(f), [[0.4413, 2.29, 2.42], [2.1358, 5.14, 5.07], [2.2679, 5.07, 5.33]]) self.assertArrayAlmostEqual(self.symm_stress.piola_kirchoff_2(f), [[0.377226, 2.1358, 2.2679], [2.1358, 5.14, 5.07], [2.2679, 5.07, 5.33]]) # voigt self.assertArrayEqual(self.symm_stress.voigt, [0.51, 5.14, 5.33, 5.07, 2.42, 2.29])
def test_convert_strain_to_deformation(self): defo = Deformation.from_index_amount((1, 2), 0.01) pass
def get_wf_elastic_constant(structure, vasp_input_set=None, vasp_cmd="vasp", norm_deformations=[-0.01, -0.005, 0.005, 0.01], shear_deformations=[-0.06, -0.03, 0.03, 0.06], db_file=None, reciprocal_density=None): """ Returns a workflow to calculate elastic constants. Firework 1 : write vasp input set for structural relaxation, run vasp, pass run location, database insertion. Firework 2 - 25: Optimize Deformed Structure Firework 26: Analyze Stress/Strain data and fit the elastic tensor Args: structure (Structure): input structure to be optimized and run norm_deformations (list): list of values to for normal deformations shear_deformations (list): list of values to for shear deformations vasp_input_set (DictVaspInputSet): vasp input set. vasp_cmd (str): command to run db_file (str): path to file containing the database credentials. reciprocal_density (int): k-points per reciprocal atom by volume Returns: Workflow """ v = vasp_input_set or MPRelaxSet(structure, force_gamma=True) if reciprocal_density: v.config_dict["KPOINTS"].update( {"reciprocal_density":reciprocal_density}) v = DictSet(structure, v.config_dict) fws = [] fws.append(OptimizeFW(structure=structure, vasp_input_set=v, vasp_cmd=vasp_cmd, db_file=db_file)) deformations = [] # Generate deformations for ind in [(0, 0), (1, 1), (2, 2)]: for amount in norm_deformations: defo = Deformation.from_index_amount(ind, amount) deformations.append(defo) for ind in [(0, 1), (0, 2), (1, 2)]: for amount in shear_deformations: defo = Deformation.from_index_amount(ind, amount) deformations.append(defo) def_vasp_params = {"user_incar_settings":{"ISIF":2, "IBRION":2, "NSW":99, "LAECHG":False, "LHVAR":False, "ALGO":"Fast", "LWAVE":False}} if reciprocal_density: def_vasp_params.update( {"reciprocal_density":reciprocal_density}) for deformation in deformations: fw = TransmuterFW(name="elastic deformation", structure=structure, transformations=['DeformStructureTransformation'], transformation_params=[ {"deformation": deformation.tolist()}], copy_vasp_outputs=True, db_file=db_file, vasp_cmd=vasp_cmd, parents=fws[0], vasp_input_params = def_vasp_params ) fw.spec['_tasks'].append( PassStressStrainData(deformation=deformation.tolist()).to_dict()) fws.append(fw) fws.append(Firework(AnalyzeStressStrainData(structure=structure, db_file=db_file), name="Analyze Elastic Data", parents=fws[1:], spec = {"_allow_fizzled_parents":True})) wfname = "{}:{}".format(structure.composition.reduced_formula, "elastic constants") return Workflow(fws, name=wfname)
def get_wf_elastic_constant( structure, vasp_input_set=None, vasp_cmd="vasp", norm_deformations=None, shear_deformations=None, additional_deformations=None, db_file=None, user_kpoints_settings=None, add_analysis_task=True, conventional=True, ): """ Returns a workflow to calculate elastic constants. Firework 1 : write vasp input set for structural relaxation, run vasp, pass run location, database insertion. Firework 2 - number of total deformations: Static runs on the deformed structures last Firework : Analyze Stress/Strain data and fit the elastic tensor Args: structure (Structure): input structure to be optimized and run. norm_deformations (list): list of values to for normal deformations. shear_deformations (list): list of values to for shear deformations. additional_deformations (list of 3x3 array-likes): list of additional deformations. vasp_input_set (DictVaspInputSet): vasp input set. vasp_cmd (str): command to run. db_file (str): path to file containing the database credentials. user_kpoints_settings (dict): example: {"grid_density": 7000} add_analysis_task (bool): boolean indicating whether to add analysis Returns: Workflow """ # Convert to conventional if conventional: structure = SpacegroupAnalyzer(structure).get_conventional_standard_structure() # Generate deformations deformations = [] if norm_deformations is not None: deformations.extend( [ Deformation.from_index_amount(ind, amount) for ind in [(0, 0), (1, 1), (2, 2)] for amount in norm_deformations ] ) if shear_deformations is not None: deformations.extend( [ Deformation.from_index_amount(ind, amount) for ind in [(0, 1), (0, 2), (1, 2)] for amount in shear_deformations ] ) if additional_deformations: deformations.extend([Deformation(defo_mat) for defo_mat in additional_deformations]) if not deformations: raise ValueError("deformations list empty") wf_elastic = get_wf_deformations( structure, deformations, vasp_input_set=vasp_input_set, lepsilon=False, vasp_cmd=vasp_cmd, db_file=db_file, user_kpoints_settings=user_kpoints_settings, pass_stress_strain=True, name="deformation", relax_deformed=True, tag="elastic", ) if add_analysis_task: fw_analysis = Firework( ElasticTensorToDbTask(structure=structure, db_file=db_file), name="Analyze Elastic Data", spec={"_allow_fizzled_parents": True}, ) append_fw_wf(wf_elastic, fw_analysis) wf_elastic.name = "{}:{}".format(structure.composition.reduced_formula, "elastic constants") return wf_elastic