def itest_not_converged(self, lp, fworker, tmpdir, input_ebands_si_low): """ Tests the running of the NscfFWWorkflow with non convergence and restart """ input_ebands_si_low[1].set_vars(nstep=5) wf = NscfFWWorkflow(*input_ebands_si_low, autoparal=False) scf_fw_id = wf.scf_fw.fw_id nscf_fw_id = wf.nscf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] nscf_fw_id = old_new[nscf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir), nlaunches=2) nscf_fw = lp.get_fw_by_id(nscf_fw_id) assert nscf_fw.state == "COMPLETED" launch = nscf_fw.launches[-1] assert any(event.yaml_tag == NscfFWTask.CRITICAL_EVENTS[0].yaml_tag for event in launch.action.stored_data['report']) links = lp.get_wf_by_fw_id(scf_fw_id).links assert nscf_fw_id in links and len(links[nscf_fw_id]) == 1 fw_child_id = links[nscf_fw_id][0] fw_child = lp.get_fw_by_id(fw_child_id) assert fw_child.state == "READY" rapidfire(lp, fworker, m_dir=str(tmpdir)) fw_child = lp.get_fw_by_id(fw_child_id) assert fw_child.state == "COMPLETED" wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" if self.check_numerical_values: scf_task = load_abitask(lp.get_fw_by_id(scf_fw_id)) with scf_task.open_gsr() as scf_gsr: assert scf_gsr.energy == pytest.approx(-241.239839134, rel=0.01) last_nscf_task = load_abitask( get_fw_by_task_index(wf, "nscf", index=-1)) with last_nscf_task.open_gsr() as nscf_gsr: assert np.allclose((-6.2581504, 5.5974646, 5.5974646), nscf_gsr.ebands.eigens[0, 0, :3], rtol=0.1)
def itest_dte_skip_permutations(self, lp, fworker, tmpdir, input_scf_phonon_gan_low): """ Simple test of DteFWWorkflow without phonons. """ # dte calculations only work with selected values of ixc input_scf_phonon_gan_low['ixc'] = 7 dte_inputs = dte_from_gsinput(input_scf_phonon_gan_low, use_phonons=False, skip_dte_permutations=False, ph_tol={"tolvrs": 1.0e-7}, ddk_tol={"tolwfr": 1.0e-16}, dde_tol={"tolvrs": 1.0e-7}) wf = DteFWWorkflow(input_scf_phonon_gan_low, ddk_inp=dte_inputs.filter_by_tags(DDK), dde_inp=dte_inputs.filter_by_tags(DDE), dte_inp=dte_inputs.filter_by_tags(DTE), ph_inp=dte_inputs.filter_by_tags(PH_Q_PERT), autoparal=False) wf.add_anaddb_dte_fw(input_scf_phonon_gan_low.structure, dieflag=2, nlflag=3, ramansr=0, alphon=0, prtmbm=0) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" if self.check_numerical_values: scf_task = load_abitask(get_fw_by_task_index(wf, "scf", index=1)) with scf_task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-680.402255069, rel=0.005) ana_task = load_abitask( get_fw_by_task_index(wf, "anaddb", index=None)) with ana_task.open_anaddbnc() as ananc: assert float(ananc.dchide[0, 0, 2]) == pytest.approx(-1.69328765210, rel=0.15)
def itest_input_wf(self, lp, fworker, tmpdir, input_scf_si_low, use_autoparal): """ Tests a simple scf run with the InputFWWorkflow """ wf = InputFWWorkflow(input_scf_si_low, task_type=ScfFWTask, autoparal=use_autoparal) scf_fw_id = wf.fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) fw = lp.get_fw_by_id(scf_fw_id) assert fw.state == "COMPLETED" wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" assert len(wf.leaf_fw_ids) == 1 if self.check_numerical_values: task = load_abitask(lp.get_fw_by_id(wf.leaf_fw_ids[0])) with task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-241.239839134, rel=0.05)
def itest_scf_wf(self, lp, fworker, tmpdir, input_scf_si_low, use_autoparal): """ Tests a simple scf run with the ScfFWWorkflow """ wf = ScfFWWorkflow(input_scf_si_low, autoparal=use_autoparal) wf.add_final_cleanup(["WFK"]) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) fw = lp.get_fw_by_id(scf_fw_id) assert fw.state == "COMPLETED" wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" # check the effect of the final cleanup scf_task = load_abitask(get_fw_by_task_index(wf, "scf", index=1)) assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_WFK"))) == 0 assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_DEN"))) == 1 assert len(glob.glob(os.path.join(scf_task.tmpdir.path, "*"))) == 0 assert len(glob.glob(os.path.join(scf_task.indir.path, "*"))) == 0 if self.check_numerical_values: with scf_task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-241.239839134, rel=0.05)
def itest_uncoverged(self, lp, fworker, tmpdir, inputs_relax_si_low): """ Testing restart when the ionic convercence is not reached """ inputs_relax_si_low[0]['ntime']=3 wf = RelaxFWWorkflow(*inputs_relax_si_low, autoparal=False) initial_ion_structure = inputs_relax_si_low[0].structure ion_fw_id = wf.ion_fw.fw_id ioncell_fw_id = wf.ioncell_fw.fw_id old_new = wf.add_to_db(lpad=lp) ion_fw_id = old_new[ion_fw_id] ioncell_fw_id = old_new[ioncell_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir), nlaunches=1) ion_fw = lp.get_fw_by_id(ion_fw_id) ioncell_fw = lp.get_fw_by_id(ioncell_fw_id) assert ion_fw.state == "COMPLETED" assert ioncell_fw.state == "WAITING" launch = ion_fw.launches[-1] assert any(event.yaml_tag == RelaxFWTask.CRITICAL_EVENTS[0].yaml_tag for event in launch.action.stored_data['report']) links_ion = lp.get_wf_by_fw_id(ion_fw_id).links[ion_fw_id] # there should be an additional child (the detour) assert len(links_ion) == 2 links_ion.remove(ioncell_fw_id) fw_detour_id = links_ion[0] # run the detour rapidfire(lp, fworker, m_dir=str(tmpdir)) fw_detour = lp.get_fw_by_id(fw_detour_id) assert fw_detour.state == "COMPLETED" restart_structure = fw_detour.spec['_tasks'][0].abiinput.structure wf = lp.get_wf_by_fw_id(ion_fw_id) assert wf.state == "COMPLETED" # check that the structure has been updated when restarting assert initial_ion_structure != restart_structure if self.check_numerical_values: last_ioncell_task = load_abitask(get_fw_by_task_index(wf, "ioncell", index=-1)) with last_ioncell_task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-240.28203726305696, rel=0.01) assert gsr.structure.lattice.abc == pytest.approx( np.array((3.8101428225862084, 3.810143911539674, 3.8101432797789698)), rel=0.05)
def itest_nscf_wf(self, lp, fworker, tmpdir, input_ebands_si_low, use_autoparal): """ Simple test of NscfFWWorkflow with autoparal True and False. """ wf = NscfFWWorkflow(*input_ebands_si_low, autoparal=False) wf.add_final_cleanup(["WFK"]) scf_fw_id = wf.scf_fw.fw_id nscf_fw_id = wf.nscf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] nscf_fw_id = old_new[nscf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" # check the effect of the final cleanup scf_task = load_abitask(get_fw_by_task_index(wf, "scf", index=1)) assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_WFK"))) == 0 assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_DEN"))) == 1 assert len(glob.glob(os.path.join(scf_task.tmpdir.path, "*"))) == 0 assert len(glob.glob(os.path.join(scf_task.indir.path, "*"))) == 0 if self.check_numerical_values: scf_task = load_abitask(lp.get_fw_by_id(scf_fw_id)) with scf_task.open_gsr() as scf_gsr: assert scf_gsr.energy == pytest.approx(-241.239839134, rel=0.01) nscf_task = load_abitask(lp.get_fw_by_id(nscf_fw_id)) with nscf_task.open_gsr() as nscf_gsr: assert np.allclose((-6.2581504, 5.5974646, 5.5974646), nscf_gsr.ebands.eigens[0, 0, :3], rtol=0.1)
def itest_dfpt_anaddb_dte(self, lp, fworker, tmpdir, input_scf_phonon_gan_low, db_data): """ Simple test of DteFWWorkflow with dte. Does not run anaddb due to problems when dealing with DDB file containing 3rd order derivatives and other terms. """ # dte calculations only work with selected values of ixc input_scf_phonon_gan_low['ixc'] = 7 dfpt_inputs = dfpt_from_gsinput(input_scf_phonon_gan_low, ph_ngqpt=[1, 1, 1], do_ddk=True, do_dde=True, do_strain=False, do_dte=True, skip_dte_permutations=True, ddk_tol={"tolwfr": 1.0e-16}, dde_tol={"tolvrs": 1.0e-7}, strain_tol={"tolvrs": 1.0e-7}, ph_tol={"tolvrs": 1.0e-7}) wf = DfptFWWorkflow(input_scf_phonon_gan_low, ddk_inp=dfpt_inputs.filter_by_tags(DDK), dde_inp=dfpt_inputs.filter_by_tags(DDE), strain_inp=dfpt_inputs.filter_by_tags(STRAIN), ph_inp=dfpt_inputs.filter_by_tags(PH_Q_PERT), dte_inp=dfpt_inputs.filter_by_tags(DTE), nscf_inp=dfpt_inputs.filter_by_tags(NSCF), initialization_info={"kppa": 100}, autoparal=False) wf.add_anaddb_dfpt_fw(input_scf_phonon_gan_low.structure) wf.add_mongoengine_db_insertion(db_data) wf.add_final_cleanup(additional_spec={"test_spec": 1}) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" if self.check_numerical_values: ana_task = load_abitask( get_fw_by_task_index(wf, "anaddb", index=None)) with ana_task.open_anaddbnc() as ananc: assert float(ananc.dchide[0, 0, 2]) == pytest.approx(-1.69328765210, rel=0.15)
def itest_dfpt_full(self, lp, fworker, tmpdir, input_scf_phonon_gan_low, use_autoparal, db_data): """ Simple test of DteFWWorkflow with autoparal True and False. Doesn't run anaddb since anaddb does not support a DDB with third order perturbations along with other perturbations. Skips dte permutations. """ # dte calculations only work with selected values of ixc input_scf_phonon_gan_low['ixc'] = 7 dfpt_inputs = dfpt_from_gsinput(input_scf_phonon_gan_low, ph_ngqpt=[2, 2, 2], do_ddk=True, do_dde=True, do_strain=True, do_dte=True, skip_dte_permutations=True, ddk_tol={"tolwfr": 1.0e-16}, dde_tol={"tolvrs": 1.0e-7}, strain_tol={"tolvrs": 1.0e-7}, ph_tol={"tolvrs": 1.0e-7}) wf = DfptFWWorkflow(input_scf_phonon_gan_low, ddk_inp=dfpt_inputs.filter_by_tags(DDK), dde_inp=dfpt_inputs.filter_by_tags(DDE), strain_inp=dfpt_inputs.filter_by_tags(STRAIN), ph_inp=dfpt_inputs.filter_by_tags(PH_Q_PERT), dte_inp=dfpt_inputs.filter_by_tags(DTE), nscf_inp=dfpt_inputs.filter_by_tags(NSCF), initialization_info={"kppa": 100}, autoparal=use_autoparal) wf.add_mongoengine_db_insertion(db_data) wf.add_final_cleanup(["WFK"]) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" # check the effect of the final cleanup scf_task = load_abitask(get_fw_by_task_index(wf, "scf", index=1)) assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_WFK"))) == 0 assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_DEN"))) == 1 assert len(glob.glob(os.path.join(scf_task.tmpdir.path, "*"))) == 0 assert len(glob.glob(os.path.join(scf_task.indir.path, "*"))) == 0
def itest_not_converged(self, lp, fworker, tmpdir, input_scf_si_low): """ Tests the ScfFWWorkflow with a calculation that does not converge on the first run. The calculation is continued until convergence is reached """ input_scf_si_low.set_vars(nstep=3) wf = ScfFWWorkflow(input_scf_si_low, autoparal=False) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir), nlaunches=1) fw = lp.get_fw_by_id(scf_fw_id) assert fw.state == "COMPLETED" launch = fw.launches[-1] assert any(event.yaml_tag == ScfFWTask.CRITICAL_EVENTS[0].yaml_tag for event in launch.action.stored_data['report']) links = lp.get_wf_by_fw_id(scf_fw_id).links assert scf_fw_id in links and len(links[scf_fw_id]) == 1 fw_child_id = links[scf_fw_id][0] fw_child = lp.get_fw_by_id(fw_child_id) assert fw_child.state == "READY" # run all the workflow to check that the calculation converged rapidfire(lp, fworker, m_dir=str(tmpdir)) fw_child = lp.get_fw_by_id(fw_child_id) assert fw_child.state == "COMPLETED" wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" if self.check_numerical_values: task = load_abitask(lp.get_fw_by_id(wf.leaf_fw_ids[0])) with task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-241.239839133, rel=0.05)
def itest_dte_skip_permutations(self, lp, fworker, tmpdir, input_scf_phonon_gan_low): """ Simple test of DteFWWorkflow without phonons. """ # dte calculations only work with selected values of ixc input_scf_phonon_gan_low['ixc'] = 7 dte_inputs = dte_from_gsinput(input_scf_phonon_gan_low, use_phonons=False, skip_dte_permutations=False, ph_tol={"tolvrs": 1.0e-7}, ddk_tol = {"tolwfr": 1.0e-16}, dde_tol = {"tolvrs": 1.0e-7}, dte_tol = {"tolwfr": 1.0e-16}) wf = DteFWWorkflow(input_scf_phonon_gan_low, ddk_inp = dte_inputs.filter_by_tags(DDK), dde_inp = dte_inputs.filter_by_tags(DDE), dte_inp = dte_inputs.filter_by_tags(DTE), ph_inp = dte_inputs.filter_by_tags(PH_Q_PERT), autoparal=False) wf.add_anaddb_dte_fw(input_scf_phonon_gan_low.structure, dieflag=2, nlflag=3, ramansr=0, alphon=0, prtmbm=0) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" if self.check_numerical_values: scf_task = load_abitask(get_fw_by_task_index(wf, "scf", index=1)) with scf_task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-680.402255069, rel=0.005) ana_task = load_abitask(get_fw_by_task_index(wf, "anaddb", index=None)) with ana_task.open_anaddbnc() as ananc: assert float(ananc.dchide[0,0,2]) == pytest.approx(-1.69328765210, rel=0.15)
def itest_dfpt_full(self, lp, fworker, tmpdir, input_scf_phonon_gan_low, use_autoparal, db_data): """ Simple test of DteFWWorkflow with autoparal True and False. Doesn't run anaddb since anaddb does not support a DDB with third order perturbations along with other perturbations. Skips dte permutations. """ # dte calculations only work with selected values of ixc input_scf_phonon_gan_low['ixc'] = 7 dfpt_inputs = dfpt_from_gsinput(input_scf_phonon_gan_low, ph_ngqpt=[2, 2, 2], do_ddk=True, do_dde=True, do_strain=True, do_dte=True, skip_dte_permutations=True, ddk_tol = {"tolwfr": 1.0e-16}, dde_tol = {"tolvrs": 1.0e-7}, strain_tol={"tolvrs": 1.0e-7}, ph_tol={"tolvrs": 1.0e-7}) wf = DfptFWWorkflow(input_scf_phonon_gan_low, ddk_inp = dfpt_inputs.filter_by_tags(DDK), dde_inp = dfpt_inputs.filter_by_tags(DDE), strain_inp=dfpt_inputs.filter_by_tags(STRAIN), ph_inp = dfpt_inputs.filter_by_tags(PH_Q_PERT), dte_inp = dfpt_inputs.filter_by_tags(DTE), nscf_inp=dfpt_inputs.filter_by_tags(NSCF),initialization_info={"kppa": 100}, autoparal=use_autoparal) wf.add_mongoengine_db_insertion(db_data) wf.add_final_cleanup(["WFK"]) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" # check the effect of the final cleanup scf_task = load_abitask(get_fw_by_task_index(wf, "scf", index=1)) assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_WFK"))) == 0 assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_DEN"))) == 1 assert len(glob.glob(os.path.join(scf_task.tmpdir.path, "*"))) == 0 assert len(glob.glob(os.path.join(scf_task.indir.path, "*"))) == 0
def itest_dfpt_anaddb_dte(self, lp, fworker, tmpdir, input_scf_phonon_gan_low, db_data): """ Simple test of DteFWWorkflow with dte. Does not run anaddb due to problems when dealing with DDB file containing 3rd order derivatives and other terms. """ # dte calculations only work with selected values of ixc input_scf_phonon_gan_low['ixc'] = 7 dfpt_inputs = dfpt_from_gsinput(input_scf_phonon_gan_low, ph_ngqpt=[1,1,1], do_ddk=True, do_dde=True, do_strain=False, do_dte=True, skip_dte_permutations=True, ddk_tol = {"tolwfr": 1.0e-16}, dde_tol = {"tolvrs": 1.0e-7}, strain_tol={"tolvrs": 1.0e-7}, ph_tol={"tolvrs": 1.0e-7}) wf = DfptFWWorkflow(input_scf_phonon_gan_low, ddk_inp = dfpt_inputs.filter_by_tags(DDK), dde_inp = dfpt_inputs.filter_by_tags(DDE), strain_inp=dfpt_inputs.filter_by_tags(STRAIN), ph_inp = dfpt_inputs.filter_by_tags(PH_Q_PERT), dte_inp = dfpt_inputs.filter_by_tags(DTE), nscf_inp=dfpt_inputs.filter_by_tags(NSCF),initialization_info={"kppa": 100}, autoparal=False) wf.add_anaddb_dfpt_fw(input_scf_phonon_gan_low.structure) wf.add_mongoengine_db_insertion(db_data) wf.add_final_cleanup(additional_spec={"test_spec":1}) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" if self.check_numerical_values: ana_task = load_abitask(get_fw_by_task_index(wf, "anaddb", index=None)) with ana_task.open_anaddbnc() as ananc: assert float(ananc.dchide[0,0,2]) == pytest.approx(-1.69328765210, rel=0.15)
def itest_phonon_wf(self, lp, fworker, tmpdir, input_scf_phonon_si_low, use_autoparal, db_data): """ Tests the complete running of PhononFullFWWorkflow and PhononFWWorkflow """ # test at gamma. ph_fac = PhononsFromGsFactory(qpoints=[[0, 0, 0]], ph_tol={"tolvrs": 1.0e-7}, ddk_tol={"tolwfr": 1.0e-16}, dde_tol={"tolvrs": 1.0e-7}, wfq_tol={"tolwfr": 1.0e-16}) # first run the phonon workflow with generation task wf_gen = PhononFWWorkflow(input_scf_phonon_si_low, ph_fac, autoparal=use_autoparal, initialization_info={ "ngqpt": [1, 1, 1], "kppa": 100 }) wf_gen.add_anaddb_ph_bs_fw(input_scf_phonon_si_low.structure, ph_ngqpt=[1, 1, 1], ndivsm=2, nqsmall=2) wf_gen.add_mongoengine_db_insertion(db_data) wf_gen.add_final_cleanup(["WFK"]) scf_id = wf_gen.scf_fw.fw_id ph_generation_fw_id = wf_gen.ph_generation_fw.fw_id old_new = wf_gen.add_to_db(lpad=lp) scf_id = old_new[scf_id] ph_generation_fw_id = old_new[ph_generation_fw_id] # run all the workflow rapidfire(lp, fworker, m_dir=str(tmpdir)) wf_gen = lp.get_wf_by_fw_id(scf_id) assert wf_gen.state == "COMPLETED" ph_task = load_abitask( get_fw_by_task_index(wf_gen, "phonon_0", index=-1)) # check the effect of the final cleanup assert len(glob.glob(os.path.join(ph_task.outdir.path, "*_WFK"))) == 0 assert len(glob.glob(os.path.join(ph_task.outdir.path, "*_DEN1"))) > 0 assert len(glob.glob(os.path.join(ph_task.tmpdir.path, "*"))) == 0 assert len(glob.glob(os.path.join(ph_task.indir.path, "*"))) == 0 # check the save in the DB from abiflows.database.mongoengine.abinit_results import PhononResult with db_data.switch_collection(PhononResult) as PhononResult: results = PhononResult.objects() assert len(results) == 1 r = results[0] assert r.abinit_input.structure.to_mgobj( ) == input_scf_phonon_si_low.structure assert r.abinit_output.structure.to_mgobj( ) == input_scf_phonon_si_low.structure assert r.abinit_input.ecut == input_scf_phonon_si_low['ecut'] assert r.abinit_input.kppa == 100 nptu.assert_array_equal( r.abinit_input.gs_input.to_mgobj()['ngkpt'], input_scf_phonon_si_low['ngkpt']) nptu.assert_array_equal(r.abinit_input.ngqpt, [1, 1, 1]) ana_task = load_abitask( get_fw_by_task_index(wf_gen, "anaddb", index=None)) with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.phonon_bs.read()) db_file.seek(0) assert filecmp.cmp(ana_task.phbst_path, db_file.name) mrgddb_task = load_abitask( get_fw_by_task_index(wf_gen, "mrgddb", index=None)) # read/write in binary for py3k compatibility with mongoengine with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.ddb.read()) db_file.seek(0) assert filecmp.cmp(mrgddb_task.merged_ddb_path, db_file.name) # then rerun a similar workflow, but completely generated at its creation wf_full = PhononFullFWWorkflow(input_scf_phonon_si_low, ph_fac, autoparal=use_autoparal) wf_full.add_anaddb_ph_bs_fw(input_scf_phonon_si_low.structure, ph_ngqpt=[1, 1, 1], ndivsm=2, nqsmall=2) wf_full.add_mongoengine_db_insertion(db_data) scf_id = wf_full.scf_fw.fw_id old_new = wf_full.add_to_db(lpad=lp) scf_id = old_new[scf_id] # run all the workflow rapidfire(lp, fworker, m_dir=str(tmpdir)) wf_full = lp.get_wf_by_fw_id(scf_id) assert wf_full.state == "COMPLETED" # the full workflow doesn't contain the generation FW and the cleanup tasks, but should have the same # amount of perturbations. if use_autoparal: diff = 1 else: diff = 2 assert len(wf_full.id_fw) + diff == len(wf_gen.id_fw) if self.check_numerical_values: gen_scf_task = load_abitask( get_fw_by_task_index(wf_gen, "scf", index=-1)) with gen_scf_task.open_gsr() as gen_gsr: gen_energy = gen_gsr.energy assert gen_energy == pytest.approx(-240.264972012, rel=0.01) gen_ana_task = load_abitask( get_fw_by_task_index(wf_gen, "anaddb", index=None)) with gen_ana_task.open_phbst() as gen_phbst: gen_phfreq = gen_phbst.phbands.phfreqs[0, 3] assert gen_phfreq == pytest.approx(0.06029885, rel=0.1) full_scf_task = load_abitask( get_fw_by_task_index(wf_gen, "scf", index=-1)) with full_scf_task.open_gsr() as full_gsr: full_energy = full_gsr.energy assert full_energy == pytest.approx(-240.264972012, rel=0.01) full_ana_task = load_abitask( get_fw_by_task_index(wf_gen, "anaddb", index=None)) with full_ana_task.open_phbst() as full_phbst: full_phfreqs = full_phbst.phbands.phfreqs[0, 3] assert full_phfreqs == pytest.approx(0.06029885, rel=0.1) assert gen_energy == pytest.approx(full_energy, rel=1e-6) assert gen_phfreq == pytest.approx(full_phfreqs, rel=1e-6)
def itest_phonon_wf(self, lp, fworker, tmpdir, input_scf_phonon_si_low, use_autoparal, db_data): """ Tests the complete running of PhononFullFWWorkflow and PhononFWWorkflow """ # test at gamma. Pass a custom manager, to check proper serialization manager_path = os.path.join(abidata.dirpath, 'managers', "travis_manager.yml") ph_fac = PhononsFromGsFactory(qpoints=[[0,0,0]], ph_tol = {"tolvrs": 1.0e-7}, ddk_tol = {"tolwfr": 1.0e-16}, dde_tol = {"tolvrs": 1.0e-7}, wfq_tol = {"tolwfr": 1.0e-16}, manager=TaskManager.from_file(manager_path)) # first run the phonon workflow with generation task wf_gen = PhononFWWorkflow(input_scf_phonon_si_low, ph_fac, autoparal=use_autoparal, initialization_info={"ngqpt": [1,1,1], "kppa": 100}) wf_gen.add_anaddb_ph_bs_fw(input_scf_phonon_si_low.structure, ph_ngqpt=[1,1,1], ndivsm=2, nqsmall=2) wf_gen.add_mongoengine_db_insertion(db_data) wf_gen.add_final_cleanup(["WFK"]) scf_id = wf_gen.scf_fw.fw_id ph_generation_fw_id = wf_gen.ph_generation_fw.fw_id old_new = wf_gen.add_to_db(lpad=lp) scf_id = old_new[scf_id] ph_generation_fw_id = old_new[ph_generation_fw_id] # run all the workflow rapidfire(lp, fworker, m_dir=str(tmpdir)) wf_gen = lp.get_wf_by_fw_id(scf_id) assert wf_gen.state == "COMPLETED" ph_task = load_abitask(get_fw_by_task_index(wf_gen, "phonon_0", index=-1)) # check the effect of the final cleanup assert len(glob.glob(os.path.join(ph_task.outdir.path, "*_WFK"))) == 0 assert len(glob.glob(os.path.join(ph_task.outdir.path, "*_DEN1"))) > 0 assert len(glob.glob(os.path.join(ph_task.tmpdir.path, "*"))) == 0 assert len(glob.glob(os.path.join(ph_task.indir.path, "*"))) == 0 # check the save in the DB from abiflows.database.mongoengine.abinit_results import PhononResult with db_data.switch_collection(PhononResult) as PhononResult: results = PhononResult.objects() assert len(results) == 1 r = results[0] assert r.abinit_input.structure.to_mgobj() == input_scf_phonon_si_low.structure assert r.abinit_output.structure.to_mgobj() == input_scf_phonon_si_low.structure assert r.abinit_input.ecut == input_scf_phonon_si_low['ecut'] assert r.abinit_input.kppa == 100 nptu.assert_array_equal(r.abinit_input.gs_input.to_mgobj()['ngkpt'], input_scf_phonon_si_low['ngkpt']) nptu.assert_array_equal(r.abinit_input.ngqpt, [1,1,1]) ana_task = load_abitask(get_fw_by_task_index(wf_gen, "anaddb", index=None)) with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.phonon_bs.read()) db_file.seek(0) assert filecmp.cmp(ana_task.phbst_path, db_file.name) mrgddb_task = load_abitask(get_fw_by_task_index(wf_gen, "mrgddb", index=None)) # read/write in binary for py3k compatibility with mongoengine with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.ddb.read()) db_file.seek(0) assert filecmp.cmp(mrgddb_task.merged_ddb_path, db_file.name) # then rerun a similar workflow, but completely generated at its creation wf_full = PhononFullFWWorkflow(input_scf_phonon_si_low, ph_fac, autoparal=use_autoparal) wf_full.add_anaddb_ph_bs_fw(input_scf_phonon_si_low.structure, ph_ngqpt=[1,1,1], ndivsm=2, nqsmall=2) wf_full.add_mongoengine_db_insertion(db_data) scf_id = wf_full.scf_fw.fw_id old_new = wf_full.add_to_db(lpad=lp) scf_id = old_new[scf_id] # run all the workflow rapidfire(lp, fworker, m_dir=str(tmpdir)) wf_full = lp.get_wf_by_fw_id(scf_id) assert wf_full.state == "COMPLETED" # the full workflow doesn't contain the generation FW and the cleanup tasks, but should have the same # amount of perturbations. if use_autoparal: diff = 1 else: diff = 2 assert len(wf_full.id_fw) + diff == len(wf_gen.id_fw) if self.check_numerical_values: gen_scf_task = load_abitask(get_fw_by_task_index(wf_gen, "scf", index=-1)) with gen_scf_task.open_gsr() as gen_gsr: gen_energy = gen_gsr.energy assert gen_energy == pytest.approx(-240.264972012, rel=0.01) gen_ana_task = load_abitask(get_fw_by_task_index(wf_gen, "anaddb", index=None)) with gen_ana_task.open_phbst() as gen_phbst: gen_phfreq = gen_phbst.phbands.phfreqs[0, 3] assert gen_phfreq == pytest.approx(0.06029885, rel=0.1) full_scf_task = load_abitask(get_fw_by_task_index(wf_gen, "scf", index=-1)) with full_scf_task.open_gsr() as full_gsr: full_energy = full_gsr.energy assert full_energy == pytest.approx(-240.264972012, rel=0.01) full_ana_task = load_abitask(get_fw_by_task_index(wf_gen, "anaddb", index=None)) with full_ana_task.open_phbst() as full_phbst: full_phfreqs = full_phbst.phbands.phfreqs[0, 3] assert full_phfreqs == pytest.approx(0.06029885, rel=0.1) assert gen_energy == pytest.approx(full_energy, rel=1e-6) assert gen_phfreq == pytest.approx(full_phfreqs, rel=1e-6)
def itest_dte_with_phonons(self, lp, fworker, tmpdir, input_scf_phonon_gan_low, use_autoparal, db_data): """ Simple test of DteFWWorkflow with autoparal True and False. Skips dte permutations. """ # dte calculations only work with selected values of ixc input_scf_phonon_gan_low['ixc'] = 7 dte_inputs = dte_from_gsinput(input_scf_phonon_gan_low, use_phonons=True, skip_dte_permutations=True, ph_tol={"tolvrs": 1.0e-7}, ddk_tol={"tolwfr": 1.0e-16}, dde_tol={"tolvrs": 1.0e-7}) wf = DteFWWorkflow(input_scf_phonon_gan_low, ddk_inp=dte_inputs.filter_by_tags(DDK), dde_inp=dte_inputs.filter_by_tags(DDE), dte_inp=dte_inputs.filter_by_tags(DTE), ph_inp=dte_inputs.filter_by_tags(PH_Q_PERT), autoparal=use_autoparal, initialization_info={"kppa": 100}) wf.add_anaddb_dte_fw(input_scf_phonon_gan_low.structure, dieflag=1, nlflag=1) wf.add_mongoengine_db_insertion(db_data) wf.add_final_cleanup(["WFK"]) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" # check the effect of the final cleanup scf_task = load_abitask(get_fw_by_task_index(wf, "scf", index=1)) assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_WFK"))) == 0 assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_DEN"))) == 1 assert len(glob.glob(os.path.join(scf_task.tmpdir.path, "*"))) == 0 assert len(glob.glob(os.path.join(scf_task.indir.path, "*"))) == 0 # check the save in the DB from abiflows.database.mongoengine.abinit_results import DteResult with db_data.switch_collection(DteResult) as DteResult: results = DteResult.objects() assert len(results) == 1 r = results[0] assert r.abinit_input.structure.to_mgobj( ) == input_scf_phonon_gan_low.structure assert r.abinit_output.structure.to_mgobj( ) == input_scf_phonon_gan_low.structure assert r.abinit_input.ecut == input_scf_phonon_gan_low['ecut'] assert r.abinit_input.kppa == 100 nptu.assert_array_equal( r.abinit_input.gs_input.to_mgobj()['ngkpt'], input_scf_phonon_gan_low['ngkpt']) ana_task = load_abitask( get_fw_by_task_index(wf, "anaddb", index=None)) with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.anaddb_nc.read()) db_file.seek(0) assert filecmp.cmp(ana_task.anaddb_nc_path, db_file.name) mrgddb_task = load_abitask( get_fw_by_task_index(wf, "mrgddb", index=None)) with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.ddb.read()) db_file.seek(0) assert filecmp.cmp(mrgddb_task.merged_ddb_path, db_file.name) if self.check_numerical_values: with scf_task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-680.402255069, rel=0.005) ana_task = load_abitask( get_fw_by_task_index(wf, "anaddb", index=None)) with ana_task.open_anaddbnc() as ananc: assert float(ananc.dchide[0, 0, 2]) == pytest.approx(-1.69328765210, rel=0.15)
def itest_dte_with_phonons(self, lp, fworker, tmpdir, input_scf_phonon_gan_low, use_autoparal, db_data): """ Simple test of DteFWWorkflow with autoparal True and False. Skips dte permutations. """ # dte calculations only work with selected values of ixc input_scf_phonon_gan_low['ixc'] = 7 dte_inputs = dte_from_gsinput(input_scf_phonon_gan_low, use_phonons=True, skip_dte_permutations=True, ph_tol={"tolvrs": 1.0e-7}, ddk_tol = {"tolwfr": 1.0e-16}, dde_tol = {"tolvrs": 1.0e-7}, dte_tol = {"tolwfr": 1.0e-15}) wf = DteFWWorkflow(input_scf_phonon_gan_low, ddk_inp = dte_inputs.filter_by_tags(DDK), dde_inp = dte_inputs.filter_by_tags(DDE), dte_inp = dte_inputs.filter_by_tags(DTE), ph_inp = dte_inputs.filter_by_tags(PH_Q_PERT), autoparal=False, initialization_info={"kppa": 100}) wf.add_anaddb_dte_fw(input_scf_phonon_gan_low.structure, dieflag=1, nlflag=1) wf.add_mongoengine_db_insertion(db_data) wf.add_final_cleanup(["WFK"]) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" # check the effect of the final cleanup scf_task = load_abitask(get_fw_by_task_index(wf, "scf", index=1)) assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_WFK"))) == 0 assert len(glob.glob(os.path.join(scf_task.outdir.path, "*_DEN"))) == 1 assert len(glob.glob(os.path.join(scf_task.tmpdir.path, "*"))) == 0 assert len(glob.glob(os.path.join(scf_task.indir.path, "*"))) == 0 # check the save in the DB from abiflows.database.mongoengine.abinit_results import DteResult with db_data.switch_collection(DteResult) as DteResult: results = DteResult.objects() assert len(results) == 1 r = results[0] assert r.abinit_input.structure.to_mgobj() == input_scf_phonon_gan_low.structure assert r.abinit_output.structure.to_mgobj() == input_scf_phonon_gan_low.structure assert r.abinit_input.ecut == input_scf_phonon_gan_low['ecut'] assert r.abinit_input.kppa == 100 nptu.assert_array_equal(r.abinit_input.gs_input.to_mgobj()['ngkpt'], input_scf_phonon_gan_low['ngkpt']) ana_task = load_abitask(get_fw_by_task_index(wf, "anaddb", index=None)) with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.anaddb_nc.read()) db_file.seek(0) assert filecmp.cmp(ana_task.anaddb_nc_path, db_file.name) mrgddb_task = load_abitask(get_fw_by_task_index(wf, "mrgddb", index=None)) with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.ddb.read()) db_file.seek(0) assert filecmp.cmp(mrgddb_task.merged_ddb_path, db_file.name) if self.check_numerical_values: with scf_task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-680.402255069, rel=0.005) ana_task = load_abitask(get_fw_by_task_index(wf, "anaddb", index=None)) with ana_task.open_anaddbnc() as ananc: assert float(ananc.dchide[0,0,2]) == pytest.approx(-1.69328765210, rel=0.15)
def itest_dilatmx(self, lp, fworker, tmpdir, inputs_relax_si_low): """ Test the workflow with a target dilatmx """ # set the dilatmx to 1.05 to keep the change independt on the generation of the input inputs_relax_si_low[1]['dilatmx'] = 1.05 wf = RelaxFWWorkflow(*inputs_relax_si_low, autoparal=False, target_dilatmx=1.03) initial_ion_structure = inputs_relax_si_low[0].structure ion_fw_id = wf.ion_fw.fw_id ioncell_fw_id = wf.ioncell_fw.fw_id old_new = wf.add_to_db(lpad=lp) ion_fw_id = old_new[ion_fw_id] ioncell_fw_id = old_new[ioncell_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir), nlaunches=2) ion_fw = lp.get_fw_by_id(ion_fw_id) ioncell_fw = lp.get_fw_by_id(ioncell_fw_id) assert ion_fw.state == "COMPLETED" assert ioncell_fw.state == "COMPLETED" launch = ioncell_fw.launches[-1] links_ioncell = lp.get_wf_by_fw_id(ioncell_fw_id).links[ioncell_fw_id] # there should be an additional child (the detour) assert len(links_ioncell) == 1 fw_detour_id = links_ioncell[0] # run the detour with lowered dilatmx rapidfire(lp, fworker, m_dir=str(tmpdir)) fw_detour = lp.get_fw_by_id(fw_detour_id) assert fw_detour.state == "COMPLETED" detour_abiinput = fw_detour.spec['_tasks'][0].abiinput assert detour_abiinput['dilatmx'] == 1.03 restart_structure = detour_abiinput.structure # check that the structure has been updated when restarting assert initial_ion_structure != restart_structure wf = lp.get_wf_by_fw_id(ion_fw_id) assert wf.state == "COMPLETED" # check that the structure has been updated when restarting assert initial_ion_structure != restart_structure if self.check_numerical_values: last_ioncell_task = load_abitask( get_fw_by_task_index(wf, "ioncell", index=-1)) with last_ioncell_task.open_gsr() as gsr: assert gsr.structure.lattice.abc == pytest.approx(np.array( (3.8101419255677951, 3.8101444011173897, 3.8101434296150889)), rel=0.05)
def itest_relax_wf(self, lp, fworker, tmpdir, inputs_relax_si_low, use_autoparal, db_data): """ Tests the basic functionality of a RelaxFWWorkflow with autoparal True and False. """ wf = RelaxFWWorkflow(*inputs_relax_si_low, autoparal=use_autoparal, initialization_info={"kppa": 100}) wf.add_mongoengine_db_insertion(db_data) wf.add_final_cleanup(["WFK"]) initial_ion_structure = inputs_relax_si_low[0].structure ion_fw_id = wf.ion_fw.fw_id ioncell_fw_id = wf.ioncell_fw.fw_id old_new = wf.add_to_db(lpad=lp) ion_fw_id = old_new[ion_fw_id] ioncell_fw_id = old_new[ioncell_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(ion_fw_id) assert wf.state == "COMPLETED" ioncell_fw = get_fw_by_task_index(wf, "ioncell", index=-1) ioncell_task = load_abitask(ioncell_fw) ioncell_hist_path = ioncell_task.outdir.has_abiext("HIST") with HistFile(ioncell_hist_path) as hist: initial_ioncell_structure = hist.structures[0] assert initial_ion_structure != initial_ioncell_structure # check the effect of the final cleanup assert len(glob.glob(os.path.join(ioncell_task.outdir.path, "*_WFK"))) == 0 assert len(glob.glob(os.path.join(ioncell_task.outdir.path, "*_DEN"))) > 0 assert len(glob.glob(os.path.join(ioncell_task.tmpdir.path, "*"))) == 0 assert len(glob.glob(os.path.join(ioncell_task.indir.path, "*"))) == 0 # check the result in the DB from abiflows.database.mongoengine.abinit_results import RelaxResult with db_data.switch_collection(RelaxResult) as RelaxResult: results = RelaxResult.objects() assert len(results) == 1 r = results[0] # test input structure assert r.abinit_input.structure.to_mgobj() == initial_ion_structure # test output structure # remove site properties, otherwise the "cartesian_forces" won't match due to the presence of a # list instead of an array in the deserialization db_structure = r.abinit_output.structure.to_mgobj() for s in db_structure: s.properties = {} hist_structure = hist.structures[-1] for s in hist_structure: s.properties = {} assert db_structure == hist_structure assert r.abinit_input.ecut == inputs_relax_si_low[0]['ecut'] assert r.abinit_input.kppa == 100 nptu.assert_array_equal( r.abinit_input.last_input.to_mgobj()['ngkpt'], inputs_relax_si_low[0]['ngkpt']) with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.gsr.read()) db_file.seek(0) assert filecmp.cmp(ioncell_task.gsr_path, db_file.name) if self.check_numerical_values: with ioncell_task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-240.28203726305696, rel=0.01) assert np.allclose((3.8101419256822333, 3.8101444012342616, 3.8101434297177068), gsr.structure.lattice.abc, rtol=0.05)
def itest_dfpt_anaddb_ph(self, lp, fworker, tmpdir, input_scf_phonon_gan_low, db_data): """ Simple test of DteFWWorkflow with autoparal True and False. Skips dte permutations. """ dfpt_inputs = dfpt_from_gsinput(input_scf_phonon_gan_low, ph_ngqpt=[2, 2, 2], do_ddk=True, do_dde=True, do_strain=True, do_dte=False, ddk_tol = {"tolwfr": 1.0e-16}, dde_tol = {"tolvrs": 1.0e-7}, strain_tol={"tolvrs": 1.0e-7}, ph_tol={"tolvrs": 1.0e-7}) wf = DfptFWWorkflow(input_scf_phonon_gan_low, ddk_inp = dfpt_inputs.filter_by_tags(DDK), dde_inp = dfpt_inputs.filter_by_tags(DDE), strain_inp=dfpt_inputs.filter_by_tags(STRAIN), ph_inp = dfpt_inputs.filter_by_tags(PH_Q_PERT), dte_inp = dfpt_inputs.filter_by_tags(DTE), nscf_inp=dfpt_inputs.filter_by_tags(NSCF),initialization_info={"kppa": 100}, autoparal=False) wf.add_anaddb_dfpt_fw(input_scf_phonon_gan_low.structure, ph_ngqpt=[2, 2, 2], nqsmall=2, ndivsm=3) wf.add_mongoengine_db_insertion(db_data) wf.add_final_cleanup(["WFK"]) scf_fw_id = wf.scf_fw.fw_id old_new = wf.add_to_db(lpad=lp) scf_fw_id = old_new[scf_fw_id] rapidfire(lp, fworker, m_dir=str(tmpdir)) wf = lp.get_wf_by_fw_id(scf_fw_id) assert wf.state == "COMPLETED" scf_task = load_abitask(get_fw_by_task_index(wf, "scf", index=1)) # check the save in the DB from abiflows.database.mongoengine.abinit_results import DfptResult with db_data.switch_collection(DfptResult) as DteResult: results = DteResult.objects() assert len(results) == 1 r = results[0] assert r.abinit_input.structure.to_mgobj() == input_scf_phonon_gan_low.structure assert r.abinit_output.structure.to_mgobj() == input_scf_phonon_gan_low.structure assert r.abinit_input.ecut == input_scf_phonon_gan_low['ecut'] assert r.abinit_input.kppa == 100 nptu.assert_array_equal(r.abinit_input.gs_input.to_mgobj()['ngkpt'], input_scf_phonon_gan_low['ngkpt']) ana_task = load_abitask(get_fw_by_task_index(wf, "anaddb", index=None)) with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.anaddb_nc.read()) db_file.seek(0) assert filecmp.cmp(ana_task.anaddb_nc_path, db_file.name) mrgddb_task = load_abitask(get_fw_by_task_index(wf, "mrgddb", index=None)) with tempfile.NamedTemporaryFile(mode="wb") as db_file: db_file.write(r.abinit_output.ddb.read()) db_file.seek(0) assert filecmp.cmp(mrgddb_task.merged_ddb_path, db_file.name) if self.check_numerical_values: with scf_task.open_gsr() as gsr: assert gsr.energy == pytest.approx(-680.402255069, rel=0.005) ana_task = load_abitask(get_fw_by_task_index(wf, "anaddb", index=None)) with ana_task.open_anaddbnc() as ananc: assert float(ananc.eps0[0,0]) == pytest.approx(64.8276774889143, rel=0.15) e = ananc.elastic_data if has_abinit("8.9.3"): assert float(e.elastic_relaxed[0,0,0,0]) == pytest.approx(41.230540749230556, rel=0.15)