use crate::orca::make_inp_block;
#[derive(Clone, Copy, PartialEq, Debug, Default)]
pub enum Method {
HartreeFock,
Hf_3c,
Dft,
Mp2Perturbation,
SpinComponentScaledMp2,
OrbitalOptimzedMp2,
RegularlizedMp2,
DoubleHybridDft,
TripleHybridDft, CoupledCluster,
Xtb,
SemiEmpericalMethods,
BP86,
BLYP,
OLYP,
GLYP,
XLYP,
PW91,
MPWPW,
MPWLYP,
PBE,
RPBE,
REVPBE,
RPW86PBE,
PWP,
B97_3c,
wB97x_3c,
B97M_V,
V97M_D3BJ,
B97M,
SCANFUNC,
RSCAN,
R2SCAN,
TPSS,
REVTPSS,
#[default]
r2SCAN_3c,
B1LYP,
B3LYP,
B3LYP_G,
O3LYP,
X3LYP,
B1P86,
B3PW91,
PW1PW,
MPW1PW,
MPW1LYP,
PBE0,
REVPBE0,
REVPBE38,
BHANDHLYP,
M06,
M062X,
PW6B95,
TPSSH,
TPSS0,
r2SCANH,
r2SCAN0,
r2SCAN50,
PBEh_3c,
B3LYP_3c,
FractionalOccupationDensity,
None, }
impl Method {
pub fn keyword(self) -> String {
match self {
Self::HartreeFock => "HF",
Self::Hf_3c => "HF-3c",
Self::Dft => "B3LYP",
Self::Mp2Perturbation => "RI-MP2", Self::SpinComponentScaledMp2 => "RI-SCS-MP2",
Self::OrbitalOptimzedMp2 => "OO-RI-MP2",
Self::RegularlizedMp2 => "RI-MP2",
Self::DoubleHybridDft => "B2PLYP",
Self::TripleHybridDft => "B3LYP-D3(BJ)", Self::CoupledCluster => "DLPNO-CCSD(T)",
Self::Xtb => "XTB", Self::SemiEmpericalMethods => "XTB2",
Self::BP86 => "BP86",
Self::BLYP => "BLYP",
Self::OLYP => "OLYP",
Self::GLYP => "GLYP",
Self::XLYP => "XLYP",
Self::PW91 => "PW91",
Self::MPWPW => "MPWPW",
Self::MPWLYP => "MPWLYP",
Self::PBE => "PBE",
Self::RPBE => "RPBE",
Self::REVPBE => "REVPBE",
Self::RPW86PBE => "RPW86PBE",
Self::PWP => "PWP",
Self::B97_3c => "B97-3c",
Self::wB97x_3c => "wB97X-3c",
Self::B97M_V => "B97M-V",
Self::V97M_D3BJ => "V97M-D3BJ",
Self::B97M => "B97M",
Self::SCANFUNC => "SCANFUNC",
Self::RSCAN => "RSCAN",
Self::R2SCAN => "R2SCAN",
Self::TPSS => "TPSS",
Self::REVTPSS => "REVTPSS",
Self::r2SCAN_3c => "r2SCAN-3c",
Self::B1LYP => "B1LYP",
Self::B3LYP => "B3LYP",
Self::B3LYP_G => "B3LYP-G",
Self::O3LYP => "O3LYP",
Self::X3LYP => "X3LYP",
Self::B1P86 => "B1P86",
Self::B3PW91 => "B3PW91",
Self::PW1PW => "PW1PW",
Self::MPW1PW => "MPW1PW",
Self::MPW1LYP => "MPW1LYP",
Self::PBE0 => "PBE0",
Self::REVPBE0 => "REVPBE0",
Self::REVPBE38 => "REVPBE38",
Self::BHANDHLYP => "BHANDHLYP",
Self::M06 => "M06",
Self::M062X => "M062X",
Self::PW6B95 => "PW6B95",
Self::TPSSH => "TPSSH",
Self::TPSS0 => "TPSS0",
Self::r2SCANH => "r2SCANH",
Self::r2SCAN0 => "r2SCAN0",
Self::r2SCAN50 => "r2SCAN50",
Self::PBEh_3c => "PBEh-3c",
Self::B3LYP_3c => "B3LYP-3c",
Self::FractionalOccupationDensity => "FOD",
Self::None => "",
}
.to_string()
}
pub fn is_composite(self) -> bool {
matches!(
self,
Self::Hf_3c
| Self::B97_3c
| Self::r2SCAN_3c
| Self::PBEh_3c
| Self::B3LYP_3c
| Self::wB97x_3c
)
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum DispersionCorrection {
DftDopt,
D3S6,
D3S8,
D3A1,
D3A2,
D3RS6,
D3alpha6,
D4S6,
D4S8,
D4A1,
D4A2,
D4S9,
DFTDScaleC6,
}
impl DispersionCorrection {
pub fn keyword(self) -> &'static str {
match self {
Self::DftDopt => "DFTDOPT",
Self::D3S6 => "D3S6",
Self::D3S8 => "D3S8",
Self::D3A1 => "D3A1",
Self::D3A2 => "D3A2",
Self::D3RS6 => "D3RS6",
Self::D3alpha6 => "D3alpha6",
Self::D4S6 => "D4S6",
Self::D4S8 => "D4S8",
Self::D4A1 => "D4A1",
Self::D4A2 => "D4A2",
Self::D4S9 => "D4S9",
Self::DFTDScaleC6 => "DFTDScaleC6",
}
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum FrozenCore {
FcElectrons,
FcEwin,
FcNone,
}
impl FrozenCore {
pub fn keyword(self) -> String {
match self {
Self::FcElectrons => "FC_ELECTRONS",
Self::FcEwin => "FC_EWIN",
Self::FcNone => "FC_NONE",
}
.to_string()
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Correlation {
C_LYP,
}
impl Correlation {
pub fn keyword(self) -> String {
match self {
Self::C_LYP => "C_LYP",
}
.to_string()
}
}
#[derive(Clone, Debug)]
pub struct MethodSection {
pub correlation: Option<Correlation>,
pub switch_to_soscf: Option<bool>,
pub frozen_core: Option<FrozenCore>,
pub check_frozen_core: Option<bool>,
pub correct_frozen_core: Option<bool>,
pub dispersion_correction: Option<(DispersionCorrection, f32)>,
}
impl MethodSection {
pub fn make_inp(&self) -> String {
let mut contents = Vec::new();
if let Some(c) = self.correlation {
contents.push(("correlation", c.keyword()));
}
if let Some(v) = self.switch_to_soscf {
contents.push(("SwitchToSOSCF", format!("{v:?}")));
}
if let Some(v) = self.frozen_core {
contents.push(("FrozenCore", v.keyword()));
}
if let Some(v) = self.check_frozen_core {
contents.push(("CheckFrozenCore", format!("{v:?}")));
}
if let Some(v) = self.correct_frozen_core {
contents.push(("CorrectFrozenCore", format!("{v:?}")));
}
if let Some((kw, v)) = self.dispersion_correction {
contents.push((kw.keyword(), format!("{v:?}")));
}
make_inp_block("method", &contents, &[])
}
}