def generate_elastic_workflow(structure, tags=None): """ Generates a standard production workflow. Notes: Uses a primitive structure transformed into the conventional basis (for equivalent deformations). Adds the "minimal" category to the minimal portion of the workflow necessary to generate the elastic tensor, and the "minimal_full_stencil" category to the portion that includes all of the strain stencil, but is symmetrically complete """ if tags == None: tags = [] # transform the structure ieee_rot = Tensor.get_ieee_rotation(structure) if not SquareTensor(ieee_rot).is_rotation(tol=0.005): raise ValueError( "Rotation matrix does not satisfy rotation conditions") symm_op = SymmOp.from_rotation_and_translation(ieee_rot) ieee_structure = structure.copy() ieee_structure.apply_operation(symm_op) # construct workflow wf = wf_elastic_constant(ieee_structure) # Set categories, starting with optimization opt_fws = get_fws_and_tasks(wf, fw_name_constraint="optimization") wf.fws[opt_fws[0][0]].spec['elastic_category'] = "minimal" # find minimal set of fireworks using symmetry reduction fws_by_strain = { Strain(fw.tasks[-1]['pass_dict']['strain']): n for n, fw in enumerate(wf.fws) if 'deformation' in fw.name } unique_tensors = symmetry_reduce(list(fws_by_strain.keys()), ieee_structure) for unique_tensor in unique_tensors: fw_index = get_tkd_value(fws_by_strain, unique_tensor) if np.isclose(unique_tensor, 0.005).any(): wf.fws[fw_index].spec['elastic_category'] = "minimal" else: wf.fws[fw_index].spec['elastic_category'] = "minimal_full_stencil" # Add tags if tags: wf = add_tags(wf, tags) wf = add_modify_incar(wf) priority = 500 - structure.num_sites wf = add_priority(wf, priority) for fw in wf.fws: if fw.spec.get('elastic_category') == 'minimal': fw.spec['_priority'] += 2000 elif fw.spec.get('elastic_category') == 'minimal_full_stencil': fw.spec['_priority'] += 1000 return wf
def setUp(self): super().setUp() self.tf_loc = os.path.join(ref_dir, "elastic_wf") self.struct_si = PymatgenTest.get_structure("Si") self.struct_si = SpacegroupAnalyzer( self.struct_si ).get_conventional_standard_structure() self.opt_struct = Structure.from_file( os.path.join(self.tf_loc, "1", "inputs", "POSCAR") ) # Base WF self.base_wf = get_wf( self.struct_si, "optimize_only.yaml", params=[{"db_file": ">>db_file<<"}] ) self.base_wf.append_wf( get_wf_elastic_constant( self.struct_si, db_file=">>db_file<<", stencils=[[0.01]] * 3 + [[0.03]] * 3, copy_vasp_outputs=True, ), self.base_wf.leaf_fw_ids, ) self.base_wf_noopt = get_wf_elastic_constant( self.opt_struct, stencils=[[0.01]] * 3 + [[0.03]] * 3, copy_vasp_outputs=False, sym_reduce=False, db_file=">>db_file<<", ) ec_incar_update = {"incar_update": {"EDIFF": 1e-6, "ENCUT": 700}} self.base_wf = add_modify_incar(self.base_wf, ec_incar_update) self.base_wf_noopt = add_modify_incar(self.base_wf_noopt, ec_incar_update) # Full preset WF self.preset_wf = wf_elastic_constant(self.struct_si) # Minimal WF self.minimal_wf = wf_elastic_constant_minimal(self.opt_struct) self.minimal_wf = add_modify_incar(self.minimal_wf, ec_incar_update) # TOEC WF (minimal) self.toec_wf = wf_elastic_constant_minimal(self.struct_si, order=3) self.toec_wf = add_modify_incar(self.toec_wf, ec_incar_update) toec_data = loadfn(os.path.join(self.tf_loc, "toec_data.json")) # Rather than run entire workflow, preload the spec to test the analysis toec_analysis = Firework( [ ElasticTensorToDb( structure=self.struct_si, order=3, db_file=">>db_file<<" ) ], spec={"deformation_tasks": toec_data["deformation_tasks"]}, ) self.toec_analysis = Workflow([toec_analysis]) # Check 4th order to see if constructed correctly self.foec_wf = wf_elastic_constant_minimal(self.struct_si, order=4)
def setUpClass(cls): if not SETTINGS.get("VASP_PSP_DIR"): SETTINGS["VASP_PSP_DIR"] = os.path.join(module_dir, "..", "..", "tests", "reference_files") print('This system is not set up to run VASP jobs. ' 'Please set VASP_PSP_DIR variable in your ~/.pmgrc.yaml file.') cls.struct_si = SpacegroupAnalyzer( PymatgenTest.get_structure("Si")).get_conventional_standard_structure() cls.scratch_dir = os.path.join(module_dir, "scratch") cls.elastic_config = {"norm_deformations":[0.01], "shear_deformations":[0.03], "vasp_cmd": ">>vasp_cmd<<", "db_file": ">>db_file<<"} cls.wf = wf_elastic_constant(cls.struct_si, cls.elastic_config)
def setUp(self): super(TestElasticWorkflow, self).setUp() self.tf_loc = os.path.join(ref_dir, 'elastic_wf') self.struct_si = PymatgenTest.get_structure("Si") self.struct_si = SpacegroupAnalyzer( self.struct_si).get_conventional_standard_structure() self.opt_struct = Structure.from_file( os.path.join(self.tf_loc, '1', 'inputs', 'POSCAR')) # Base WF self.base_wf = get_wf(self.struct_si, "optimize_only.yaml", params=[{ "db_file": ">>db_file<<" }]) self.base_wf.append_wf( get_wf_elastic_constant(self.struct_si, db_file='>>db_file<<', stencils=[[0.01]] * 3 + [[0.03]] * 3, copy_vasp_outputs=True), self.base_wf.leaf_fw_ids) self.base_wf_noopt = get_wf_elastic_constant(self.opt_struct, stencils=[[0.01]] * 3 + [[0.03]] * 3, copy_vasp_outputs=False, sym_reduce=False, db_file='>>db_file<<') ec_incar_update = {'incar_update': {'EDIFF': 1e-6, 'ENCUT': 700}} self.base_wf = add_modify_incar(self.base_wf, ec_incar_update) self.base_wf_noopt = add_modify_incar(self.base_wf_noopt, ec_incar_update) # Full preset WF self.preset_wf = wf_elastic_constant(self.struct_si) # Minimal WF self.minimal_wf = wf_elastic_constant_minimal(self.opt_struct) self.minimal_wf = add_modify_incar(self.minimal_wf, ec_incar_update) # TOEC WF (minimal) self.toec_wf = wf_elastic_constant_minimal(self.struct_si, order=3) self.toec_wf = add_modify_incar(self.toec_wf, ec_incar_update) toec_data = loadfn(os.path.join(self.tf_loc, 'toec_data.json')) # Rather than run entire workflow, preload the spec to test the analysis toec_analysis = Firework( [ ElasticTensorToDb( structure=self.struct_si, order=3, db_file=">>db_file<<") ], spec={"deformation_tasks": toec_data['deformation_tasks']}) self.toec_analysis = Workflow([toec_analysis])
def setUp(self): super(TestElasticWorkflow, self).setUp() self.tf_loc = os.path.join(ref_dir, 'elastic_wf') self.struct_si = PymatgenTest.get_structure("Si") self.struct_si = SpacegroupAnalyzer(self.struct_si).get_conventional_standard_structure() self.opt_struct = Structure.from_file(os.path.join(self.tf_loc, '1', 'inputs', 'POSCAR')) # Base WF self.base_wf = get_wf(self.struct_si, "optimize_only.yaml", params=[{"db_file": ">>db_file<<"}]) self.base_wf.append_wf(get_wf_elastic_constant(self.struct_si, db_file='>>db_file<<', stencils=[[0.01]]*3 + [[0.03]]*3, copy_vasp_outputs=True), self.base_wf.leaf_fw_ids) self.base_wf_noopt = get_wf_elastic_constant(self.opt_struct, stencils=[[0.01]]*3 + [[0.03]]*3, copy_vasp_outputs=False, sym_reduce=False, db_file='>>db_file<<') ec_incar_update = {'incar_update': {'EDIFF': 1e-6, 'ENCUT': 700}} self.base_wf = add_modify_incar(self.base_wf, ec_incar_update) self.base_wf_noopt = add_modify_incar(self.base_wf_noopt, ec_incar_update) # Full preset WF self.preset_wf = wf_elastic_constant(self.struct_si) # Minimal WF self.minimal_wf = wf_elastic_constant_minimal(self.opt_struct) self.minimal_wf = add_modify_incar(self.minimal_wf, ec_incar_update) # TOEC WF (minimal) self.toec_wf = wf_elastic_constant_minimal(self.struct_si, order=3) self.toec_wf = add_modify_incar(self.toec_wf, ec_incar_update) toec_data = loadfn(os.path.join(self.tf_loc, 'toec_data.json')) # Rather than run entire workflow, preload the spec to test the analysis toec_analysis = Firework([ElasticTensorToDb(structure=self.struct_si, order=3, db_file=">>db_file<<")], spec={"deformation_tasks": toec_data['deformation_tasks']}) self.toec_analysis = Workflow([toec_analysis]) # Check 4th order to see if constructed correctly self.foec_wf = wf_elastic_constant_minimal(self.struct_si, order=4)