def check_relax_path(relax_path, db_file, tag, run_isif2, pass_isif4): from atomate.vasp.database import VaspCalcDb if db_file != ">>db_file<<": vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) else: t_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(t_file, admin=True) if relax_path != '': if os.path.exists(relax_path): return (relax_path, run_isif2, pass_isif4) if vasp_db.db["relax"].count_documents({'metadata.tag': tag}) > 0: items = vasp_db.db["relax"].find({ 'metadata.tag': tag }).sort([('_id', -1)]).limit(1) if os.path.exists(items[0]['path']): print( 'Relax result "%s" with "run_isif2 = %s" and "run_isif4 = %s" has been found, and will be used for new static calculations.' % (items[0]['path'], items[0]['run_isif2'], items[0]['pass_isif4'])) return (items[0]['path'], items[0]['run_isif2'], items[0]['pass_isif4']) else: print( 'Relax result "%s" has been found but NOT exists. Change tag and try again!' % relax_path) return ('', run_isif2, pass_isif4) else: print('No relax result found.') return ('', run_isif2, pass_isif4)
def get_eq_structure_by_metadata(metadata, db_file=None): ''' Get the equilibrium structure by metadata Parameters ---------- metadata: dict The metadata use for searching the database db_file: filepath-like The file path of db.json(the settings for mongodb file) if it is None or >>db_file<<, then using the db_file of fireworks configurations Returns ------- eq_structure: pymatgen.Strucutre object the equilibrium structure ''' if (db_file is None) or (db_file == '>>db_file<<'): db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) static_items = list(vasp_db.db['tasks'].find({ 'metadata.tag': metadata['tag'] }).sort('_id', 1)) structure_list = [itemi['output']['structure'] for itemi in static_items] if structure_list: #not empty eq_structure = Structure.from_dict(structure_list[0]) return eq_structure
def consistent_check_db(db_file, tag): ''' In the subsequent running(run DFTTK again with the same tag exists in Mongo DB), if phonon method is committed, it'd better to check the lengths of "task" and "phonon" collections. ''' from atomate.vasp.database import VaspCalcDb if db_file != ">>db_file<<": vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) else: t_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(t_file, admin=True) num_task = vasp_db.collection.count_documents( {'$and': [{ 'metadata.tag': tag }, { 'adopted': True }]}) num_phonon = vasp_db.db['phonon'].count_documents( {'$and': [{ 'metadata.tag': tag }, { 'adopted': True }]}) if num_task == num_phonon: return (True) else: print( 'The records length of "task"(%s) differs to the length of "phonon"(%s) in mongodb.' % (num_task, num_phonon)) return (False)
def mark_adopted(tag, db_file, volumes, phonon=False): mark_adopted_TF(tag, db_file, False, phonon=phonon) # Mark all as adpoted from atomate.vasp.database import VaspCalcDb if db_file != ">>db_file<<": vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) else: t_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(t_file, admin=True) for volume in volumes: vasp_db.collection.update( { '$and': [{ 'metadata.tag': tag }, { 'output.structure.lattice.volume': volume }] }, {'$set': { 'adopted': True }}, upsert=True, multi=False) # Mark only one if phonon: vasp_db.db['phonon'].update( {'$and': [{ 'metadata.tag': tag }, { 'volume': volume }]}, {'$set': { 'adopted': True }}, upsert=True, multi=False)
def get_static_structure_by_metadata(metadata, db_file=None): ''' Get the static structure by metadata Parameters ---------- metadata: dict The metadata use for searching the database db_file: filepath-like The file path of db.json(the settings for mongodb file) if it is None or >>db_file<<, then using the db_file of fireworks configurations Returns ------- structure_list: list The list of different structures. The structures are sorted by volume ''' if (db_file is None) or (db_file == '>>db_file<<'): db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) static_items = list( vasp_db.collection.find( {'$and': [{ 'metadata.tag': metadata['tag'] }, { 'adopted': True }]})) #static_items = list(vasp_db.db['tasks'].find({'metadata.tag': metadata})) structure_list = [ Structure.from_dict(itemi['output']['structure']) for itemi in static_items ] volumes = [ itemi['output']['structure']['lattice']['volume'] for itemi in static_items ] energies = [itemi['output']['energy_per_atom'] for itemi in static_items] band_gap = [] static_settings = {} for itemi in static_items: if itemi['output']['is_gap_direct']: band_gap.append(itemi['output']['bandgap']) else: band_gap.append(itemi['output']['direct_gap']) if not static_settings: pot = itemi['input']['pseudo_potential']['functional'].upper() if pot == "": pot = itemi['orig_inputs']['potcar']['functional'].upper() if pot == 'Perdew-Zunger81'.upper(): pot = "LDA" static_settings['user_potcar_functional'] = pot static_settings['user_incar_settings'] = itemi['input']['incar'] structure_list = sort_x_by_y(structure_list, volumes) band_gap = sort_x_by_y(band_gap, volumes) energies = sort_x_by_y(energies, volumes) volumes = sorted(volumes) return (structure_list, energies, band_gap, static_settings, volumes)
def ext_thfind(args, vasp_db=None): """ find the metadata tag that has finished. Parameters STR_FOLDER = args.STRUCTURE_FOLDER folder/file containing structures MATCH_PATTERN = args.MATCH_PATTERN Match patterns for structure file, e.g. *POSCAR RECURSIVE = args.RECURSIVE recursive or not WORKFLOW = args.WORKFLOW workflow, current only get_wf_gibbs """ if args.db_file is not None: vasp_db = VaspCalcDb.from_db_file(args.db_file, admin=False) elif vasp_db is None: db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(db_file, admin=False) proc=thfindMDB(args,vasp_db) tags = proc.run_console() if args.get: with open("runs.log", "a") as fp: fp.write ('\nPostprocessing run at {}\n\n'.format(datetime.now())) for t in tags: if isinstance(t,dict): print("\nDownloading data by metadata tag:", t['tag'], "\n") args.metatag = t['tag'] args.phasename = t['phasename'] ext_thelec(args, vasp_db=vasp_db) #args.metatag = None #args.phasename = None else: ext_thelec(args,plotfiles=t, vasp_db=vasp_db) elif args.qha_phonon_repair: from dfttk.scripts.qha_phonon_repair import QHAAnalysis_failure for t in tags: if isinstance(t,dict): tag = t['tag'] qha_phonon = list(vasp_db.db['qha_phonon'].find({'metadata.tag': tag})) if len(qha_phonon) : continue # already ok skip phonon_calculations = list(vasp_db.db['phonon'].find({'$and':[ {'metadata.tag': tag}, {'adopted': True} ]})) T = phonon_calculations[0]['temperatures'] t_min = min(T) t_max = max(T) t_step = T[1]-T[0] print("Repairing data by metadata tag:", t) proc = QHAAnalysis_failure(phonon=True, t_min=t_min, t_max=t_max, t_step=t_step, db_file=db_file, test_failure=False, admin=True, metadata={'tag':tag}, tag=tag) proc.run_task()
def __init__(self, args): db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] self.vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) self.items = (self.vasp_db).collection.find({'adopted': True}) self.within = [] self.containall = [] self.containany = [] self.excludeall = [] self.excludeany = [] self.nV = args.nV self.print = args.print self.plot = args.plot self.findbandgap = args.findbandgap if args.within is not None: self.within, tmp = formula2composition(args.within) if args.containall is not None: self.containall, tmp = formula2composition(args.containall) if args.containany is not None: self.containany, tmp = formula2composition(args.containany) if args.excludeall is not None: self.excludeall, tmp = formula2composition(args.excludeall)
def ext_EVfind(args, vasp_db=None): """ find the metadata tag that has finished. Parameters STR_FOLDER = args.STRUCTURE_FOLDER folder/file containing structures MATCH_PATTERN = args.MATCH_PATTERN Match patterns for structure file, e.g. *POSCAR RECURSIVE = args.RECURSIVE recursive or not WORKFLOW = args.WORKFLOW workflow, current only get_wf_gibbs """ if vasp_db is None: db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(db_file, admin=False) proc=EVfindMDB(args, vasp_db=vasp_db) tags = proc.run_console()
def mark_adopted_TF(tag, db_file, adpoted, phonon=False): from atomate.vasp.database import VaspCalcDb if db_file != ">>db_file<<": vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) else: t_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(t_file, admin=True) if vasp_db: vasp_db.collection.update({'metadata.tag': tag}, {'$set': { 'adopted': adpoted }}, upsert=True, multi=True) if phonon: vasp_db.db['phonon'].update({'metadata.tag': tag}, {'$set': { 'adopted': adpoted }}, upsert=True, multi=True)
def is_property_exist_in_db(metadata, db_file=None, collection='tasks'): ''' Search the MongoDB collection by metadata ''' if (db_file is None) or (db_file == '>>db_file<<'): db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] if collection == 'tasks': return get_static_structure_by_metadata(metadata=metadata, db_file=db_file) else: #try: if True: vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) search_items = list(vasp_db.db[collection].find( {'metadata.tag': metadata['tag']}, { '_id': 0, 'volume': 1 })) try: volumes = [f['volume'] for f in search_items] except: volumes = [] if not volumes: try: search_items = list(vasp_db.db[collection].find( {'metadata.tag': metadata['tag']}, { '_id': 0, 'initial_structure': 1 })) volumes = [ f['initial_structure']['lattice']['volume'] for f in search_items ] except: volumes = [] #except: # volumes = [] return volumes
def remove_data_by_metadata(tag, db_file=None, rem_mode='vol', forcedelete=False): ''' rem_mode: str/list allvol: remove all volume collection vol: remove volume collection except bandstructure and dos property: other collections except volume all: all aeccar: remove all aeccar related chgcar: remove chgcar locpot: remove locpot ''' if (db_file is None) or (db_file == '>>db_file<<'): db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) metadata = {'tag': tag} VOL1_COLLECTION = [ 'aeccar0', 'aeccar1', 'aeccar2', 'chgcar', 'locpot', 'elfcar' ] VOL2_COLLECTION = ['bandstructure', 'dos'] VOL_COLLECTION = VOL1_COLLECTION + VOL2_COLLECTION OTHER_COLLECTION = [ 'borncharge', 'phonon', 'qha', 'qha_phonon', 'relax', 'relax_scheme', 'relaxations', 'tasks', 'xmlgz' ] if isinstance(rem_mode, str): rem_mode = rem_mode.lower() if rem_mode == 'all': collections = VOL_COLLECTION + OTHER_COLLECTION elif rem_mode == 'allvol': collections = VOL_COLLECTION elif rem_mode == 'vol': collections = VOL1_COLLECTION elif rem_mode == 'property': collections = OTHER_COLLECTION elif rem_mode == 'aeccar': collections = ['aeccar0', 'aeccar1', 'aeccar2'] else: collections = [rem_mode] elif isinstance(rem_mode, list): collections = rem_mode else: raise ValueError( 'Unsupported remove mode, please provide a str or list') flag_remove = False if forcedelete: flag_remove = True else: if tag: if input( 'Are you sure? This will remove all data in {} collection with metadata.tag={}. (Y/N)' .format(collections, tag))[0].upper() == 'Y': flag_remove = True else: #tag is None, which means remove the collection if input( 'Are you sure? This will remove the {} collections. (Y/N)'. format(collections))[0].upper() == 'Y': flag_remove = True if flag_remove: for collectioni in collections: if collectioni in VOL_COLLECTION: collectioni_file = collectioni + '_fs.files' collectioni_chunk = collectioni + '_fs.chunks' #It has files and chunks if tag: static_items = list(vasp_db.db['tasks'].find( {'metadata.tag': tag})) for itemi in static_items: task_id = itemi['task_id'] files_id = list(vasp_db.db[collectioni_file].find( {'metadata.task_id': task_id})) if files_id: vasp_db.db[collectioni_chunk].remove( {'files_id': files_id[0]['_id']}) vasp_db.db[collectioni_file].remove( {'metadata.task_id': task_id}) print( 'The volume data with metadata.tag={} in {} collection is removed' .format(tag, collectioni)) else: vasp_db.db[collectioni_chunk].remove() vasp_db.db[collectioni_file].remove() print('The data in {} collection is removed'.format( collectioni)) else: if tag: vasp_db.db[collectioni].remove({'metadata.tag': tag}) print( 'The data with metadata.tag={} in {} collection is removed' .format(tag, collectioni)) else: if input( 'Are you really sure to remove all the {} collections. (Yes/N)' .format(collections))[0].upper() == 'Yes': vasp_db.db[collectioni].remove() print('The data in {} collection is removed'.format( collectioni))
def __init__(self, args): self.plotonly = args.plotonly if args.qhamode is not None: self.qhamode = args.qhamode else: self.qhamode = 'phonon' if args.qhamode == 'debye': self.qhamode = 'qha' from fireworks.fw_config import config_to_dict from monty.serialization import loadfn db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] if not self.plotonly: try: self.vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) self.items = (self.vasp_db).db[self.qhamode].find({}) if self.qhamode == 'phonon': self.items = list((self.vasp_db).db['phonon'].find({"S_vib": { "$exists": True } },\ {'metadata':1, 'unitcell':1, 'volume':1, 'supercell_matrix':1})) else: self.items = list((self.vasp_db).db['qha'].find({"debye": { "$exists": True } },\ {'metadata':1, 'structure':1})) except: self.vasp_db = None print( "\n*********WARNING: CANNOT get MongoDB service, so I will proceed using local data" ) print( "*********WARNING: CANNOT get MongoDB service, so I will proceed using local data" ) print( "*********WARNING: CANNOT get MongoDB service, so I will proceed using local data\n" ) #items = vasp_db.db['phonon'].find(properties=['metadata.tag','F_vib', 'CV_vib', 'S_vib']) #items = vasp_db.db['phonon'].find({F_vib: {$gt: 0}}) #items = vasp_db.db['phonon'].find({'metadata.tag': "djdjd"}) #items = vasp_db.db['phonon'].find({}) self.check = args.check self.remove = args.remove self.tags = [] self._Yphon = [] self.within = [] self.containall = [] self.containany = [] self.excludeall = [] self.excludeany = [] self.nV = args.nV self.metatag = args.metatag self.get = args.get self.supercellN = args.supercellN self.t0 = args.t0 self.t1 = args.t1 self.td = args.td self.jobpath = args.jobpath self.findbandgap = args.findbandgap if args.within is not None: self.within, tmp = formula2composition(args.within) if args.containall is not None: self.containall, tmp = formula2composition(args.containall) if args.containany is not None: self.containany, tmp = formula2composition(args.containany) if args.excludeall is not None: self.excludeall, tmp = formula2composition(args.excludeall)
def get_wf_single(structure, WORKFLOW="get_wf_gibbs", settings={}): """ Get a single workflow Parameters structure: pymatgen.Structure The structure WORKFLOW: str The name of the workflow, now only gibbs energy workflow(get_wf_gibbs) is supported settings: dict User settings for the workflow Return """ ################ PARAMETERS FOR WF ############################# #str, the absolute path of db.json file, e.g. /storage/home/mjl6505/atomate/config/db.json # If None, it will use the configuration in fireworks db_file = settings.get('db_file', None) #list, the MAGMOM of the structure, e.g. [4.0, 4.0, -4.0, -4.0] magmom = settings.get('magmom', None) #int, the number of initial deformations, e.g. 7 num_deformations = settings.get('num_deformations', 7) #list/tuple(min, max) or float(-max, max), the maximum amplitude of deformation, e.g. (-0.15, 0.15) means (0.95, 1.1) in volume deformation_fraction = settings.get('deformation_fraction', (-0.15, 0.15)) #float, minimum ratio of Volumes spacing, e.g. 0.05 volume_spacing_min = settings.get('volume_spacing_min', 0.05) #bool, run phonon(True) or not(False) phonon = settings.get('phonon', False) #list(3x3), the supercell matrix for phonon, e.g. [[2.0, 0, 0], [0, 2.0, 0], [0, 0, 2.0]] phonon_supercell_matrix = settings.get('phonon_supercell_matrix', None) phonon_supercell_matrix_min = settings.get('phonon_supercell_matrix_min', None) phonon_supercell_matrix_max = settings.get('phonon_supercell_matrix_max', None) optimize_sc = settings.get('optimize_sc', False) #run phonon always, no matter ISIF=4 passed or not force_phonon = settings.get('force_phonon', False) #The tolerance for phonon stable stable_tor = settings.get('stable_tor', 0.01) #float, the mimimum of temperature in QHA process, e.g. 5 t_min = settings.get('t_min', 5) #float, the maximum of temperature in QHA process, e.g. 2000 t_max = settings.get('t_max', 2000) #float, the step of temperature in QHA process, e.g. 5 t_step = settings.get('t_step', 5) #float, acceptable value for average RMS, recommend >= 0.005 eos_tolerance = settings.get('eos_tolerance', 0.01) #str, the vasp command, if None then find in the FWorker configuration vasp_cmd = settings.get('vasp_cmd', None) #dict, metadata to be included, this parameter is useful for filter the data, e.g. metadata={"phase": "BCC_A2", "tag": "AFM"} metadata = settings.get('metadata', None) #It is for RobustOptimizeFW, if run ISIF=4 followed ISIF=7 isif4 = settings.get('isif4', False) #The level for robust optimization level = settings.get('level', 1) #float, the tolerannce for symmetry, e.g. 0.05 symmetry_tolerance = settings.get('symmetry_tolerance', 0.05) #bool, set True to pass initial VASP running if the results exist in DB, use carefully to keep data consistent. passinitrun = settings.get('passinitrun', False) #bool, Whether run isif=2 calculation before isif=4 running run_isif2 = settings.get('run_isif2', False) #bool, Whether pass isif=4 calculation. pass_isif4 = settings.get('pass_isif4', False) #Set the path already exists for new static calculations; if set as '', will try to get the path from db_file relax_path = settings.get('relax_path', '') #The symmetry tolerance, including three keys, #e.g. override_symmetry_tolerances={'tol_strain': 0.05, 'tol_energy': 0.025, 'tol_bond': 0.10} override_symmetry_tolerances = settings.get('override_symmetry_tolerances', None) #Global settings for all vasp job, e.g. #override_default_vasp_params = {'user_incar_settings': {}, 'user_kpoints_settings': {}, 'user_potcar_functional': str} #If some value in 'user_incar_settings' is set to None, it will use vasp's default value override_default_vasp_params = settings.get('override_default_vasp_params', {}) #dict, dict of class ModifyIncar with keywords in Workflow name. e.g. """ modify_incar_params = { 'Full relax': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, 'PreStatic': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, 'PS2': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, 'static': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, """ modify_incar_params = settings.get('modify_incar_params', {}) #dict, dict of class ModifyKpoints with keywords in Workflow name, similar with modify_incar_params modify_kpoints_params = settings.get('modify_kpoints_params', {}) #bool, print(True) or not(False) some informations, used for debug verbose = settings.get('verbose', False) #Save the volume data or not ("chgcar", "aeccar0", "aeccar2", "elfcar", "locpot") store_volumetric_data = settings.get('store_volumetric_data', False) ## The following settings only work for elastic constants workflow strain_states = settings.get('strain_states', None) stencils = settings.get('stencils', None) analysis = settings.get('analysis', True) sym_reduce = settings.get('sym_reduce', False) order = settings.get('order', 2) conventional = settings.get('conventional', False) """ #debug "eeeeeeeeeeeee" stencils = settings.get('stencils', [0.01]) #sym_reduce = settings.get('sym_reduce', True) stencils = settings.get('stencils', [-0.01,0.01]) #conventional = settings.get('conventional', True) """ uis = override_default_vasp_params.get('user_incar_settings', {}) #Set the default value for phonon_supercell_matrix_min/max if isinstance(phonon_supercell_matrix, str) and (phonon_supercell_matrix_min is None): if phonon_supercell_matrix.lower().startswith('a'): phonon_supercell_matrix_min = 60 phonon_supercell_matrix_max = 130 elif phonon_supercell_matrix.lower().startswith('l'): phonon_supercell_matrix_min = 8 phonon_supercell_matrix_max = 12 elif phonon_supercell_matrix.lower().startswith('v'): phonon_supercell_matrix_min = 512 phonon_supercell_matrix_max = 1728 else: raise ValueError( "Unknown parameters for phonon_supercell_matrix({}), support 'atoms', 'lattice' or 'volume' or 3x3 list." .format(phonon_supercell_matrix)) if magmom: structure.add_site_property('magmom', magmom) elif 'MAGMOM' in uis: magmom = uis['MAGMOM'] if isinstance(magmom, str): magmom = Incar.from_string( 'MAGMOM={}'.format(magmom)).as_dict()['MAGMOM'] structure.add_site_property('magmom', magmom) if not db_file: from fireworks.fw_config import config_to_dict db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] """ if WORKFLOW == "get_wf_gibbs": #Currently, only this workflow is supported wf = get_wf_gibbs(structure, num_deformations=num_deformations, deformation_fraction=deformation_fraction, phonon=phonon, phonon_supercell_matrix=phonon_supercell_matrix, t_min=t_min, t_max=t_max, t_step=t_step, eos_tolerance=eos_tolerance, volume_spacing_min=volume_spacing_min,vasp_cmd=vasp_cmd, db_file=db_file, metadata=metadata, name='EV_QHA', symmetry_tolerance=symmetry_tolerance, run_isif2=run_isif2, pass_isif4=pass_isif4, passinitrun=passinitrun, relax_path=relax_path, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params, verbose=verbose, store_volumetric_data=store_volumetric_data) elif WORKFLOW == "eos": """ if WORKFLOW == "eos": wf = get_wf_EV_bjb( structure, deformation_fraction=deformation_fraction, store_volumetric_data=store_volumetric_data, num_deformations=num_deformations, override_symmetry_tolerances=override_default_vasp_params, metadata=metadata) elif WORKFLOW == "robust" or WORKFLOW == "get_wf_gibbs": wf = get_wf_gibbs_robust( structure, num_deformations=num_deformations, deformation_fraction=deformation_fraction, phonon=phonon, phonon_supercell_matrix=phonon_supercell_matrix, t_min=t_min, t_max=t_max, t_step=t_step, eos_tolerance=eos_tolerance, volume_spacing_min=volume_spacing_min, vasp_cmd=vasp_cmd, db_file=db_file, isif4=isif4, metadata=metadata, name='EV_QHA', override_symmetry_tolerances=override_symmetry_tolerances, override_default_vasp_params=override_default_vasp_params, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params, verbose=verbose, phonon_supercell_matrix_min=phonon_supercell_matrix_min, phonon_supercell_matrix_max=phonon_supercell_matrix_max, optimize_sc=optimize_sc, level=level, force_phonon=force_phonon, stable_tor=stable_tor, store_volumetric_data=store_volumetric_data) elif WORKFLOW == "born": wf = get_wf_borncharge( structure=structure, metadata=metadata, db_file=db_file, isif=2, name="born charge", vasp_cmd=vasp_cmd, override_default_vasp_params=override_default_vasp_params, modify_incar=modify_incar_params) elif WORKFLOW == 'elastic': wf = get_wf_elastic( structure=structure, metadata=metadata, vasp_cmd=vasp_cmd, db_file=db_file, name="elastic", override_default_vasp_params=override_default_vasp_params, strain_states=strain_states, stencils=stencils, analysis=analysis, sym_reduce=sym_reduce, order=order, conventional=conventional) else: raise ValueError( "Currently, only the gibbs energy workflow is supported.") return wf
#!python #A work flow run OptimizeFW followed by StaticFW # from dfttk.fworks import OptimizeFW, StaticFW from fireworks import Workflow, LaunchPad from pymatgen import Structure from uuid import uuid4 from fireworks.fw_config import config_to_dict from monty.serialization import loadfn, dumpfn DB_FILE = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] VASP_CMD = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["vasp_cmd"] def wf_opt_static(structure, vasp_cmd=None, db_file=None, metadata=None, tag=None): #Set the default value of input parameters if db_file is None: db_file = DB_FILE if vasp_cmd is None: vasp_cmd = VASP_CMD if not metadata: metadata = {} tag = metadata.get('tag', None) if tag is None: tag = str(uuid4())
def get_wf_gibbs(structure, num_deformations=7, deformation_fraction=(-0.1, 0.1), run_isif2=False, phonon=False, phonon_supercell_matrix=None, pass_isif4=False, t_min=5, t_max=2000, t_step=5, tolerance=0.01, volume_spacing_min=0.03, vasp_cmd=None, db_file=None, metadata=None, name='EV_QHA', symmetry_tolerance=0.05, passinitrun=False, relax_path='', modify_incar_params={}, modify_kpoints_params={}, verbose=False, store_volumetric_data=False): """ E - V curve workflow Parameters ------ structure: pymatgen.Structure num_deformations: int deformation_fraction: float Can be a float (a single value) or a 2-type of a min,max deformation fraction. Default is (-0.05, 0.1) leading to volumes of 0.95-1.10. A single value gives plus/minus by default. phonon : bool Whether to do a phonon calculation. Defaults to False, meaning the Debye model. phonon_supercell_matrix : list 3x3 array of the supercell matrix, e.g. [[2,0,0],[0,2,0],[0,0,2]]. Must be specified if phonon is specified. t_min : float Minimum temperature t_step : float Temperature step size t_max : float Maximum temperature (inclusive) tolerance: float Acceptable value for average RMS, recommend >= 0.005. volume_spacing_min: float Minimum ratio of Volumes spacing vasp_cmd : str Command to run VASP. If None (the default) is passed, the command will be looked up in the FWorker. db_file : str Points to the database JSON file. If None (the default) is passed, the path will be looked up in the FWorker. name : str Name of the workflow metadata : dict Metadata to include passinitrun : bool Set True to pass initial VASP running if the results exist in DB, use carefully to keep data consistent. relax_path : str Set the path already exists for new static calculations; if set as '', will try to get the path from db_file. modify_incar_params : dict User can use these params to modify the INCAR set. It is a dict of class ModifyIncar with keywords in Workflow name. modify_kpoints_params : dict User can use these params to modify the KPOINTS set. It is a dict of class ModifyKpoints with keywords in Workflow name. Only 'kpts' supported now. run_isif2: bool Whether run isif=2 calculation before isif=4 running. pass_isif4: bool Whether pass isif=4 calculation. """ vasp_cmd = vasp_cmd or VASP_CMD db_file = db_file or DB_FILE if db_file == ">>db_file<<": #In PengGao's version, some function used the absolute db_file from fireworks.fw_config import config_to_dict from monty.serialization import loadfn db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] site_properties = deepcopy(structure).site_properties metadata = metadata or {} tag = metadata.get('tag', '{}'.format(str(uuid4()))) if isinstance(deformation_fraction, (list, tuple)): deformations = np.linspace(1 + deformation_fraction[0], 1 + deformation_fraction[1], num_deformations) vol_spacing = max((deformation_fraction[1] - deformation_fraction[0]) / (num_deformations - 0.999999) + 0.001, volume_spacing_min) else: deformations = np.linspace(1 - deformation_fraction, 1 + deformation_fraction, num_deformations) vol_spacing = max( deformation_fraction / (num_deformations - 0.999999) * 2 + 0.001, volume_spacing_min) fws = [] if 'tag' not in metadata.keys(): metadata['tag'] = tag relax_path, run_isif2, pass_isif4 = check_relax_path( relax_path, db_file, tag, run_isif2, pass_isif4) if (relax_path == ''): # follow a scheme of # 1. Full relax + symmetry check # 2. If symmetry check fails, detour to 1. Volume relax, 2. inflection detection # 3. Inflection detection # 4. Static EV # 5. Phonon EV # for each FW, we set the structure to the original structure to verify to ourselves that the # volume deformed structure is set by input set. vis_relax = RelaxSet(structure) print('Full relax will be running ...') full_relax_fw = OptimizeFW(structure, symmetry_tolerance=symmetry_tolerance, job_type='normal', name='Full relax', prev_calc_loc=False, vasp_input_set=vis_relax, vasp_cmd=vasp_cmd, db_file=db_file, metadata=metadata, record_path=True, run_isif2=run_isif2, pass_isif4=pass_isif4, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params, store_volumetric_data=store_volumetric_data, spec={'_preserve_fworker': True}) fws.append(full_relax_fw) else: full_relax_fw = None check_result = Firework( EVcheck_QHA(db_file=db_file, tag=tag, relax_path=relax_path, deformations=deformations, site_properties=site_properties, tolerance=tolerance, threshold=14, vol_spacing=vol_spacing, vasp_cmd=vasp_cmd, metadata=metadata, t_min=t_min, t_max=t_max, t_step=t_step, phonon=phonon, symmetry_tolerance=symmetry_tolerance, phonon_supercell_matrix=phonon_supercell_matrix, verbose=verbose, run_isif2=run_isif2, pass_isif4=pass_isif4, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params, store_volumetric_data=store_volumetric_data), parents=full_relax_fw, name='%s-EVcheck_QHA' % structure.composition.reduced_formula) fws.append(check_result) wfname = "{}:{}".format(structure.composition.reduced_formula, name) wf = Workflow(fws, name=wfname, metadata=metadata) add_modify_incar_by_FWname(wf, modify_incar_params=modify_incar_params) add_modify_kpoints_by_FWname(wf, modify_kpoints_params=modify_kpoints_params) return wf
def ext_thelec(args, plotfiles=None, vasp_db=None): global no_MongoDB print ("Postprocess for thermodynamic properties, Seebeck, Lorenz number etc. Yi Wang\n") """ Postprocess for thermodynamic properties, Seebeck, Lorenz number etc Parameters STR_FOLDER = args.STRUCTURE_FOLDER folder/file containing structures MATCH_PATTERN = args.MATCH_PATTERN Match patterns for structure file, e.g. *POSCAR RECURSIVE = args.RECURSIVE recursive or not WORKFLOW = args.WORKFLOW workflow, current only get_wf_gibbs LAUNCH = args.LAUNCH Launch to lpad or not MAX_JOB = args.MAX_JOB Max job to submit SETTINGS = args.SETTINGS Settings file WRITE_OUT_WF = args.WRITE_OUT_WF Write out wf file or not """ t0 = args.t0 t1 = args.t1 td = args.td xdn = args.xdn xup = args.xup ndosmx = args.ndosmx natom = args.natom gaussian = args.gaussian dope = args.dope doscar = args.doscar outf = args.outf qhamode = args.qhamode eqmode = args.eqmode elmode = args.elmode metatag = args.metatag everyT = args.everyT noel = args.noel smooth = args.smooth expt = args.expt xlim = args.xlim if abs(dope)<5.e-9: ndosmx = max(100001, int(ndosmx)) gaussian = max(10000., float(gaussian)) formula = None if args.local != "": print("\nRun using local data\n") readme = {} record_cmd(readme) proc = thelecMDB(t0, t1, td, xdn, xup, dope, ndosmx, gaussian, natom, outf, noel=noel, qhamode=qhamode, eqmode=eqmode, elmode=elmode, smooth=smooth, debug=args.debug, phasename=args.local, pyphon=True, renew=args.renew, fitF=args.fitF, args=args) volumes, energies, thermofile, comments = proc.run_console() if comments!=None: readme.update(comments) else: return if "ERROR" in readme.keys(): record_cmd_print(thermofile, readme, dir=args.phasename) return print("\nFull thermodynamic properties have outputed into:", thermofile) #print(args.plot, "eeeeeeeee", volumes, energies, thermofile, comments) if args.plot==None: print("\nSupply '-plot phasename' for plot\n") else: from dfttk.analysis.ywplot import plotAPI #print("xxxxxxx",proc.get_formula()) if plotAPI(readme, thermofile, volumes, energies, expt=expt, xlim=xlim, _fitCp=args.SGTEfitCp, formula = proc.get_formula(), debug=args.debug, plotlabel=args.plot, local=args.local): #print ("xxxxxxx",proc.get_formula()) vtof = proc.get_free_energy_for_plot(readme) if vtof is not None: plotAPI(readme, thermofile, volumes, energies, expt=expt, xlim=xlim, _fitCp=args.SGTEfitCp, formula = proc.get_formula(), vtof=vtof, plotlabel=args.plot) """ """ #print("xxxxxxxxxxxx",readme) record_cmd_print(thermofile, readme) elif no_MongoDB: print("\n*********WARNING: CANNOT get MongoDB service, so I will proceed using local data") print("*********WARNING: CANNOT get MongoDB service, so I will proceed using local data") print("*********WARNING: CANNOT get MongoDB service, so I will proceed using local data\n") elif not args.plotonly: #if True: try: if vasp_db is None: db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] vasp_db = VaspCalcDb.from_db_file(db_file, admin=False) static_calculations = vasp_db.collection.\ find({'$and':[ {'metadata.tag': metatag}, {'adopted': True} ]}) structure = Structure.from_dict(static_calculations[0]['output']['structure']) formula = reduced_formula(structure.composition.alphabetical_formula) except: no_MongoDB = True print("\n*********WARNING: CANNOT get MongoDB service, so I will proceed using local data") print("*********WARNING: CANNOT get MongoDB service, so I will proceed using local data") print("*********WARNING: CANNOT get MongoDB service, so I will proceed using local data\n") """ """ #call API if args.plotonly and plotfiles!=None: metatag, thermofile, volumes, energies, dir, formula = plotfiles sys.stdout.write('Processing {}, dir: {}, formula: {}\n'.format(metatag, dir, formula)) #print(thermofile, volumes, energies, formula) #print(thermofile, dir, formula) readme={} from dfttk.analysis.ywplot import plotAPI plotAPI(readme, thermofile, None, energies, expt=expt, xlim=xlim, _fitCp=args.SGTEfitCp, formula = formula, vtof=None, plotlabel=args.plot) elif vasp_db==None and plotfiles!=None: metatag, thermofile, volumes, energies, dir, formula = plotfiles sys.stdout.write('Processing {}, dir: {}, formula: {}\n'.format(metatag, dir, formula)) #print("xxxxxxxxxx", plotfiles) if expt!=None: _t1 = get_melting_temperature(expt, formula) if _t1!=None: t1 = _t1 readme = {} record_cmd(readme) proc = thelecMDB(t0, t1, td, xdn, xup, dope, ndosmx, gaussian, natom, outf, vasp_db=vasp_db, noel=noel, metatag=metatag, qhamode=qhamode, eqmode=eqmode, elmode=elmode, everyT=everyT, smooth=smooth, debug=args.debug, phasename=dir, pyphon=args.pyphon, renew=args.renew, fitF=args.fitF, args=args) volumes, energies, thermofile, comments = proc.run_console() #print ("xxxxxxx", comments) if comments!=None: readme.update(comments) else: return if "ERROR" in readme.keys(): #record_cmd_print(thermofile, readme, dir=args.phasename) return print("\nFull thermodynamic properties have outputed into:", thermofile) #print(args.plot, "eeeeeeeee", volumes, energies, thermofile, comments) if args.plot==None: print("\nSupply '-plot phasename' for plot\n") else: from dfttk.analysis.ywplot import plotAPI if plotAPI(readme, thermofile, volumes, energies, expt=expt, xlim=xlim, _fitCp=args.SGTEfitCp, formula = proc.get_formula(), debug=args.debug, plotlabel=args.plot): vtof = proc.get_free_energy_for_plot(readme) if vtof is not None: plotAPI(readme, thermofile, volumes, energies, expt=expt, xlim=xlim, _fitCp=args.SGTEfitCp, formula = proc.get_formula(), vtof=vtof, plotlabel=args.plot) """ """ record_cmd_print(thermofile, readme) elif metatag != None: if expt!=None: _t1 = get_melting_temperature(expt, formula) if _t1!=None: t1 = _t1 readme = {} record_cmd(readme) proc = thelecMDB(t0, t1, td, xdn, xup, dope, ndosmx, gaussian, natom, outf, vasp_db=vasp_db, noel=noel, metatag=metatag, qhamode=qhamode, eqmode=eqmode, elmode=elmode, everyT=everyT, smooth=smooth, debug=args.debug, phasename=args.phasename, pyphon=args.pyphon, renew=args.renew, fitF=args.fitF, args=args) volumes, energies, thermofile, comments = proc.run_console() if comments!=None: readme.update(comments) else: return if "ERROR" in readme.keys(): record_cmd_print(thermofile, readme, dir=args.phasename) return print("\nFull thermodynamic properties have outputed into:", thermofile) #print(args.plot, "eeeeeeeee", volumes, energies, thermofile, comments) if args.plot==None: print("\nSupply '-plot phasename' for plot\n") else: from dfttk.analysis.ywplot import plotAPI if plotAPI(readme, thermofile, volumes, energies, expt=expt, xlim=xlim, _fitCp=args.SGTEfitCp, formula = proc.get_formula(), debug=args.debug, plotlabel=args.plot): vtof = proc.get_free_energy_for_plot(readme) if vtof is not None: plotAPI(readme, thermofile, volumes, energies, expt=expt, xlim=xlim, _fitCp=args.SGTEfitCp, formula = proc.get_formula(), vtof=vtof, plotlabel=args.plot) """ """ record_cmd_print(thermofile, readme) elif args.vdos is not None: readme = {} record_cmd(readme) proc = thelecMDB(t0, t1, td, xdn, xup, dope, ndosmx, gaussian, natom, outf, renew=True, args=args) thermofile, comments, natoms = proc.run_single() if thermofile is None: return readme.update(comments) #record_cmd(thermofile, readme) print("\nFull thermodynamic properties have outputed into:", thermofile) if args.plot!=None: from dfttk.analysis.ywplot import plotAPI if plotAPI(readme, thermofile, None, None, expt=expt, xlim=xlim, _fitCp=args.SGTEfitCp, formula = proc.get_formula(), debug=args.debug, poscar=args.poscar,vdos=args.vdos, doscar=args.doscar, natoms=natoms, plotlabel=args.plot): record_cmd_print(thermofile, readme) elif args.local == "": pythelec.thelecAPI(t0, t1, td, xdn, xup, dope, ndosmx, gaussian, natom, outf, doscar)
self.unit = ['eV', '', '', ''] self.data = np.vstack( (energies, densities, densities_up, -densities_dn)).T self.parameter = dos['input']['incar'] def get_debye(self, debye): self.head = ['Temperature', 'Optimum_volume', 'Gibbs_energy'] self.unit = ['K', 'A^3', 'eV'] self.data = np.vstack( (debye.pop('temperatures'), debye.pop('optimum_volumes'), debye.pop('gibbs_free_energy'))).T self.parameter = debye #db_file = 'db.json' db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] properties = 'phonon' #for Ni metadata = {'tag': '217fecb5-4b27-4a7d-8ba9-1acc0bf5ffa9'} phonon = True band = True phonon_dos = True savefig = True savedata = True t_min = 5. t_max = 2000. t_step = 5. poisson = 0.363615
def get_wf_single(structure, WORKFLOW="get_wf_gibbs", settings={}): """ Get a single workflow Parameters structure: pymatgen.Structure The structure WORKFLOW: str The name of the workflow, now only gibbs energy workflow(get_wf_gibbs) is supported settings: dict User settings for the workflow Return """ ################ PARAMETERS FOR WF ############################# #str, the absolute path of db.json file, e.g. /storage/home/mjl6505/atomate/config/db.json # If None, it will use the configuration in fireworks db_file = settings.get('db_file', None) #list, the MAGMOM of the structure, e.g. [4.0, 4.0, -4.0, -4.0] magmom = settings.get('magmom', None) #int, the number of initial deformations, e.g. 7 num_deformations = settings.get('num_deformations', 7) #list/tuple(min, max) or float(-max, max), the maximum amplitude of deformation, e.g. (-0.05, 0.1) means (0.95, 1.1) in volume deformation_fraction = settings.get('deformation_fraction', (-0.1, 0.1)) #float, minimum ratio of Volumes spacing, e.g. 0.03 volume_spacing_min = settings.get('volume_spacing_min', 0.03) #bool, run phonon(True) or not(False) phonon = settings.get('phonon', False) #list(3x3), the supercell matrix for phonon, e.g. [[2.0, 0, 0], [0, 2.0, 0], [0, 0, 2.0]] phonon_supercell_matrix = settings.get('phonon_supercell_matrix', None) #float, the mimimum of temperature in QHA process, e.g. 5 t_min = settings.get('t_min', 5) #float, the maximum of temperature in QHA process, e.g. 2000 t_max = settings.get('t_max', 2000) #float, the step of temperature in QHA process, e.g. 5 t_step = settings.get('t_step', 5) #float, acceptable value for average RMS, recommend >= 0.005 tolerance = settings.get('tolerance', 0.01) #str, the vasp command, if None then find in the FWorker configuration vasp_cmd = settings.get('vasp_cmd', None) #dict, metadata to be included, this parameter is useful for filter the data, e.g. metadata={"phase": "BCC_A2", "tag": "AFM"} metadata = settings.get('metadata', None) #float, the tolerannce for symmetry, e.g. 0.05 symmetry_tolerance = settings.get('symmetry_tolerance', 0.05) #bool, set True to pass initial VASP running if the results exist in DB, use carefully to keep data consistent. passinitrun = settings.get('passinitrun', False) #bool, Whether run isif=2 calculation before isif=4 running run_isif2 = settings.get('run_isif2', False) #bool, Whether pass isif=4 calculation. pass_isif4 = settings.get('pass_isif4', False) #Set the path already exists for new static calculations; if set as '', will try to get the path from db_file relax_path = settings.get('relax_path', '') #dict, dict of class ModifyIncar with keywords in Workflow name. e.g. """ modify_incar_params = { 'Full relax': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, 'PreStatic': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, 'PS2': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, 'static': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, """ modify_incar_params = settings.get('modify_incar_params', {}) #dict, dict of class ModifyKpoints with keywords in Workflow name, similar with modify_incar_params modify_kpoints_params = settings.get('modify_kpoints_params', {}) #bool, print(True) or not(False) some informations, used for debug verbose = settings.get('verbose', False) if magmom: structure.add_site_property('magmom', magmom) if not db_file: from fireworks.fw_config import config_to_dict db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] if WORKFLOW == "get_wf_gibbs": #Currently, only this workflow is supported wf = get_wf_gibbs(structure, num_deformations=num_deformations, deformation_fraction=deformation_fraction, phonon=phonon, phonon_supercell_matrix=phonon_supercell_matrix, t_min=t_min, t_max=t_max, t_step=t_step, tolerance=tolerance, volume_spacing_min=volume_spacing_min, vasp_cmd=vasp_cmd, db_file=db_file, metadata=metadata, name='EV_QHA', symmetry_tolerance=symmetry_tolerance, run_isif2=run_isif2, pass_isif4=pass_isif4, passinitrun=passinitrun, relax_path=relax_path, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params, verbose=verbose) else: raise ValueError( "Currently, only the gibbs energy workflow is supported.") return wf