diff --git a/aiida_quantumespresso/calculations/pw.py b/aiida_quantumespresso/calculations/pw.py index ec343119f..84c9e4303 100644 --- a/aiida_quantumespresso/calculations/pw.py +++ b/aiida_quantumespresso/calculations/pw.py @@ -145,6 +145,11 @@ def define(cls, spec): message='The electronic minimization cycle did not reach self-consistency.') spec.exit_code(541, 'ERROR_SYMMETRY_NON_ORTHOGONAL_OPERATION', message='The variable cell optimization broke the symmetry of the k-points.') + + # Strong warnings about calculation results, but something tells us that you're ok with that + spec.exit_code(710, 'WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED', + message='The electronic minimization cycle did not reach self-consistency, but `scf_must_converge` ' + 'is `False` and/or `electron_maxstep` is 0.') # yapf: enable @classproperty diff --git a/aiida_quantumespresso/parsers/pw.py b/aiida_quantumespresso/parsers/pw.py index ed7538774..bf31a91f5 100644 --- a/aiida_quantumespresso/parsers/pw.py +++ b/aiida_quantumespresso/parsers/pw.py @@ -150,7 +150,14 @@ def validate_electronic(self, trajectory, parameters, logs): return if 'ERROR_ELECTRONIC_CONVERGENCE_NOT_REACHED' in logs['error']: - return self.exit_codes.ERROR_ELECTRONIC_CONVERGENCE_NOT_REACHED + scf_must_converge = self.node.inputs.parameters.get_attribute('ELECTRONS', + {}).get('scf_must_converge', True) + electron_maxstep = self.node.inputs.parameters.get_attribute('ELECTRONS', {}).get('electron_maxstep', 1) + + if electron_maxstep == 0 or not scf_must_converge: + return self.exit_codes.WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED + else: + return self.exit_codes.ERROR_ELECTRONIC_CONVERGENCE_NOT_REACHED def validate_dynamics(self, trajectory, parameters, logs): """Analyze problems that are specific to `dynamics` type calculations: i.e. `md` and `vc-md`.""" diff --git a/aiida_quantumespresso/workflows/pw/base.py b/aiida_quantumespresso/workflows/pw/base.py index 4ecbf35f4..53fa9a442 100644 --- a/aiida_quantumespresso/workflows/pw/base.py +++ b/aiida_quantumespresso/workflows/pw/base.py @@ -115,6 +115,9 @@ def define(cls, spec): message='The initialization calculation failed.') spec.exit_code(501, 'ERROR_IONIC_CONVERGENCE_REACHED_EXCEPT_IN_FINAL_SCF', message='Then ionic minimization cycle converged but the thresholds are exceeded in the final SCF.') + spec.exit_code(710, 'WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED', + message='The electronic minimization cycle did not reach self-consistency, but `scf_must_converge` ' + 'is `False` and/or `electron_maxstep` is 0.') # yapf: enable @classmethod @@ -588,3 +591,15 @@ def handle_electronic_convergence_not_achieved(self, calculation): action = f'reduced beta mixing from {mixing_beta} to {mixing_beta_new} and restarting from the last calculation' self.report_error_handled(calculation, action) return ProcessHandlerReport(True) + + @process_handler(priority=420, exit_codes=[ + PwCalculation.exit_codes.WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED, + ]) + def handle_electronic_convergence_warning(self, calculation): + """Handle `WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED': consider finished.""" + self.ctx.is_finished = True + self.ctx.restart_calc = calculation + action = 'electronic convergence not reached but inputs say this is ok: consider finished.' + self.report_error_handled(calculation, action) + self.results() # Call the results method to attach the output nodes + return ProcessHandlerReport(True, self.exit_codes.WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED) diff --git a/tests/parsers/fixtures/pw/failed_scf_not_converged_intentional/aiida.out b/tests/parsers/fixtures/pw/failed_scf_not_converged_intentional/aiida.out new file mode 100644 index 000000000..35eefaf5d --- /dev/null +++ b/tests/parsers/fixtures/pw/failed_scf_not_converged_intentional/aiida.out @@ -0,0 +1,167 @@ + + Program PWSCF v.6.1 (svn rev. 13369) starts on 7Jun2019 at 17:14: 0 + + This program is part of the open-source Quantum ESPRESSO suite + for quantum simulation of materials; please cite + "P. Giannozzi et al., J. Phys.:Condens. Matter 21 395502 (2009); + URL http://www.quantum-espresso.org", + in publications or presentations arising from this work. More details at + http://www.quantum-espresso.org/quote + + Parallel version (MPI), running on 1 processors + Reading input from aiida.in + + Current dimensions of program PWSCF are: + Max number of different atomic species (ntypx) = 10 + Max number of k-points (npk) = 40000 + Max angular momentum in pseudopotentials (lmaxx) = 3 + + Subspace diagonalization in iterative solution of the eigenvalue problem: + a serial algorithm will be used + + + G-vector sticks info + -------------------- + sticks: dense smooth PW G-vecs: dense smooth PW + Sum 859 433 127 16889 5985 965 + + + + bravais-lattice index = 0 + lattice parameter (alat) = 7.2558 a.u. + unit-cell volume = 270.1072 (a.u.)^3 + number of atoms/cell = 2 + number of atomic types = 1 + number of electrons = 8.00 + number of Kohn-Sham states= 4 + kinetic-energy cutoff = 30.0000 Ry + charge density cutoff = 240.0000 Ry + convergence threshold = 1.0E-06 + mixing beta = 0.7000 + number of iterations used = 8 plain mixing + Exchange-correlation = PBE ( 1 4 3 4 0 0) + + celldm(1)= 7.255773 celldm(2)= 0.000000 celldm(3)= 0.000000 + celldm(4)= 0.000000 celldm(5)= 0.000000 celldm(6)= 0.000000 + + crystal axes: (cart. coord. in units of alat) + a(1) = ( 0.707107 0.707107 0.000000 ) + a(2) = ( 0.707107 0.000000 0.707107 ) + a(3) = ( 0.000000 0.707107 0.707107 ) + + reciprocal axes: (cart. coord. in units 2 pi/alat) + b(1) = ( 0.707107 0.707107 -0.707107 ) + b(2) = ( 0.707107 -0.707107 0.707107 ) + b(3) = ( -0.707107 0.707107 0.707107 ) + + + PseudoPot. # 1 for Si read from file: + ./pseudo/Si.pbe-n-rrkjus_psl.1.0.0.UPF + MD5 check sum: 0b0bb1205258b0d07b9f9672cf965d36 + Pseudo is Ultrasoft + core correction, Zval = 4.0 + Generated using "atomic" code by A. Dal Corso v.5.1 + Using radial grid of 1141 points, 6 beta functions with: + l(1) = 0 + l(2) = 0 + l(3) = 1 + l(4) = 1 + l(5) = 2 + l(6) = 2 + Q(r) pseudized with 0 coefficients + + + atomic species valence mass pseudopotential + Si 4.00 28.08550 Si( 1.00) + + +---- OUTPUT REMOVED ---- + + Cartesian axes + + site n. atom positions (alat units) + 1 Si tau( 1) = ( 0.0000000 0.0000000 0.0000000 ) + 2 Si tau( 2) = ( 0.3535534 0.3535534 0.3535534 ) + + Crystallographic axes + + site n. atom positions (cryst. coord.) + 1 Si tau( 1) = ( 0.0000000 0.0000000 0.0000000 ) + 2 Si tau( 2) = ( 0.2500000 0.2500000 0.2500000 ) + + number of k points= 3 + cart. coord. in units 2pi/alat + k( 1) = ( 0.0000000 0.0000000 0.0000000), wk = 0.2500000 + k( 2) = ( 0.3535534 -0.3535534 -0.3535534), wk = 1.0000000 + k( 3) = ( 0.0000000 0.0000000 -0.7071068), wk = 0.7500000 + + cryst. coord. + k( 1) = ( 0.0000000 0.0000000 0.0000000), wk = 0.2500000 + k( 2) = ( 0.0000000 0.0000000 -0.5000000), wk = 1.0000000 + k( 3) = ( 0.0000000 -0.5000000 -0.5000000), wk = 0.7500000 + + Dense grid: 16889 G-vectors FFT dimensions: ( 36, 36, 36) + + Smooth grid: 5985 G-vectors FFT dimensions: ( 25, 25, 25) + + Estimated max dynamical RAM per process > 10.86MB + + Initial potential from superposition of free atoms + + starting charge 7.99888, renormalised to 8.00000 + Starting wfc are 8 randomized atomic wfcs + + total cpu time spent up to now is 0.9 secs + + per-process dynamical memory: 20.0 Mb + + Self-consistent Calculation + + iteration # 1 ecut= 30.00 Ry beta=0.70 + Davidson diagonalization with overlap + ethr = 1.00E-02, avg # of iterations = 2.0 + + total cpu time spent up to now is 1.1 secs + + total energy = -22.64340821 Ry + Harris-Foulkes estimate = -22.67223092 Ry + estimated scf accuracy < 0.10529730 Ry + + iteration # 2 ecut= 30.00 Ry beta=0.70 + Davidson diagonalization with overlap + ethr = 1.32E-03, avg # of iterations = 1.0 + + total cpu time spent up to now is 1.3 secs + + total energy = -22.64972429 Ry + Harris-Foulkes estimate = -22.65005091 Ry + estimated scf accuracy < 0.00535578 Ry + + iteration # 3 ecut= 30.00 Ry beta=0.70 + Davidson diagonalization with overlap + ethr = 6.69E-05, avg # of iterations = 3.0 + + total cpu time spent up to now is 1.5 secs + + total energy = -22.65168183 Ry + Harris-Foulkes estimate = -22.65176063 Ry + estimated scf accuracy < 0.00032274 Ry + + End of self-consistent calculation + + convergence NOT achieved after 3 iterations: stopping + + Writing output data file aiida.save + +---- OUTPUT REMOVED ---- + + Parallel routines + fft_scatter : 0.01s CPU 0.01s WALL ( 343 calls) + + PWSCF : 1.37s CPU 1.51s WALL + + + This run was terminated on: 17:14: 2 7Jun2019 + +=------------------------------------------------------------------------------= + JOB DONE. +=------------------------------------------------------------------------------= diff --git a/tests/parsers/fixtures/pw/failed_scf_not_converged_intentional/data-file.xml b/tests/parsers/fixtures/pw/failed_scf_not_converged_intentional/data-file.xml new file mode 100644 index 000000000..8d9c8ae39 --- /dev/null +++ b/tests/parsers/fixtures/pw/failed_scf_not_converged_intentional/data-file.xml @@ -0,0 +1,398 @@ + + + + + + +
+ + +
+ + +F + + +T + + +F + + +F + + +F + + +F + + + + +None + + +free + + + 7.255773225898359E+000 + + + 7.255773225898359E+000 + 0.000000000000000E+000 + 0.000000000000000E+000 + 0.000000000000000E+000 + 0.000000000000000E+000 + 0.000000000000000E+000 + + + + + 5.130606450784521E+000 5.130606450784521E+000 0.000000000000000E+000 + + + 5.130606450784521E+000 0.000000000000000E+000 5.130606450784521E+000 + + + 0.000000000000000E+000 5.130606450784521E+000 5.130606450784521E+000 + + + + + + 7.071067811865476E-001 7.071067811865476E-001 -7.071067811865476E-001 + + + 7.071067811865476E-001 -7.071067811865476E-001 7.071067811865476E-001 + + +-7.071067811865476E-001 7.071067811865476E-001 7.071067811865476E-001 + + + + + + 2 + + + 1 + + + + +Si + + + 2.808550000000000E+001 + + +Si.pbe-n-rrkjus_psl.1.0.0.UPF + + + +./pseudo/ + + + + + + + + 1 + + + 1 + + +T + + +F + + +T + + +F + + + 2 + + + + + + 1 0 0 + 0 1 0 + 0 0 1 + + + 0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000 + + + 1 2 + + + + + +F + + +F + + + 1 + + + 5.000000000000000E-001 + + + 1.000000000000000E-001 + + + 0.000000000000000E+000 + + +F + + + 5.000000000000000E-001 + + +F + + +F + + + 4.499999880790710E-001 + + + 5.500000119209290E-001 + + + 0.000000000000000E+000 + + + + + + 1.500000000000000E+001 + + + 1.200000000000000E+002 + + + 754 + + +F + + + + 16889 + + + + 5985 + + + + + +F + + +F + + +F + + +F + + + + + 0 + + + 1 + + + + 0.000000000000000E+000 + + + 0.000000000000000E+000 + + + 0.000000000000000E+000 + + + +F + + + + +PBE + + +F + + +F + + + + + 4 + + + 0.000000000000000E+000 + + + 0.000000000000000E+000 + + + 0.000000000000000E+000 + + +pbc + + + + +F + + +F + + +F + + + + + 3 + + + + + + + + + 0.000000000000000E+000 + + + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + + + 3 + + + 1 + + +F + + + 8 + + + 4 + + + 8.000000000000000E+000 + + + + + 2.407492208705585E-001 + + + + + + 0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000 + + + 2.500000000000000E-001 + + + + + + + + 3.535533905932738E-001 -3.535533905932738E-001 -3.535533905932738E-001 + + + 1.000000000000000E+000 + + + + + + + + 0.000000000000000E+000 0.000000000000000E+000 -7.071067811865476E-001 + + + 7.500000000000000E-001 + + + + + + + + + 754 + + + + 749 + + + + + 754 + + + + + 740 + + + +
diff --git a/tests/parsers/test_pw.py b/tests/parsers/test_pw.py index f5d758745..e1dec3229 100644 --- a/tests/parsers/test_pw.py +++ b/tests/parsers/test_pw.py @@ -483,6 +483,34 @@ def test_pw_failed_scf_not_converged( }) +@pytest.mark.parametrize('parameters', ( # yapf:disable + {'ELECTRONS': {'scf_must_converge': False}}, + {'ELECTRONS': {'electron_maxstep': 0}}, + {'ELECTRONS': {'scf_must_converge': False, 'electron_maxstep': 0}} +)) # yapf:enable +def test_pw_failed_scf_not_converged_intentional( + fixture_localhost, generate_calc_job_node, generate_parser, generate_inputs, parameters +): + """Test the parsing of an scf calculation that intentionally did not reach convergence. + + This can be the case if `scf_must_converge = False` or `electron_maxstep = 0`. + """ + name = 'failed_scf_not_converged_intentional' + entry_point_calc_job = 'quantumespresso.pw' + entry_point_parser = 'quantumespresso.pw' + + node = generate_calc_job_node(entry_point_calc_job, fixture_localhost, name, generate_inputs(parameters=parameters)) + parser = generate_parser(entry_point_parser) + results, calcfunction = parser.parse_from_node(node, store_provenance=False) + + assert calcfunction.is_finished, calcfunction.exception + assert calcfunction.is_failed, calcfunction.exit_status + assert calcfunction.exit_status == node.process_class.exit_codes.WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED.status + assert orm.Log.objects.get_logs_for(node) + assert 'output_parameters' in results + assert 'output_trajectory' in results + + def test_pw_relax_success(fixture_localhost, generate_calc_job_node, generate_parser, generate_inputs, data_regression): """Test a `relax` that successfully converges.""" name = 'relax_success' diff --git a/tests/workflows/pw/test_base.py b/tests/workflows/pw/test_base.py index 8cd89a52c..8c915889a 100644 --- a/tests/workflows/pw/test_base.py +++ b/tests/workflows/pw/test_base.py @@ -130,6 +130,34 @@ def test_handle_relax_recoverable_ionic_convergence_error(generate_workchain_pw, assert result.status == 0 +def test_handle_electronic_convergence_warning(generate_workchain_pw, generate_structure): + """Test `PwBaseWorkChain.handle_electronic_convergence_warning`.""" + from aiida.common.links import LinkType + + inputs = generate_workchain_pw(return_inputs=True) + inputs['pw']['parameters']['scf_maxstep'] = 0 + inputs['pw']['parameters']['scf_must_converge'] = False + + process = generate_workchain_pw( + exit_code=PwBaseWorkChain.exit_codes.WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED, inputs=inputs + ) + process.setup() + + calculation = process.ctx.children[-1] + structure = generate_structure().store() + structure.add_incoming(calculation, link_label='output_structure', link_type=LinkType.CREATE) + + result = process.handle_electronic_convergence_warning(calculation) + assert isinstance(result, ProcessHandlerReport) + assert result.do_break + assert result.exit_code == PwBaseWorkChain.exit_codes.WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED + assert process.node.get_outgoing().all() is not None + assert process.ctx.restart_calc is calculation + + result = process.inspect_process() + assert result == PwBaseWorkChain.exit_codes.WARNING_ELECTRONIC_CONVERGENCE_NOT_REACHED + + def test_sanity_check_no_bands(generate_workchain_pw): """Test that `sanity_check_insufficient_bands` does not except if there is no `output_band`, which is optional.""" process = generate_workchain_pw(exit_code=ExitCode(0))