From c6b57e459edd2a8d4d863d71e22f66a1bf21c4e1 Mon Sep 17 00:00:00 2001 From: Lilachn91 Date: Wed, 3 Jun 2026 16:18:39 +0300 Subject: [PATCH] modified orca opt and freq settings for better convergence --- arc/job/adapters/orca.py | 7 +- arc/job/adapters/orca_test.py | 160 ++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 3 deletions(-) diff --git a/arc/job/adapters/orca.py b/arc/job/adapters/orca.py index 11a0404e5a..190de98a1a 100644 --- a/arc/job/adapters/orca.py +++ b/arc/job/adapters/orca.py @@ -1,5 +1,5 @@ """ -An adapter for executing Orca 5 jobs +An adapter for executing Orca 5/6 jobs https://orcaforum.kofo.mpg.de/app.php/portal """ @@ -291,9 +291,10 @@ def write_input_file(self) -> None: # Orca requires different blocks for wavefunction methods and DFT methods if self.level.method_type == 'dft': input_dict['method_class'] = 'KS' - # DFT grid must be the same for both opt and freq. + # Use a consistent DFT grid for fine_opt jobs and for any job with a frequency calculation + # (`freq` and `optfreq`), so `optfreq` is treated like `freq` here and defaults to `defgrid3`. # Users can override by setting `dft_grid` in args.keyword (e.g. dft_grid: DEFGRID1). - self.args['keyword'].setdefault('dft_grid', 'defgrid3' if self.fine else 'defgrid2') + self.args['keyword'].setdefault('dft_grid', 'defgrid3' if self.fine or self.job_type in ['freq', 'optfreq'] else 'defgrid2') elif self.level.method_type == 'wavefunction': input_dict['method_class'] = 'HF' if 'dlpno' in self.level.method: diff --git a/arc/job/adapters/orca_test.py b/arc/job/adapters/orca_test.py index f4c077efb4..436d7b77cb 100644 --- a/arc/job/adapters/orca_test.py +++ b/arc/job/adapters/orca_test.py @@ -315,6 +315,166 @@ def test_set_files(self): self.assertEqual(self.job_1.files_to_upload, job_1_files_to_upload) self.assertEqual(self.job_1.files_to_download, job_1_files_to_download) + def test_dft_grid_regular_opt(self): + """Test that regular opt job uses defgrid2 for DFT""" + job_opt = OrcaAdapter(execution_type='queue', + job_type='opt', + level=Level(method='wb97x-d3', basis='def2-tzvp'), + project='test_dft_grid', + project_directory=os.path.join(ARC_TESTING_PATH, 'test_OrcaAdapter'), + species=[ARCSpecies(label='CH3O', + xyz="""C 0.03807240 0.00035621 -0.00484242 + O 1.35198769 0.01264937 -0.17195885 + H -0.33965241 -0.14992727 1.02079480 + H -0.51702680 0.90828035 -0.29592912 + H -0.53338088 -0.77135867 -0.54806440""")], + testing=True, + fine=False, + ) + job_opt.write_input_file() + with open(os.path.join(job_opt.local_path, input_filenames[job_opt.job_adapter]), 'r') as f: + content = f.read() + self.assertIn('defgrid2', content) + self.assertNotIn('defgrid3', content) + + def test_dft_grid_fine_opt(self): + """Test that fine opt job uses defgrid3 for DFT""" + job_fine_opt = OrcaAdapter(execution_type='queue', + job_type='opt', + level=Level(method='wb97x-d3', basis='def2-tzvp'), + project='test_dft_grid_fine', + project_directory=os.path.join(ARC_TESTING_PATH, 'test_OrcaAdapter'), + species=[ARCSpecies(label='CH3O', + xyz="""C 0.03807240 0.00035621 -0.00484242 + O 1.35198769 0.01264937 -0.17195885 + H -0.33965241 -0.14992727 1.02079480 + H -0.51702680 0.90828035 -0.29592912 + H -0.53338088 -0.77135867 -0.54806440""")], + testing=True, + fine=True, + ) + job_fine_opt.write_input_file() + with open(os.path.join(job_fine_opt.local_path, input_filenames[job_fine_opt.job_adapter]), 'r') as f: + content = f.read() + self.assertIn('defgrid3', content) + + def test_dft_grid_freq(self): + """Test that freq job uses defgrid3 for DFT""" + job_freq = OrcaAdapter(execution_type='queue', + job_type='freq', + level=Level(method='wb97x-d3', basis='def2-tzvp'), + project='test_dft_grid_freq', + project_directory=os.path.join(ARC_TESTING_PATH, 'test_OrcaAdapter'), + species=[ARCSpecies(label='CH3O', + xyz="""C 0.03807240 0.00035621 -0.00484242 + O 1.35198769 0.01264937 -0.17195885 + H -0.33965241 -0.14992727 1.02079480 + H -0.51702680 0.90828035 -0.29592912 + H -0.53338088 -0.77135867 -0.54806440""")], + testing=True, + fine=False, + ) + job_freq.write_input_file() + with open(os.path.join(job_freq.local_path, input_filenames[job_freq.job_adapter]), 'r') as f: + content = f.read() + self.assertIn('defgrid3', content) + + def test_dft_grid_optfreq(self): + """Test that optfreq job uses defgrid3 for DFT""" + job_optfreq = OrcaAdapter(execution_type='queue', + job_type='optfreq', + level=Level(method='wb97x-d3', basis='def2-tzvp'), + project='test_dft_grid_optfreq', + project_directory=os.path.join(ARC_TESTING_PATH, 'test_OrcaAdapter'), + species=[ARCSpecies(label='CH3O', + xyz="""C 0.03807240 0.00035621 -0.00484242 + O 1.35198769 0.01264937 -0.17195885 + H -0.33965241 -0.14992727 1.02079480 + H -0.51702680 0.90828035 -0.29592912 + H -0.53338088 -0.77135867 -0.54806440""")], + testing=True, + fine=False, + ) + job_optfreq.write_input_file() + with open(os.path.join(job_optfreq.local_path, input_filenames[job_optfreq.job_adapter]), 'r') as f: + content = f.read() + self.assertIn('defgrid3', content) + + def test_fine_opt_convergence_tightopt(self): + """Test that fine opt job uses TightOpt convergence for DFT""" + job_fine_opt = OrcaAdapter(execution_type='queue', + job_type='opt', + level=Level(method='wb97x-d3', basis='def2-tzvp'), + project='test_fine_opt_conv', + project_directory=os.path.join(ARC_TESTING_PATH, 'test_OrcaAdapter'), + species=[ARCSpecies(label='CH3O', + xyz="""C 0.03807240 0.00035621 -0.00484242 + O 1.35198769 0.01264937 -0.17195885 + H -0.33965241 -0.14992727 1.02079480 + H -0.51702680 0.90828035 -0.29592912 + H -0.53338088 -0.77135867 -0.54806440""")], + testing=True, + fine=True, + ) + job_fine_opt.write_input_file() + with open(os.path.join(job_fine_opt.local_path, input_filenames[job_fine_opt.job_adapter]), 'r') as f: + content = f.read() + # TightOpt should be present in fine opt + self.assertIn('tightopt', content.lower()) + + def test_recalc_hess_in_optts(self): + """Test that OptTS job includes calc_Hess true in %geom block""" + job_optts = OrcaAdapter(execution_type='queue', + job_type='opt', + level=Level(method='wb97x-d3', basis='def2-tzvp'), + project='test_optts_hess', + project_directory=os.path.join(ARC_TESTING_PATH, 'test_OrcaAdapter'), + species=[ARCSpecies(label='TS_example', + xyz="""C 0.03807240 0.00035621 -0.00484242 + O 1.35198769 0.01264937 -0.17195885 + H -0.33965241 -0.14992727 1.02079480 + H -0.51702680 0.90828035 -0.29592912 + H -0.53338088 -0.77135867 -0.54806440""", + is_ts=True)], + testing=True, + fine=False, + ) + job_optts.write_input_file() + with open(os.path.join(job_optts.local_path, input_filenames[job_optts.job_adapter]), 'r') as f: + content = f.read() + # Check that the file contains the %geom block with Calc_Hess and Recalc_Hess + self.assertIn('%geom', content) + self.assertIn('Calc_Hess true', content) + # Check that it's an OptTS job + self.assertIn('OptTS', content) + + def test_recalc_hess_not_in_regular_opt(self): + """Test that regular Opt job (non-TS) does NOT include Recalc_Hess block""" + job_opt_regular = OrcaAdapter(execution_type='queue', + job_type='opt', + level=Level(method='wb97x-d3', basis='def2-tzvp'), + project='test_opt_no_hess', + project_directory=os.path.join(ARC_TESTING_PATH, 'test_OrcaAdapter'), + species=[ARCSpecies(label='CH3O', + xyz="""C 0.03807240 0.00035621 -0.00484242 + O 1.35198769 0.01264937 -0.17195885 + H -0.33965241 -0.14992727 1.02079480 + H -0.51702680 0.90828035 -0.29592912 + H -0.53338088 -0.77135867 -0.54806440""", + is_ts=False)], + testing=True, + fine=False, + ) + job_opt_regular.write_input_file() + with open(os.path.join(job_opt_regular.local_path, input_filenames[job_opt_regular.job_adapter]), 'r') as f: + content = f.read() + # Check that it's a regular Opt job, not OptTS + self.assertIn('!Opt', content) + self.assertNotIn('OptTS', content) + # The %geom Calc_Hess block should NOT be present for regular opt + self.assertNotIn('Calc_Hess true', content) + self.assertNotIn('Recalc_Hess 5', content) + @classmethod def tearDownClass(cls): """