GANSU2 C API Reference

Overview

The GANSU2 C API (gansu2_api.h) provides a stable, language-agnostic interface to GANSU2’s quantum chemistry engine. It uses opaque handles and extern "C" linkage, making it callable from virtually any programming language.

Shared library: libgansu2.so (Linux) / libgansu2.dylib (macOS)

Header: include/gansu2_api.h

Getting the shared library

libgansu2.so ships with the gansu2 Python wheel and is also fetched on first use to ~/.cache/gansu2/<version>/. Install it with pip install gansu2, or download it from the latest release. The C header gansu2_api.h is bundled with the wheel (include/gansu2_api.h).


API Reference

Lifecycle

gansu2_init

void gansu2_init(int force_cpu);

Initialize the GANSU2 runtime. Call once before any other function.

  • force_cpu = 0: Auto-detect GPU
  • force_cpu = 1: Force CPU-only mode

gansu2_finalize

void gansu2_finalize(void);

Finalize the GANSU2 runtime. Call at program exit.

gansu2_create

gansu2_handle_t gansu2_create(void);

Create a new calculation context. Returns an opaque handle.

gansu2_destroy

void gansu2_destroy(gansu2_handle_t h);

Destroy a calculation context and free all associated resources.


Configuration

gansu2_set

int gansu2_set(gansu2_handle_t h, const char* key, const char* value);

Set an arbitrary parameter. Returns 0 on success.

Common keys: "xyzfilename", "gbsfilename", "method", "post_hf_method", "run_type", "eri_method", "initial_guess", "convergence_method", "n_excited_states", "optimizer", "quiet".

See parameters.md for the full list.

Special key: "quiet" — set to "true" to suppress stdout during gansu2_run.

Convenience functions

int gansu2_set_xyz(gansu2_handle_t h, const char* path);      // set xyzfilename
int gansu2_set_basis(gansu2_handle_t h, const char* path);     // set gbsfilename
int gansu2_set_method(gansu2_handle_t h, const char* method);  // set method
int gansu2_set_post_hf(gansu2_handle_t h, const char* post_hf); // set post_hf_method

Any post_hf_method value from parameters.md is accepted as a string, including the correlation methods ("mp2", "ccsd", "ccsd_t", "dlpno_ccsd", "fci", …) and the excited-state / spectroscopy methods ("cis", "adc2", "thc_sos_adc2", "eom_ccsd", "ip_eom_ccsd", "ea_eom_ccsd", "steom_ccsd", "dlpno_steom_ccsd", …). For excited-state methods, set "n_excited_states" and read the results with gansu2_get_excited_state_report.


Execution

gansu2_run

int gansu2_run(gansu2_handle_t h);

Run the calculation (SCF + post-HF if configured). Returns 0 on success, nonzero on error.


Results

gansu2_get_total_energy

double gansu2_get_total_energy(gansu2_handle_t h);

HF total energy (electronic + nuclear repulsion) in Hartree.

gansu2_get_post_hf_energy

double gansu2_get_post_hf_energy(gansu2_handle_t h);

Post-HF correlation energy in Hartree. Returns 0 if no post-HF method was used.

gansu2_get_nuclear_repulsion_energy

double gansu2_get_nuclear_repulsion_energy(gansu2_handle_t h);

Nuclear repulsion energy in Hartree.

gansu2_get_num_basis

int gansu2_get_num_basis(gansu2_handle_t h);

Number of basis functions (nao).

gansu2_get_num_electrons

int gansu2_get_num_electrons(gansu2_handle_t h);

Number of electrons.

gansu2_get_num_atoms

int gansu2_get_num_atoms(gansu2_handle_t h);

Number of atoms.

gansu2_get_orbital_energies

int gansu2_get_orbital_energies(gansu2_handle_t h, double* buf, int buf_size);

Copy orbital energies into buf. Returns number of values written, or -1 on error. Buffer must have at least num_basis elements.

gansu2_get_mo_coefficients

int gansu2_get_mo_coefficients(gansu2_handle_t h, double* buf, int buf_size);

Copy MO coefficient matrix (nao x nao, row-major) into buf. Returns nao*nao on success.

gansu2_get_ccsd_1rdm_mo

int gansu2_get_ccsd_1rdm_mo(gansu2_handle_t h, double* buf, int buf_size);

Copy CCSD 1-RDM in MO basis (nao x nao, row-major) into buf. Only available after running with post_hf_method = "ccsd_density".

gansu2_get_excited_state_report

const char* gansu2_get_excited_state_report(gansu2_handle_t h);

Returns a formatted string with excited state energies, oscillator strengths, and dominant transitions. Pointer is valid until gansu2_destroy.

gansu2_get_excited_states

int gansu2_get_excited_states(gansu2_handle_t h, double* energies_out, double* osc_out, int n_max);

Excited-state data as raw arrays (after a CIS/ADC/EOM/STEOM run). Writes up to n_max excitation energies (Hartree) into energies_out and oscillator strengths into osc_out; either pointer may be NULL to skip it. Returns the number of states written, or -1 on error.

Derivatives and molecular properties

gansu2_get_energy_gradient

int gansu2_get_energy_gradient(gansu2_handle_t h, double* buf, int len);

Analytic energy gradient (nuclear forces), computed on demand. Writes 3*num_atoms values (dE/dx, dE/dy, dE/dz per atom, Hartree/Bohr). Returns 3*num_atoms, -1 on error, or -2 if unavailable for the current method. len must be ≥ 3*num_atoms.

gansu2_get_hessian

int gansu2_get_hessian(gansu2_handle_t h, double* buf, int len);

Analytic Hessian d²E/dR_i dR_j (Hartree/Bohr²), 3N x 3N row-major, computed on demand. Returns (3*num_atoms)^2, -1 on error, or -2 if unavailable. len must be ≥ (3*num_atoms)^2.

gansu2_get_frequencies

int gansu2_get_frequencies(gansu2_handle_t h, double* buf, int len);

Harmonic vibrational frequencies (cm⁻¹), computed on demand (Hessian + mass-weighting + translation/rotation projection + diagonalization). Imaginary modes are returned as negative values. Returns the number of frequencies (3N − 5 or 3N − 6), -1 on error, or -2 if unavailable. len should be ≥ 3*num_atoms.

gansu2_get_dipole

int gansu2_get_dipole(gansu2_handle_t h, double* xyz);

Ground-state SCF dipole moment in atomic units (e·Bohr). Writes 3 doubles (mu_x, mu_y, mu_z) into xyz. Multiply by 2.5417464157 for Debye. Closed-shell RHF only. Returns 0 on success, -1 on error, -3 if not RHF.


Usage Examples

C

#include "gansu2_api.h"
#include <stdio.h>

int main() {
    gansu2_init(0);

    gansu2_handle_t h = gansu2_create();
    gansu2_set_xyz(h, "H2O.xyz");
    gansu2_set_basis(h, "cc-pvdz");
    gansu2_set_method(h, "RHF");
    gansu2_set_post_hf(h, "ccsd");
    gansu2_set(h, "quiet", "true");

    if (gansu2_run(h) == 0) {
        double e_hf   = gansu2_get_total_energy(h);
        double e_corr = gansu2_get_post_hf_energy(h);
        printf("HF energy:   %.8f Hartree\n", e_hf);
        printf("CCSD corr:   %.8f Hartree\n", e_corr);
        printf("Total:       %.8f Hartree\n", e_hf + e_corr);
        printf("nao=%d, ne=%d\n", gansu2_get_num_basis(h), gansu2_get_num_electrons(h));
    }

    gansu2_destroy(h);
    gansu2_finalize();
    return 0;
}

Compile:

gcc -o my_calc my_calc.c -L/path/to/lib -lgansu2 -lstdc++ -lm   # -L: the directory holding libgansu2.so

Rust

use std::ffi::CString;
use std::os::raw::{c_int, c_double, c_char, c_void};

extern "C" {
    fn gansu2_init(force_cpu: c_int);
    fn gansu2_finalize();
    fn gansu2_create() -> *mut c_void;
    fn gansu2_destroy(h: *mut c_void);
    fn gansu2_set_xyz(h: *mut c_void, path: *const c_char) -> c_int;
    fn gansu2_set_basis(h: *mut c_void, path: *const c_char) -> c_int;
    fn gansu2_set(h: *mut c_void, key: *const c_char, val: *const c_char) -> c_int;
    fn gansu2_run(h: *mut c_void) -> c_int;
    fn gansu2_get_total_energy(h: *mut c_void) -> c_double;
    fn gansu2_get_post_hf_energy(h: *mut c_void) -> c_double;
}

fn main() {
    unsafe {
        gansu2_init(0);
        let h = gansu2_create();
        let xyz = CString::new("H2O.xyz").unwrap();
        let basis = CString::new("cc-pvdz").unwrap();
        let quiet_k = CString::new("quiet").unwrap();
        let quiet_v = CString::new("true").unwrap();
        let post = CString::new("post_hf_method").unwrap();
        let ccsd = CString::new("ccsd").unwrap();

        gansu2_set_xyz(h, xyz.as_ptr());
        gansu2_set_basis(h, basis.as_ptr());
        gansu2_set(h, quiet_k.as_ptr(), quiet_v.as_ptr());
        gansu2_set(h, post.as_ptr(), ccsd.as_ptr());
        gansu2_run(h);

        let e = gansu2_get_total_energy(h) + gansu2_get_post_hf_energy(h);
        println!("E = {:.8} Hartree", e);

        gansu2_destroy(h);
        gansu2_finalize();
    }
}

Julia

const lib = "libgansu2.so"

ccall((:gansu2_init, lib), Cvoid, (Cint,), 0)
h = ccall((:gansu2_create, lib), Ptr{Cvoid}, ())

ccall((:gansu2_set_xyz, lib), Cint, (Ptr{Cvoid}, Cstring), h, "H2O.xyz")
ccall((:gansu2_set_basis, lib), Cint, (Ptr{Cvoid}, Cstring), h, "cc-pvdz")
ccall((:gansu2_set, lib), Cint, (Ptr{Cvoid}, Cstring, Cstring), h, "post_hf_method", "ccsd")
ccall((:gansu2_set, lib), Cint, (Ptr{Cvoid}, Cstring, Cstring), h, "quiet", "true")
ccall((:gansu2_run, lib), Cint, (Ptr{Cvoid},), h)

e_hf   = ccall((:gansu2_get_total_energy, lib), Cdouble, (Ptr{Cvoid},), h)
e_corr = ccall((:gansu2_get_post_hf_energy, lib), Cdouble, (Ptr{Cvoid},), h)
println("E = $(e_hf + e_corr) Hartree")

ccall((:gansu2_destroy, lib), Cvoid, (Ptr{Cvoid},), h)
ccall((:gansu2_finalize, lib), Cvoid, ())

JavaScript (Node.js with ffi-napi)

const ffi = require('ffi-napi');
const ref = require('ref-napi');

const gansu2 = ffi.Library('./libgansu2.so', {
    'gansu2_init':               ['void',   ['int']],
    'gansu2_finalize':           ['void',   []],
    'gansu2_create':             ['pointer', []],
    'gansu2_destroy':            ['void',   ['pointer']],
    'gansu2_set_xyz':            ['int',    ['pointer', 'string']],
    'gansu2_set_basis':          ['int',    ['pointer', 'string']],
    'gansu2_set':                ['int',    ['pointer', 'string', 'string']],
    'gansu2_run':                ['int',    ['pointer']],
    'gansu2_get_total_energy':   ['double', ['pointer']],
    'gansu2_get_post_hf_energy': ['double', ['pointer']],
});

gansu2.gansu2_init(0);
const h = gansu2.gansu2_create();
gansu2.gansu2_set_xyz(h, 'H2O.xyz');
gansu2.gansu2_set_basis(h, 'cc-pvdz');
gansu2.gansu2_set(h, 'post_hf_method', 'ccsd');
gansu2.gansu2_set(h, 'quiet', 'true');
gansu2.gansu2_run(h);

const E = gansu2.gansu2_get_total_energy(h) + gansu2.gansu2_get_post_hf_energy(h);
console.log(`E = ${E.toFixed(8)} Hartree`);

gansu2.gansu2_destroy(h);
gansu2.gansu2_finalize();

Thread Safety

The C API is NOT thread-safe. GPU state is global. Do not call gansu2_run concurrently from multiple threads. Sequential calls with separate handles are safe.

Error Handling

  • Functions returning int return 0 on success, nonzero on error.
  • Functions returning double return 0.0 if the handle is invalid or calculation has not been run.
  • Error messages are printed to stderr.

This site uses Just the Docs, a documentation theme for Jekyll.