def test_spg_standardize(self): from matador.utils.cell_utils import standardize_doc_cell from matador.scrapers import cif2dict import glob doc, s = castep2dict(REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep") std_doc = standardize_doc_cell(doc) dist = pdf_sim_dist(doc, std_doc) self.assertLess(dist, 0.01) fnames = glob.glob(REAL_PATH + "data/bs_test/*.res") for fname in fnames: doc, s = res2dict(fname, db=False) doc["cell_volume"] = cart2volume(doc["lattice_cart"]) std_doc = standardize_doc_cell(doc) dist = pdf_sim_dist(doc, std_doc) self.assertLess(dist, 0.01) doc = Crystal( castep2dict(REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep")[0]) std_doc = standardize_doc_cell(doc) dist = pdf_sim_dist(doc, std_doc) self.assertLess(dist, 0.01) doc = Crystal(cif2dict(REAL_PATH + "data/cif_files/AgBiI.cif")[0]) with self.assertRaises(RuntimeError): std_doc = standardize_doc_cell(doc)
def testSpg(self): doc, s = castep2dict(REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep") crystal = Crystal(doc) print(crystal.get_space_group(symprec=0.01)) print(crystal.get_space_group(symprec=0.001)) self.assertEqual(crystal.get_space_group(symprec=0.0000001), "Pm")
def _scrape_single_file_structures(self, file_lists, root): """ Scrape data from one of CASTEP-like, .synth and .expt files, and push to database. Parameters: file_lists (dict): filenames and filetype counts stored by directory name key. root (str): directory name to scrape. Returns: int: number of successfully structures imported to database. """ import_count = 0 for _, file in enumerate( loading_bar(file_lists[root]['castep'], verbosity=self.verbosity)): castep_dict, success = castep2dict(file, debug=False, verbosity=self.verbosity) if not success: self.logfile.write('! {}'.format(castep_dict)) else: final_struct = castep_dict if not self.dryrun: final_struct.update(self.tag_dict) import_count += self._struct2db(final_struct) return import_count
def test_random_noise(self): """ Test that zero amplitude random noise doesn't do anything, but any other amplitude does. """ from matador.utils.cell_utils import add_noise castep_fname = REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep" test_doc, s = castep2dict(castep_fname, db=True, verbosity=VERBOSITY) init_positions_frac = test_doc["positions_frac"] test_doc = add_noise(test_doc, amplitude=0) np.testing.assert_almost_equal(init_positions_frac, test_doc["positions_frac"], decimal=10) test_doc = add_noise(test_doc, amplitude=0.1) np.testing.assert_almost_equal(init_positions_frac, test_doc["positions_frac"], decimal=1) diff = np.sqrt( np.sum( (np.asarray(init_positions_frac) - np.asarray(test_doc["positions_frac"]))**2, axis=-1, )) self.assertTrue(np.max(diff) <= 0.1) self.assertTrue(np.max(diff) >= 0)
def test_getters_setters(self): doc, s = castep2dict(REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep") crystal = Crystal(doc) self.assertEqual(list(crystal.lattice_cart[0]), [9.0397727, 0.0081202, 0.0000000]) self.assertEqual(crystal.num_atoms, 14) with self.assertRaises(AttributeError): crystal["positions_frac"] = [[0, 1, 2]] # check we can set fields to the same value crystal["new_field"] = [1, 2, 3] crystal["new_field"] = [1, 2, 3] crystal["new_field_2"] = np.nan crystal["new_field_2"] = np.nan crystal["new_field_3"] = [1, 2, 4] with self.assertRaises(AttributeError): crystal["new_field_3"] = [1, 2, 5] crystal["new_field_4"] = [1, 2, np.nan] crystal["new_field_4"] = [1, 2, np.nan] crystal["new_field_5"] = [1, np.nan, 2] with self.assertRaises(AttributeError): crystal["new_field_5"] = [1, 2, np.nan] crystal["new_field_6"] = np.linspace(0, 1, 1000).tolist() crystal["new_field_6"] = np.array(crystal["new_field_6"], copy=True).tolist()
def test_benchmark_dual_core_scf(self): """ Test the time taken to perform a set number of SCF steps on 2 cores. CASTEP prints no total timing data for single core jobs. """ from os import makedirs seed = "_LiC.res" shutil.copy(REAL_PATH + "data/structures/LiC.res", "_LiC.res") cell_dict, s = cell2dict( REAL_PATH + "/data/benchmark/LiC_scf/LiC_scf.cell", verbosity=VERBOSITY, db=False, ) self.assertTrue(s) param_dict, s = param2dict( REAL_PATH + "/data/benchmark/LiC_scf/LiC_scf.param", verbosity=VERBOSITY, db=False, ) self.assertTrue(s) shutil.copy(REAL_PATH + "data/pspots/Li_00PBE.usp", ".") shutil.copy(REAL_PATH + "data/pspots/C_00PBE.usp", ".") with self.assertRaises(CalculationError): ComputeTask( ncores=2, nnodes=None, node=None, res=seed, param_dict=param_dict, cell_dict=cell_dict, verbosity=0, executable=EXECUTABLE, start=True, ) outputs_exist = [ isfile("bad_castep/_LiC.res"), isfile("bad_castep/_LiC.castep"), ] results, s = castep2dict("bad_castep/_LiC.castep", db=False) makedirs(REAL_PATH + "/data/benchmark/results", exist_ok=True) shutil.copy( "bad_castep/_LiC.castep", REAL_PATH + "/data/benchmark/results/_LiC_2core_castep{}.castep".format( results.get("castep_version", "xxx") ), ) self.assertTrue(all(outputs_exist), "couldn't find output files!") self.assertTrue(s, "couldn't read output files!") self.assertLess(results["_time_estimated"], 8)
def test_conversion_transitivity(self): """ Test that cart2frac(frac2cart(A)) == A. """ castep_fname = REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep" test_doc, s = castep2dict(castep_fname, db=True, verbosity=VERBOSITY) lattice_cart = test_doc["lattice_cart"] positions_frac = test_doc["positions_frac"] np.testing.assert_almost_equal( cart2frac(lattice_cart, frac2cart(lattice_cart, positions_frac)), positions_frac, decimal=10, )
def test_td_hull(self): from matador.hull.hull_temperature import TemperatureDependentHull from matador.scrapers import castep2dict cursor, s = castep2dict(REAL_PATH + "data/castep_phonon_files/*.castep", db=False) td_hull = TemperatureDependentHull(cursor=cursor, energy_key="total_energy_per_atom") self.assertEqual(len(td_hull.phase_diagrams), 21)
def test_cart2abc_star(self): castep_fname = REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep" self.assertTrue(os.path.isfile(castep_fname)) test_doc, success = castep2dict(castep_fname, db=True, verbosity=VERBOSITY) self.assertTrue(success) self.assertTrue( np.allclose( real2recip(test_doc["lattice_cart"]), 2 * np.pi * np.asarray(cart2abcstar(test_doc["lattice_cart"])), ), msg="Conversion cart2abc failed.", )
def test_pseudoternary_hull_NaVSO4(self): cursor, s = castep2dict(REAL_PATH + "data/hull-NaVSO4/*.castep") print(80 * "-") self.assertEqual( len(cursor), 9, "Error with test castep files, please check installation...") hull = QueryConvexHull( cursor=cursor, elements=["Na", "V", "SO4"], chempots=[-999, -999, 100], no_plot=True, ) self.assertEqual(len(hull.cursor), 8) self.assertEqual(len(hull.hull_cursor), 6)
def test_set_positions(self): doc, s = castep2dict(REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep") doc = Crystal(doc) copydoc = copy.deepcopy(doc) old_pos = np.asarray(doc.positions_frac) copydoc.set_positions(np.zeros_like(old_pos), fractional=True) np.testing.assert_array_almost_equal( np.asarray(copydoc.positions_frac), np.zeros_like(old_pos)) np.testing.assert_array_almost_equal(np.asarray(copydoc.positions_abs), np.zeros_like(old_pos)) self.assertNotAlmostEqual(doc.positions_frac[-1][0], 0.0)
def testSites(self): doc, s = castep2dict(REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep") del doc["lattice_cart"] crystal = Crystal(doc) np.testing.assert_array_almost_equal(crystal[0].coords, [0.776467, 0.466319, 0.0]) with self.assertRaises(RuntimeError): crystal[0].set_position([0.5, 0.6, 0.7, 0.8], "fractional") with self.assertRaises(RuntimeError): crystal[0].set_position([[1, 2, 3], [4, 5, 6], [7, 8, 9]], "fractional") self.assertEqual([atom for atom in crystal], [atom[1] for atom in enumerate(crystal)]) atom = Site( species="Cl", position=[0.2, 0.5, 0.2], lattice=[[10, 0, 0], [0, 10, 0], [0, 0, 10]], ) atom2 = copy.deepcopy(atom) atom2.species = "Br" self.assertEqual(atom.species, "Cl") self.assertEqual(atom2.species, "Br") atom2.set_position([1.2, -0.5, 0.2], "fractional") np.testing.assert_array_almost_equal( atom2.displacement_between_sites(atom), [0.0, 0.0, 0.0], decimal=10) self.assertAlmostEqual(atom2.distance_between_sites(atom), 0.0, places=10) atom2.set_position([1.3, -0.5, 0.2], "fractional") np.testing.assert_array_almost_equal( atom2.displacement_between_sites(atom), [1.0, 0.0, 0.0], decimal=10) self.assertAlmostEqual(atom2.distance_between_sites(atom), 1.0, places=10) atom2.set_position([1.3, -0.5, 0.3], "fractional") np.testing.assert_array_almost_equal( atom2.displacement_between_sites(atom), [1.0, 0.0, 1.0], decimal=10) self.assertAlmostEqual(atom2.distance_between_sites(atom), np.sqrt(2), places=10)
def get_convergence_files(path, only=None): """ Find all CASTEP files in the directory. """ structure_files = defaultdict(list) files = glob.glob(path + '/*.castep') for file in files: if only is None or only in file: castep_dict, success = castep2dict(file, db=False) if not success: print('Failure to read castep file {}'.format(file)) else: source = castep_dict['source'][0].split('/')[-1] source = source.replace('.castep', '') source = ''.join(source.split('_')[:-1]) structure_files[source].append(castep_dict) return structure_files
def get_convergence_files(path, only=None): """ Find all CASTEP files in the directory. """ structure_files = defaultdict(list) files = glob.glob(path + "/*.castep") for file in files: if only is None or only in file: castep_dict, success = castep2dict(file, db=False) if not success: print("Failure to read castep file {}".format(file)) else: source = castep_dict["source"][0].split("/")[-1] source = source.replace(".castep", "") source = "".join(source.split("_")[:-1]) structure_files[source].append(castep_dict) return structure_files
def test_cart2abc(self): castep_fname = REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep" self.assertTrue(os.path.isfile(castep_fname)) test_doc, s = castep2dict(castep_fname, db=True, verbosity=VERBOSITY) try: self.assertTrue( np.allclose(test_doc["lattice_abc"], cart2abc(test_doc["lattice_cart"])), msg="Conversion cart2abc failed.", ) self.assertTrue( np.allclose( cart2abc(test_doc["lattice_cart"]), cart2abc(abc2cart(test_doc["lattice_abc"])), ), msg="Conversion abc2cart failed.", ) self.assertAlmostEqual( test_doc["cell_volume"], cart2volume(test_doc["lattice_cart"]), msg="Failed to calculate volume from lattice vectors.", places=5, ) self.assertIsInstance(test_doc["lattice_abc"], list, msg="Failed abc numpy cast to list") self.assertIsInstance( test_doc["lattice_cart"], list, msg="Failed cartesian numpy cast to list", ) cart_pos = frac2cart(test_doc["lattice_cart"], test_doc["positions_frac"]) back2frac = cart2frac(test_doc["lattice_cart"], cart_pos) np.testing.assert_array_almost_equal(back2frac, test_doc["positions_frac"]) except AssertionError: print("cart:", test_doc["lattice_cart"], abc2cart(test_doc["lattice_abc"])) print("abc:", test_doc["lattice_abc"], cart2abc(test_doc["lattice_cart"])) print( "volume:", test_doc["cell_volume"], cart2volume(test_doc["lattice_cart"]), ) raise AssertionError
def test_beef_hull(self): from matador.hull import EnsembleHull from matador.scrapers import castep2dict cursor, s = castep2dict(REAL_PATH + "data/beef_files/*.castep", db=False) beef_hull = EnsembleHull(cursor, "_beef", energy_key="total_energy_per_atom", parameter_key="thetas") self.assertEqual(len(beef_hull.phase_diagrams), 5000) self.assertEqual(len(beef_hull.cursor[0]["_beef"]["hull_distance"]), 5000) self.assertEqual(len(beef_hull.cursor[1]["_beef"]["hull_distance"]), 5000)
def test_supercell_creator(self): castep_fname = REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep" self.assertTrue(os.path.isfile(castep_fname)) num_tests = 3 test_doc, s = castep2dict(castep_fname, db=True, verbosity=VERBOSITY) _iter = 0 while _iter < num_tests: extension = np.random.randint(low=1, high=5, size=(3)).tolist() if extension == [1, 1, 1]: extension[np.random.randint(low=0, high=2)] += 1 num_images = np.prod(extension) standardize = bool(_iter % 2) symmetric = bool(_iter % 2) supercell = create_simple_supercell(test_doc, tuple(extension), standardize=standardize, symmetric=symmetric) self.assertEqual(supercell["num_atoms"], num_images * test_doc["num_atoms"]) self.assertAlmostEqual(supercell["cell_volume"], num_images * test_doc["cell_volume"], places=3) self.assertEqual( len(supercell["positions_frac"]), num_images * len(test_doc["positions_frac"]), ) for i in range(3): if not standardize: np.testing.assert_array_equal( np.asarray(supercell["lattice_cart"][i]), extension[i] * np.asarray(test_doc["lattice_cart"][i]), ) self.assertLess(pdf_sim_dist(test_doc, supercell), 1e-3) _iter += 1 # test error for 1x1x1 with self.assertRaises(RuntimeError): supercell = create_simple_supercell(test_doc, (1, 1, 1))
def test_relax_to_queue(self): """ Mimic GA and test Queue relaxations. """ newborn, s = res2dict( REAL_PATH + "/data/structures/LiAs_testcase.res", verbosity=VERBOSITY, db=False, ) assert s cell_dict, s = cell2dict(REAL_PATH + "/data/LiAs_tests/LiAs.cell", verbosity=VERBOSITY, db=False) assert s param_dict, s = param2dict(REAL_PATH + "/data/LiAs_tests/LiAs.param", verbosity=VERBOSITY, db=False) assert s node = None executable = "castep" newborn["source"] = [REAL_PATH + "/data/GA_TESTCASE.res"] shutil.copy(REAL_PATH + "data/pspots/Li_00PBE.usp", ".") shutil.copy(REAL_PATH + "data/pspots/As_00PBE.usp", ".") queue = mp.Queue() relaxer = ComputeTask( ncores=NCORES, nnodes=None, node=node, res=newborn, param_dict=param_dict, cell_dict=cell_dict, verbosity=VERBOSITY, killcheck=True, reopt=False, executable=executable, output_queue=queue, start=True, ) # store proc object with structure ID, node name, output queue and number of cores proc = (1, node, mp.Process(target=relaxer.relax), NCORES) proc[2].start() while proc[2].is_alive(): time.sleep(1) result, success = castep2dict("completed/GA_TESTCASE.castep") queue_result = queue.get() match_dict = dict() for key in queue_result: if key in ["source", "site_occupancy", "geom_iter"]: continue match_dict[key] = queue_result[key] == result[key] if not match_dict[key]: print(key, queue_result[key], result[key]) completed_exists = isfile("completed/GA_TESTCASE.res") input_exists = isfile("input/GA_TESTCASE.res") self.assertTrue(completed_exists, "couldn't find output file!") self.assertTrue(input_exists, "couldn't find shutil.copy of input file!") self.assertTrue(success, "couldn't parse output file!") self.assertTrue(all([match_dict[key] for key in match_dict]))
def test_kpt_path(self): cell, s = castep2dict(REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep") std_cell, path, seekpath_results = get_seekpath_kpoint_path( cell, spacing=0.01, debug=False) self.assertEqual(539, len(path)) self.assertLess(pdf_sim_dist(cell, std_cell), 0.05) import glob from os import remove from matador.utils.cell_utils import frac2cart fnames = glob.glob(REAL_PATH + "data/bs_test/*.res") spacing = 0.01 for fname in fnames: doc, s = res2dict(fname, db=False) doc["cell_volume"] = cart2volume(doc["lattice_cart"]) std_doc, path, seekpath_results = get_seekpath_kpoint_path( doc, spacing=spacing, debug=False) seekpath_results_path = get_path(doc2spg(doc)) rel_path = seekpath_results["explicit_kpoints_rel"] abs_path = seekpath_results["explicit_kpoints_abs"] cart_kpts = np.asarray( frac2cart(real2recip(std_doc["lattice_cart"]), path)) diffs = np.zeros((len(cart_kpts[:-1]))) np.testing.assert_array_almost_equal(cart_kpts, abs_path) np.testing.assert_array_almost_equal(path, rel_path) for ind, kpt in enumerate(cart_kpts[:-1]): diffs[ind] = np.sqrt(np.sum((kpt - cart_kpts[ind + 1])**2)) self.assertLess( len(np.where(diffs > 1.1 * spacing)[0]), len(seekpath_results["explicit_segments"]), ) if "flrys4-1x109" in fname: bs, s = bands2dict(fname.replace(".res", ".bands")) np.testing.assert_array_almost_equal(bs["kpoint_path"], rel_path) np.testing.assert_array_almost_equal(bs["lattice_cart"], std_doc["lattice_cart"]) self.assertLess( len(np.where(diffs > 1.1 * spacing)[0]), len(seekpath_results["explicit_segments"]), ) cell_path = fname.replace(".res", ".cell") doc2cell(std_doc, cell_path) new_doc, s = cell2dict(cell_path, lattice=True, positions=True, db=False) assert "positions_frac" in new_doc remove(cell_path) seekpath_new_results = get_path(doc2spg(new_doc)) self.assertEqual( seekpath_new_results["bravais_lattice_extended"], seekpath_results_path["bravais_lattice_extended"], ) dist = pdf_sim_dist(doc, std_doc) self.assertLess(dist, 0.01) dist = pdf_sim_dist(doc, new_doc) self.assertLess(dist, 0.01)
def _scrape_multi_file_results(self, file_lists, root): """ Add structures to database by parsing .res or .castep files., with DFT data scraped from .castep/.cell/.param files in the same folder, i.e. data from multiple files. Parameters: file_lists: dictionary containing counts of file types in each sub-directory. root: name of sub-directory. Returns: int: number of structures successfully imported. """ multi = False # are there multiple param/cell files? cell = False # was the cell file successfully scraped? param = False # was the param file successfully scraped? import_count = 0 # how many files have been successfully imported? success = False if file_lists[root]['param_count'] == 1: param_dict, success = param2dict(file_lists[root]['param'][0], debug=self.debug, noglob=True, verbosity=self.verbosity) param = success if not success: self.logfile.write(param_dict) elif file_lists[root]['param_count'] > 1: self.log.warning('Multiple param files found: {}'.format( file_lists[root]['param'])) multi = True if file_lists[root]['cell_count'] == 1: cell_dict, success = cell2dict(file_lists[root]['cell'][0], db=True, debug=self.debug, noglob=True, verbosity=self.verbosity) cell = success if not success: self.logfile.write(str(cell_dict)) elif file_lists[root]['cell_count'] > 1: multi = True self.log.warning('Multiple param files found: {}'.format( file_lists[root]['cell'])) if multi: found_multi = False for param_name in file_lists[root]['param']: for cell_name in file_lists[root]['cell']: if param_name.split('.')[0] in cell_name: cell_dict, success = cell2dict( cell_name, debug=self.debug, db=True, verbosity=self.verbosity) cell = success if not success: self.logfile.write(str(cell_dict)) continue param_dict, success = param2dict( param_name, debug=self.debug, verbosity=self.verbosity) param = success if not success: self.logfile.write(param_dict) if success: found_multi = True self.log.info( 'Found matching cell and param files: {}'. format(param_name)) break if not found_multi: self.log.warning( "Unable to find matching cell and param files for {}". format(root)) # combine cell and param dicts for folder input_dict = dict() if cell and param: input_dict.update(cell_dict) input_dict.update(param_dict) input_dict['source'] = cell_dict['source'] + param_dict['source'] else: self.logfile.write( '! {} failed to scrape any cell and param \n'.format(root)) # create res dicts and combine them with input_dict for _, _file in enumerate( loading_bar(file_lists[root]['res'], verbosity=self.verbosity)): exts_with_precedence = ['.castep', '.history', 'history.gz'] # check if a castep-like file exists instead of scraping res if any([ _file.replace('.res', ext) in file_lists[root]['castep'] for ext in exts_with_precedence ]): for ext in exts_with_precedence: if _file.replace('.res', ext) in file_lists[root]['castep']: struct_dict, success = castep2dict( _file.replace('.res', ext), debug=False, noglob=True, dryrun=self.args.get('dryrun'), verbosity=self.verbosity) break # otherwise, scrape res file else: struct_dict, success = res2dict(_file, verbosity=self.verbosity, noglob=True) if not success: self.logfile.write('! {}'.format(struct_dict)) else: try: final_struct = copy.deepcopy(input_dict) final_struct.update(struct_dict) # calculate kpoint spacing if not found if 'lattice_cart' not in final_struct and 'lattice_abc' not in final_struct: msg = '! {} missing lattice'.format(_file) self.logfile.write(msg) if 'kpoints_mp_spacing' not in final_struct and 'kpoints_mp_grid' in final_struct: final_struct['kpoints_mp_spacing'] = calc_mp_spacing( final_struct['lattice_cart'], final_struct['mp_grid']) final_struct['source'] = struct_dict['source'] if 'source' in input_dict: final_struct['source'] += input_dict['source'] if not self.dryrun: final_struct.update(self.tag_dict) import_count += self._struct2db(final_struct) except Exception as exc: self.log.error('Unexpected error for {}, {}'.format( _file, final_struct)) raise exc return import_count
def test_benchmark_manycore_scf(self): """ Test the time taken to perform a set number of SCF steps on many cores. """ from os import makedirs seed = "_LiC.res" shutil.copy(REAL_PATH + "data/structures/LiC.res", "_LiC.res") cell_dict, s = cell2dict( REAL_PATH + "/data/benchmark/LiC_scf/LiC_scf.cell", verbosity=VERBOSITY, db=False, ) self.assertTrue(s) param_dict, s = param2dict( REAL_PATH + "/data/benchmark/LiC_scf/LiC_scf.param", verbosity=VERBOSITY, db=False, ) self.assertTrue(s) shutil.copy(REAL_PATH + "data/pspots/Li_00PBE.usp", ".") shutil.copy(REAL_PATH + "data/pspots/C_00PBE.usp", ".") with self.assertRaises(CalculationError): ComputeTask( ncores=NCORES, nnodes=None, node=None, res=seed, param_dict=param_dict, cell_dict=cell_dict, verbosity=0, executable=EXECUTABLE, start=True, ) outputs_exist = [ isfile("bad_castep/_LiC.res"), isfile("bad_castep/_LiC.castep"), ] results, s = castep2dict("bad_castep/_LiC.castep", db=False) makedirs(REAL_PATH + "/data/benchmark/results", exist_ok=True) shutil.copy( "bad_castep/_LiC.castep", REAL_PATH + "/data/benchmark/results/_LiC_{}core_castep{}.castep".format( results.get("num_mpi_processes", 0), results.get("castep_version", "xxx"), ), ) self.assertTrue(all(outputs_exist), "couldn't find output files!") self.assertTrue(s, "couldn't read output files!") print(results["_time_estimated"]) benchmark_data = {2: 2 * 7.4, 4: 4 * 4.0, 12: 16.8, 14: 22.4, 18: 23.4} warnings.warn( RuntimeWarning( "Run took {} s with {} MPI processes, with cumulative CPU time of {:.1f} s. Benchmark data\n = {}" .format( results["_time_estimated"], results["num_mpi_processes"], results["_time_estimated"] * results["num_mpi_processes"], benchmark_data, )))