Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
900992f
fci: add core GAS FCI C kernels
yideng2025 Jul 19, 2026
bb8ee90
build: add CMake target for GAS FCI kernels
yideng2025 Jul 19, 2026
c0c298d
feat(mcscf): add GASCI solver
yideng2025 Jul 27, 2026
661b773
fix(mcscf): finalize GASCI kernel and Python interfaces
yideng2025 Jul 27, 2026
c19f834
test(mcscf): add GASCI tests and examples
yideng2025 Jul 27, 2026
64a2d7d
fix(mcscf): propagate solver spin through GASCI
yideng2025 Jul 27, 2026
4bb49e3
fix(mcscf): address GASCI review feedback
yideng2025 Jul 27, 2026
39bf496
fix(mcscf): label GASCI kernel output
yideng2025 Jul 27, 2026
830cefc
examples: validate GASCI energies against OpenMolcas
yideng2025 Jul 28, 2026
9b05539
mcscf: add O2 GASCI energy regression test
yideng2025 Jul 28, 2026
635e413
mcscf: add OpenMolcas GASCI regression coverage
yideng2025 Jul 29, 2026
3b845a4
Merge upstream master into feature/gasci
yideng2025 Aug 8, 2026
83e2ba7
mcscf: add GAS-FCI projection validation
yideng2025 Aug 9, 2026
be5ca13
mcscf: unify GAS Hamiltonian contraction plans
yideng2025 Aug 9, 2026
8fa10f9
mcscf: move spin-free GAS RDM assembly to Python
yideng2025 Aug 9, 2026
2b1443c
mcscf: manage GAS contraction intermediates in Python
yideng2025 Aug 9, 2026
dded087
mcscf: reuse PySCF electron-count unpacking
yideng2025 Aug 9, 2026
9569800
mcscf: require integer GAS restriction inputs
yideng2025 Aug 9, 2026
e928f40
mcscf: simplify GAS scalar validation
yideng2025 Aug 9, 2026
336a2d2
mcscf: inline GAS CAS block construction
yideng2025 Aug 9, 2026
088d544
mcscf: remove unused GAS helper
yideng2025 Aug 9, 2026
93604c7
mcscf: align GAS diagonal selection with PySCF
yideng2025 Aug 9, 2026
bcdc313
mcscf: reuse GAS space for CI initial guesses
yideng2025 Aug 9, 2026
73bede5
mcscf: reuse CASCI one-electron Hamiltonian helper
yideng2025 Aug 9, 2026
f72f9f9
mcscf: add transition metal RASCI example
yideng2025 Aug 9, 2026
8934119
fix(mcscf): update Al2FeO4+ RASCI orbitals
yideng2025 Aug 9, 2026
2c540a7
refactor(mcscf): make GAS binomial table static
yideng2025 Aug 9, 2026
9f7520a
style(mcscf): clean up GAS comments and spacing
yideng2025 Aug 10, 2026
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
43 changes: 43 additions & 0 deletions examples/mcscf/90_gasci_spin_supergroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env python
#
# Author: Yi Deng <yideng@uchicago.edu>
#

"""Fixed-orbital GASCI with an explicit spin-supergroup set D."""

import numpy

from pyscf import gto
from pyscf import scf
from pyscf.mcscf import gasci


mol = gto.M(
atom="N 0 0 0; N 0 0 1.10",
basis="sto-3g",
spin=0,
verbose=0,
)
mf = scf.RHF(mol).run()

# Each row is (alpha occupations, beta occupations). Rows are normalized to
# lexicographic order and duplicates are removed before entering the C kernel.
gas_restr = numpy.asarray([
[0, 2, 2, 0],
[1, 1, 1, 1],
[2, 0, 0, 2],
], dtype=numpy.int32)

mc = gasci.GASCI(
mf, 4, (2, 2), ncore=5,
gas_orbs=(2, 2),
gas_restr=gas_restr,
gas_restr_type="spin-supergroup",
)
mc.verbose = 4
e_tot, e_gas, ci, _, _ = mc.kernel()

print("GASCI total energy = %.12f" % e_tot)
print("GASCI active-space energy = %.12f" % e_gas)
print("GAS determinant count = %d" % ci.size)
print("GAS space information = %s" % mc.gas_space_info())
38 changes: 38 additions & 0 deletions examples/mcscf/91_gas_restriction_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env python
#
# Author: Yi Deng <yideng@uchicago.edu>
#

"""Normalize the four supported GAS restriction input formats."""

import numpy

from pyscf.mcscf import addons_gas


gas_orbs = (2, 2)
nelec = (2, 2)

spin_supergroups = numpy.asarray([
[2, 0, 0, 2],
[1, 1, 1, 1],
[0, 2, 2, 0],
[1, 1, 1, 1], # Duplicate rows are removed.
])
supergroups = numpy.asarray([[2, 2]])
cumulative_occ = numpy.asarray([[2, 2], [4, 4]])

for restriction_type, restriction in (
("spin-supergroup", spin_supergroups),
("supergroup", supergroups),
("cumulative-occ", cumulative_occ)):
blocks = addons_gas.normalize_gas_restr(
gas_orbs, nelec, restriction, restriction_type)
print("%-17s ->\n%s" % (restriction_type, blocks))

ras_blocks = addons_gas.normalize_gas_restr(
(1, 2, 1), nelec,
{"max_holes": 1, "max_particles": 1},
"ras",
)
print("ras ->\n%s" % ras_blocks)
48 changes: 48 additions & 0 deletions examples/mcscf/92_gasci_multiroot_rdm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env python
#
# Author: Yi Deng <yideng@uchicago.edu>
#

"""Multiroot GASCI with cumulative restrictions and state-resolved RDMs."""

import numpy

from pyscf import gto
from pyscf import scf
from pyscf.mcscf import gasci


mol = gto.M(
atom="N 0 0 0; N 0 0 1.10", basis="sto-3g", spin=0, verbose=0)
mf = scf.RHF(mol).run()

# Each row gives the lower and upper cumulative electron occupation after
# adding the corresponding GAS subspace.
mc = gasci.GASCI(
mf, 4, (2, 2), ncore=5,
gas_orbs=(2, 2),
gas_restr=[[1, 3], [4, 4]],
gas_restr_type="cumulative-occ",
)
mc.fcisolver.nroots = 3
mc.verbose = 4
energies, _, _, _, _ = mc.kernel()

for state, energy in enumerate(numpy.asarray(energies).reshape(-1)):
dm1, dm2 = mc.make_gasdm12(state=state)
ss, multiplicity = mc.spin_square(state=state)
pair_trace = numpy.einsum("pprr", dm2).real
print("state %d E = %.12f Tr(D1) = %.8f S^2 = %.8f mult = %.4f" %
(state, energy, numpy.trace(dm1), ss, multiplicity))
print("state %d Tr_pair(D2) = %.8f" % (state, pair_trace))

tdm1, tdm2 = mc.trans_gasdm12(bra_state=0, ket_state=2)
print("transition 0 -> 2: ||D1|| = %.8f ||D2|| = %.8f" %
(numpy.linalg.norm(tdm1), numpy.linalg.norm(tdm2)))

_, natural_occ = mc.get_gas_natorb(state=0)
_, pseudo_occ = mc.get_gas_pseudo_natorb(state=0)
print("natural occupations = %s" % natural_occ)
for igas, occupations in enumerate(pseudo_occ):
print("GAS%d pseudo-natural occupations = %s" %
(igas + 1, occupations))
75 changes: 74 additions & 1 deletion pyscf/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,77 @@
cmake_minimum_required (VERSION 3.5)
project (pyscf_forge)
Comment thread
sunqm marked this conversation as resolved.

# Build only the GAS FCI kernel library. This mode is intended for
# reproducible local kernel builds and deliberately bypasses unrelated
# dependencies such as BLAS, FFTW, and the other PySCF-forge extensions.
option(
BUILD_GAS_FCI_ONLY
"Configure only the GAS FCI shared library"
OFF
)

option(ENABLE_OPENMP "Compiling C extensions with openmp" ON)

function(add_gas_fci_library)
set(GAS_FCI_SOURCE_FILES
mcscf/fci_string_gas.c
mcscf/fci_contract_gas.c
mcscf/fci_hdiag_gas.c
mcscf/fci_rdm_gas.c
)

add_library(clib_fci_gas SHARED ${GAS_FCI_SOURCE_FILES})

target_include_directories(clib_fci_gas PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/mcscf
)

target_compile_features(clib_fci_gas PRIVATE c_std_11)

if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(clib_fci_gas PRIVATE
-Wall
-Wextra
-Wpedantic
)
endif()

target_link_libraries(clib_fci_gas PRIVATE m)

if(ENABLE_OPENMP AND TARGET OpenMP::OpenMP_C)
target_link_libraries(clib_fci_gas PRIVATE OpenMP::OpenMP_C)
endif()

set_target_properties(clib_fci_gas PROPERTIES
LINKER_LANGUAGE C
C_STANDARD 11
C_STANDARD_REQUIRED ON
C_EXTENSIONS OFF
CLEAN_DIRECT_OUTPUT 1
LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_NAME "fci_gas"
)
endfunction()

if(BUILD_GAS_FCI_ONLY)
if(NOT ENABLE_OPENMP)
message(FATAL_ERROR
"BUILD_GAS_FCI_ONLY=ON requires ENABLE_OPENMP=ON"
)
endif()

find_package(OpenMP REQUIRED COMPONENTS C)

if(NOT TARGET OpenMP::OpenMP_C)
message(FATAL_ERROR
"OpenMP was reported as found, but OpenMP::OpenMP_C is unavailable"
)
endif()

add_gas_fci_library()
return()
endif()

set(CMAKE_VERBOSE_MAKEFILE OFF)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
Expand Down Expand Up @@ -71,7 +142,6 @@ find_package(BLAS REQUIRED)
#find_package (LAPACK REQUIRED)

# OpenMP
option(ENABLE_OPENMP "Compiling C extensions with openmp" ON)
set(OPENMP_C_PROPERTIES "")
if(ENABLE_OPENMP)
find_package(OpenMP)
Expand Down Expand Up @@ -112,6 +182,9 @@ else ()
set(CMAKE_INSTALL_RPATH "\$ORIGIN:\$ORIGIN/deps/lib:\$ORIGIN/deps/lib64")
endif ()

# Build the GAS FCI kernel library as part of the normal PySCF-forge build.
add_gas_fci_library()

# Build the occri library (optional - depends on availability of FFTW, OpenMP)
option(BUILD_OCCRI "Build OCCRI C extension (requires FFTW, OpenMP)" ON)

Expand Down
Loading
Loading