Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 49 additions & 5 deletions arc/job/adapters/orca.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,50 @@

logger = get_logger()

ORCA_METHOD_ALIASES = {
'wb97xd3': 'wb97x-d3',
}


def _format_orca_method(method: str) -> str:
"""
Convert ARC method names to ORCA-friendly labels when needed.
"""
if not method:
return method
if method.lower() == 'wb97xd':
logger.warning('ORCA does not support wb97xd; use wb97x or wb97x-d3.')
return ORCA_METHOD_ALIASES.get(method.lower(), method)


def _format_orca_basis_token(token: str) -> str:
"""
Convert def2 basis tokens to ORCA formatting (e.g., def2tzvp -> def2-tzvp).
"""
if not token:
return token
parts = token.split('/')
base = parts[0]
if base.lower().startswith('def2'):
base_rest = base[4:]
if base_rest.startswith('-'):
base_rest = base_rest[1:]
if base_rest:
base = f"def2-{base_rest.lower()}"
if len(parts) > 1:
parts = [base] + [part.lower() for part in parts[1:]]
return '/'.join(parts)
return base


def _format_orca_basis(basis: str) -> str:
"""
Convert basis strings to ORCA-friendly labels where applicable.
"""
if not basis:
return basis
return ' '.join(_format_orca_basis_token(token) for token in basis.split())

default_job_settings, global_ess_settings, input_filenames, output_filenames, servers, submit_filenames = \
settings['default_job_settings'], settings['global_ess_settings'], settings['input_filenames'], \
settings['output_filenames'], settings['servers'], settings['submit_filenames']
Expand Down Expand Up @@ -219,13 +263,13 @@ def write_input_file(self) -> None:
'keywords',
]:
input_dict[key] = ''
input_dict['auxiliary_basis'] = self.level.auxiliary_basis or ''
input_dict['basis'] = self.level.basis or ''
input_dict['auxiliary_basis'] = _format_orca_basis(self.level.auxiliary_basis or '')
input_dict['basis'] = _format_orca_basis(self.level.basis or '')
input_dict['charge'] = self.charge
input_dict['cpus'] = self.cpu_cores
input_dict['label'] = self.species_label
input_dict['memory'] = self.input_file_memory
input_dict['method'] = self.level.method
input_dict['method'] = _format_orca_method(self.level.method)
input_dict['multiplicity'] = self.multiplicity
input_dict['xyz'] = xyz_to_str(self.xyz)

Expand All @@ -241,9 +285,9 @@ def write_input_file(self) -> None:
input_dict['method_class'] = 'KS'
# DFT grid must be the same for both opt and freq
if self.fine:
self.add_to_args(val='Grid6 NoFinalGrid', key1='keyword')
self.add_to_args(val='defgrid3', key1='keyword')
else:
self.add_to_args(val='Grid5 NoFinalGrid', key1='keyword')
self.add_to_args(val='defgrid2', key1='keyword')
elif self.level.method_type == 'wavefunction':
input_dict['method_class'] = 'HF'
if 'dlpno' in self.level.method:
Expand Down
28 changes: 27 additions & 1 deletion arc/job/adapters/orca_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
import unittest

from arc.common import ARC_PATH
from arc.job.adapters.orca import OrcaAdapter
from arc.job.adapters.orca import (OrcaAdapter,
_format_orca_basis,
_format_orca_basis_token,
_format_orca_method,
)
from arc.level import Level
from arc.settings.settings import input_filenames, output_filenames
from arc.species import ARCSpecies
Expand Down Expand Up @@ -173,6 +177,28 @@ def test_write_input_file_with_CPCM_solvation(self):
"""
self.assertEqual(content_3, job_3_expected_input_file)

def test_format_orca_method(self):
"""Test ORCA method formatting helper."""
self.assertEqual(_format_orca_method('wb97xd3'), 'wb97x-d3')
self.assertEqual(_format_orca_method('wb97xd'), 'wb97xd')
self.assertEqual(_format_orca_method('B3LYP'), 'B3LYP')

def test_format_orca_basis_token(self):
"""Test ORCA basis token formatting helper."""
self.assertEqual(_format_orca_basis_token('def2tzvp'), 'def2-tzvp')
self.assertEqual(_format_orca_basis_token('def2-TZVP'), 'def2-tzvp')
self.assertEqual(_format_orca_basis_token('def2tzvp/c'), 'def2-tzvp/c')
self.assertEqual(_format_orca_basis_token('def2-TZVP/C'), 'def2-tzvp/c')
self.assertEqual(_format_orca_basis_token('cc-pvtz'), 'cc-pvtz')

def test_format_orca_basis(self):
"""Test ORCA basis formatting helper."""
self.assertEqual(_format_orca_basis('def2tzvp'), 'def2-tzvp')
self.assertEqual(_format_orca_basis('def2-TZVP'), 'def2-tzvp')
self.assertEqual(_format_orca_basis('def2tzvp/c'), 'def2-tzvp/c')
self.assertEqual(_format_orca_basis('def2tzvp def2tzvp/c'),
'def2-tzvp def2-tzvp/c')

def test_set_files(self):
"""Test setting files"""
job_1_files_to_upload = [{'file_name': 'submit.sub',
Expand Down
6 changes: 5 additions & 1 deletion arc/parser/adapters/orca.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,11 @@ def parse_zpe_correction(self) -> Optional[float]:
if 'Zero point energy' in line:
# Example: Zero point energy ... 0.025410 Eh
try:
zpe = float(line.split()[-2])
parts = line.split()
if 'Eh' in parts:
zpe = float(parts[parts.index('Eh') - 1])
else:
zpe = float(parts[-2])
break
except (ValueError, IndexError):
continue
Expand Down
Loading