diff --git a/README.rst b/README.rst index 3e8f3cbc..e224ceb3 100644 Binary files a/README.rst and b/README.rst differ diff --git a/mpworks/check_snl/builders/base.py b/mpworks/check_snl/builders/base.py index 5d8bd641..2ff34f48 100644 --- a/mpworks/check_snl/builders/base.py +++ b/mpworks/check_snl/builders/base.py @@ -1,10 +1,15 @@ -import sys, multiprocessing, time -from mpworks.snl_utils.mpsnl import SNLGroup +import multiprocessing +import sys +import time + +from init_plotly import py, stream_ids, categories from matgendb.builders.core import Builder from matgendb.builders.util import get_builder_log -from mpworks.check_snl.utils import div_plus_mod from pymatgen.analysis.structure_matcher import StructureMatcher, ElementComparator -from init_plotly import py, stream_ids, categories + +from mpworks.check_snl.utils import div_plus_mod +from mpworks.snl_utils.mpsnl import SNLGroup + if py is not None: from plotly.graph_objs import * @@ -66,7 +71,7 @@ def get_items(self, snls=None, snlgroups=None, ncols=None): return self._snls.query(distinct_key='snl_id') def process_item(self, item, index): - nrow, ncol = index/self._ncols, index%self._ncols + nrow, ncol = index//self._ncols, index%self._ncols snlgroups = {} # keep {snlgroup_id: SNLGroup} to avoid dupe queries if isinstance(item, dict) and 'snlgroup_ids' in item: for gid in item['snlgroup_ids']: @@ -83,19 +88,19 @@ def _push_to_plotly(self): heatmap_z = self._counter._getvalue() if not self._seq else self._counter bar_x = self._mismatch_counter._getvalue() if not self._seq else self._mismatch_counter md = self._mismatch_dict._getvalue() if not self._seq else self._mismatch_dict - try: - self._streams[0].write(Heatmap(z=heatmap_z)) - except: - exc_type, exc_value, exc_traceback = sys.exc_info() - _log.info('%r %r', exc_type, exc_value) - _log.info('_push_to_plotly ERROR: heatmap=%r', heatmap_z) - try: - self._streams[1].write(Bar(x=bar_x)) - except: - exc_type, exc_value, exc_traceback = sys.exc_info() - _log.info('%r %r', exc_type, exc_value) - _log.info('_push_to_plotly ERROR: bar=%r', bar_x) - for k,v in md.iteritems(): + try: + self._streams[0].write(Heatmap(z=heatmap_z)) + except: + exc_type, exc_value, exc_traceback = sys.exc_info() + _log.info('%r %r', exc_type, exc_value) + _log.info('_push_to_plotly ERROR: heatmap=%r', heatmap_z) + try: + self._streams[1].write(Bar(x=bar_x)) + except: + exc_type, exc_value, exc_traceback = sys.exc_info() + _log.info('%r %r', exc_type, exc_value) + _log.info('_push_to_plotly ERROR: bar=%r', bar_x) + for k, v in md.items(): if len(v) < 1: continue try: self._streams[2].write(Scatter( @@ -103,7 +108,7 @@ def _push_to_plotly(self): y=k, text='
'.join(v) )) _log.info('_push_to_plotly: mismatch_dict[%r]=%r', k, v) - self._mismatch_dict.update({k:[]}) # clean + self._mismatch_dict.update({k: []}) # clean time.sleep(0.052) except: exc_type, exc_value, exc_traceback = sys.exc_info() @@ -122,7 +127,7 @@ def _increase_counter(self, nrow, ncol, mismatch_dict): for k in categories[self.checker_name]: mc[categories[self.checker_name].index(k)] += len(mismatch_dict[k]) self._mismatch_counter = mc - for k,v in mismatch_dict.iteritems(): + for k,v in mismatch_dict.items(): self._mismatch_dict[k] += v currow = self._counter[nrow] currow[ncol] += 1 @@ -136,7 +141,7 @@ def _increase_counter(self, nrow, ncol, mismatch_dict): if self._lock is not None: self._lock.release() def finalize(self, errors): - if py is not None: self._push_to_plotly() + if py is not None: self._push_to_plotly() _log.info("%d items processed.", self._counter_total.value) return True diff --git a/mpworks/check_snl/builders/init_plotly.py b/mpworks/check_snl/builders/init_plotly.py index 263d1bed..da8a6fa7 100644 --- a/mpworks/check_snl/builders/init_plotly.py +++ b/mpworks/check_snl/builders/init_plotly.py @@ -90,4 +90,4 @@ fig['layout'] = layout py.plot(fig, filename='builder_stream', auto_open=False) else: - print 'plotly ImportError' + print('plotly ImportError') diff --git a/mpworks/check_snl/check_snl.py b/mpworks/check_snl/check_snl.py index 989df0d3..703ba187 100644 --- a/mpworks/check_snl/check_snl.py +++ b/mpworks/check_snl/check_snl.py @@ -36,16 +36,16 @@ ) num_ids_per_stream = 20000 -num_ids_per_stream_k = num_ids_per_stream/1000 +num_ids_per_stream_k = num_ids_per_stream//1000 num_snls = sma.snl.count() num_snlgroups = sma.snlgroups.count() num_pairs_per_job = 1000 * num_ids_per_stream -num_pairs_max = num_snlgroups*(num_snlgroups-1)/2 +num_pairs_max = num_snlgroups*(num_snlgroups-1)//2 num_snl_streams = div_plus_mod(num_snls, num_ids_per_stream) num_snlgroup_streams = div_plus_mod(num_snlgroups, num_ids_per_stream) num_jobs = div_plus_mod(num_pairs_max, num_pairs_per_job) -print num_snl_streams, num_snlgroup_streams, num_jobs +print(num_snl_streams, num_snlgroup_streams, num_jobs) checks = ['spacegroups', 'groupmembers', 'canonicals'] categories = [ 'SG Change', 'SG Default', 'PybTeX', 'Others' ] @@ -113,7 +113,7 @@ def __iter__(self): def _get_initial_pair(self, job_id): N, J, M = num_snlgroups, job_id, num_pairs_per_job i = int(N+.5-sqrt(N*(N-1)+.25-2*J*M)) - j = J*M-(i-1)*(2*N-i)/2+i+1 + j = J*M-(i-1)*(2*N-i)//2+i+1 return Pair(i,j) def next(self): if self.num_pairs > num_pairs_per_job: @@ -202,7 +202,7 @@ def init_plotly(args): def check_snl_spacegroups(args): """check spacegroups of all available SNLs""" - range_index = args.start / num_ids_per_stream + range_index = args.start // num_ids_per_stream idxs = [range_index*2] idxs += [idxs[0]+1] s = [py.Stream(stream_ids[i]) for i in idxs] @@ -242,7 +242,7 @@ def check_snl_spacegroups(args): def check_snls_in_snlgroups(args): """check whether SNLs in each SNLGroup still match resp. canonical SNL""" - range_index = args.start / num_ids_per_stream + range_index = args.start // num_ids_per_stream idxs = [2*(num_snl_streams+range_index)] idxs += [idxs[0]+1] s = [py.Stream(stream_ids[i]) for i in idxs] @@ -314,7 +314,7 @@ def analyze(args): if args.t: if args.fig_id == 42: label_entries = filter(None, '
'.join(fig['data'][2]['text']).split('
')) - pairs = map(make_tuple, label_entries) + pairs = list(map(make_tuple, label_entries)) grps = set(chain.from_iterable(pairs)) snlgrp_cursor = sma.snlgroups.aggregate([ { '$match': { @@ -326,7 +326,7 @@ def analyze(args): snlgroup_keys = {} for d in snlgrp_cursor: snlgroup_keys[d['snlgroup_id']] = d['canonical_snl']['snlgroup_key'] - print snlgroup_keys[40890] + print(snlgroup_keys[40890]) sma2 = SNLMongoAdapter.from_file( os.path.join(os.environ['DB_LOC'], 'materials_db.yaml') ) @@ -353,7 +353,7 @@ def analyze(args): 'band_gap': band_gap, 'task_id': material['task_id'], 'volume_per_atom': volume_per_atom } - print snlgroup_data[40890] + print(snlgroup_data[40890]) filestem = 'mpworks/check_snl/results/bad_snlgroups_2_' with open(filestem+'in_matdb.csv', 'wb') as f, \ open(filestem+'notin_matdb.csv', 'wb') as g: @@ -402,7 +402,7 @@ def analyze(args): rms_dist = matcher.get_rms_dist(primary_structure, secondary_structure) if rms_dist is not None: rms_dist_str = "({0:.3g},{1:.3g})".format(*rms_dist) - print rms_dist_str + print(rms_dist_str) row = [ category, composition, primary_id, primary_sg_num, @@ -420,13 +420,13 @@ def analyze(args): out_fig = Figure() badsnls_trace = Scatter(x=[], y=[], text=[], mode='markers', name='SG Changes') bisectrix = Scatter(x=[0,230], y=[0,230], mode='lines', name='bisectrix') - print 'pulling bad snls from plotly ...' + print('pulling bad snls from plotly ...') bad_snls = OrderedDict() for category, text in zip(fig['data'][2]['y'], fig['data'][2]['text']): for snl_id in map(int, text.split('
')): bad_snls[snl_id] = category with open('mpworks/check_snl/results/bad_snls.csv', 'wb') as f: - print 'pulling bad snls from database ...' + print('pulling bad snls from database ...') mpsnl_cursor = sma.snl.find({ 'snl_id': { '$in': bad_snls.keys() }, 'about.projects': {'$ne': 'CederDahn Challenge'} @@ -435,7 +435,7 @@ def analyze(args): writer.writerow([ 'snl_id', 'category', 'snlgroup_key', 'nsites', 'remarks', 'projects', 'authors' ]) - print 'writing bad snls to file ...' + print('writing bad snls to file ...') for mpsnl_dict in mpsnl_cursor: mpsnl = MPStructureNL.from_dict(mpsnl_dict) row = [ mpsnl.snl_id, bad_snls[mpsnl.snl_id], mpsnl.snlgroup_key ] @@ -450,8 +450,8 @@ def analyze(args): badsnls_trace['y'].append(sf.get_spacegroup_number()) badsnls_trace['text'].append(mpsnl.snl_id) if bad_snls[mpsnl.snl_id] == 'SG default': - print sg_num, sf.get_spacegroup_number() - print 'plotting out-fig ...' + print(sg_num, sf.get_spacegroup_number()) + print('plotting out-fig ...') out_fig['data'] = Data([bisectrix, badsnls_trace]) out_fig['layout'] = Layout( showlegend=False, hovermode='closest', @@ -467,7 +467,7 @@ def analyze(args): ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, comparator=ElementComparator() ) - print 'pulling data from plotly ...' + print('pulling data from plotly ...') trace = Scatter(x=[], y=[], text=[], mode='markers', name='mismatches') bad_snls = OrderedDict() # snlgroup_id : [ mismatching snl_ids ] for category, text in zip(fig['data'][2]['y'], fig['data'][2]['text']): @@ -475,7 +475,7 @@ def analyze(args): for entry in text.split('
'): fields = entry.split(':') snlgroup_id = int(fields[0].split(',')[0]) - print snlgroup_id + print(snlgroup_id) snlgrp_dict = sma.snlgroups.find_one({ 'snlgroup_id': snlgroup_id }) snlgrp = SNLGroup.from_dict(snlgrp_dict) s1 = snlgrp.canonical_structure.get_primitive_structure() @@ -483,7 +483,7 @@ def analyze(args): for i, snl_id in enumerate(fields[1].split(',')): mpsnl_dict = sma.snl.find_one({ 'snl_id': int(snl_id) }) if 'CederDahn Challenge' in mpsnl_dict['about']['projects']: - print 'skip CederDahn: %s' % snl_id + print('skip CederDahn: %s' % snl_id) continue mpsnl = MPStructureNL.from_dict(mpsnl_dict) s2 = mpsnl.structure.get_primitive_structure() @@ -496,13 +496,13 @@ def analyze(args): if len(bad_snls[snlgroup_id]) < 1: bad_snls.pop(snlgroup_id, None) with open('mpworks/check_snl/results/bad_snlgroups.csv', 'wb') as f: - print 'pulling bad snlgroups from database ...' + print('pulling bad snlgroups from database ...') snlgroup_cursor = sma.snlgroups.find({ 'snlgroup_id': { '$in': bad_snls.keys() }, }) writer = csv.writer(f) writer.writerow(['snlgroup_id', 'snlgroup_key', 'mismatching snl_ids']) - print 'writing bad snlgroups to file ...' + print('writing bad snlgroups to file ...') for snlgroup_dict in snlgroup_cursor: snlgroup = SNLGroup.from_dict(snlgroup_dict) row = [ @@ -510,7 +510,7 @@ def analyze(args): ' '.join(bad_snls[snlgroup.snlgroup_id]) ] writer.writerow(row) - print 'plotting out-fig ...' + print('plotting out-fig ...') out_fig = Figure() out_fig['data'] = Data([trace]) out_fig['layout'] = Layout( @@ -544,11 +544,11 @@ def analyze(args): snlgroup_id = start_id + d['x'][idx] mismatch_snl_id, canonical_snl_id = d['text'][idx].split(' != ') bad_snlgroups[snlgroup_id] = int(mismatch_snl_id) - print errors + print(errors) fig_data = fig['data'][-1] fig_data['x'] = [ errors[color] for color in fig_data['marker']['color'] ] filename = _get_filename() - print filename + print(filename) #py.plot(fig, filename=filename) with open('mpworks/check_snl/results/bad_snls.csv', 'wb') as f: mpsnl_cursor = sma.snl.find({ 'snl_id': { '$in': bad_snls.keys() } }) diff --git a/mpworks/check_snl/icsd.py b/mpworks/check_snl/icsd.py index 4dadd5f8..9ecf76ea 100644 --- a/mpworks/check_snl/icsd.py +++ b/mpworks/check_snl/icsd.py @@ -10,8 +10,8 @@ for category, text in zip(fig['data'][2]['y'], fig['data'][2]['text']): for line in text.split('
'): before_colon, after_colon = line.split(':') - snlgroup1, snlgroup2 = map(int, before_colon[1:-1].split(',')) + snlgroup1, snlgroup2 = list(map(int, before_colon[1:-1].split(','))) snls, icsd_matches = after_colon.split('->') - snl1, snl2 = map(int, snls[2:-2].split(',')) + snl1, snl2 = list(map(int, snls[2:-2].split(','))) icsd, matches = icsd_matches.strip().split(' ') writer.writerow([snlgroup1, snlgroup2, snl1, snl2, int(icsd), matches[1:-1]]) diff --git a/mpworks/check_snl/scripts/sg_changes_examples.py b/mpworks/check_snl/scripts/sg_changes_examples.py index 466c2626..e3dad567 100644 --- a/mpworks/check_snl/scripts/sg_changes_examples.py +++ b/mpworks/check_snl/scripts/sg_changes_examples.py @@ -34,8 +34,8 @@ def _get_mp_link(mp_id): fig = py.get_figure('tschaume',11) df = DataFrame.from_dict(fig['data'][1]).filter(['x','y','text']) grouped_x = df.groupby('x') -print '|===============================' -print '| old SG | close to bisectrix | far from bisectrix' +print('|===============================') +print('| old SG | close to bisectrix | far from bisectrix') for n,g in grouped_x: if g.shape[0] < 2: continue # at least two entries at same old SG grouped_y = g.groupby('y') @@ -50,9 +50,9 @@ def _get_mp_link(mp_id): if ratios[0] > 0.2 or ratios[1] < 0.8: continue snlgroup_ids = _get_snlgroup_id(first['text']), _get_snlgroup_id(last['text']) mp_ids = _get_mp_id(snlgroup_ids[0]), _get_mp_id(snlgroup_ids[1]) - print '| %d | %d (%d) -> %d -> %s | %d (%d) -> %d -> %s' % ( + print('| %d | %d (%d) -> %d -> %s | %d (%d) -> %d -> %s' % ( first['x'], first['text'], first['y'], snlgroup_ids[0], _get_mp_link(mp_ids[0]), last['text'], last['y'], snlgroup_ids[1], _get_mp_link(mp_ids[1]) - ) -print '|===============================' + )) +print('|===============================') diff --git a/mpworks/check_snl/scripts/sg_default_bad_snls_check.py b/mpworks/check_snl/scripts/sg_default_bad_snls_check.py index 24345e9a..034fd592 100644 --- a/mpworks/check_snl/scripts/sg_default_bad_snls_check.py +++ b/mpworks/check_snl/scripts/sg_default_bad_snls_check.py @@ -119,4 +119,4 @@ nonvalid_snlids.append(snl['snl_id']) else: valid_snlids.append(snl['snl_id']) -print len(valid_snlids), len(nonvalid_snlids) +print(len(valid_snlids), len(nonvalid_snlids)) diff --git a/mpworks/drones/mp_vaspdrone.py b/mpworks/drones/mp_vaspdrone.py index 3df970e5..5e4146ba 100644 --- a/mpworks/drones/mp_vaspdrone.py +++ b/mpworks/drones/mp_vaspdrone.py @@ -5,6 +5,8 @@ import pprint import re import traceback +import warnings + from monty.io import zopen from monty.os.path import zpath from pymongo import MongoClient @@ -66,16 +68,16 @@ def assimilate(self, path, launches_coll=None): d["dir_name"] = get_block_part(d["dir_name_full"]) d["stored_data"] = {} except: - print 'COULD NOT GET DIR NAME' + print('COULD NOT GET DIR NAME') pprint.pprint(d) - print traceback.format_exc() + print(traceback.format_exc()) raise ValueError('IMPROPER PARSING OF {}'.format(path)) if not self.simulate: # Perform actual insertion into db. Because db connections cannot # be pickled, every insertion needs to create a new connection # to the db. - conn = MongoClient(self.host, self.port) + conn = MongoClient(self.host, self.port, connect=False) db = conn[self.database] if self.user: db.authenticate(self.user, self.password) @@ -101,8 +103,8 @@ def assimilate(self, path, launches_coll=None): if ("task_id" not in d) or (not d["task_id"]): d["task_id"] = "mp-{}".format( db.counter.find_one_and_update( - {"_id": "taskid"}, {"$inc": {"c": 1}} - )["c"]) + {"_id": "taskid"}, {"$inc": {"c": 1}}) + ["c"]) logger.info("Inserting {} with taskid = {}" .format(d["dir_name"], d["task_id"])) elif self.update_duplicates: @@ -166,7 +168,7 @@ def assimilate(self, path, launches_coll=None): d['is_compatible'] = bool(mpc.process_entry(entry)) except: traceback.print_exc() - print 'ERROR in getting compatibility' + print('ERROR in getting compatibility') d['is_compatible'] = None @@ -215,7 +217,7 @@ def string_to_numlist(stringlist): d['analysis'].update(update_doc) d['calculations'][0]['output'].update(update_doc) - coll.update_one({"dir_name": d["dir_name"]}, {'$set': d}, upsert=True) + coll.update_one({"dir_name": d["dir_name"]}, {'$set': d}, upsert=True) return d["task_id"], d else: @@ -238,7 +240,7 @@ def process_fw(self, dir_name, d): break # custom Materials Project post-processing for FireWorks - with zopen(zpath(os.path.join(dir_name, 'FW.json'))) as f: + with zopen(zpath(os.path.join(dir_name, 'FW.json')), 'rt') as f: fw_dict = json.load(f) d['fw_id'] = fw_dict['fw_id'] d['snl'] = fw_dict['spec']['mpsnl'] @@ -250,7 +252,9 @@ def process_fw(self, dir_name, d): d['deformation_matrix'] = fw_dict['spec']['deformation_matrix'] d['original_task_id'] = fw_dict['spec']['original_task_id'] if not self.update_duplicates: - if 'optimize structure' in d['task_type'] and 'output' in d: + if ('optimize structure' in d['task_type'] or + 'Triple Jump Relax' in d['task_type']) \ + and 'output' in d: # create a new SNL based on optimized structure new_s = Structure.from_dict(d['output']['crystal']) old_snl = StructureNL.from_dict(d['snl']) @@ -275,6 +279,14 @@ def process_fw(self, dir_name, d): d['snlgroup_id_final'] = snlgroup_id d['snlgroup_changed'] = (d['snlgroup_id'] != d['snlgroup_id_final']) + if len(d["calculations"][-1]["output"]["ionic_steps"]) >= 3 and not d['snlgroup_changed']: + message = "The structure has been relaxed for >=3 step, however, final structure" \ + "ends in the snlgroup with the initial group, please change either structure" \ + "relax criteria or StructureMatcher tolerance" + if "NMR" not in mpsnl.projects: + warnings.warn(message) + else: + raise ValueError(message) else: d['snl_final'] = d['snl'] d['snlgroup_id_final'] = d['snlgroup_id'] @@ -309,7 +321,7 @@ def process_fw(self, dir_name, d): vasp_signals['last_relax_dir'] = last_relax_dir ## see what error signals are present - print "getting signals for dir :{}".format(last_relax_dir) + print("getting signals for dir :{}".format(last_relax_dir)) sl = SignalDetectorList() sl.append(VASPInputsExistSignal()) diff --git a/mpworks/drones/signals.py b/mpworks/drones/signals.py index 28ce3c65..ccc39c38 100644 --- a/mpworks/drones/signals.py +++ b/mpworks/drones/signals.py @@ -30,7 +30,7 @@ def string_list_in_file(s_list, filename, ignore_case=True): """ matches = set() - with zopen(filename, 'r') as f: + with zopen(filename, 'rt') as f: for line in f: for s in s_list: if (ignore_case and s.lower() in line.lower()) or s in line: @@ -184,7 +184,7 @@ def detect(self, dir_name): file_names = glob.glob("%s/*.error" % dir_name) rx = re.compile(r'segmentation', re.IGNORECASE) for file_name in file_names: - with zopen(file_name, 'r') as f: + with zopen(file_name, 'rt') as f: lines = f.readlines() for line in lines: if rx.search(line) is not None: diff --git a/mpworks/dupefinders/dupefinder_vasp.py b/mpworks/dupefinders/dupefinder_vasp.py index c27ed7a7..66ff2335 100644 --- a/mpworks/dupefinders/dupefinder_vasp.py +++ b/mpworks/dupefinders/dupefinder_vasp.py @@ -15,13 +15,10 @@ class DupeFinderVasp(DupeFinderBase): _fw_name = 'Dupe Finder Vasp' - def verify(self, spec1, spec2): - # assert: task_type and snlgroup_id have already been checked through query - return set(spec1.get('run_tags', [])) == set(spec2.get('run_tags', [])) - def query(self, spec): return {'spec.task_type': spec['task_type'], - 'spec.snlgroup_id': spec['snlgroup_id']} + 'spec.snlgroup_id': spec['snlgroup_id'], + 'spec.run_tags': spec['run_tags']} class DupeFinderDB(DupeFinderBase): diff --git a/mpworks/examples/firetasks_ex.py b/mpworks/examples/firetasks_ex.py index 39d6068a..d1f1fcbf 100644 --- a/mpworks/examples/firetasks_ex.py +++ b/mpworks/examples/firetasks_ex.py @@ -89,7 +89,7 @@ def run_task(self, fw_spec): t_id = drone.assimilate(prev_dir) if t_id: - print 'ENTERED task id:', t_id + print('ENTERED task id:', t_id) stored_data = {'task_id': t_id} update_spec = {'prev_vasp_dir': prev_dir, 'prev_task_type': fw_spec['prev_task_type']} return FWAction(stored_data=stored_data, update_spec=update_spec) diff --git a/mpworks/firetasks/boltztrap_tasks.py b/mpworks/firetasks/boltztrap_tasks.py index 9538fdad..46f3c642 100644 --- a/mpworks/firetasks/boltztrap_tasks.py +++ b/mpworks/firetasks/boltztrap_tasks.py @@ -162,13 +162,13 @@ def run_task(self, fw_spec): nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] - print bs_id, type(bs_id) + print(bs_id, type(bs_id)) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output']['crystal'] bs = BandStructure.from_dict(bs_dict) - print 'Band Structure found:', bool(bs) - print nelect + print('Band Structure found:', bool(bs)) + print(nelect) # run Boltztrap runner = BoltztrapRunner(bs, nelect) @@ -233,7 +233,7 @@ def run_task(self, fw_spec): ted['kappa_best_dope19'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=4) try: - from mpcollab.thermoelectrics.boltztrap_TE import BoltzSPB + from mpcollab.thermoelectrics.boltztrap_TE import BoltzSPB bzspb = BoltzSPB(ted) maxpf_p = bzspb.get_maximum_power_factor('p', temperature=0, tau=1E-14, ZT=False, kappal=0.5,\ otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ @@ -254,7 +254,7 @@ def run_task(self, fw_spec): except: import traceback traceback.print_exc() - print 'COULD NOT GET FINE MESH DATA' + print('COULD NOT GET FINE MESH DATA') # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") @@ -273,7 +273,7 @@ def run_task(self, fw_spec): ted["is_compatible"] = bool(mpc.process_entry(entry)) except: traceback.print_exc() - print 'ERROR in getting compatibility, task_id: {}'.format(m_task["task_id"]) + print('ERROR in getting compatibility, task_id: {}'.format(m_task["task_id"])) ted["is_compatible"] = None tdb.boltztrap.insert(jsanitize(ted)) diff --git a/mpworks/firetasks/controller_tasks.py b/mpworks/firetasks/controller_tasks.py index 55425211..77072563 100644 --- a/mpworks/firetasks/controller_tasks.py +++ b/mpworks/firetasks/controller_tasks.py @@ -33,10 +33,10 @@ def __init__(self, parameters=None): self.metal_cutoff = parameters.get('metal_cutoff', 0.05) def run_task(self, fw_spec): - print 'sleeping 10s for Mongo' + print('sleeping 10s for Mongo') time.sleep(10) - print 'done sleeping' - print 'the gap is {}, the cutoff is {}'.format(fw_spec['analysis']['bandgap'], self.gap_cutoff) + print('done sleeping') + print('the gap is {}, the cutoff is {}'.format(fw_spec['analysis']['bandgap'], self.gap_cutoff)) if fw_spec['analysis']['bandgap'] >= self.gap_cutoff: static_dens = 90 uniform_dens = 1000 @@ -51,7 +51,7 @@ def run_task(self, fw_spec): else: user_incar_settings = {} - print 'Adding more runs...' + print('Adding more runs...') type_name = 'GGA+U' if 'GGA+U' in fw_spec['prev_task_type'] else 'GGA' @@ -123,7 +123,7 @@ def run_task(self, fw_spec): wf = Workflow(fws, connections) - print 'Done adding more runs...' + print('Done adding more runs...') return FWAction(additions=wf) @@ -145,13 +145,13 @@ def __init__(self, parameters=None): self.gap_cutoff = parameters.get('gap_cutoff', 0.5) # see e-mail from Geoffroy, 5/1/2013 def run_task(self, fw_spec): - print 'sleeping 10s for Mongo' + print('sleeping 10s for Mongo') time.sleep(10) - print 'done sleeping' - print 'the gap is {}, the cutoff is {}'.format(fw_spec['analysis']['bandgap'], self.gap_cutoff) + print('done sleeping') + print('the gap is {}, the cutoff is {}'.format(fw_spec['analysis']['bandgap'], self.gap_cutoff)) if fw_spec['analysis']['bandgap'] >= self.gap_cutoff: - print 'Adding more runs...' + print('Adding more runs...') type_name = 'GGA+U' if 'GGA+U' in fw_spec['prev_task_type'] else 'GGA' snl = fw_spec['mpsnl'] @@ -211,7 +211,7 @@ def run_task(self, fw_spec): wf = Workflow(fws, connections) - print 'Done adding more runs...' + print('Done adding more runs...') return FWAction(additions=wf) return FWAction() diff --git a/mpworks/firetasks/custodian_task.py b/mpworks/firetasks/custodian_task.py index c48f11da..fe156fd2 100644 --- a/mpworks/firetasks/custodian_task.py +++ b/mpworks/firetasks/custodian_task.py @@ -1,18 +1,22 @@ +import tarfile +from glob import glob from gzip import GzipFile import logging import socket +import shutil from fireworks.fw_config import FWData from monty.os.path import which from custodian.vasp.handlers import VaspErrorHandler, NonConvergingErrorHandler, \ - FrozenJobErrorHandler, MeshSymmetryErrorHandler, PositiveEnergyErrorHandler + FrozenJobErrorHandler, MeshSymmetryErrorHandler, PositiveEnergyErrorHandler, StdErrHandler from custodian.vasp.validators import VasprunXMLValidator from fireworks.core.firework import FireTaskBase, FWAction from fireworks.utilities.fw_serializers import FWSerializable -from custodian.custodian import Custodian +from custodian.custodian import Custodian, CustodianError from custodian.vasp.jobs import VaspJob import shlex import os +import copy from fireworks.utilities.fw_utilities import get_slug from mpworks.workflows.wf_utils import j_decorate, ScancelJobStepTerminator from pymatgen.io.vasp.inputs import Incar @@ -29,7 +33,7 @@ def check_incar(task_type): errors = [] incar = Incar.from_file("INCAR") - + if 'deformed' in task_type: if incar['ISIF'] != 2: errors.append("Deformed optimization requires ISIF = 2") @@ -45,10 +49,10 @@ def check_incar(task_type): errors.append("LCHARG must be True for static runs") if 'Uniform' in task_type and incar["ICHARG"] != 11: - errors.append("ICHARG must be 11 for Uniform runs") + errors.append("ICHARG must be 11 for Uniform runs") if 'band structure' in task_type and incar["ICHARG"] != 11: - errors.append("ICHARG must be 11 for band structure runs") + errors.append("ICHARG must be 11 for band structure runs") if 'GGA+U' in task_type: # check LDAU @@ -70,8 +74,6 @@ class VaspCustodianTask(FireTaskBase, FWSerializable): def __init__(self, parameters): self.update(parameters) self.jobs = self['jobs'] - dec = MontyDecoder() - self.handlers = map(dec.process_decoded, self['handlers']) self.max_errors = self.get('max_errors', 1) self.gzip_output = self.get('gzip_output', True) @@ -130,10 +132,35 @@ def run_task(self, fw_spec): logging.basicConfig(level=logging.DEBUG) - c = Custodian(self.handlers, self.jobs, max_errors=self.max_errors, gzipped_output=False, - validators=[VasprunXMLValidator()], - terminate_func=terminate_func) # manual gzip - custodian_out = c.run() + error_list = [] + cus_ex = None + + if "alt_cmds" in fw_env and fw_spec['task_type'] in fw_env["alt_cmds"]: + try: + logging.info("Initiate VASP calculations using alternate binaries") + all_errors = self._run_alt_vasp_cmd(terminate_func, v_exe, gv_exe, + fw_env.get("vasp_cmd", "vasp"), + fw_env.get("gvasp_cmd", "gvasp"), + fw_env["alt_cmds"][fw_spec['task_type']], + fw_env.get("input_rewind", True), + fw_spec['mpsnl'].structure) + error_list.extend(all_errors) + except Exception as ex: + cus_ex = ex + try: + all_errors = self._run_custodian(terminate_func) + error_list.extend(all_errors) + except Exception as ex: + cus_ex = ex + + dynamic_wf = None + if cus_ex is not None: + if os.path.exists("std_err.txt") and \ + self._is_kpts_parallel_chemical_shift_eligible(fw_spec): + from mpworks.firetasks.nmr_tasks import chemical_shift_spec_to_dynamic_kpt_average_wfs + dynamic_wf = chemical_shift_spec_to_dynamic_kpt_average_wfs(fw_spec) + else: + raise cus_ex if self.gzip_output: for f in os.listdir(os.getcwd()): @@ -143,20 +170,116 @@ def run_task(self, fw_spec): f_out.writelines(f_in) os.remove(f) - all_errors = set() - for run in custodian_out: - for correction in run['corrections']: - all_errors.update(correction['errors']) - - stored_data = {'error_list': list(all_errors)} + stored_data = {'error_list': error_list} update_spec = {'prev_vasp_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'], 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters')} + for k in ['kpoint_tag', 'scf_vasp_dir', 'functional', 'total_kpts']: + if k in fw_spec: + update_spec[k] = fw_spec[k] - return FWAction(stored_data=stored_data, update_spec=update_spec) + if dynamic_wf is None: + return FWAction(stored_data=stored_data, update_spec=update_spec) + else: + return FWAction(stored_data=stored_data, update_spec=update_spec, + detours=dynamic_wf) + + def _is_kpts_parallel_chemical_shift_eligible(self, fw_spec): + if fw_spec['task_type'] == "NMR CS": + eh = StdErrHandler(output_filename="std_err.txt") + eh.check() + if set(eh.errors) & {'out_of_memory', 'seg_fault'}: + return True + return False + + + def _run_alt_vasp_cmd(self, terminate_func, v_exe, gv_exe, vasp_cmd, + gvasp_cmd, alt_cmds, input_rewind, structure): + error_list = [] + cus_ex = None + for new_vasp_path in alt_cmds: + new_vasp_cmd = new_vasp_path["vasp_cmd"] + new_gvasp_cmd = new_vasp_path["gvasp_cmd"] + new_v_exe = shlex.split(" ".join(v_exe).replace(vasp_cmd, new_vasp_cmd)) + new_gv_exe = shlex.split(" ".join(gv_exe).replace(gvasp_cmd, new_gvasp_cmd)) + logging.info("Run VASP with binary from {}".format(os.path.dirname(new_vasp_cmd))) + for job in self.jobs: + # set the vasp command to the alternative binaries + job.vasp_cmd = new_v_exe + job.gamma_vasp_cmd = new_gv_exe + + # backup the files for the last VASP binary run + error_file_prefix = "error" + error_num = max([0] + [int(f.split(".")[1]) + for f in glob("{}.*.tar.gz".format(error_file_prefix))]) + error_filename = "{}.{}.tar.gz".format(error_file_prefix, error_num) + binary_file_prefix = "binary" + binary_num = max([0] + [int(f.split(".")[1]) + for f in glob("{}.*.tar.gz".format(binary_file_prefix))]) + binary_filename = "{}.{}.tar.gz".format(binary_file_prefix, binary_num + 1) + + with tarfile.open(binary_filename, "w:gz") as tar: + for fname in ["custodian.json", error_filename, "CONTCAR", "OUTCAR", + "vasp.out", "std_err.txt", "INCAR", "POSCAR", "KPOINTS"]: + for f in glob(fname): + tar.add(f) + + for fname in ["OSZICAR", "vasp.out", "std_err.txt", "custodian.json", + "OUTCAR"]: + # remove old file before starting new calculations to + # avoid confuse custodian + if os.path.exists(fname): + os.remove(fname) + + if input_rewind: + # rewind the input to every beginning + if os.path.exists("error.1.tar.gz") and os.path.isfile("error.1.tar.gz"): + # restore to initial input set + with tarfile.open("error.1.tar.gz", "r") as tf: + for filename in ["INCAR", "KPOINTS", "POSCAR"]: + tf.extract(filename) + + if os.path.exists("CONTCAR"): + natoms = len(structure) + with open("CONTCAR") as f: + contcar_lines = f.readlines() + n_contcar_lines = len(contcar_lines) + if n_contcar_lines > natoms + 5: + # valid CONTCAR file + if os.path.exists("POSCAR"): + os.remove("POSCAR") + shutil.move("CONTCAR", "POSCAR") + + # run the calculation + cus_ex = None + try: + all_errors = self._run_custodian(terminate_func) + error_list.extend(all_errors) + except Exception as ex: + cus_ex = ex + if cus_ex is None: + break + if cus_ex is not None: + raise cus_ex + + return error_list + + def _run_custodian(self, terminate_func): + dec = MontyDecoder() + h_dict = copy.deepcopy(self['handlers']) + handlers = list(map(dec.process_decoded, h_dict)) + c = Custodian(handlers, self.jobs, max_errors=self.max_errors, gzipped_output=False, + validators=[VasprunXMLValidator()], + terminate_func=terminate_func) # manual gzip + custodian_out = c.run() + all_errors = set() + for run in custodian_out: + for correction in run['corrections']: + all_errors.update(correction['errors']) + return all_errors @staticmethod def _get_vasp_cmd_in_job_packing(fw_data, fw_env, mpi_cmd): @@ -172,24 +295,22 @@ def _get_vasp_cmd_in_job_packing(fw_data, fw_env, mpi_cmd): nodes_spec = {"srun": "--nodes {}".format(len(fw_data.NODE_LIST)), "mpirun": "", "aprun": ""} - verbose_flag = {"srun": "-v", - "mpirun": "", - "aprun": ""} mpirun = mpi_cmd.split()[0] + if "srun" in mpi_cmd: + mpi_cmd += " -v" fw_data = FWData() # Don't honor the SLURM_NTASKS in case of job packing, Because SLURM_NTASKS is referring # to total number of processes of the parent job sub_nproc = fw_data.SUB_NPROCS vasp_cmds = [fw_env.get("vasp_cmd", "vasp"), fw_env.get("gvasp_cmd", "gvasp")] - vasp_exes = [shlex.split('{mpi_cmd} {verbose_flag} {nodes_spec} {ranks_flag} {nproc} {tpn_flag} {tpn} ' + vasp_exes = [shlex.split('{mpi_cmd} {nodes_spec} {ranks_flag} {nproc} {tpn_flag} {tpn} ' '{nl_flag} {nl} {vasp_cmd}'. format(mpi_cmd=mpi_cmd, - verbose_flag=verbose_flag, nodes_spec=nodes_spec[mpirun], ranks_flag=ranks_num_flag[mpirun], nproc=sub_nproc, tpn_flag=tasks_per_node_flag[mpirun], - tpn=int(fw_data.SUB_NPROCS) / len(fw_data.NODE_LIST), + tpn=int(fw_data.SUB_NPROCS)//len(fw_data.NODE_LIST), nl_flag=nodelist_flag[mpirun], nl=','.join(fw_data.NODE_LIST), vasp_cmd=vasp_cmd)) @@ -209,12 +330,21 @@ def _write_formula_file(fw_spec): def get_custodian_task(spec): task_type = spec['task_type'] v_exe = 'VASP_EXE' # will be transformed to vasp executable on the node - handlers = [VaspErrorHandler(), FrozenJobErrorHandler(), - MeshSymmetryErrorHandler(), NonConvergingErrorHandler(), PositiveEnergyErrorHandler()] + if {'NMR EFG', 'NMR CS', 'Triple Jump Relax S1', + 'Triple Jump Relax S2', 'Triple Jump Relax S3', + 'Pre Kpt CS SCF', 'Single Kpt CS'} & {task_type}: + handlers = [VaspErrorHandler(natoms_large_cell=50), + StdErrHandler(output_filename="std_err.txt")] + else: + handlers = [VaspErrorHandler()] + handlers += [FrozenJobErrorHandler(), + MeshSymmetryErrorHandler(), NonConvergingErrorHandler(), PositiveEnergyErrorHandler()] if 'optimize structure (2x)' in task_type: jobs = VaspJob.double_relaxation_run(v_exe) - elif 'static' in task_type or 'deformed' in task_type: + elif {'static', 'deformed', 'NMR EFG', 'NMR CS', 'Triple Jump Relax S1', + 'Triple Jump Relax S2', 'Triple Jump Relax S3', 'Pre Kpt CS SCF', + 'Single Kpt CS'} & {task_type}: jobs = [VaspJob(v_exe)] else: # non-SCF runs diff --git a/mpworks/firetasks/elastic_tasks.py b/mpworks/firetasks/elastic_tasks.py index 33bd1a4f..12372eae 100644 --- a/mpworks/firetasks/elastic_tasks.py +++ b/mpworks/firetasks/elastic_tasks.py @@ -148,9 +148,9 @@ def run_task(self, fw_spec): "state":"successful"}).count() existing_doc = elasticity.find_one({"relaxation_task_id" : i}) if existing_doc: - print "Updating: " + i + print("Updating: " + i) else: - print "New material: " + i + print("New material: " + i) d = {"analysis": {}, "error": [], "warning": []} d["ndocs"] = ndocs o = tasks.find_one({"task_id" : i}, @@ -178,8 +178,8 @@ def run_task(self, fw_spec): "{:.0e}".format(delta)]) sm = IndependentStrain(defo) if dtype in d["deformation_tasks"].keys(): - print "old_task: {}".format(d["deformation_tasks"][dtype]["task_id"]) - print "new_task: {}".format(k["task_id"]) + print("old_task: {}".format(d["deformation_tasks"][dtype]["task_id"])) + print("new_task: {}".format(k["task_id"])) raise ValueError("Duplicate deformation task in database.") d["deformation_tasks"][dtype] = {"state" : k["state"], "deformation_matrix" : defo, diff --git a/mpworks/firetasks/nmr_tasks.py b/mpworks/firetasks/nmr_tasks.py new file mode 100644 index 00000000..9ab34e39 --- /dev/null +++ b/mpworks/firetasks/nmr_tasks.py @@ -0,0 +1,670 @@ +import copy +import hashlib +import json +import os + +import shutil +import yaml +from fireworks import FireTaskBase +from fireworks.core.firework import FWAction, Firework, Workflow +from fireworks.utilities.fw_serializers import FWSerializable +from fireworks.utilities.fw_utilities import get_slug +from monty.os.path import zpath +from pymatgen.analysis.bond_valence import BVAnalyzer +from pymatgen.io.vasp import Outcar, Kpoints +from monty.io import zopen +import re +import math +from pymatgen.analysis.nmr import NMRChemicalShiftNotation +from pymatgen.io.vasp.sets import DictSet + +from mpworks.dupefinders.dupefinder_vasp import DupeFinderVasp +from mpworks.firetasks.vasp_io_tasks import VaspToDBTask, VaspCopyTask +from mpworks.firetasks.vasp_setup_tasks import SetupUnconvergedHandlerTask +from mpworks.workflows.wf_settings import WFSettings +from mpworks.workflows.wf_utils import get_loc + +__author__ = 'Xiaohui Qu' +__copyright__ = 'Copyright 2016, The Materials Project' +__version__ = '0.1' +__maintainer__ = 'Xiaohui Qu' +__email__ = 'xhqu1981@gmail.com' +__date__ = 'May 31, 2016' + + +""" +This is modified from Wei Chen & Joseph Montoya's elastic_tasks. +""" + +tri_val_elements = {"Ce", "Dy", "Er", "Eu", "Gd", "Ho", "Lu", "Nd", "Pm", "Pr", "Sm", "Tb", "Tm"} +di_val_elements = {"Er", "Eu", "Yb"} + +def _get_nuclear_quadrupole_moment(element, nqm_dict, parameters): + if element not in nqm_dict: + return 0.0 + d = nqm_dict[element] + if len(d) > 1: + prefered_isotopes = set(parameters.get("isotopes", [])) + pi = prefered_isotopes & set(list(d.keys())) + if len(pi) == 1: + return d[list(pi)[0]] + if len(pi) >= 1: + raise ValueError("Multiple isotope is requested \"{}\", " + "please request only one for each elements".format(list(pi))) + isotopes = list(d.keys()) + isotopes.sort(key=lambda x: int(x.split("-")[1]), reverse=False) + return d[isotopes[0]] + else: + return list(d.values())[0] + + +def _config_dict_to_input_set(config_dict, structure, incar_enforce, parameters): + functional = parameters.get("functional", "PBE") + pot_map = {"PBE": "PBE", "SCAN": "PBE_52"} + potcar_functional = pot_map[functional] + trial_set = DictSet(structure, config_dict=config_dict, + user_incar_settings=incar_enforce, + potcar_functional=potcar_functional) + trial_potcar = trial_set.potcar + all_enmax = [sp.enmax for sp in trial_potcar] + all_eaug = [sp.eaug for sp in trial_potcar] + all_elements = [sp.element for sp in trial_potcar] + num_species = len(all_enmax) + processed_config_dict = copy.deepcopy(config_dict) + for k1, pot_values in [("ENCUT", all_enmax), ("ENAUG", all_eaug)]: + k2 = "{}_ENHANCE_RATIO".format(k1) + if k2 in config_dict["INCAR"]: + ratio = 1.0 + config_dict["INCAR"][k2] + processed_config_dict["INCAR"].pop(k2) + processed_config_dict["INCAR"][k1] = round(ratio * max(pot_values), 0) + if "ROPT_PER_ATOM" in config_dict["INCAR"]: + processed_config_dict["INCAR"].pop("ROPT_PER_ATOM") + processed_config_dict["INCAR"]["ROPT"] = \ + [config_dict["INCAR"]["ROPT_PER_ATOM"]] * num_species + if "QUAD_EFG_MAP" in config_dict["INCAR"]: + nqm_map = processed_config_dict["INCAR"].pop("QUAD_EFG_MAP") + quad_efg = [_get_nuclear_quadrupole_moment(el, nqm_map, parameters) for el in all_elements] + processed_config_dict["INCAR"]["QUAD_EFG"] = quad_efg + vis = DictSet(structure, config_dict=processed_config_dict, + user_incar_settings=incar_enforce, + potcar_functional=potcar_functional) + return vis + + +def _change_garden_setting(): + db_dir = os.environ['DB_LOC'] + db_path = os.path.join(db_dir, 'tasks_db.json') + with open(db_path) as f: + db_creds = json.load(f) + if 'prod' in db_creds['database']: + WFSettings().MOVE_TO_GARDEN_PROD = True + elif 'test' in db_creds['database']: + WFSettings().MOVE_TO_GARDEN_DEV = True + if 'nmr' not in WFSettings().GARDEN: + WFSettings().GARDEN = os.path.join(WFSettings().GARDEN, 'nmr') + + +def _assign_potcar_valence(structure, potcar_dict): + st_elements = set([specie.symbol for specie in structure.species]) + bva = BVAnalyzer() + valences = bva.get_valences(structure) + for val, val_elements in [[3, tri_val_elements], + [2, di_val_elements]]: + for el in sorted(val_elements & st_elements): + if "_" in potcar_dict[el]: + continue + el_indices = structure.indices_from_symbol(el) + cur_el_valences = {valences[i] for i in el_indices} + if len(cur_el_valences) == 1 and val in cur_el_valences: + potcar_dict[el] = "{el}_{val:d}".format(el=el, val=val) + + +def snl_to_nmr_spec(structure, istep_triple_jump, parameters=None, additional_run_tags=()): + parameters = copy.deepcopy(parameters) if parameters else {} + spec = {'parameters': parameters} + + module_dir = os.path.abspath(os.path.dirname(__file__)) + if 1 <= istep_triple_jump <= 3: + config_file = os.path.join(module_dir, "triple_jump_relax_set.yaml") + config_key = "STEP{}".format(istep_triple_jump) + config_name = "Triple Jump Relax S{}".format(istep_triple_jump) + elif istep_triple_jump == -1: + # NMR Chemical Shit calculations + config_file = os.path.join(module_dir, "nmr_tensor_set.yaml") + config_key = "CS" + config_name = "NMR CS" + elif istep_triple_jump == -2: + # NMR Chemical Shit calculations + config_file = os.path.join(module_dir, "nmr_tensor_set.yaml") + config_key = "EFG" + config_name = "NMR EFG" + else: + raise ValueError("Unknow Step Index \"{}\"".format(istep_triple_jump)) + with open(config_file) as f: + parent_config_dict = yaml.load(stream=f) + config_dict = parent_config_dict[config_key] + if len(structure) < 64: + par_num = 4 + else: + par_num = 8 + if config_name == "NMR CS": + incar_enforce = {'KPAR': par_num} + else: + incar_enforce = {'NPAR': par_num} + spec['run_tags'] = spec.get('run_tags', []) + spec['run_tags'].extend(additional_run_tags) + elements_in_structure = set([sp.symbol for sp in structure.species]) + if elements_in_structure & \ + (tri_val_elements | di_val_elements): + _assign_potcar_valence(structure, config_dict["POTCAR"]) + if not elements_in_structure <= set(config_dict["POTCAR"].keys()): + missing_elements = elements_in_structure - set(config_dict["POTCAR"].keys()) + raise ValueError("Element {} is not available in config dict".format(missing_elements)) + + mpvis = _config_dict_to_input_set(config_dict, structure, + incar_enforce, parameters=parameters) + incar = mpvis.incar + poscar = mpvis.poscar + potcar = mpvis.potcar + + spec["input_set_config_dict"] = mpvis.config_dict + spec["input_set_incar_enforce"] = incar_enforce + spec["custodian_default_input_set"] = mpvis + + # Add run tags of pseudopotential + spec['run_tags'] = spec.get('run_tags', [potcar.functional]) + spec['run_tags'].extend(potcar.symbols) + + # Add run tags of +U + u_tags = ['%s=%s' % t for t in + zip(poscar.site_symbols, incar.get('LDAUU', [0] * len(poscar.site_symbols)))] + spec['run_tags'].extend(u_tags) + + # add user run tags + if 'run_tags' in parameters: + spec['run_tags'].extend(parameters['run_tags']) + del spec['parameters']['run_tags'] + + spec['_dupefinder'] = DupeFinderVasp().to_dict() + spec['task_type'] = config_name + spec['vaspinputset_name'] = config_name + ' DictSet' + + return spec + +def chemical_shift_spec_to_dynamic_kpt_average_wfs(fw_spec): + no_jobs_spec = copy.deepcopy(fw_spec) + no_jobs_spec.pop('jobs', None) + no_jobs_spec.pop('handlers', None) + no_jobs_spec.pop('max_errors', None) + no_jobs_spec.pop('_tasks', None) + no_jobs_spec.pop('custodian_default_input_set', None) + no_jobs_spec.pop('prev_task_type', None) + no_jobs_spec.pop('prev_vasp_dir', None) + no_jobs_spec.pop('task_type', None) + no_jobs_spec.pop('vaspinputset_name', None) + nick_name = no_jobs_spec['parameters']['nick_name'] + priority = no_jobs_spec['_priority'] + + cur_fwid = -1 + fws = [] + + # Pre Single Kpt CS SCF Task + scf_spec = copy.deepcopy(no_jobs_spec) + for k in ["DQ", "ICHIBARE", "LCHIMAG", "LNMR_SYM_RED", "NSLPLINE"]: + scf_spec['input_set_config_dict']['INCAR'].pop(k, None) + scf_spec['input_set_config_dict']['INCAR']['ISMEAR'] = 0 + scf_spec['input_set_config_dict']['INCAR']['LCHARG'] = True + scf_spec['input_set_incar_enforce'] = {"NPAR": fw_spec['input_set_incar_enforce']["KPAR"]} + scf_spec['task_type'] = 'Pre Kpt CS SCF' + scf_spec['vaspinputset_name'] = scf_spec['task_type'] + " DictSet" + scf_spec['prev_task_type'] = fw_spec['task_type'] + scf_spec['prev_vasp_dir'] = os.getcwd() + scf_tasks = [DictVaspSetupTask()] + functional = scf_spec["functional"] + if functional != "PBE": + scf_tasks.append(ScanFunctionalSetupTask()) + from mpworks.firetasks.custodian_task import get_custodian_task + scf_tasks.append(get_custodian_task(scf_spec)) + scf_tasks.append(TagFileChecksumTask({"files": ["CHGCAR"]})) + scf_vasp_fwid = cur_fwid + cur_fwid -= 1 + vasp_fw = Firework(scf_tasks, scf_spec, name=get_slug(nick_name + '--' + scf_spec['task_type']), + fw_id=scf_vasp_fwid) + fws.append(vasp_fw) + + scf_db_fwid = cur_fwid + cur_fwid -= 1 + scf_db_type_class = VaspToDBTask + from mpworks.workflows.snl_to_wf_nmr import get_nmr_db_fw + scf_db_fw = get_nmr_db_fw(nick_name=nick_name, fwid=scf_db_fwid, prev_task_type=scf_spec['task_type'], + priority=priority, task_class=scf_db_type_class) + fws.append(scf_db_fw) + + # Single Kpt CS Generation + gen_spec = copy.deepcopy(no_jobs_spec) + gen_spec['input_set_config_dict']['INCAR']['ISMEAR'] = 0 + gen_spec['input_set_config_dict']['INCAR']['ICHARG'] = 11 + gen_spec['task_type'] = 'Single Kpt CS Generation' + gen_spec['vaspinputset_name'] = gen_spec['task_type'] + " DictSet" + gen_tasks = [ChemicalShiftKptsAverageGenerationTask()] + gen_fwid = cur_fwid + cur_fwid -= 1 + gen_fw = Firework(gen_tasks, gen_spec, + name=get_slug(nick_name + '--' + gen_spec['task_type']), + fw_id=gen_fwid) + fws.append(gen_fw) + connections = {scf_vasp_fwid: scf_db_fwid, + scf_db_fwid: gen_fwid} + wf = Workflow(fws, connections) + return wf + + +class NmrVaspToDBTask(VaspToDBTask): + _fw_name = "NMR Tensor to Database Task" + + def __init__(self, parameters=None): + super(NmrVaspToDBTask, self).__init__(parameters) + + def run_task(self, fw_spec): + _change_garden_setting() + prev_dir = get_loc(fw_spec['prev_vasp_dir']) + outcar = Outcar(zpath(os.path.join(prev_dir, "OUTCAR"))) + prev_task_type = fw_spec['prev_task_type'] + nmr_fields = dict() + update_spec = None + if prev_task_type == "NMR CS": + outcar.read_chemical_shifts() + cs_fiels = {"chemical_shifts": [x.as_dict() for x in outcar.data["chemical_shifts"]["valence_only"]]} + nmr_fields.update(cs_fiels) + elif prev_task_type == "Single Kpt CS": + update_spec = dict() + update_spec["total_kpts"] = fw_spec['total_kpts'] + update_spec['scf_vasp_dir'] = fw_spec['scf_vasp_dir'] + cs_kpt_name = fw_spec['kpoint_tag'] + update_spec[cs_kpt_name] = dict() + update_spec[cs_kpt_name]["kpt_vasp_dir"] = prev_dir + outcar.read_chemical_shifts() + update_spec[cs_kpt_name]["chemical_shifts"] = outcar.data["chemical_shifts"] + elif prev_task_type == 'Single Kpt CS Collect': + for k in ['chemical_shifts', 'manual_kpt_average', 'rmsd', + 'rmsd_header', 'manual_kpt_data']: + nmr_fields[k] = fw_spec[k] + sub_dir_name = "fake_nmr_vasp_files" + shutil.copytree(prev_dir, sub_dir_name) + for fn in ["CHGCAR", "CHGCAR.gz"]: + ffn = os.path.join(sub_dir_name, fn) + if os.path.exists(ffn): + os.remove(ffn) + fake_prev_dir = os.path.abspath(sub_dir_name) + fw_spec['prev_vasp_dir'] = fake_prev_dir + with zopen(zpath(os.path.join(fake_prev_dir, 'FW.json')), 'rt') as f: + fw_dict = json.load(f) + fw_dict["spec"]["task_type"] = "NMR CS" + with zopen(zpath(os.path.join(fake_prev_dir, 'FW.json')), 'wt') as f: + json.dump(fw_dict, f, sort_keys=True, indent=4) + elif prev_task_type == "NMR EFG": + outcar.read_nmr_efg() + efg_fields = {"efg": outcar.data["efg"]} + nmr_fields.update(efg_fields) + else: + raise ValueError("Unsupported Task Type: \"{}\"".format(prev_task_type)) + self.additional_fields.update(nmr_fields) + m_action = super(NmrVaspToDBTask, self).run_task(fw_spec) + if update_spec is not None: + update_spec.update(m_action.update_spec) + m_action.update_spec = update_spec + return m_action + + +class TripleJumpRelaxVaspToDBTask(VaspToDBTask): + _fw_name = "Triple Jump Relax to Database Task" + + def __init__(self, parameters=None): + super(TripleJumpRelaxVaspToDBTask, self).__init__(parameters) + + def run_task(self, fw_spec): + _change_garden_setting() + return super(TripleJumpRelaxVaspToDBTask, self).run_task(fw_spec) + + +class SetupTripleJumpRelaxS3UnconvergedHandlerTask(SetupUnconvergedHandlerTask): + _fw_name = "Triple Jump Relax S3 Unconverged Handler Task" + + def run_task(self, fw_spec): + module_dir = os.path.abspath(os.path.dirname(__file__)) + config_file = os.path.join(module_dir, "triple_jump_relax_set.yaml") + config_key = "STEP_DYNA3" + with open(config_file) as f: + parent_config_dict = yaml.load(stream=f) + config_dict = parent_config_dict[config_key] + incar_update = config_dict["INCAR"] + actions = [{"dict": "INCAR", + "action": {"_set": incar_update}}] + from custodian.vasp.interpreter import VaspModder + VaspModder().apply_actions(actions) + parent_action = super(SetupTripleJumpRelaxS3UnconvergedHandlerTask, self).run_task(fw_spec) + return parent_action + + +class DictVaspSetupTask(FireTaskBase, FWSerializable): + _fw_name = "Dict Vasp Input Setup Task" + + def __init__(self, parameters=None): + parameters = parameters if parameters else {} + default_files = ["INCAR", "POSCAR", "POTCAR", "KPOINTS"] + self.update(parameters) + self.files = parameters.get("files", default_files) + + @staticmethod + def _sort_structure_by_encut(structure, config_dict): + # put the larger ENMAX specie first + trial_vis = DictSet(structure, config_dict=config_dict) + trial_potcar = trial_vis.potcar + enmax_dict = {p.symbol.split("_")[0]: p.keywords["ENMAX"] + p.keywords["ENMIN"] * 1.0E-3 + for p in trial_potcar} + structure = structure.get_sorted_structure(key=lambda site: enmax_dict[site.specie.symbol], reverse=True) + return structure + + @staticmethod + def _reorder_nqm(vis, parameters): + incar = vis.incar + old_quad_efg_set = set(incar["QUAD_EFG"]) + module_dir = os.path.abspath(os.path.dirname(__file__)) + config_file = os.path.join(module_dir, "nmr_tensor_set.yaml") + with open(config_file) as f: + parent_config_dict = yaml.load(stream=f) + nqm_map = parent_config_dict["EFG"]["INCAR"]["QUAD_EFG_MAP"] + all_elements = [sp.element for sp in vis.potcar] + quad_efg = [_get_nuclear_quadrupole_moment(el, nqm_map, parameters) for el in all_elements] + incar["QUAD_EFG"] = quad_efg + assert old_quad_efg_set == set(incar["QUAD_EFG"]) + return incar + + def run_task(self, fw_spec): + config_dict = fw_spec["input_set_config_dict"] + incar_enforce = fw_spec["input_set_incar_enforce"] + mpsnl = fw_spec["mpsnl"] + structure = self._sort_structure_by_encut(mpsnl.structure, config_dict) + vis = DictSet(structure, config_dict=config_dict, + user_incar_settings=incar_enforce, + sort_structure=False) + if "INCAR" in self.files: + incar = vis.incar + if fw_spec["task_type"] == "NMR EFG": + incar = self._reorder_nqm(vis, fw_spec["parameters"]) + incar.write_file("INCAR") + if "POSCAR" in self.files: + vis.poscar.write_file("POSCAR") + if "POTCAR" in self.files: + vis.potcar.write_file("POTCAR") + if "KPOINTS" in self.files: + if "kpoints_enforce" not in fw_spec: + vis.kpoints.write_file("KPOINTS") + else: + fw_spec["kpoints_enforce"].write_file("KPOINTS") + return FWAction(stored_data={"vasp_input_set": vis.as_dict()}) + + +class ScanFunctionalSetupTask(FireTaskBase, FWSerializable): + """ + This class is to setup the SCAN functional calculation for the + hack version of VASP. If official SCAN functional supported VASP + is release, the run_task() method body can be set to "pass". It + will make the workflow compatible with the new VASP version. + """ + _fw_name = "SCAN Functional Setup Task" + + def run_task(self, fw_spec): + functional = fw_spec.get("functional", "PBE") + if functional == "SCAN": + incar_update = {"METAGGA": "Rtpss", + "LASPH": True} + actions = [{"dict": "INCAR", + "action": {"_set": incar_update}}] + from custodian.vasp.interpreter import VaspModder + VaspModder().apply_actions(actions) + + # guarantee VASP is the hacked version + fw_env = fw_spec.get("_fw_env", {}) + vasp_cmd = fw_env.get("vasp_cmd", "vasp") + if os.path.exists(vasp_cmd): + vasp_path = vasp_cmd + else: + vasp_path = shutil.which("vasp") + hacked_path = "/global/common/matgen/das/vasp/5.3.5-scan-beta/bin/vasp" + if vasp_path != hacked_path: + my_name = str(self.__class__).replace("", "") + raise ValueError("'{}' is designed to support the hack of VASP, " + "upon official release of VASP SCAN function, this class" + "should be modified".format(my_name)) + else: + pass + + +class ChemicalShiftKptsAverageGenerationTask(FireTaskBase, FWSerializable): + """ + This class is to spawn the dynamical fws to calculate NMR chemical shfit on each + individual and then do K-points weighted average manually. + """ + _fw_name = "Chemical Shift K-Points Average Generation Task" + + def run_task(self, fw_spec): + no_jobs_spec = copy.deepcopy(fw_spec) + no_jobs_spec.pop('jobs', None) + no_jobs_spec.pop('handlers', None) + no_jobs_spec.pop('max_errors', None) + no_jobs_spec.pop('_tasks', None) + no_jobs_spec.pop('custodian_default_input_set', None) + no_jobs_spec.pop('task_type', None) + no_jobs_spec.pop('vaspinputset_name', None) + nick_name = no_jobs_spec['parameters']['nick_name'] + priority = no_jobs_spec['_priority'] + no_jobs_spec['input_set_config_dict']['INCAR']['ISMEAR'] = 0 + no_jobs_spec['input_set_config_dict']['INCAR']['ICHARG'] = 11 + no_jobs_spec['input_set_incar_enforce'] = {"KPAR": 1} + no_jobs_spec['task_type'] = 'Single Kpt CS' + no_jobs_spec['vaspinputset_name'] = no_jobs_spec['task_type'] + " DictSet" + no_jobs_spec["scf_vasp_dir"] = fw_spec['prev_vasp_dir'] + + fws = [] + connections = dict() + db_fwids = [] + cur_fwid = -1 + prev_dir = get_loc(fw_spec['prev_vasp_dir']) + scf_kpoint_filename = zpath(os.path.join(prev_dir, 'IBZKPT')) + whole_kpts = Kpoints.from_file(scf_kpoint_filename) + no_jobs_spec['total_kpts'] = len(whole_kpts.kpts) + + for (i, kpt) in enumerate(whole_kpts.kpts): + kweight = int(whole_kpts.kpts_weights[i]) + task_tag = "kpt_#{:d}_weight_{:d}".format(i + 1, kweight) + comment = "Individual {}th Kpoint for CS Calculation".format(i + 1) + cur_kpoints = Kpoints(comment=comment, num_kpts=1, + style=Kpoints.supported_modes.Reciprocal, + kpts=[kpt], kpts_weights=[1], + tet_number=0) + + # Individual K-Point Chemical Shift VASP + kpt_cs_spec = copy.deepcopy(no_jobs_spec) + kpt_cs_spec['run_tags'].append(task_tag) + kpt_cs_spec['kpoints_enforce'] = cur_kpoints + kpt_cs_spec["kpoint_tag"] = task_tag + + kpt_cs_tasks = [DictVaspSetupTask({'files': ['INCAR', "KPOINTS"]}), + VaspCopyTask({'files': ['CHGCAR', "POTCAR"], + 'use_CONTCAR': True, + 'keep_velocities': False})] + functional = kpt_cs_spec["functional"] + if functional != "PBE": + kpt_cs_tasks.append(ScanFunctionalSetupTask()) + kpt_cs_tasks.append(TagFileChecksumTask({"files": ["CHGCAR"]})) + from mpworks.firetasks.custodian_task import get_custodian_task + kpt_cs_tasks.append(get_custodian_task(kpt_cs_spec)) + kpt_cs_tasks.append(DeleteFileTask({"files": ["CHGCAR"]})) + kpt_cs_task_name = get_slug(nick_name + '--' + kpt_cs_spec['task_type'] + "--#{}".format(i)) + kpt_cs_vasp_fwid = cur_fwid # Links + cur_fwid -= 1 + vasp_fw = Firework(kpt_cs_tasks, kpt_cs_spec, name=kpt_cs_task_name, + fw_id=kpt_cs_vasp_fwid) + fws.append(vasp_fw) + + # Individual K-Point Chemical Shift VASP DB Insertion + kpt_cs_db_fwid = cur_fwid # Links + cur_fwid -= 1 + kpt_cs_db_type_class = NmrVaspToDBTask + from mpworks.workflows.snl_to_wf_nmr import get_nmr_db_fw + kpt_cs_db_fw = get_nmr_db_fw(nick_name=nick_name, fwid=kpt_cs_db_fwid, + prev_task_type=kpt_cs_spec['task_type'], + priority=priority, task_class=kpt_cs_db_type_class) + fws.append(kpt_cs_db_fw) + connections[kpt_cs_vasp_fwid] = kpt_cs_db_fwid + db_fwids.append(kpt_cs_db_fwid) + + # K-Points Average Collect + collect_spec = copy.deepcopy(no_jobs_spec) + collect_spec['task_type'] = 'Single Kpt CS Collect' + collect_spec['vaspinputset_name'] = collect_spec['task_type'] + " DictSet" + collect_tasks = [ChemicalShiftKptsAverageCollectTask()] + collect_fwid = cur_fwid + cur_fwid -= 1 + collect_fw = Firework(collect_tasks, collect_spec, + name=get_slug(nick_name + '--' + collect_spec['task_type']), + fw_id=collect_fwid) + fws.append(collect_fw) + for dbid in db_fwids: + connections[dbid] = collect_fwid + wf = Workflow(fws, connections) + update_spec = {'total_kpts': no_jobs_spec['total_kpts'], + "scf_vasp_dir": fw_spec['prev_vasp_dir'], + 'prev_vasp_dir': fw_spec['prev_vasp_dir'], + 'prev_task_type': fw_spec['task_type']} + stored_data = {'total_kpts': no_jobs_spec['total_kpts'], + "scf_vasp_dir": fw_spec['prev_vasp_dir']} + return FWAction(update_spec=update_spec, stored_data=stored_data, + detours=wf) + +class ChemicalShiftKptsAverageCollectTask(FireTaskBase, FWSerializable): + """ + This class do K-points weighted chemical shift average from the previous K-points + specific calculations. + """ + _fw_name = "Chemical Shift K-Points Average Collect Task" + + def run_task(self, fw_spec): + kpt_name_pattern = re.compile(r'kpt_#(?P\d+)_weight_(?P\d+)') + kpt_name_weigths = [] + for kpt_name in fw_spec.keys(): + m = kpt_name_pattern.match(kpt_name) + if m: + kpt_weight = m.group("weight") + kpt_name_weigths.append([kpt_name, kpt_weight]) + num_kpts = fw_spec["total_kpts"] + assert len(kpt_name_weigths) == num_kpts + num_atoms = len(fw_spec[kpt_name_weigths[0][0]]['chemical_shifts']['valence_only']) + num_ave_components = 7 + atom_cs_weight_vo_vc = [[list() for _ in range(num_ave_components)] + for _ in range(num_atoms)] + for i_kpt, (kpt_name, weight) in enumerate(kpt_name_weigths): + kpt_cs = fw_spec[kpt_name]['chemical_shifts'] + for i_atom in range(num_atoms): + vo_tensor_notation = NMRChemicalShiftNotation.from_dict(kpt_cs['valence_only'][i_atom]) + vc_tensor_notation = NMRChemicalShiftNotation.from_dict(kpt_cs['valence_and_core'][i_atom]) + val_only_tensor_pas = vo_tensor_notation.mehring_values[1:4] + val_core_tensor_pas = vc_tensor_notation.mehring_values[1:4] + components = (float(weight),) + val_only_tensor_pas + val_core_tensor_pas + for i_comp in range(num_ave_components): + atom_cs_weight_vo_vc[i_atom][i_comp].append(components[i_comp]) + for i_atom in range(num_atoms): + for i_comp in range(num_ave_components): + assert len(atom_cs_weight_vo_vc[i_atom][i_comp]) == num_kpts + ave_pas_tensors = [] + tensor_rmsd = [] + for i_atom in range(num_atoms): + atom_ave_tensor = [] + atom_tensor_rmsd = [] + for i_comp in range(1, num_ave_components): + sum_value = sum([weight * tensor for weight, tensor + in zip(atom_cs_weight_vo_vc[i_atom][0], + atom_cs_weight_vo_vc[i_atom][i_comp])]) + sum_weights = sum(atom_cs_weight_vo_vc[i_atom][0]) + ave_value = sum_value / sum_weights + atom_ave_tensor.append(ave_value) + sum_square_dev = sum([weight * ((tensor - ave_value) ** 2) for weight, tensor + in zip(atom_cs_weight_vo_vc[i_atom][0], + atom_cs_weight_vo_vc[i_atom][i_comp])]) + rmsd_value = math.sqrt(sum_square_dev / sum_weights) + atom_tensor_rmsd.append(rmsd_value) + ave_pas_tensors.append(atom_ave_tensor) + tensor_rmsd.append(atom_tensor_rmsd) + ave_tensor_notations = {"valence_only": [], 'valence_and_core': []} + for pas in ave_pas_tensors: + assert len(pas) == 6 + for comp_indices, comp_key in [[range(0, 3), "valence_only"], + [range(3, 6), 'valence_and_core']]: + sigmas = [pas[i] for i in comp_indices] + notation = NMRChemicalShiftNotation(*sigmas) + ave_tensor_notations[comp_key].append(notation.as_dict()) + single_kpt_vasp_calcs = {kpt_name: fw_spec[kpt_name] for kpt_name, weight + in kpt_name_weigths} + cs_fields = {"chemical_shifts": ave_tensor_notations, + "manual_kpt_average": True, + "rmsd": tensor_rmsd, + "rmsd_header": ["valence_only_11", "valence_only_22", "valence_only_33", + "valence_and_core_11", "valence_and_core_22", "valence_and_core_33"], + "manual_kpt_data": { + "total_kpts": fw_spec["total_kpts"], + "single_kpt_vasp_calcs": single_kpt_vasp_calcs + }} + stored_data = copy.deepcopy(cs_fields) + update_spec = copy.deepcopy(cs_fields) + update_spec['prev_task_type'] = fw_spec['task_type'] + update_spec['prev_vasp_dir'] = fw_spec['scf_vasp_dir'] + for k in ['scf_vasp_dir', 'functional']: + update_spec[k] = fw_spec[k] + return FWAction(stored_data=stored_data, update_spec=update_spec) + +class TagFileChecksumTask(FireTaskBase, FWSerializable): + + _fw_name = "Tag File Checksum Task" + + def __init__(self, parameters=None): + parameters = parameters if parameters else {} + default_files = ["CHGCAR", "WAVCAR"] + self.update(parameters) + self.files = parameters.get("files", default_files) + + def run_task(self, fw_spec): + file_checksums = dict() + blocksize = 10 * 2 ** 20 # 10 MB + for fn in self.files: + with zopen(zpath(fn), 'rb') as f: + hash = hashlib.sha224() + for block in iter(lambda: f.read(blocksize), b""): + hash.update(block) + checksum = hash.hexdigest() + file_checksums[fn] = {"type": "sha224", + "value": checksum} + with open("checksum.{}.{}".format(fn, checksum[:10]), "w") as f: + f.write("sha224") + stored_data = {"file_checksum": file_checksums} + return FWAction(stored_data=stored_data) + + +class DeleteFileTask(FireTaskBase, FWSerializable): + + _fw_name = "Delete File Task" + + def __init__(self, parameters=None): + parameters = parameters if parameters else {} + default_files = ["CHGCAR", "WAVCAR"] + self.update(parameters) + self.files = parameters.get("files", default_files) + + def run_task(self, fw_spec): + for fn in self.files: + gzfn = fn + ".gz" + if os.path.exists(fn): + os.remove(fn) + if os.path.exists(gzfn): + os.remove(gzfn) + diff --git a/mpworks/firetasks/nmr_tensor_set.yaml b/mpworks/firetasks/nmr_tensor_set.yaml new file mode 100644 index 00000000..0cc412a3 --- /dev/null +++ b/mpworks/firetasks/nmr_tensor_set.yaml @@ -0,0 +1,180 @@ +CS: + INCAR: + DQ: 0.001 + EDIFF: -1.0e-10 + ENCUT_ENHANCE_RATIO: 0.3 + ICHIBARE: 1 + ISMEAR: -5 + ISTART: 0 + ISYM: 0 + LCHARG: false + LCHIMAG: true + LNMR_SYM_RED: true + LREAL: AUTO + LWAVE: false + NELMIN: 10 + NSLPLINE: true + PREC: ACCURATE + SIGMA: 0.01 + KPOINTS: + length: 32 + POTCAR: + C: C_h + H: H_h + Mg: Mg_sv + O: O_h + N: N_h + F: F_h + Na: Na_sv + Al: Al + Si: Si_h + P: P_h + Cl: Cl_h + K: K_sv + Ca: Ca_sv + Y: Y_sv + Gd: Gd + Be: Be_sv + Fe: Fe_sv_h + Ge: Ge_h + Li: Li_sv + S: S_h + Zn: Zn_pv + Ti: Ti_sv_h + Zr: Zr_sv_new + Sr: Sr_sv + Ba: Ba_sv + La: La + In: In_d + B: B_h + Pb: Pb_d + +EFG: + INCAR: + ALGO: FAST + EDIFF: -1.0e-10 + ENCUT_ENHANCE_RATIO: 0.3 + ISMEAR: -5 + ISTART: 0 + ISYM: 0 + LCHARG: false + LEFG: true + LREAL: AUTO + LWAVE: false + NELMIN: 10 + PREC: ACCURATE + QUAD_EFG_MAP: + H: + H-2: 2.860 + Li: + Li-6: -0.808 + Li-7: -40.1 + Be: + Be-9: 52.88 + B: + B-10: 84.59 + B-11: 40.59 + C: + C-11: 33.27 + N: + N-14: 20.44 + O: + O-17: -25.58 + F: + F-19: -94.2 + Ne: + Ne-21: 101.55 + Na: + Na-23: 104.1 + Mg: + Mg-25: 199.4 + Al: + Al-27: 146.6 + S: + S-33: -67.8 + S-35: 47.1 + Cl: + Cl-35: -81.65 + Cl-37: -64.35 + K: + K-39: 58.5 + K-40: -73.0 + K-41: 71.1 + Ca: + Ca-41: -66.5 + Ca-43: -40.8 + Sc: + Sc-45: -220.2 + Ti: + Ti-47: 302.10 + Ti-49: 247.11 + V: + V-50: 210.40 + V-51: -52.10 + Cr: + Cr-53: -150.50 + Mn: + Mn-55: 330.10 + Fe: + Fe-57: 160.0 + Co: + Co-59: 420.30 + Ni: + Ni-61: 162.15 + Cu: + Cu-63: -220.15 + Cu-65: -204.14 + Zn: + Zn-67: 150.15 + Sr: + Sr-87: 305.2 + In: + In-113: 759.8 + In-115: 770.8 + Sn: + Sn-119: -132.1 + Sb: + Sb-121: -543.11 + Sb-123: -692.14 + I: + I-127: -696.12 + I-129: -604.10 + La: + La-139: 200.6 + Hg: + Hg-201: 387.6 + Ra: + Ra-223: 1210.3 + SIGMA: 0.01 + KPOINTS: + length: 32 + POTCAR: + C: C_h + H: H_h + Mg: Mg_sv + O: O_h + N: N_h + F: F_h + Na: Na_sv + Al: Al + Si: Si_h + P: P_h + Cl: Cl_h + K: K_sv + Ca: Ca_sv + Y: Y_sv + Gd: Gd + Be: Be_sv + Fe: Fe_sv_h + Ge: Ge_h + Li: Li_sv + S: S_h + Zn: Zn_pv + Ti: Ti_sv_h + Zr: Zr_sv_new + Sr: Sr_sv + Ba: Ba_sv + La: La + In: In_d + B: B_h + Pb: Pb_d diff --git a/mpworks/firetasks/triple_jump_relax_set.yaml b/mpworks/firetasks/triple_jump_relax_set.yaml new file mode 100644 index 00000000..304e66e7 --- /dev/null +++ b/mpworks/firetasks/triple_jump_relax_set.yaml @@ -0,0 +1,169 @@ +STEP1: + INCAR: + ALGO: FAST + EDIFF: -1.0e-06 + EDIFFG: -0.1 + ENCUT_ENHANCE_RATIO: 0.05 + IBRION: 1 + ISIF: 3 + ISMEAR: -5 + ISTART: 0 + LCHARG: false + LREAL: AUTO + LWAVE: false + NELMIN: 5 + NSW: 200 + POTIM: 0.3 + PREC: ACCURATE + SIGMA: 0.1 + KPOINTS: + length: 16 + POTCAR: + C: C + H: H + Mg: Mg + O: O + N: N + F: F + Na: Na + Al: Al + Si: Si + P: P + Cl: Cl + K: K_pv + Ca: Ca_pv + Y: Y_sv + Gd: Gd + Be: Be_sv + Fe: Fe_sv + Ge: Ge_d + Li: Li_sv + S: S + Zn: Zn_pv + Ti: Ti_sv_new + Zr: Zr_sv_new + Sr: Sr_sv + Ba: Ba_sv + La: La + In: In_d + B: B + Pb: Pb_d + +STEP2: + INCAR: + ADDGRID: true + ALGO: FAST + EDIFF: -1.0e-08 + EDIFFG: -0.01 + ENCUT_ENHANCE_RATIO: 0.2 + IBRION: 3 + IOPT: 7 + ISIF: 3 + ISMEAR: -5 + ISTART: 0 + ISYM: 0 + LCHARG: false + LREAL: AUTO + LWAVE: false + NELMIN: 5 + NSW: 200 + POTIM: 0 + PREC: ACCURATE + SIGMA: 0.03 + KPOINTS: + length: 24 + POTCAR: + C: C_h + H: H_h + Mg: Mg_sv + O: O_h + N: N_h + F: F_h + Na: Na_sv + Al: Al + Si: Si_h + P: P_h + Cl: Cl_h + K: K_sv + Ca: Ca_sv + Y: Y_sv + Gd: Gd + Be: Be_sv + Fe: Fe_sv_h + Ge: Ge_h + Li: Li_sv + S: S_h + Zn: Zn_pv + Ti: Ti_sv_h + Zr: Zr_sv_new + Sr: Sr_sv + Ba: Ba_sv + La: La + In: In_d + B: B_h + Pb: Pb_d + +STEP3: + INCAR: + ADDGRID: true + ALGO: FAST + EDIFF: -1.0e-10 + EDIFFG: -0.002 + ENCUT_ENHANCE_RATIO: 0.3 + FTIMEMAX: 0.1 + IBRION: 3 + IOPT: 7 + ISIF: 3 + ISMEAR: -5 + ISTART: 0 + ISYM: 0 + LCHARG: false + LREAL: AUTO + LWAVE: false + MAXMOVE: 0.02 + NELMIN: 10 + NSW: 100 + POTIM: 0 + PREC: ACCURATE + SIGMA: 0.01 + TIMESTEP: 0.01 + FNMIN: 3 + KPOINTS: + length: 32 + POTCAR: + C: C_h + H: H_h + Mg: Mg_sv + O: O_h + N: N_h + F: F_h + Na: Na_sv + Al: Al + Si: Si_h + P: P_h + Cl: Cl_h + K: K_sv + Ca: Ca_sv + Y: Y_sv + Gd: Gd + Be: Be_sv + Fe: Fe_sv_h + Ge: Ge_h + Li: Li_sv + S: S_h + Zn: Zn_pv + Ti: Ti_sv_h + Zr: Zr_sv_new + Sr: Sr_sv + Ba: Ba_sv + La: La + In: In_d + B: B_h + Pb: Pb_d + +STEP_DYNA3: + INCAR: + FTIMEMAX: 0.05 + MAXMOVE: 0.01 + TIMESTEP: 0.005 + FNMIN: 2 diff --git a/mpworks/firetasks/vasp_io_tasks.py b/mpworks/firetasks/vasp_io_tasks.py index 596fd136..14adb2d4 100644 --- a/mpworks/firetasks/vasp_io_tasks.py +++ b/mpworks/firetasks/vasp_io_tasks.py @@ -9,6 +9,9 @@ import os import shutil import sys + +from fireworks.fw_config import FWData +from monty.io import zopen from monty.os.path import zpath from custodian.vasp.handlers import UnconvergedErrorHandler from fireworks.core.launchpad import LaunchPad @@ -20,7 +23,7 @@ from mpworks.dupefinders.dupefinder_vasp import DupeFinderVasp from mpworks.firetasks.custodian_task import get_custodian_task from mpworks.firetasks.vasp_setup_tasks import SetupUnconvergedHandlerTask -from mpworks.workflows.wf_settings import QA_VASP, QA_DB, MOVE_TO_GARDEN_PROD, MOVE_TO_GARDEN_DEV +from mpworks.workflows.wf_settings import WFSettings, QA_VASP, QA_DB from mpworks.workflows.wf_utils import last_relax, get_loc, move_to_garden from pymatgen import Composition from pymatgen.io.vasp.inputs import Incar, Poscar, Potcar, Kpoints @@ -72,6 +75,8 @@ def __init__(self, parameters=None): self.files = parameters.get('files', default_files) # files to move self.use_contcar = parameters.get('use_CONTCAR', True) # whether to move CONTCAR to POSCAR + self.keep_velocities = parameters.get('keep_velocities', True) # whether to keep the + # velocities in POSCAR/CONTCAR, if set to False, velocities will be removed. if self.use_contcar: self.files.append('CONTCAR') @@ -89,21 +94,22 @@ def run_task(self, fw_spec): if prev_filename.endswith('.gz'): dest_file += '.gz' - print 'COPYING', prev_filename, dest_file + print('COPYING', prev_filename, dest_file) if self.missing_CHGCAR_OK and 'CHGCAR' in dest_file and not os.path.exists(zpath(prev_filename)): - print 'Skipping missing CHGCAR' + print('Skipping missing CHGCAR') else: shutil.copy2(prev_filename, dest_file) if '.gz' in dest_file: # unzip dest file - f = gzip.open(dest_file, 'rb') - file_content = f.read() - with open(dest_file[0:-3], 'wb') as f_out: - f_out.writelines(file_content) - f.close() + with gzip.open(dest_file, 'rb') as f_in: + with open(dest_file[0:-3], 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) os.remove(dest_file) - + if self.use_contcar and not self.keep_velocities: + shutil.move("POSCAR", "POSCAR.orig.velocity") + poscar = Poscar.from_file("POSCAR.orig.velocity", read_velocities=False) + poscar.write_file(filename="POSCAR") return FWAction(stored_data={'copied_files': self.files}) @@ -125,6 +131,20 @@ def __init__(self, parameters=None): self.additional_fields = self.get('additional_fields', {}) self.update_duplicates = self.get('update_duplicates', False) # off so DOS/BS doesn't get entered twice + def same_fw_occurrences_in_cur_wflow(self, prev_dir, lp): + with zopen(zpath(os.path.join(prev_dir, 'FW.json')), 'rt') as f: + fw_dict = json.load(f) + prev_vasp_fw_id = fw_dict["launches"][0]["fw_id"] + prev_vasp_launch_id = fw_dict["launches"][0]["launch_id"] + prev_vasp_launch_assoc_fw_ids = [doc["fw_id"] for doc in + lp.fireworks.find({"launches": prev_vasp_launch_id}, projection=["fw_id"])] + + cur_wf_fw_ids = lp.workflows.find({"nodes": prev_vasp_fw_id})[0]["nodes"] + # preferably current fw_id, however, there no mechanism to get it. + + num_occurrences = len(set(cur_wf_fw_ids) & set(prev_vasp_launch_assoc_fw_ids)) + return num_occurrences + def run_task(self, fw_spec): if '_fizzled_parents' in fw_spec and not 'prev_vasp_dir' in fw_spec: prev_dir = get_loc(fw_spec['_fizzled_parents'][0]['launches'][0]['launch_dir']) @@ -143,10 +163,10 @@ def run_task(self, fw_spec): else: self.additional_fields['run_tags'] = fw_spec['_fizzled_parents'][0]['spec']['run_tags'] - if MOVE_TO_GARDEN_DEV: + if WFSettings().MOVE_TO_GARDEN_DEV: prev_dir = move_to_garden(prev_dir, prod=False) - elif MOVE_TO_GARDEN_PROD: + elif WFSettings().MOVE_TO_GARDEN_PROD: prev_dir = move_to_garden(prev_dir, prod=True) # get the directory containing the db file @@ -159,6 +179,8 @@ def run_task(self, fw_spec): sh = logging.StreamHandler(stream=sys.stdout) sh.setLevel(getattr(logging, 'INFO')) logger.addHandler(sh) + lp = LaunchPad.auto_load() + launch_coll = lp.launches with open(db_path) as f: db_creds = json.load(f) drone = MPVaspDrone(host=db_creds['host'], port=db_creds['port'], @@ -167,30 +189,37 @@ def run_task(self, fw_spec): collection=db_creds['collection'], parse_dos=parse_dos, additional_fields=self.additional_fields, update_duplicates=self.update_duplicates) - t_id, d = drone.assimilate(prev_dir, launches_coll=LaunchPad.auto_load().launches) + t_id, d = drone.assimilate(prev_dir, launches_coll=launch_coll) mpsnl = d['snl_final'] if 'snl_final' in d else d['snl'] snlgroup_id = d['snlgroup_id_final'] if 'snlgroup_id_final' in d else d['snlgroup_id'] update_spec.update({'mpsnl': mpsnl, 'snlgroup_id': snlgroup_id}) + if 'functional' in fw_spec: + d['functional'] = fw_spec['functional'] - print 'ENTERED task id:', t_id + print('ENTERED task id:', t_id) stored_data = {'task_id': t_id} if d['state'] == 'successful': update_spec['analysis'] = d['analysis'] update_spec['output'] = d['output'] - update_spec['vasp']={'incar':d['calculations'][-1]['input']['incar'], - 'kpoints':d['calculations'][-1]['input']['kpoints']} + if self.get("update_input", True): + update_spec['vasp']={'incar':d['calculations'][-1]['input']['incar'], + 'kpoints':d['calculations'][-1]['input']['kpoints']} update_spec["task_id"]=t_id return FWAction(stored_data=stored_data, update_spec=update_spec) # not successful - first test to see if UnconvergedHandler is needed if not fizzled_parent: unconverged_tag = 'unconverged_handler--{}'.format(fw_spec['prev_task_type']) + if self.same_fw_occurrences_in_cur_wflow(prev_dir, lp) > 1: + raise ValueError("Same Dynamics FW launch has been already existed in" + "the database for more than twice, stop spawn new FW" + "to avoid infinite loop") output_dir = last_relax(os.path.join(prev_dir, 'vasprun.xml')) ueh = UnconvergedErrorHandler(output_filename=output_dir) # TODO: make this a little more flexible if ueh.check() and unconverged_tag not in fw_spec['run_tags']: - print 'Unconverged run! Creating dynamic FW...' + print('Unconverged run! Creating dynamic FW...') spec = {'prev_vasp_dir': prev_dir, 'prev_task_type': fw_spec['task_type'], @@ -207,6 +236,8 @@ def run_task(self, fw_spec): snl = StructureNL.from_dict(spec['mpsnl']) spec['run_tags'].append(unconverged_tag) spec['_queueadapter'] = QA_VASP + if 'functional' in fw_spec: + spec['functional'] = fw_spec['functional'] fws = [] connections = {} @@ -214,9 +245,15 @@ def run_task(self, fw_spec): f = Composition( snl.structure.composition.reduced_formula).alphabetical_formula + if fw_spec['prev_task_type'] == "Triple Jump Relax S3": + from mpworks.firetasks.nmr_tasks import SetupTripleJumpRelaxS3UnconvergedHandlerTask + unconv_handler_task = SetupTripleJumpRelaxS3UnconvergedHandlerTask() + else: + unconv_handler_task = SetupUnconvergedHandlerTask() + fws.append(Firework( [VaspCopyTask({'files': ['INCAR', 'KPOINTS', 'POSCAR', 'POTCAR', 'CONTCAR'], - 'use_CONTCAR': False}), SetupUnconvergedHandlerTask(), + 'use_CONTCAR': False}), unconv_handler_task, get_custodian_task(spec)], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=-2)) diff --git a/mpworks/firetasks/vasp_setup_tasks.py b/mpworks/firetasks/vasp_setup_tasks.py index c93f3486..05c8f1e5 100644 --- a/mpworks/firetasks/vasp_setup_tasks.py +++ b/mpworks/firetasks/vasp_setup_tasks.py @@ -44,7 +44,7 @@ def run_task(self, fw_spec): kppra_vol = self.kpoints_density / vol new_set = MPStaticSet.from_prev_calc( os.getcwd(), - user_incar_settings=self.user_incar_settings, + user_incar_settings=self.user_incar_settings, reciprocal_density=kppra_vol) new_set.write_input('.') structure = new_set.structure diff --git a/mpworks/firetasks_staging/surface_tasks.py b/mpworks/firetasks_staging/surface_tasks.py index 7ea82491..2d1dea5d 100644 --- a/mpworks/firetasks_staging/surface_tasks.py +++ b/mpworks/firetasks_staging/surface_tasks.py @@ -154,10 +154,10 @@ def run_task(self, fw_spec): dec.process_decoded(self.get("potcar_fuctional", 'PBE')) # Will continue an incomplete job from a previous contcar file if it exists - print 'cwd is %s' %(os.getcwd()) - print 'the folder is %s' %(folder) - print os.path.join(os.getcwd(), folder) - print cwd+'/'+folder + print('cwd is %s' %(os.getcwd())) + print('the folder is %s' %(folder)) + print(os.path.join(os.getcwd(), folder)) + print(cwd+'/'+folder) path = cwd+'/'+folder # path = os.path.join(os.getcwd(), folder) @@ -170,17 +170,17 @@ def run_task(self, fw_spec): # print os.stat(os.path.join(path, 'CONTCAR.gz')).st_size !=0 def continue_vasp(contcar): - print folder, 'already exists, will now continue calculation' - print 'making prev_run folder' + print(folder, 'already exists, will now continue calculation') + print('making prev_run folder') os.system('mkdir %s' %(newfolder)) - print 'moving outputs to prev_run' + print('moving outputs to prev_run') os.system('mv %s/* %s/prev_run' %(path, path)) - print 'moving outputs as inputs for next calculation' + print('moving outputs as inputs for next calculation') os.system('cp %s/%s %s/INCAR %s/POTCAR %s/KPOINTS %s' %(newfolder, contcar, newfolder, newfolder, newfolder, path)) - print 'unzipping new inputs' + print('unzipping new inputs') os.system('gunzip %s/*' %(path)) - print 'copying contcar as new poscar' + print('copying contcar as new poscar') if contcar == 'CONTCAR.relax1.gz': os.system('mv %s/CONTCAR.relax1 %s/POSCAR' %(path , path)) else: @@ -273,7 +273,7 @@ def run_task(self, fw_spec): min_vacuum_size = dec.process_decoded(self.get("min_vacuum_size", 10)) miller_index = dec.process_decoded(self.get("miller_index")) - print 'about to make mplb' + print('about to make mplb') mplb = MPSlabVaspInputSet(user_incar_settings=user_incar_settings, k_product=k_product, @@ -284,12 +284,12 @@ def run_task(self, fw_spec): # cell is already oriented with the miller index, entering (0,0,1) # into SlabGenerator is the same as obtaining a slab in the # orienetation of the original miller index. - print 'about to copy contcar' + print('about to copy contcar') contcar = Poscar.from_file("%s/CONTCAR.relax2.gz" %(cwd+folder)) relax_orient_uc = contcar.structure - print 'made relaxed oriented structure' - print relax_orient_uc - print 'making slab' + print('made relaxed oriented structure') + print(relax_orient_uc) + print('making slab') slabs = SlabGenerator(relax_orient_uc, (0,0,1), min_slab_size=min_slab_size, @@ -298,43 +298,43 @@ def run_task(self, fw_spec): # Whether or not to create a list of Fireworks # based on different slab terminations - print 'deciding terminations' + print('deciding terminations') slab_list = slabs.get_slabs() if terminations else [slabs.get_slab()] qe = QueryEngine(**vaspdbinsert_parameters) optional_data = ["state"] - print 'query bulk entry for job completion' + print('query bulk entry for job completion') bulk_entry = qe.get_entries({'chemsys': relax_orient_uc.composition.reduced_formula, 'structure_type': 'oriented_unit_cell', 'miller_index': miller_index}, optional_data=optional_data) - print 'chemical formula', relax_orient_uc.composition.reduced_formula - print 'fomular data type is ', type(relax_orient_uc.composition.reduced_formula) - print 'checking job completion' - print bulk_entry + print('chemical formula', relax_orient_uc.composition.reduced_formula) + print('fomular data type is ', type(relax_orient_uc.composition.reduced_formula)) + print('checking job completion') + print(bulk_entry) for entry in bulk_entry: - print 'for loop' - print entry.data['state'] + print('for loop') + print(entry.data['state']) if entry.data['state'] != 'successful': - print "%s bulk calculations were incomplete, cancelling FW" \ - %(relax_orient_uc.composition.reduced_formula) + print("%s bulk calculations were incomplete, cancelling FW" \ + %(relax_orient_uc.composition.reduced_formula)) return FWAction() else: - print entry.data['state'] + print(entry.data['state']) FWs = [] for slab in slab_list: - print slab + print(slab) new_folder = folder.replace('bulk', 'slab')+'_shift%s' \ %(slab.shift) # Will continue an incomplete job from a previous contcar file if it exists - print 'cwd is %s' %(os.getcwd()) - print 'the folder is %s' %(new_folder) - print os.path.join(os.getcwd(), new_folder) - print cwd+'/'+new_folder + print('cwd is %s' %(os.getcwd())) + print('the folder is %s' %(new_folder)) + print(os.path.join(os.getcwd(), new_folder)) + print(cwd+'/'+new_folder) path = cwd+'/'+new_folder # path = os.path.join(os.getcwd(), folder) @@ -347,17 +347,17 @@ def run_task(self, fw_spec): # print os.stat(os.path.join(path, 'CONTCAR.gz')).st_size !=0 def continue_vasp(contcar): - print folder, 'already exists, will now continue calculation' - print 'making prev_run folder' + print(folder, 'already exists, will now continue calculation') + print('making prev_run folder') os.system('mkdir %s' %(newfolder)) - print 'moving outputs to prev_run' + print('moving outputs to prev_run') os.system('mv %s/* %s/prev_run' %(path, path)) - print 'moving outputs as inputs for next calculation' + print('moving outputs as inputs for next calculation') os.system('cp %s/%s %s/INCAR %s/POTCAR %s/KPOINTS %s' %(newfolder, contcar, newfolder, newfolder, newfolder, path)) - print 'unzipping new inputs' + print('unzipping new inputs') os.system('gunzip %s/*' %(path)) - print 'copying contcar as new poscar' + print('copying contcar as new poscar') if contcar == 'CONTCAR.relax1.gz': os.system('mv %s/CONTCAR.relax1 %s/POSCAR' %(path , path)) else: diff --git a/mpworks/fix_scripts/add_icsd_materials.py b/mpworks/fix_scripts/add_icsd_materials.py index 39a8e652..a44f459a 100644 --- a/mpworks/fix_scripts/add_icsd_materials.py +++ b/mpworks/fix_scripts/add_icsd_materials.py @@ -62,13 +62,13 @@ def process_material(self, material_id): icsd_ids = self.get_icsd_ids_from_snlgroup(snlgroup_id) self.materials.find_and_modify({"task_ids": material_id}, {"$set": {"icsd_id": icsd_ids}}) - print material_id, icsd_ids - print 'FINISHED', material_id + print(material_id, icsd_ids) + print('FINISHED', material_id) except: - print '-----' - print 'ENCOUNTERED AN EXCEPTION!!!', material_id + print('-----') + print('ENCOUNTERED AN EXCEPTION!!!', material_id) traceback.print_exc() - print '-----' + print('-----') def get_icsd_ids_from_snlgroup(self, snlgroup_id): @@ -93,11 +93,11 @@ def _analyze(data): o = ICSDBuilder() o.setup() materials = o.materials - print materials.count() + print(materials.count()) m_data = [] for d in materials.find({}, {'task_id': 1}, timeout=False): m_data.append(d['task_id']) pool = multiprocessing.Pool(8) pool.map(_analyze, m_data) - print 'DONE' \ No newline at end of file + print('DONE') \ No newline at end of file diff --git a/mpworks/fix_scripts/add_old_taskids.py b/mpworks/fix_scripts/add_old_taskids.py index 13324763..a3c5662e 100644 --- a/mpworks/fix_scripts/add_old_taskids.py +++ b/mpworks/fix_scripts/add_old_taskids.py @@ -51,12 +51,12 @@ def process_task(self, task_id): try: task_id_deprecated = int(task_id.split('-')[-1]) self.tasks.update({"task_id": task_id}, {"$set": {"task_id_deprecated": task_id_deprecated}}) - print 'FINISHED', task_id + print('FINISHED', task_id) except: - print '-----' - print 'ENCOUNTERED AN EXCEPTION!!!', task_id + print('-----') + print('ENCOUNTERED AN EXCEPTION!!!', task_id) traceback.print_exc() - print '-----' + print('-----') def _analyze(data): @@ -80,4 +80,4 @@ def _analyze(data): q = {} for d in tasks.find(q, {'task_id': 1}, timeout=False): o.process_task(d['task_id']) - print 'DONE' \ No newline at end of file + print('DONE') \ No newline at end of file diff --git a/mpworks/fix_scripts/clear_FWs.py b/mpworks/fix_scripts/clear_FWs.py index ad510447..96c25ee8 100644 --- a/mpworks/fix_scripts/clear_FWs.py +++ b/mpworks/fix_scripts/clear_FWs.py @@ -45,15 +45,15 @@ def _defuse_fw(data): # archive READY WORKFLOWS for d in lp.workflows.find({"state": "READY"}, {'nodes': 1}): fw_ids.append(d['nodes'][0]) - print 'GOT all fw_ids...' + print('GOT all fw_ids...') pool = multiprocessing.Pool(8) states = pool.map(_archive_fw, fw_ids) - print 'DONE', all(states) + print('DONE', all(states)) # defuse any READY/WAITING FWs for d in lp.fireworks.find({"state": {"$in":["READY", "WAITING"]}}, {'fw_id': 1}): fw_ids.append(d['fw_id']) - print 'GOT all fw_ids...' + print('GOT all fw_ids...') pool = multiprocessing.Pool(8) states = pool.map(_defuse_fw, fw_ids) - print 'DONE', all(states) \ No newline at end of file + print('DONE', all(states)) \ No newline at end of file diff --git a/mpworks/fix_scripts/find_missing_snl.py b/mpworks/fix_scripts/find_missing_snl.py index d2e15824..bfa254b8 100644 --- a/mpworks/fix_scripts/find_missing_snl.py +++ b/mpworks/fix_scripts/find_missing_snl.py @@ -22,26 +22,26 @@ all_snl_ids = [] # snl ids that have a group all_missing_ids = [] # snl ids missing a group idx = 0 - print 'GETTING GROUPS' + print('GETTING GROUPS') for x in snldb.snlgroups.find({}, {"all_snl_ids": 1}): all_snl_ids.extend(x['all_snl_ids']) - print 'CHECKING SNL' + print('CHECKING SNL') for x in snldb.snl.find({}, {'snl_id': 1}, timeout=False): - print x['snl_id'] + print(x['snl_id']) if x['snl_id'] not in all_snl_ids: - print x['snl_id'], '*********' + print(x['snl_id'], '*********') all_missing_ids.append(x['snl_id']) - print 'FIXING / ADDING GROUPS' - print all_missing_ids + print('FIXING / ADDING GROUPS') + print(all_missing_ids) for snl_id in all_missing_ids: try: mpsnl = MPStructureNL.from_dict(snldb.snl.find_one({"snl_id": snl_id})) snldb.build_groups(mpsnl) - print 'SUCCESSFUL', snl_id + print('SUCCESSFUL', snl_id) except: - print 'ERROR with snl_id', snl_id + print('ERROR with snl_id', snl_id) traceback.print_exc() diff --git a/mpworks/fix_scripts/fix_bad_crystals.py b/mpworks/fix_scripts/fix_bad_crystals.py index e6ba53d3..dfa41acf 100644 --- a/mpworks/fix_scripts/fix_bad_crystals.py +++ b/mpworks/fix_scripts/fix_bad_crystals.py @@ -40,7 +40,7 @@ def detect(): n_groups = snlgroups.find({"all_snl_ids":{"$in":[old_s['snl_id'], new_s['snl_id']]}}).count() if n_groups != 1: # The crystal_id is bad - print crystal_id + print(crystal_id) def fix(): @@ -90,7 +90,7 @@ def fix(): for c_id in bad_crystal_ids: if c_id == 100892 or c_id == 100202: - print 'SKIP' + print('SKIP') else: # FIX SNL @@ -122,7 +122,7 @@ def fix(): for s in submissions.find({'about._materialsproject.deprecated.crystal_id_deprecated': c_id}, {'submission_id': 1}): submissions.update({'submission_id': s['submission_id']}, {'$pushAll': {"about.remarks": ['DEPRECATED', 'SEVERE BUG IN ICSD CONVERSION']}}) - print 'FIXED', c_id + print('FIXED', c_id) def find_alternate_canonical(): @@ -139,10 +139,10 @@ def find_alternate_canonical(): for s in snl.find({"snl_id": {"$in": g['all_snl_ids']}, "about.remarks": {"$ne": "DEPRECATED"}}): canonical_mpsnl = MPStructureNL.from_dict(s) snldb.switch_canonical_snl(g['snlgroup_id'], canonical_mpsnl) - print g['snlgroup_id'] + print(g['snlgroup_id']) break - print 'DONE' + print('DONE') def archive_deprecated_fws(): # find all snlgroups that are deprecated, and archive all WFs that have deprecated fw_ids so we don't run them @@ -157,11 +157,11 @@ def archive_deprecated_fws(): for g in snlgroups.find({'canonical_snl.about.remarks':'DEPRECATED'}, {'snlgroup_id': 1}): while lpdb.fireworks.find_one({'spec.snlgroup_id': g['snlgroup_id'], 'state': {'$ne': 'ARCHIVED'}}, {'fw_id': 1}): fw = lpdb.fireworks.find_one({'spec.snlgroup_id': g['snlgroup_id'], 'state': {'$ne': 'ARCHIVED'}}, {'fw_id': 1}) - print fw['fw_id'] + print(fw['fw_id']) lpdb.archive_wf(fw['fw_id']) - print 'DONE' + print('DONE') diff --git a/mpworks/fix_scripts/fix_bs_controller_tasks.py b/mpworks/fix_scripts/fix_bs_controller_tasks.py index 33144ef9..96b20750 100644 --- a/mpworks/fix_scripts/fix_bs_controller_tasks.py +++ b/mpworks/fix_scripts/fix_bs_controller_tasks.py @@ -1,14 +1,12 @@ -import time, yaml, sys, os -from fireworks.core.launchpad import LaunchPad +import os +import yaml from fireworks.core.firework import Firework, Workflow -from mpworks.firetasks.controller_tasks import AddEStructureTask +from fireworks.core.launchpad import LaunchPad from fireworks.utilities.fw_utilities import get_slug -from mpworks.snl_utils.snl_mongo import SNLMongoAdapter from pymongo import MongoClient -from collections import Counter -from datetime import datetime -from fnmatch import fnmatch -from custodian.vasp.handlers import VaspErrorHandler + +from mpworks.firetasks.controller_tasks import AddEStructureTask +from mpworks.snl_utils.snl_mongo import SNLMongoAdapter cwd = os.getcwd() @@ -24,7 +22,7 @@ db.authenticate(creds['username'], creds['password']) materials = db['materials'] tasks = db['tasks'] -print materials.count() +print(materials.count()) def append_wf(fw_id, parent_fw_id=None): wf = lpdb.workflows.find_one({'nodes':fw_id}, {'parent_links':1,'links':1,'name':1}) @@ -38,25 +36,25 @@ def append_wf(fw_id, parent_fw_id=None): if child_fw['spec']['task_type'] == 'Controller: add Electronic Structure v2': if child_fw['state'] == 'DEFUSED': lpdb.reignite_fw(child_fw_id) - print 'AddEStructureTask v2', child_fw_id , 'reignited for', fw_id + print('AddEStructureTask v2', child_fw_id , 'reignited for', fw_id) elif child_fw['state'] == 'FIZZLED': lpdb.rerun_fw(child_fw_id) - print 'AddEStructureTask v2', child_fw_id , 'marked for rerun for', fw_id + print('AddEStructureTask v2', child_fw_id , 'marked for rerun for', fw_id) elif child_fw['state'] == 'COMPLETED': - print 'AddEStructureTask v2 already successfully run for', fw_id + print('AddEStructureTask v2 already successfully run for', fw_id) sec_child_fw_id = wf['links'][str(child_fw_id)][0] - sec_child_fw = lpdb.fireworks.find_one({'fw_id': sec_child_fw_id}, {'spec.task_type':1, 'state':1}) - if sec_child_fw['state'] == 'FIZZLED': - lpdb.rerun_fw(sec_child_fw_id) - print 'FIZZLED -> marked for rerun:', sec_child_fw_id, sec_child_fw['spec']['task_type'] - else: - print 'AddEStructureTask v2 added but neither DEFUSED, FIZZLED, or COMPLETED for', fw_id + sec_child_fw = lpdb.fireworks.find_one({'fw_id': sec_child_fw_id}, {'spec.task_type':1, 'state':1}) + if sec_child_fw['state'] == 'FIZZLED': + lpdb.rerun_fw(sec_child_fw_id) + print('FIZZLED -> marked for rerun:', sec_child_fw_id, sec_child_fw['spec']['task_type']) + else: + print('AddEStructureTask v2 added but neither DEFUSED, FIZZLED, or COMPLETED for', fw_id) return f = lpdb.get_wf_summary_dict(fw_id)['name'].replace(' ', '_') name = get_slug(f + '--' + spec['task_type']) fw = Firework([AddEStructureTask()], spec, name=name) lpdb.append_wf(Workflow([fw]), [parent_fw_id]) - print name, 'added for', fw_id + print(name, 'added for', fw_id) except ValueError: raise ValueError('could not append controller task to wf', wf['name']) @@ -91,14 +89,14 @@ def append_wf(fw_id, parent_fw_id=None): #print 'nfws =', nfws mp_ids = [ - 'mp-2123', 'mp-10886', 'mp-582799', 'mp-21477', 'mp-535', 'mp-21293', 'mp-8700', - 'mp-9568', 'mp-973', 'mp-505622', 'mp-20839', 'mp-1940', 'mp-16521', 'mp-30354', - 'mp-568953', 'mp-454', 'mp-1010', 'mp-1416', 'mp-21385', 'mp-27659', 'mp-22481', - 'mp-569529', 'mp-1057', 'mp-1834', 'mp-2336', 'mp-12857', 'mp-21109', 'mp-30387', - 'mp-30599', 'mp-21884', 'mp-11397', 'mp-11814', 'mp-510437', 'mp-12565', 'mp-33032', + 'mp-2123', 'mp-10886', 'mp-582799', 'mp-21477', 'mp-535', 'mp-21293', 'mp-8700', + 'mp-9568', 'mp-973', 'mp-505622', 'mp-20839', 'mp-1940', 'mp-16521', 'mp-30354', + 'mp-568953', 'mp-454', 'mp-1010', 'mp-1416', 'mp-21385', 'mp-27659', 'mp-22481', + 'mp-569529', 'mp-1057', 'mp-1834', 'mp-2336', 'mp-12857', 'mp-21109', 'mp-30387', + 'mp-30599', 'mp-21884', 'mp-11397', 'mp-11814', 'mp-510437', 'mp-12565', 'mp-33032', 'mp-20885', 'mp-1891', - "mp-987", "mp-1542", "mp-2252", "mp-966", "mp-6945", "mp-1598", - "mp-7547", "mp-554340", "mp-384", "mp-2437", "mp-1167", "mp-571266", + "mp-987", "mp-1542", "mp-2252", "mp-966", "mp-6945", "mp-1598", + "mp-7547", "mp-554340", "mp-384", "mp-2437", "mp-1167", "mp-571266", "mp-560338", "mp-27253", "mp-1705", "mp-2131", "mp-676", "mp-2402", "mp-9588", "mp-2452", "mp-690", "mp-30033", "mp-10155", "mp-9921", "mp-9548", "mp-569857", "mp-29487", "mp-909", "mp-1536", "mp-28391", "mp-558811", "mp-1033", "mp-1220", @@ -140,17 +138,17 @@ def append_wf(fw_id, parent_fw_id=None): ] mp_ids = [ "mp-134", "mp-127", "mp-58", "mp-135", "mp-70", "mp-1" ] mp_ids = [doc['task_id'] for doc in materials.find({'has_bandstructure': False}, {'task_id':1})] - print '#mp_ids =', len(mp_ids) + print('#mp_ids =', len(mp_ids)) counter = Counter() materials_wBS = [] for matidx, material in enumerate(materials.find({'task_id': {'$in': mp_ids}}, {'task_id': 1, '_id': 0, 'snlgroup_id_final': 1, 'has_bandstructure': 1, 'pretty_formula': 1})): mp_id, snlgroup_id = material['task_id'], material['snlgroup_id_final'] - url = 'https://materialsproject.org/materials/' + mp_id + url = 'https://materialsproject.org/materials/' + mp_id if material['has_bandstructure']: materials_wBS.append((mp_id, material['pretty_formula'])) counter['has_bandstructure'] += 1 - print matidx, '========', mp_id, snlgroup_id, '=============' + print(matidx, '========', mp_id, snlgroup_id, '=============') fw_list = list(lpdb.fireworks.find( {'spec.snlgroup_id': snlgroup_id}, {'_id': 0, 'state': 1, 'name': 1, 'fw_id': 1, 'spec.snlgroup_id': 1, 'spec.task_type': 1, 'launches': 1} @@ -162,7 +160,7 @@ def append_wf(fw_id, parent_fw_id=None): has_gga_static = True if fw['state'] == 'FIZZLED': #counter[fw['spec']['task_type']] += 1 - print '--'.join([fw['name'], str(fw['fw_id'])]), fw['state'] + print('--'.join([fw['name'], str(fw['fw_id'])]), fw['state']) launch_dir = lpdb.launches.find_one({'launch_id': fw['launches'][0]}, {'launch_dir':1})['launch_dir'] launch_subdir = '/'.join(launch_dir.split('/')[-2:]) if 'oasis' in launch_dir: @@ -180,12 +178,12 @@ def append_wf(fw_id, parent_fw_id=None): try: os.chdir(launch_dir) except: - print ' |===> could not find launch directory in usual locations' + print(' |===> could not find launch directory in usual locations') lpdb.rerun_fw(fw['fw_id']) - print ' |===> marked for RERUN' + print(' |===> marked for RERUN') counter['LOCATION_NOT_FOUND'] += 1 continue - print ' |===>', launch_dir + print(' |===>', launch_dir) vaspout = os.path.join(launch_dir, "vasp.out") if not os.path.exists(vaspout): vaspout = os.path.join(launch_dir, "vasp.out.gz") @@ -200,9 +198,9 @@ def append_wf(fw_id, parent_fw_id=None): counter['GGA_static_' + err] += 1 if 'brmix' in d['errors']: #lpdb.rerun_fw(fw['fw_id']) - print ' |===> BRMIX error -> marked for RERUN with alternative strategy' + print(' |===> BRMIX error -> marked for RERUN with alternative strategy') else: - print ' |===> no vasp error indicated -> TODO' + print(' |===> no vasp error indicated -> TODO') counter['GGA_STATIC_NO_VASP_ERROR'] += 1 os.chdir(cwd) else: @@ -211,20 +209,20 @@ def append_wf(fw_id, parent_fw_id=None): {'state': 1, '_id': 0, 'fw_states': 1, 'nodes': 1, 'updated_on': 1, 'parent_links': 1} ) if workflow is None: - print ' |==> workflow not found', fw['fw_id'] + print(' |==> workflow not found', fw['fw_id']) counter['WF_NOT_FOUND'] += 1 continue is_new = bool(datetime(2016, 1, 1) < workflow['updated_on']) if workflow['state'] == 'FIZZLED': - for fw_id_fizzled, fw_state in workflow['fw_states'].iteritems(): + for fw_id_fizzled, fw_state in workflow['fw_states'].items(): if fw_state == 'FIZZLED': fw_fizzled = lpdb.fireworks.find_one({'fw_id': int(fw_id_fizzled)}, {'_id': 0, 'name': 1, 'fw_id': 1, 'spec.task_type': 1}) counter[fw_fizzled['spec']['task_type']] += 1 - print url, is_new, material['has_bandstructure'], fw_id_fizzled - print 'http://fireworks.dash.materialsproject.org/wf/'+str(fw['fw_id']), workflow['state'] - print ' |==>', '--'.join([fw_fizzled['name'], fw_id_fizzled]) + print(url, is_new, material['has_bandstructure'], fw_id_fizzled) + print('http://fireworks.dash.materialsproject.org/wf/'+str(fw['fw_id']), workflow['state']) + print(' |==>', '--'.join([fw_fizzled['name'], fw_id_fizzled])) if fnmatch(fw_fizzled['spec']['task_type'], '*Boltztrap*'): - print ' |====> marked for RERUN (Boltztrap, physical constants from scipy, missing libmkl_lapack.so, BoltzTrap_TE -> pymatgen)' + print(' |====> marked for RERUN (Boltztrap, physical constants from scipy, missing libmkl_lapack.so, BoltzTrap_TE -> pymatgen)') #lpdb.rerun_fw(fw_fizzled['fw_id']) continue elif fw_fizzled['spec']['task_type'] == 'GGA Uniform v2': @@ -233,42 +231,42 @@ def append_wf(fw_id, parent_fw_id=None): fw_id_rerun = str(workflow['parent_links'][fw_id_rerun][-1]) fw_rerun = lpdb.fireworks.find_one({'fw_id': int(fw_id_rerun)}, {'_id': 0, 'spec.task_type': 1}) if fw_rerun['spec']['task_type'] != 'VASP db insertion': - print 'http://fireworks.dash.materialsproject.org/wf/'+fw_id_rerun + print('http://fireworks.dash.materialsproject.org/wf/'+fw_id_rerun) break #lpdb.rerun_fw(int(fw_id_rerun)) - print ' |====> marked for RERUN (could not get valid results from prev_vasp_dir, GGAstatic vasprun.xml validation error)' + print(' |====> marked for RERUN (could not get valid results from prev_vasp_dir, GGAstatic vasprun.xml validation error)') elif fw_fizzled['spec']['task_type'] == 'GGA band structure v2': - print ' |===> marked for RERUN (trial & error)' + print(' |===> marked for RERUN (trial & error)') #try: # lpdb.rerun_fw(fw_fizzled['fw_id']) #except: # print ' |===> could not rerun firework' # counter['WF_LOCKED'] += 1 elif fw_fizzled['spec']['task_type'] == 'VASP db insertion': - print ' |===> marked for RERUN (trial & error)' + print(' |===> marked for RERUN (trial & error)') #lpdb.rerun_fw(fw_fizzled['fw_id']) #sys.exit(0) break elif workflow['state'] == 'COMPLETED': - print url, is_new, material['has_bandstructure'], workflow['nodes'][0] + print(url, is_new, material['has_bandstructure'], workflow['nodes'][0]) if not is_new and not material['has_bandstructure']: #lpdb.rerun_fw(fw['fw_id']) - print ' |===> marked for RERUN with alternative brmix strategy (WF completed but BS missing)' + print(' |===> marked for RERUN with alternative brmix strategy (WF completed but BS missing)') counter['WF_COMPLETED_MISSING_BS'] += 1 #sys.exit(0) else: counter['COMPLETED'] += 1 if not has_gga_static: - print 'ERROR: no GGA static run found!' - print '\n'.join([ + print('ERROR: no GGA static run found!') + print('\n'.join([ '--'.join([fw['name'], str(fw['fw_id']), fw['state']]) for fw in fw_list - ]) + ])) counter['NO_GGA_STATIC'] += 1 #break else: - print 'ERROR: no fireworks found!' + print('ERROR: no fireworks found!') counter['NO_FWS'] += 1 #break - print '#mp_ids =', len(mp_ids) - print counter + print('#mp_ids =', len(mp_ids)) + print(counter) #print materials_wBS diff --git a/mpworks/fix_scripts/fix_float_priorities.py b/mpworks/fix_scripts/fix_float_priorities.py index edfad619..f9f9595b 100644 --- a/mpworks/fix_scripts/fix_float_priorities.py +++ b/mpworks/fix_scripts/fix_float_priorities.py @@ -17,7 +17,7 @@ for fw in lpdb.fireworks.find({"spec._tasks.1.max_errors":{"$type": 1}}, {"fw_id": 1, "state": 1, "spec._tasks": 1}, timeout=False): - print fw['fw_id'], fw['state'] + print(fw['fw_id'], fw['state']) lpdb.fireworks.find_and_modify({"fw_id": fw['fw_id']}, {"$set": {"spec._tasks.1.max_errors": int(5)}}) if fw['state'] == 'FIZZLED': lpdb.rerun_fw(fw['fw_id']) \ No newline at end of file diff --git a/mpworks/fix_scripts/fix_mpcomplete.py b/mpworks/fix_scripts/fix_mpcomplete.py index 83f8534a..d7954771 100644 --- a/mpworks/fix_scripts/fix_mpcomplete.py +++ b/mpworks/fix_scripts/fix_mpcomplete.py @@ -34,7 +34,7 @@ projection=projection, return_document=ReturnDocument.AFTER ) - print doc['fw_id'], '----> walltime updated' + print(doc['fw_id'], '----> walltime updated') if 'nnodes' in doc['spec']['_queueadapter'] and not 'nodes' in doc['spec']['_queueadapter']: launchpad.fireworks.find_one_and_update( {'fw_id': doc['fw_id']}, @@ -42,7 +42,7 @@ projection=projection, return_document=ReturnDocument.AFTER ) - print doc['fw_id'], '----> nodes key renamed' + print(doc['fw_id'], '----> nodes key renamed') if 'pre_rocket' in doc['spec']['_queueadapter']: launchpad.fireworks.find_one_and_update( m_query, @@ -50,12 +50,12 @@ projection=projection, return_document=ReturnDocument.AFTER ) - print doc['fw_id'], '----> pre_rocket dropped' + print(doc['fw_id'], '----> pre_rocket dropped') if 'prev_vasp_dir' in doc['spec'] and not os.path.exists(doc['spec']['prev_vasp_dir']): block_dir = doc['spec']['prev_vasp_dir'].split('/')[-2:] launch_dir = '/'.join('/oasis/projects/nsf/csd436/phuck/garden'.split('/') + block_dir) if not os.path.exists(launch_dir): - print doc['fw_id'], '---->', '/'.join(block_dir), 'does not exists!' - continue + print(doc['fw_id'], '---->', '/'.join(block_dir), 'does not exists!') + continue fw_ids.append(doc['fw_id']) -print 'fixed', fw_ids +print('fixed', fw_ids) diff --git a/mpworks/fix_scripts/fix_unmoved_dirs.py b/mpworks/fix_scripts/fix_unmoved_dirs.py index 17ea77bf..b44cde51 100644 --- a/mpworks/fix_scripts/fix_unmoved_dirs.py +++ b/mpworks/fix_scripts/fix_unmoved_dirs.py @@ -26,7 +26,7 @@ def detect(): block_part = get_block_part(d) garden_dir = os.path.join(GARDEN_PATH, block_part) if os.path.exists(garden_dir): - print garden_dir + print(garden_dir) if __name__ == '__main__': diff --git a/mpworks/fix_scripts/legacy/actions/add_snl_final.py b/mpworks/fix_scripts/legacy/actions/add_snl_final.py index 9ce82df0..e2a99241 100644 --- a/mpworks/fix_scripts/legacy/actions/add_snl_final.py +++ b/mpworks/fix_scripts/legacy/actions/add_snl_final.py @@ -24,4 +24,4 @@ for d in new_tasks.find({'snlgroup_id_final': {'$exists': False}}, {'task_id': 1, 'snl': 1, 'snlgroup_id': 1, 'snlgroup_changed': 1}): new_tasks.update({'task_id': d['task_id']}, {'$set': {'snl_final': d['snl'], 'snlgroup_id_final': d['snlgroup_id'], 'snlgroup_changed': False}}) count+=1 - print count + print(count) diff --git a/mpworks/fix_scripts/legacy/actions/do_fw_conversion.py b/mpworks/fix_scripts/legacy/actions/do_fw_conversion.py index 38e6aab6..ac0310fe 100644 --- a/mpworks/fix_scripts/legacy/actions/do_fw_conversion.py +++ b/mpworks/fix_scripts/legacy/actions/do_fw_conversion.py @@ -28,7 +28,7 @@ db2.authenticate(db_creds['admin_user'], db_creds['admin_password']) new_tasks = db2['tasks'] - print new_tasks.count() + print(new_tasks.count()) new_tasks.ensure_index("task_id", unique=True) new_tasks.ensure_index("task_id_deprecated", unique=True) diff --git a/mpworks/fix_scripts/legacy/actions/do_icsd_to_snl.py b/mpworks/fix_scripts/legacy/actions/do_icsd_to_snl.py index a0201334..e2ad719f 100644 --- a/mpworks/fix_scripts/legacy/actions/do_icsd_to_snl.py +++ b/mpworks/fix_scripts/legacy/actions/do_icsd_to_snl.py @@ -40,6 +40,6 @@ snldb.add_snl(snl) except: traceback.print_exc() - print 'ERROR - icsd id:', icsd_dict['icsd_id'] + print('ERROR - icsd id:', icsd_dict['icsd_id']) - print 'DONE' + print('DONE') diff --git a/mpworks/fix_scripts/legacy/actions/do_mps_to_snl.py b/mpworks/fix_scripts/legacy/actions/do_mps_to_snl.py index 8b4d4223..72794873 100644 --- a/mpworks/fix_scripts/legacy/actions/do_mps_to_snl.py +++ b/mpworks/fix_scripts/legacy/actions/do_mps_to_snl.py @@ -36,7 +36,7 @@ prev_ids = [] # MPS ids that we already took care of - print 'INITIALIZING' + print('INITIALIZING') if RESET: snldb._reset() time.sleep(10) # makes me sleep better at night @@ -45,7 +45,7 @@ for mps in snldb.snl.find({}, {"about._materialsproject.deprecated.mps_ids": 1}): prev_ids.extend(mps['about']['_materialsproject']['deprecated']['mps_ids']) - print 'PROCESSING' + print('PROCESSING') for mps in db.mps.find(timeout=False): try: if not mps['mps_id'] in prev_ids: @@ -53,9 +53,9 @@ if snl: snldb.add_snl(snl) else: - print 'SKIPPING', mps['mps_id'] + print('SKIPPING', mps['mps_id']) except: traceback.print_exc() - print 'ERROR - mps id:', mps['mps_id'] + print('ERROR - mps id:', mps['mps_id']) - print 'DONE' + print('DONE') diff --git a/mpworks/fix_scripts/legacy/actions/do_task_conversion.py b/mpworks/fix_scripts/legacy/actions/do_task_conversion.py index 9bc0670e..37d8b7b5 100644 --- a/mpworks/fix_scripts/legacy/actions/do_task_conversion.py +++ b/mpworks/fix_scripts/legacy/actions/do_task_conversion.py @@ -58,12 +58,12 @@ def process_task(self, task_id): t = self.old_tasks.find_one({'task_id': task_id}) try: t_id, d = self.drone.assimilate(t) - print 'ENTERED', t_id + print('ENTERED', t_id) except: - print 'ERROR entering', t['task_id'] + print('ERROR entering', t['task_id']) traceback.print_exc() else: - print 'skip' + print('skip') def _analyze(task_id): @@ -77,10 +77,10 @@ def parallel_build(min, max): for i in tasks_old.find({'task_id': {'$gte': min, '$lt': max}}, {'task_id': 1}): task_ids.append(i['task_id']) - print 'GOT all tasks...' + print('GOT all tasks...') pool = multiprocessing.Pool(16) pool.map(_analyze, task_ids) - print 'DONE' + print('DONE') if __name__ == '__main__': o = OldTaskBuilder() diff --git a/mpworks/fix_scripts/legacy/actions/do_task_conversion_fixes.py b/mpworks/fix_scripts/legacy/actions/do_task_conversion_fixes.py index b01dc0bb..17f1bb3c 100644 --- a/mpworks/fix_scripts/legacy/actions/do_task_conversion_fixes.py +++ b/mpworks/fix_scripts/legacy/actions/do_task_conversion_fixes.py @@ -54,9 +54,9 @@ def process_task(self, task_id): t = self.old_tasks.find_one({'task_id': task_id}) try: t_id, d = self.drone.assimilate(t) - print 'ENTERED', t_id + print('ENTERED', t_id) except: - print 'ERROR entering', t['task_id'] + print('ERROR entering', t['task_id']) traceback.print_exc() @@ -83,5 +83,5 @@ def process_task(self, task_id): t = o.new_tasks.find_one({"task_id": new_task_id}, {"state": 1}) if t: o.new_tasks.remove({'task_id': new_task_id}) - print 'REPARSING', old_task_id + print('REPARSING', old_task_id) o.process_task(old_task_id) diff --git a/mpworks/fix_scripts/legacy/mps_to_snl.py b/mpworks/fix_scripts/legacy/mps_to_snl.py index 1257a53f..563ff741 100644 --- a/mpworks/fix_scripts/legacy/mps_to_snl.py +++ b/mpworks/fix_scripts/legacy/mps_to_snl.py @@ -19,7 +19,7 @@ def mps_dict_to_snl(mps_dict): return None if 'Carbon Capture Storage Initiative (CCSI)' in m['about']['metadata']['project_names']: - print 'rejected old CCSI' + print('rejected old CCSI') return None mps_ids = [m['mps_id']] @@ -38,7 +38,7 @@ def mps_dict_to_snl(mps_dict): projects.append(project) data = {'_materialsproject': {'deprecated': {'mps_ids': mps_ids}}, '_icsd': {}} - for k, v in m['about']['metadata']['info'].iteritems(): + for k, v in m['about']['metadata']['info'].items(): if k == 'icsd_comments': data['_icsd']['comments'] = v elif k == 'icsd_id': diff --git a/mpworks/fix_scripts/legacy/old_task_drone.py b/mpworks/fix_scripts/legacy/old_task_drone.py index 3611924f..b30ef79f 100644 --- a/mpworks/fix_scripts/legacy/old_task_drone.py +++ b/mpworks/fix_scripts/legacy/old_task_drone.py @@ -193,7 +193,7 @@ def process_fw(self, old_task, d): vasp_signals['last_relax_dir'] = last_relax_dir ## see what error signals are present - print "getting signals for dir :{}".format(last_relax_dir) + print("getting signals for dir :{}".format(last_relax_dir)) sl = SignalDetectorList() sl.append(VASPInputsExistSignal()) diff --git a/mpworks/fix_scripts/legacy/task_to_fw.py b/mpworks/fix_scripts/legacy/task_to_fw.py index 0bc3c71f..e3bcfc35 100644 --- a/mpworks/fix_scripts/legacy/task_to_fw.py +++ b/mpworks/fix_scripts/legacy/task_to_fw.py @@ -57,6 +57,6 @@ def task_dict_to_wf(task_dict, launchpad): launchpad.add_wf(wf, reassign_all=False) launchpad._upsert_launch(launches[0]) - print 'ADDED', fw_id + print('ADDED', fw_id) # return fw_id return fw_id \ No newline at end of file diff --git a/mpworks/fix_scripts/reparse_old_tasks.py b/mpworks/fix_scripts/reparse_old_tasks.py index 4adb4d91..2eec8efc 100644 --- a/mpworks/fix_scripts/reparse_old_tasks.py +++ b/mpworks/fix_scripts/reparse_old_tasks.py @@ -73,14 +73,14 @@ def process_task(self, path): logger.error("Bad run stats for {}.".format(path)) self.tasks.update({'dir_name_full': path}, {'$set': {"run_stats": run_stats}}) - print 'FINISHED', path + print('FINISHED', path) else: - print 'SKIPPING', path + print('SKIPPING', path) except: - print '-----' - print 'ENCOUNTERED AN EXCEPTION!!!', path + print('-----') + print('ENCOUNTERED AN EXCEPTION!!!', path) traceback.print_exc() - print '-----' + print('-----') def _analyze(data): @@ -104,7 +104,7 @@ def _analyze(data): q = {'submission_id': {'$exists': True}} # these are all old-style tasks for d in tasks.find(q, {'dir_name_full': 1}): m_data.append(d['dir_name_full']) - print 'GOT all tasks...' + print('GOT all tasks...') pool = multiprocessing.Pool(16) pool.map(_analyze, m_data) - print 'DONE' + print('DONE') diff --git a/mpworks/fix_scripts/reparse_old_tasks_again.py b/mpworks/fix_scripts/reparse_old_tasks_again.py index 232d14cd..186c3ba0 100644 --- a/mpworks/fix_scripts/reparse_old_tasks_again.py +++ b/mpworks/fix_scripts/reparse_old_tasks_again.py @@ -73,14 +73,14 @@ def process_task(self, path): logger.error("Bad run stats for {}.".format(path)) self.tasks.update({'dir_name_full': path}, {'$set': {"run_stats": run_stats}}) - print 'FINISHED', path + print('FINISHED', path) else: - print 'SKIPPING', path + print('SKIPPING', path) except: - print '-----' - print 'ENCOUNTERED AN EXCEPTION!!!', path + print('-----') + print('ENCOUNTERED AN EXCEPTION!!!', path) traceback.print_exc() - print '-----' + print('-----') def _analyze(data): @@ -105,9 +105,9 @@ def _analyze(data): for line in f: old_task = line.split(' ')[1].strip() m_data.append(tasks.find_one({"task_id":old_task}, {'dir_name_full': 1})["dir_name_full"]) - print 'GOT all tasks...' + print('GOT all tasks...') # print len(m_data) # print m_data[1] pool = multiprocessing.Pool(2) pool.map(_analyze, m_data) - print 'DONE' + print('DONE') diff --git a/mpworks/fix_scripts/rerun_boltztrap.py b/mpworks/fix_scripts/rerun_boltztrap.py index 67cd9873..06912dd9 100644 --- a/mpworks/fix_scripts/rerun_boltztrap.py +++ b/mpworks/fix_scripts/rerun_boltztrap.py @@ -62,7 +62,7 @@ last_line = ferr.readlines()[-1].strip() if 'TIME LIMIT' in last_line: lpdb.rerun_fw(fw_doc['fw_id']) - print '[{}] rerun due to TIME LIMIT'.format(fw_doc['fw_id']) + print('[{}] rerun due to TIME LIMIT'.format(fw_doc['fw_id'])) else: counter['RECENT_BTZ_FWS_' + fw_doc['state']] += 1 else: @@ -71,7 +71,7 @@ #parent_fw = lpdb.fireworks.find_one({'fw_id': parent_fw_id}, {'state':1}) #if parent_fw['state'] == 'COMPLETED': counter['RECENT_BTZ_FWS_' + fw_doc['state']] += 1 -print counter +print(counter) nfws = 0 for fw_doc in lpdb.fireworks.find( @@ -85,8 +85,8 @@ if 'parent job unsuccessful' in last_line or 'Could not find task' in last_line: parent_fw_id = wf['parent_links'][str(fw_doc['fw_id'])][-1] lpdb.rerun_fw(parent_fw_id) - print '[{}] {} --> marked parent {} for rerun'.format(nfws, fw_doc['fw_id'], parent_fw_id) + print('[{}] {} --> marked parent {} for rerun'.format(nfws, fw_doc['fw_id'], parent_fw_id)) else: #lpdb.rerun_fw(fw_doc['fw_id']) - print '[{}] {} --> {}'.format(nfws, fw_doc['fw_id'], last_line) + print('[{}] {} --> {}'.format(nfws, fw_doc['fw_id'], last_line)) nfws += 1 diff --git a/mpworks/fix_scripts/submit_bo_jobs.py b/mpworks/fix_scripts/submit_bo_jobs.py index 2f2c5105..8f115067 100644 --- a/mpworks/fix_scripts/submit_bo_jobs.py +++ b/mpworks/fix_scripts/submit_bo_jobs.py @@ -20,11 +20,11 @@ for s in os.listdir(os.path.join(module_dir, "snls")): if '.json' in s: - print 'submitting', s + print('submitting', s) with open(os.path.join(module_dir, "snls",s)) as f: snl = StructureNL.from_dict(json.load(f)) sma.submit_snl(snl, 'anubhavster@gmail.com', {"priority": 10}) - print 'DONE submitting', s + print('DONE submitting', s) -print 'DONE!' \ No newline at end of file +print('DONE!') \ No newline at end of file diff --git a/mpworks/maintenance_scripts/classify_fizzled.py b/mpworks/maintenance_scripts/classify_fizzled.py index 2f644071..243ea3f3 100644 --- a/mpworks/maintenance_scripts/classify_fizzled.py +++ b/mpworks/maintenance_scripts/classify_fizzled.py @@ -69,7 +69,7 @@ def get_task_info(fw_id, tdb): except_str = l['action']['stored_data'].get('_exception') if 'Disk quota exceeded' in except_str: except_dict['DISK_QUOTA_EXCEEDED'] = except_dict['DISK_QUOTA_EXCEEDED']+1 - print l['fw_id'], '*' + print(l['fw_id'], '*') lpdb.rerun_fw(l['fw_id']) elif 'No such file' in except_str: # this is due to missing CHGCAR from Michael's old runs @@ -110,7 +110,7 @@ def get_task_info(fw_id, tdb): else: except_dict[except_str] = except_dict[except_str]+1 - print '-----' - for k, v in except_dict.iteritems(): - print {"{}\t{}".format(v, k)} + print('-----') + for k, v in except_dict.items(): + print({"{}\t{}".format(v, k)}) diff --git a/mpworks/maintenance_scripts/icsd2012_to_snl.py b/mpworks/maintenance_scripts/icsd2012_to_snl.py index c7b3c79b..c5751d8a 100644 --- a/mpworks/maintenance_scripts/icsd2012_to_snl.py +++ b/mpworks/maintenance_scripts/icsd2012_to_snl.py @@ -23,7 +23,7 @@ def icsd_dict_to_snl(icsd_dict): data = {'_icsd': {}} excluded_data = ['_id', 'a_len', 'b_len', 'c_len', 'alpha', 'beta', 'gamma', 'compostion', 'composition', 'created_at', 'crystal_id', 'idnum', 'journal', 'tstruct', 'updated_at', 'username'] - for k, v in icsd_dict.iteritems(): + for k, v in icsd_dict.items(): if k not in excluded_data: if isinstance(v, datetime.datetime): v = v.strftime(format='%Y-%m-%d %H:%M:%S') diff --git a/mpworks/maintenance_scripts/modify_snl.py b/mpworks/maintenance_scripts/modify_snl.py index 08044fb4..8863dd81 100644 --- a/mpworks/maintenance_scripts/modify_snl.py +++ b/mpworks/maintenance_scripts/modify_snl.py @@ -66,35 +66,35 @@ def modify_snl(snl_id, new_snl, colls, reject_bad_tasks=False): snl_d['snl_timestamp'] = snl_old['snl_timestamp'] # insert the new SNL into the snl collection - print 'INSERTING SNL_ID', {'snl_id': snl_id}, snl_d + print('INSERTING SNL_ID', {'snl_id': snl_id}, snl_d) colls.snl.update({'snl_id': snl_id}, snl_d) # update the canonical SNL of the group for s in colls.snlgroups.find({'canonical_snl.about._materialsproject.snl_id': snl_id}, {'snlgroup_id': 1}): - print 'CHANGING SNLGROUP_ID', s['snlgroup_id'] + print('CHANGING SNLGROUP_ID', s['snlgroup_id']) colls.snlgroups.find_and_modify({'snlgroup_id': s['snlgroup_id']}, {'$set': {'canonical_snl': snl_d}}) # update FWs pt 1 for f in colls.fireworks.find({'spec.mpsnl.about._materialsproject.snl_id': snl_id}, {'fw_id': 1}): - print 'CHANGING FW_ID', f['fw_id'] + print('CHANGING FW_ID', f['fw_id']) colls.fireworks.find_and_modify({'fw_id': f['fw_id']}, {'$set': {'spec.mpsnl': snl_d}}) # update FWs pt 2 for f in colls.fireworks.find({'spec.force_mpsnl.about._materialsproject.snl_id': snl_id}, {'fw_id': 1}): - print 'CHANGING FW_ID', f['fw_id'] + print('CHANGING FW_ID', f['fw_id']) colls.fireworks.find_and_modify({'fw_id': f['fw_id']}, {'$set': {'spec.force_mpsnl': snl_d}}) # update Launches for l in colls.launches.find({'action.update_spec.mpsnl.about._materialsproject.snl_id': snl_id}, {'launch_id': 1}): - print 'CHANGING LAUNCH_ID', l['launch_id'] + print('CHANGING LAUNCH_ID', l['launch_id']) colls.launches.find_and_modify({'launch_id': l['launch_id']}, {'$set': {'action.update_spec.mpsnl': snl_d}}) # update tasks initial for t in colls.tasks.find({'snl.about._materialsproject.snl_id': snl_id}, {'task_id': 1}): - print 'CHANGING init TASK_ID', t['task_id'] + print('CHANGING init TASK_ID', t['task_id']) colls.tasks.find_and_modify({'task_id': t['task_id']}, {'$set': {'snl': snl_d}}) if reject_bad_tasks: - print 'REJECTING TASK_ID', t['task_id'] + print('REJECTING TASK_ID', t['task_id']) colls.tasks.find_and_modify({'task_id': t['task_id']}, {'$set': {'state': 'rejected'}}) colls.tasks.find_and_modify({'task_id': t['task_id']}, {'$push': {'analysis.errors_MP.critical_signals': 'BAD STRUCTURE SNL'}}) colls.tasks.find_and_modify({'task_id': t['task_id']}, {'$inc': {'analysis.errors_MP.num_critical': 1}}) @@ -102,17 +102,17 @@ def modify_snl(snl_id, new_snl, colls, reject_bad_tasks=False): # update tasks final for t in colls.tasks.find({'snl_final.about._materialsproject.snl_id': snl_id}, {'task_id': 1}): - print 'CHANGING final TASK_ID', t['task_id'] + print('CHANGING final TASK_ID', t['task_id']) colls.tasks.find_and_modify({'task_id': t['task_id']}, {'$set': {'snl_final': snl_d}}) if reject_bad_tasks: - print 'REJECTING TASK_ID', t['task_id'] + print('REJECTING TASK_ID', t['task_id']) colls.tasks.find_and_modify({'task_id': t['task_id']}, {'$set': {'state': 'rejected'}}) colls.tasks.find_and_modify({'task_id': t['task_id']}, {'$push': {'analysis.errors_MP.critical_signals': 'BAD STRUCTURE SNL'}}) colls.tasks.find_and_modify({'task_id': t['task_id']}, {'$inc': {'analysis.errors_MP.num_critical': 1}}) # note: for now we are not fixing submissions in order to keep a record of submissions accurate, and also because the SNL assignment comes after submission - print 'DONE PROCESSING', snl_id + print('DONE PROCESSING', snl_id) def get_deprecated_snl(snl_id, colls): @@ -128,6 +128,6 @@ def get_deprecated_snl(snl_id, colls): snl_id = 1579 snl_new = get_deprecated_snl(snl_id, colls) - print snl_new.as_dict() + print(snl_new.as_dict()) modify_snl(snl_id, snl_new, colls, reject_bad_tasks=True) \ No newline at end of file diff --git a/mpworks/maintenance_scripts/reparse_tasks.py b/mpworks/maintenance_scripts/reparse_tasks.py index f8c7f057..6e7c171f 100644 --- a/mpworks/maintenance_scripts/reparse_tasks.py +++ b/mpworks/maintenance_scripts/reparse_tasks.py @@ -63,12 +63,12 @@ def process_task(self, data): self.tasks.update({"task_id": t_id}, {"$set": {"snl_final": prev_info['snl_final'], "snlgroup_id_final": prev_info['snlgroup_id_final'], "snlgroup_changed": prev_info['snlgroup_changed']}}) - print 'FINISHED', t_id + print('FINISHED', t_id) except: - print '-----' - print 'ENCOUNTERED AN EXCEPTION!!!', data[0] + print('-----') + print('ENCOUNTERED AN EXCEPTION!!!', data[0]) traceback.print_exc() - print '-----' + print('-----') def _analyze(data): @@ -108,8 +108,8 @@ def _analyze(data): for d in tasks.find(q, {'dir_name_full': 1, 'task_type': 1, 'task_id': 1}, timeout=False): if d['task_id'] in finished_tasks: - print 'DUPLICATE', d['task_id'] + print('DUPLICATE', d['task_id']) else: o.process_task((d['dir_name_full'], 'Uniform' in d['task_type'])) # m_data.append((d['dir_name_full'], 'Uniform' in d['task_type'])) - print 'DONE' \ No newline at end of file + print('DONE') \ No newline at end of file diff --git a/mpworks/osti_doi/__main__.py b/mpworks/osti_doi/__main__.py index 4adbda01..b67a74d1 100644 --- a/mpworks/osti_doi/__main__.py +++ b/mpworks/osti_doi/__main__.py @@ -24,15 +24,15 @@ logger.setLevel(getattr(logging, loglevel)) db_yaml = 'materials_db_{}.yaml'.format('prod' if args.prod else 'dev') -print db_yaml +print(db_yaml) if args.reset or args.info or args.plotly: matad = OstiMongoAdapter.from_config(db_yaml=db_yaml) if args.reset: matad._reset() elif args.info: - print '{} DOIs in DOI collection.'.format(matad.doicoll.count()) + print('{} DOIs in DOI collection.'.format(matad.doicoll.count())) dois = matad.get_all_dois() - print '{}/{} materials have DOIs.'.format(len(dois), matad.matcoll.count()) + print('{}/{} materials have DOIs.'.format(len(dois), matad.matcoll.count())) elif args.plotly: import os, datetime import plotly.plotly as py @@ -56,7 +56,7 @@ ) for idx,count in enumerate(counts) ]) filename = 'dois_{}'.format(today) - print py.plot(data, filename=filename, auto_open=False) + print(py.plot(data, filename=filename, auto_open=False)) else: # generate records for either n or all (n=0) not-yet-submitted materials # OR generate records for specific materials (submitted or not) diff --git a/mpworks/osti_doi/osti_record.py b/mpworks/osti_doi/osti_record.py index cc9547d3..3d14871c 100644 --- a/mpworks/osti_doi/osti_record.py +++ b/mpworks/osti_doi/osti_record.py @@ -93,10 +93,10 @@ def insert_dois(self, dois): dois_insert = [ {'_id': mpid, 'doi': d['doi'], 'valid': False, 'created_at': datetime.datetime.now().isoformat()} - for mpid,d in dois.iteritems() if not d['updated'] + for mpid,d in dois.items() if not d['updated'] ] if dois_insert: logger.info(self.doicoll.insert(dois_insert)) - dois_update = [ mpid for mpid,d in dois.iteritems() if d['updated'] ] + dois_update = [ mpid for mpid,d in dois.items() if d['updated'] ] if dois_update: logger.info(self.doicoll.update( {'_id': {'$in': dois_update}}, diff --git a/mpworks/processors/process_submissions.py b/mpworks/processors/process_submissions.py index 0bce2c72..a1833b6b 100644 --- a/mpworks/processors/process_submissions.py +++ b/mpworks/processors/process_submissions.py @@ -3,8 +3,6 @@ from fireworks.core.launchpad import LaunchPad from mpworks.snl_utils.mpsnl import MPStructureNL from mpworks.submission.submission_mongo import SubmissionMongoAdapter -from mpworks.workflows.snl_to_wf import snl_to_wf -from mpworks.workflows.snl_to_wf_elastic import snl_to_wf_elastic from mpworks.workflows.wf_utils import NO_POTCARS from pymatgen.matproj.snl import StructureNL @@ -30,11 +28,11 @@ def run(self, sleep_time=None, infinite=False): sleep_time = sleep_time if sleep_time else 30 while True: self.submit_all_new_workflows() - print "Updating existing workflows..." + print("Updating existing workflows...") self.update_existing_workflows() # for updating the display if not infinite: break - print 'sleeping', sleep_time + print('sleeping', sleep_time) time.sleep(sleep_time) def submit_all_new_workflows(self): @@ -44,7 +42,7 @@ def submit_all_new_workflows(self): def submit_new_workflow(self): # finds a submitted job, creates a workflow, and submits it to FireWorks - job = self.jobs.find_and_modify({'state': 'SUBMITTED'}, {'$set': {'state': 'WAITING'}}) + job = self.jobs.find_one_and_update({'state': 'SUBMITTED'}, {'$set': {'state': 'WAITING'}}) if job: submission_id = job['submission_id'] try: @@ -54,37 +52,47 @@ def submit_new_workflow(self): snl = StructureNL.from_dict(job) if len(snl.structure.sites) > SubmissionProcessor.MAX_SITES: self.sma.update_state(submission_id, 'REJECTED', 'too many sites', {}) - print 'REJECTED WORKFLOW FOR {} - too many sites ({})'.format( - snl.structure.formula, len(snl.structure.sites)) + print('REJECTED WORKFLOW FOR {} - too many sites ({})'.format( + snl.structure.formula, len(snl.structure.sites))) elif not job['is_valid']: self.sma.update_state(submission_id, 'REJECTED', 'invalid structure (atoms too close)', {}) - print 'REJECTED WORKFLOW FOR {} - invalid structure'.format( - snl.structure.formula) + print('REJECTED WORKFLOW FOR {} - invalid structure'.format( + snl.structure.formula)) elif len(set(NO_POTCARS) & set(job['elements'])) > 0: self.sma.update_state(submission_id, 'REJECTED', 'invalid structure (no POTCAR)', {}) - print 'REJECTED WORKFLOW FOR {} - invalid element (No POTCAR)'.format( - snl.structure.formula) + print('REJECTED WORKFLOW FOR {} - invalid element (No POTCAR)'.format( + snl.structure.formula)) elif not job['is_ordered']: self.sma.update_state(submission_id, 'REJECTED', 'invalid structure (disordered)', {}) - print 'REJECTED WORKFLOW FOR {} - invalid structure'.format( - snl.structure.formula) + print('REJECTED WORKFLOW FOR {} - invalid structure'.format( + snl.structure.formula)) else: snl.data['_materialsproject'] = snl.data.get('_materialsproject', {}) snl.data['_materialsproject']['submission_id'] = submission_id # create a workflow if "Elasticity" in snl.projects: - wf=snl_to_wf_elastic(snl, job['parameters']) + from mpworks.workflows.snl_to_wf_elastic import snl_to_wf_elastic + wf = snl_to_wf_elastic(snl, job['parameters']) + elif "NMR" in snl.projects: + # The deferred imported is a dirty fix to avoid the import + # error from pymatgen.io.vasp.sets, although pointing to + # sets_deprecated would make things work temporally, the + # ultimate solution would be to use the new style VaspInputSets + # in pymatgen. NMR workflow uses the new style API. + from mpworks.workflows.snl_to_wf_nmr import snl_to_wf_nmr + wf = snl_to_wf_nmr(snl, job['parameters']) else: + from mpworks.workflows.snl_to_wf import snl_to_wf wf = snl_to_wf(snl, job['parameters']) self.launchpad.add_wf(wf) - print 'ADDED WORKFLOW FOR {}'.format(snl.structure.formula) + print('ADDED WORKFLOW FOR {}'.format(snl.structure.formula)) except: - self.jobs.find_and_modify({'submission_id': submission_id}, - {'$set': {'state': 'ERROR'}}) + self.jobs.find_one_and_update({'submission_id': submission_id}, + {'$set': {'state': 'ERROR'}}) traceback.print_exc() return submission_id @@ -99,7 +107,7 @@ def update_existing_workflows(self): try: self.update_wf_state(submission_id) except: - print 'ERROR while processing s_id', submission_id + print('ERROR while processing s_id', submission_id) traceback.print_exc() @@ -109,10 +117,10 @@ def update_wf_state(self, submission_id): wf = self.launchpad.workflows.find_one({'metadata.submission_id': submission_id}, sort=[('updated_on', -1)]) - if not wf: - # submission_id from jobs collection doesn't exist in workflows collection - # workflow has probably been removed manually by user via `lpad delete_wflows` - return + if not wf: + # submission_id from jobs collection doesn't exist in workflows collection + # workflow has probably been removed manually by user via `lpad delete_wflows` + return details = '(none)' for e in self.launchpad.fireworks.find({'fw_id': {'$in' : wf['nodes']}}, diff --git a/mpworks/processors/submit_canonical.py b/mpworks/processors/submit_canonical.py index e3e57e72..6f07d5dc 100644 --- a/mpworks/processors/submit_canonical.py +++ b/mpworks/processors/submit_canonical.py @@ -34,9 +34,10 @@ def clear_env(): lp.reset('', require_password=False) snl._reset() - conn = MongoClient(db_creds['host'], db_creds['port']) + conn = MongoClient(db_creds['host'], db_creds['port'], connect=False) db = conn[db_creds['database']] - db.authenticate(db_creds['admin_user'], db_creds['admin_password']) + if db_creds['admin_user'] is not None: + db.authenticate(db_creds['admin_user'], db_creds['admin_password']) db.tasks.remove() db.boltztrap.remove() db.counter.remove() @@ -63,7 +64,7 @@ def submit_tests(names=None, params=None): mpr = MPRester() - for name, sid in compounds.iteritems(): + for name, sid in compounds.items(): if not names or name in names: sid = mpr.get_materials_id_from_task_id("mp-{}".format(sid)) s = mpr.get_structure_by_material_id(sid, final=False) diff --git a/mpworks/snl_utils/mpsnl.py b/mpworks/snl_utils/mpsnl.py index cee62fa7..efd831b2 100644 --- a/mpworks/snl_utils/mpsnl.py +++ b/mpworks/snl_utils/mpsnl.py @@ -142,7 +142,7 @@ def as_dict(self): d['all_snl_ids'] = self.all_snl_ids d['num_snl'] = len(self.all_snl_ids) d['species_snl'] = [s.as_dict() for s in self.species_snl] - d['species_groups'] = dict([(str(k), v) for k, v in self.species_groups.iteritems()]) + d['species_groups'] = dict([(str(k), v) for k, v in self.species_groups.items()]) d['snlgroup_key'] = self.canonical_snl.snlgroup_key return d @@ -150,7 +150,7 @@ def as_dict(self): def from_dict(cls, d): sp_snl = [MPStructureNL.from_dict(s) for s in d['species_snl']] if 'species_snl' in d else None # to account for no int keys in Mongo dicts - species_groups = dict([(int(k), v) for k, v in d['species_groups'].iteritems()]) if 'species_groups' in d else None + species_groups = dict([(int(k), v) for k, v in d['species_groups'].items()]) if 'species_groups' in d else None return SNLGroup(d['snlgroup_id'], MPStructureNL.from_dict(d['canonical_snl']), d['all_snl_ids'], sp_snl, species_groups) @@ -171,19 +171,27 @@ def add_if_belongs(self, cand_snl): chemsys = '-'.join(elsyms) if ( cand_snl.structure.num_sites > 1500 or self.canonical_structure.num_sites > 1500) and chemsys == 'C-Ce': - print 'SKIPPING LARGE C-Ce' + print('SKIPPING LARGE C-Ce') return False, None # make sure the structure is not already in all_structures if cand_snl.snl_id in self.all_snl_ids: - print 'WARNING: add_if_belongs() has detected that you are trying to add the same SNL id twice!' + print('WARNING: add_if_belongs() has detected that you are trying to add the same SNL id twice!') return False, None #try a structure fit to the canonical structure - # use default Structure Matcher params from April 24, 2013, as suggested by Shyue - # we are using the ElementComparator() because this is how we want to group results - sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, + if "NMR" not in cand_snl.projects: + # use default Structure Matcher params from April 24, 2013, as suggested by Shyue + # we are using the ElementComparator() because this is how we want to group results + ltol = 0.2 + stol = 0.3 + angle_tol = 5.0 + else: + ltol = 0.00002 + stol = 0.00003 + angle_tol = 0.0005 + sm = StructureMatcher(ltol=ltol, stol=stol, angle_tol=angle_tol, primitive_cell=True, scale=True, attempt_supercell=False, comparator=ElementComparator()) if not sm.fit(cand_snl.structure, self.canonical_structure): @@ -198,8 +206,9 @@ def add_if_belongs(self, cand_snl): if has_species_properties(cand_snl.structure): for snl in self.species_snl: - sms = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, - attempt_supercell=False, comparator=SpeciesComparator()) + sms = StructureMatcher(ltol=ltol, stol=stol, angle_tol=angle_tol, primitive_cell=True, + scale=True, attempt_supercell=False, + comparator=SpeciesComparator()) if sms.fit(cand_snl.structure, snl.structure): spec_group = snl.snl_id self.species_groups[snl.snl_id].append(cand_snl.snl_id) diff --git a/mpworks/snl_utils/snl_mongo.py b/mpworks/snl_utils/snl_mongo.py index b0394566..bdc45a5a 100644 --- a/mpworks/snl_utils/snl_mongo.py +++ b/mpworks/snl_utils/snl_mongo.py @@ -28,7 +28,7 @@ def __init__(self, host='localhost', port=27017, db='snl', username=None, self.username = username self.password = password - self.connection = MongoClient(host, port, j=False) + self.connection = MongoClient(host, port, j=False, connect=False) self.database = self.connection[db] if self.username: self.database.authenticate(username, password) @@ -122,9 +122,9 @@ def add_mpsnl(self, mpsnl, force_new=False, snlgroup_guess=None): def _add_if_belongs(self, snlgroup, mpsnl, testing_mode): match_found, spec_group = snlgroup.add_if_belongs(mpsnl) if match_found: - print 'MATCH FOUND, grouping (snl_id, snlgroup): {}'.format((mpsnl.snl_id, snlgroup.snlgroup_id)) + print('MATCH FOUND, grouping (snl_id, snlgroup): {}'.format((mpsnl.snl_id, snlgroup.snlgroup_id))) if not testing_mode: - self.snlgroups.update_one({'snlgroup_id': snlgroup.snlgroup_id}, {'$set': snlgroup.as_dict()}) + self.snlgroups.update_one({'snlgroup_id': snlgroup.snlgroup_id}, {'$set': snlgroup.as_dict()}) return match_found, spec_group @@ -181,7 +181,7 @@ def lock_db(self, n_tried=0, n_max_tries=10): # DB was already locked by another process in a race condition self.lock_db(n_tried=n_tried, n_max_tries=n_max_tries) else: - raise ValueError('DB locked by another process! Could not lock even after {} minutes!'.format(n_max_tries/60)) + raise ValueError('DB locked by another process! Could not lock even after {} minutes!'.format(n_max_tries//60)) def release_lock(self): self.id_assigner.update_many({}, {'$set':{'lock': False}}) diff --git a/mpworks/submission/submission_mongo.py b/mpworks/submission/submission_mongo.py index 3cfb2523..9b87a57b 100644 --- a/mpworks/submission/submission_mongo.py +++ b/mpworks/submission/submission_mongo.py @@ -1,6 +1,7 @@ import json import os import datetime +import sys from pymongo import MongoClient, DESCENDING from mpworks.snl_utils.mpsnl import MPStructureNL @@ -34,7 +35,11 @@ def reconstitute_dates(obj_dict): if isinstance(obj_dict, list): return [reconstitute_dates(v) for v in obj_dict] - if isinstance(obj_dict, basestring): + if sys.version_info[0] > 2: + str_type = str + else: + str_type = basestring + if isinstance(obj_dict, str_type): try: return datetime.datetime.strptime(obj_dict, "%Y-%m-%dT%H:%M:%S.%f") except ValueError: @@ -73,7 +78,7 @@ def __init__(self, host='localhost', port=27017, db='snl', username=None, self.username = username self.password = password - self.connection = MongoClient(host, port, j=False) + self.connection = MongoClient(host, port, j=False, connect=False) self.database = self.connection[db] if self.username: self.database.authenticate(username, password) @@ -88,13 +93,13 @@ def _reset(self): self.jobs.remove() def _update_indices(self): - self.jobs.ensure_index('submission_id', unique=True) - self.jobs.ensure_index('state') - self.jobs.ensure_index('submitter_email') + self.jobs.create_index('submission_id', unique=True) + self.jobs.create_index('state') + self.jobs.create_index('submitter_email') def _get_next_submission_id(self): - return self.id_assigner.find_and_modify( - query={}, update={'$inc': {'next_submission_id': 1}})[ + return self.id_assigner.find_one_and_update( + filter={}, update={'$inc': {'next_submission_id': 1}})[ 'next_submission_id'] def _restart_id_assigner_at(self, next_submission_id): @@ -140,7 +145,7 @@ def resubmit(self, submission_id, snl_db=None): updates['parameters'] = self.jobs.find_one({'submission_id': submission_id}, {'parameters': 1})['parameters'] updates['parameters'].update({"mpsnl": mpsnl.as_dict(), "snlgroup_id": snlgroup_id}) - self.jobs.find_and_modify({'submission_id': submission_id}, {'$set': updates}) + self.jobs.find_one_and_update({'submission_id': submission_id}, {'$set': updates}) def cancel_submission(self, submission_id): @@ -165,8 +170,8 @@ def to_dict(self): return d def update_state(self, submission_id, state, state_details, task_dict): - self.jobs.find_and_modify({'submission_id': submission_id}, - {'$set': {'state': state, 'state_details': state_details, 'task_dict': task_dict}}) + self.jobs.find_one_and_update({'submission_id': submission_id}, + {'$set': {'state': state, 'state_details': state_details, 'task_dict': task_dict}}) @classmethod def from_dict(cls, d): diff --git a/mpworks/workflows/snl_to_wf.py b/mpworks/workflows/snl_to_wf.py index 40f00dcc..35fad742 100644 --- a/mpworks/workflows/snl_to_wf.py +++ b/mpworks/workflows/snl_to_wf.py @@ -119,7 +119,7 @@ def snl_to_wf(snl, parameters=None): # insert into DB - GGA structure optimization spec = {'task_type': 'VASP db insertion', '_priority': priority*2, - '_allow_fizzled_parents': True, '_queueadapter': QA_DB, + '_allow_fizzled_parents': True, '_queueadapter': QA_DB, "_dupefinder": DupeFinderDB().to_dict(), '_trackers': trackers_db} fws.append(Firework([VaspToDBTask()], spec, fw_id=2, name=get_slug(f + '--' + spec['task_type']))) @@ -131,7 +131,7 @@ def snl_to_wf(snl, parameters=None): if not parameters.get('skip_bandstructure', False) and \ (not ggau_compound or parameters.get('force_gga_bandstructure', False)): - spec = {'task_type': 'Controller: add Electronic Structure v2', + spec = {'task_type': 'Controller: add Electronic Structure v2', '_priority': priority, '_queueadapter': QA_CONTROL} fws.append(Firework([AddEStructureTask()], spec, fw_id=3, name=get_slug(f + '--' + spec['task_type']))) @@ -149,16 +149,16 @@ def snl_to_wf(snl, parameters=None): connections[2].append(10) spec = {'task_type': 'VASP db insertion', '_queueadapter': QA_DB, - '_allow_fizzled_parents': True, '_priority': priority, - "_dupefinder": DupeFinderDB().to_dict(), + '_allow_fizzled_parents': True, '_priority': priority, + "_dupefinder": DupeFinderDB().to_dict(), '_trackers': trackers_db} fws.append( - Firework([VaspToDBTask()], spec, + Firework([VaspToDBTask()], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=11)) connections[10] = [11] if not parameters.get('skip_bandstructure', False): - spec = {'task_type': 'Controller: add Electronic Structure v2', + spec = {'task_type': 'Controller: add Electronic Structure v2', '_priority': priority, '_queueadapter': QA_CONTROL} fws.append( Firework([AddEStructureTask()], spec, fw_id=12, diff --git a/mpworks/workflows/snl_to_wf_nmr.py b/mpworks/workflows/snl_to_wf_nmr.py new file mode 100644 index 00000000..3aa456f3 --- /dev/null +++ b/mpworks/workflows/snl_to_wf_nmr.py @@ -0,0 +1,156 @@ +import copy +from collections import defaultdict + +from fireworks import Firework +from fireworks.core.firework import Tracker, Workflow +from fireworks.utilities.fw_utilities import get_slug +from pymatgen import Composition + +from mpworks.dupefinders.dupefinder_vasp import DupeFinderDB +from mpworks.firetasks.custodian_task import get_custodian_task +from mpworks.firetasks.nmr_tasks import snl_to_nmr_spec, NmrVaspToDBTask, DictVaspSetupTask, \ + TripleJumpRelaxVaspToDBTask, ScanFunctionalSetupTask +from mpworks.firetasks.snl_tasks import AddSNLTask +from mpworks.firetasks.vasp_io_tasks import VaspWriterTask, VaspCopyTask, VaspToDBTask +from mpworks.snl_utils.mpsnl import MPStructureNL, get_meta_from_structure +from mpworks.workflows.wf_settings import QA_DB, QA_VASP + +__author__ = 'Xiaohui Qu' +__copyright__ = 'Copyright 2016, The Materials Project' +__version__ = '0.1' +__maintainer__ = 'Xiaohui Qu' +__email__ = 'xhqu1981@gmail.com' +__date__ = 'May 31, 2016' + + +""" +This is modified from Wei Chen's snl_to_wf_elastic. +""" + + +def get_nmr_vasp_fw(fwid, copy_contcar, istep, nick_name, parameters, priority, structure, additional_run_tags): + spec = snl_to_nmr_spec(structure, istep, parameters, additional_run_tags) + trackers = [Tracker('FW_job.out'), Tracker('FW_job.error'), Tracker('vasp.out'), Tracker('OUTCAR'), + Tracker('OSZICAR'), Tracker('OUTCAR.relax1'), Tracker('OUTCAR.relax2')] + spec['_priority'] = priority + spec['_queueadapter'] = QA_VASP + spec['_trackers'] = trackers + tasks = [DictVaspSetupTask()] + functional = parameters.get("functional", "PBE") + spec["functional"] = functional + if functional != "PBE": + tasks.append(ScanFunctionalSetupTask()) + tasks.append(get_custodian_task(spec)) + vasp_fw = Firework(tasks, spec, name=get_slug(nick_name + '--' + spec['task_type']), + fw_id=fwid) + return vasp_fw + + +def get_nmr_db_fw(nick_name, fwid, prev_task_type, priority, task_class): + trackers_db = [Tracker('FW_job.out'), Tracker('FW_job.error')] + spec = {'task_type': 'VASP db insertion', '_priority': priority * 2, + '_allow_fizzled_parents': True, '_queueadapter': QA_DB, "_dupefinder": DupeFinderDB().to_dict(), + '_trackers': trackers_db} + db_fw = Firework([task_class(parameters={"update_input": False})], spec, name=get_slug(nick_name + '--' + spec['task_type'] + + '--' + prev_task_type), + fw_id=fwid) + return db_fw + + +def snl_to_wf_nmr(snl, parameters): + # parameters["user_vasp_settings"] specifies user defined incar/kpoints parameters + fws = [] + connections = defaultdict(list) + cur_fwid = 0 + parameters = parameters if parameters else {} + + snl_priority = parameters.get('priority', 1) + priority = snl_priority * 2 # once we start a job, keep going! + + f = Composition(snl.structure.composition.reduced_formula).alphabetical_formula + nick_name = parameters.get("nick_name", f) + functional = parameters.get("functional", "PBE") + if functional != "PBE": + nick_name += "_FUNC_" + functional + + if 'exact_structure' in parameters and parameters['exact_structure']: + structure = snl.structure + else: + structure = snl.structure.get_primitive_structure() + + additional_run_tags = [] + # add exact structure run tag automatically if we have a unique situation + if 'exact_structure' in parameters and parameters['exact_structure'] and \ + snl.structure != structure: + additional_run_tags.append('exact_structure') + + # add the SNL to the SNL DB and figure out duplicate group + tasks = [AddSNLTask()] + spec = {'task_type': 'Add to SNL database', 'snl': snl.as_dict(), + '_queueadapter': QA_DB, '_priority': snl_priority} + if 'snlgroup_id' in parameters and isinstance(snl, MPStructureNL): + spec['force_mpsnl'] = snl.as_dict() + spec['force_snlgroup_id'] = parameters['snlgroup_id'] + del spec['snl'] + addsnl_fwid = cur_fwid + cur_fwid += 1 + fws.append(Firework(tasks, spec, + name=get_slug(nick_name + '--' + spec['task_type']), fw_id=addsnl_fwid)) + + parameters["exact_structure"] = True + # run Triple Jump Structure Relaxation to Converge to a Very Small Force + geom_calc_fwid = None + geom_db_fwid = None + for istep in [1, 2, 3]: + # Geometry Optimization + copy_contcar = istep >= 2 + geom_calc_fwid = cur_fwid + cur_fwid += 1 + vasp_fw = get_nmr_vasp_fw(geom_calc_fwid, copy_contcar, istep, nick_name, + copy.deepcopy(parameters), priority, copy.deepcopy(structure), + additional_run_tags) + fws.append(vasp_fw) + geom_task_type = vasp_fw.spec['task_type'] + if istep == 1: + connections[addsnl_fwid] = [geom_calc_fwid] + else: + prev_db_fwid = geom_db_fwid + connections[prev_db_fwid] = [geom_calc_fwid] + + # insert into DB + task_class = TripleJumpRelaxVaspToDBTask + prev_task_type = geom_task_type + geom_db_fwid = cur_fwid + cur_fwid += 1 + db_fw = get_nmr_db_fw(nick_name, geom_db_fwid, prev_task_type, priority, task_class) + fws.append(db_fw) + connections[geom_calc_fwid] = [geom_db_fwid] + + # Calculate NMR Tensors + for istep in [-1, -2]: + # -1: Chemical Shift, -2: EFG + # Geometry Optimization + nmr_calc_fwid = cur_fwid + cur_fwid += 1 + vasp_fw = get_nmr_vasp_fw(nmr_calc_fwid, True, istep, nick_name, copy.deepcopy(parameters), + priority, copy.deepcopy(structure), additional_run_tags) + fws.append(vasp_fw) + nmr_task_type = vasp_fw.spec['task_type'] + connections[geom_db_fwid].extend([nmr_calc_fwid]) + + # insert into DB + task_class = NmrVaspToDBTask + prev_task_type = nmr_task_type + nmr_db_fwid = cur_fwid + cur_fwid += 1 + db_fw = get_nmr_db_fw(nick_name, nmr_db_fwid, prev_task_type, priority, task_class) + fws.append(db_fw) + connections[nmr_calc_fwid] = [nmr_db_fwid] + + wf_meta = get_meta_from_structure(snl.structure) + wf_meta['run_version'] = 'June 2016 (1)' + + if '_materialsproject' in snl.data and 'submission_id' in snl.data['_materialsproject']: + wf_meta['submission_id'] = snl.data['_materialsproject']['submission_id'] + + return Workflow(fws, connections, name=nick_name, metadata=wf_meta) diff --git a/mpworks/workflows/surface_wf.py b/mpworks/workflows/surface_wf.py index 51038b19..16a1be8b 100644 --- a/mpworks/workflows/surface_wf.py +++ b/mpworks/workflows/surface_wf.py @@ -103,9 +103,9 @@ def __init__(self, api_key, list_of_elements=[], indices_dict=None, spa = SpacegroupAnalyzer(prim_unit_cell, symprec=symprec, angle_tolerance=angle_tolerance) conv_unit_cell = spa.get_conventional_standard_structure() - print conv_unit_cell + print(conv_unit_cell) unit_cells_dict[el] = [conv_unit_cell, min(e_per_atom)] - print el + print(el) self.api_key = api_key @@ -146,9 +146,9 @@ def from_max_index(self, max_index, max_normal_search=True, get_symmetrically_distinct_miller_indices(self.unit_cells_dict[el][0], max_index) - print 'surface ', el + print('surface ', el) - print '# ', el + print('# ', el) if max_only: for hkl in list_of_indices: @@ -310,17 +310,17 @@ def launch_workflow(self, launchpad_dir="", k_product=50, job=None, for key in self.miller_dict.keys(): # Enumerate through all compounds in the dictionary, # the key is the compositional formula of the compound - print key + print(key) for miller_index in self.miller_dict[key]: # Enumerates through all miller indices we # want to create slabs of that compound from - print str(miller_index) + print(str(miller_index)) max_norm = max(miller_index) if self.max_normal_search else None # Whether or not we want to use the # max_normal_search algorithm from surface.py - print 'true or false max norm is ', max_norm, self.max_normal_search + print('true or false max norm is ', max_norm, self.max_normal_search) slab = SlabGenerator(self.unit_cells_dict[key][0], miller_index, self.ssize, self.vsize, max_normal_search=max_norm) diff --git a/mpworks/workflows/wf_settings.py b/mpworks/workflows/wf_settings.py index 01ea9e39..242f45e8 100644 --- a/mpworks/workflows/wf_settings.py +++ b/mpworks/workflows/wf_settings.py @@ -1,3 +1,7 @@ +import os + +from monty.design_patterns import singleton + __author__ = 'Anubhav Jain' __copyright__ = 'Copyright 2013, The Materials Project' __version__ = '0.1' @@ -12,18 +16,30 @@ QA_DB = {'nnodes': 1, 'nodes' : 1, 'walltime': '2:00:00'} QA_CONTROL = {'nnodes': 1, 'nodes': 1, 'walltime': '00:30:00'} -MOVE_TO_GARDEN_DEV = False -MOVE_TO_GARDEN_PROD = False +@singleton +class WFSettings(object): + """ + This class stores settings for the Workflows. Use Singleton to enable runtime dynamic chage + """ + + def __init__(self): + self.MOVE_TO_GARDEN_DEV = False + self.MOVE_TO_GARDEN_PROD = False + if "GARDEN_LOC" in os.environ: + self.GARDEN = os.environ["GARDEN_LOC"] + else: + self.GARDEN = '/project/projectdirs/matgen/garden' -GARDEN = '/project/projectdirs/matgen/garden' + @property + def RUN_LOCS(self): + return [self.GARDEN, self.GARDEN + '/dev', + '/project/projectdirs/matgen/garden/control_blocks', + '/project/projectdirs/matgen/scratch', + '/global/scratch/sd/matcomp/', '/global/homes/m/matcomp', + '/scratch/scratchdirs/matcomp/', '/scratch2/scratchdirs/matcomp/', + '/global/scratch/sd/matcomp/aj_tests/', + '/global/scratch/sd/matcomp/wc_tests/', + '/global/scratch/sd/matcomp/aj_prod/', + '/global/scratch2/sd/matcomp/mp_prod/', + '/global/scratch2/sd/matcomp/mp_prod_hopper/'] -RUN_LOCS = [GARDEN, GARDEN+'/dev', - '/project/projectdirs/matgen/garden/control_blocks', - '/project/projectdirs/matgen/scratch', - '/global/scratch/sd/matcomp/', '/global/homes/m/matcomp', - '/scratch/scratchdirs/matcomp/', '/scratch2/scratchdirs/matcomp/', - '/global/scratch/sd/matcomp/aj_tests/', - '/global/scratch/sd/matcomp/wc_tests/', - '/global/scratch/sd/matcomp/aj_prod/', - '/global/scratch2/sd/matcomp/mp_prod/', - '/global/scratch2/sd/matcomp/mp_prod_hopper/'] diff --git a/mpworks/workflows/wf_utils.py b/mpworks/workflows/wf_utils.py index 79897a9d..237677d9 100644 --- a/mpworks/workflows/wf_utils.py +++ b/mpworks/workflows/wf_utils.py @@ -10,7 +10,7 @@ import re from monty.os.path import zpath -from mpworks.workflows.wf_settings import RUN_LOCS, GARDEN +from mpworks.workflows.wf_settings import WFSettings __author__ = 'Anubhav Jain' @@ -68,9 +68,13 @@ def get_block_part(m_dir): def get_loc(m_dir): if os.path.exists(m_dir): return m_dir + if re.match("/global/cscratch1/sd/\w+[.]new/.+", m_dir): + new_scr = m_dir.replace(".new", "") + if os.path.exists(new_scr): + return new_scr block_part = get_block_part(m_dir) - for preamble in RUN_LOCS: + for preamble in WFSettings().RUN_LOCS: new_loc = os.path.join(preamble, block_part) if os.path.exists(new_loc): return new_loc @@ -80,7 +84,7 @@ def get_loc(m_dir): def move_to_garden(m_dir, prod=False): block_part = get_block_part(m_dir) - garden_part = GARDEN if prod else GARDEN+'/dev' + garden_part = WFSettings().GARDEN if prod else WFSettings().GARDEN+'/dev' f_dir = os.path.join(garden_part, block_part) if os.path.exists(m_dir) and not os.path.exists(f_dir) and m_dir != f_dir: try: diff --git a/requirements.txt b/requirements.txt index 78067974..f7d512ed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,6 @@ monty==0.6.4 pybtex==0.18 PyYAML==3.11 requests==2.6.0 -six==1.9.0 +six==1.10.0 xmltodict==0.9.2 pymatgen>=4.0.0 diff --git a/setup.py b/setup.py index 3eb14f93..1fa73930 100644 --- a/setup.py +++ b/setup.py @@ -7,18 +7,22 @@ __email__ = "ajain@lbl.gov" __date__ = "Mar 15, 2013" -from setuptools import setup, find_packages +import os, sys + from mpworks import __version__ -import os -import multiprocessing, logging # AJ: for some reason this is needed to not have "python setup.py test" freak out +from setuptools import setup, find_packages module_dir = os.path.dirname(os.path.abspath(__file__)) if __name__ == "__main__": + if sys.version_info[0] > 2: + readme_text = open(os.path.join(module_dir, 'README.rst'), encoding="UTF-16").read() + else: + readme_text = open(os.path.join(module_dir, 'README.rst')).read() setup(name='MPWorks', version=__version__, description='Materials Project codes', - long_description=open(os.path.join(module_dir, 'README.rst')).read(), + long_description=readme_text, url='https://github.com/materialsproject/MPWorks', author='Anubhav Jain', author_email='anubhavster@gmail.com',