Data Tags and Tagarray¶
OpenQP uses a tagarray container to move arrays and scalar records across Fortran, C, and Python. It is the shared storage for matrices, orbital data, response vectors, SOC arrays, Hessians, and other intermediate or result data that must survive across language boundaries.
The container is provided by
Open-Quantum-Platform/tagarray
(v1.0.0), pinned as an external dependency in external/CMakeLists.txt.
Naming¶
Tag names use the OQP:: prefix. Fortran code usually imports named constants
from source/tagarray_driver.F90, such as:
| Tag | Typical content |
|---|---|
OQP::DM_A, OQP::DM_B |
Alpha and beta density matrices. |
OQP::FOCK_A, OQP::FOCK_B |
Alpha and beta Fock matrices. |
OQP::E_MO_A, OQP::E_MO_B |
Molecular-orbital energies. |
OQP::VEC_MO_A, OQP::VEC_MO_B |
Molecular-orbital coefficient matrices. |
OQP::Hcore, OQP::SM, OQP::TM |
Core Hamiltonian, overlap, and kinetic-energy matrices. |
OQP::td_energies, OQP::td_bvec_mo |
TDHF/TDDFT/MRSF response data. |
OQP::soc_eval, OQP::soc_hsoc_re, OQP::soc_hsoc_im |
SOC eigenvalues and Hamiltonian components. |
OQP::hf_hessian |
Native analytical HF/DFT Hessian matrix. |
Fortran Pattern¶
Creating an output record¶
To create a container-owned array and obtain a writable, correctly typed Fortran
pointer to it, use the one-call alloc_or_die:
use oqp_tagarray_driver, only: OQP_hf_hessian, OQP_hf_hessian_comment
real(kind=dp), contiguous, pointer :: hess_store(:,:)
! Allocate the record AND bind the pointer in a single call. The TA_TYPE_* id is
! inferred from the pointer kind, the shape is given as plain integers, an
! existing record under the tag is replaced, and a failure aborts with a message.
call infos%dat%alloc_or_die(OQP_hf_hessian, (/ ncart, ncart /), hess_store, &
description=OQP_hf_hessian_comment)
alloc_or_die replaces the older three-step ritual (reserve_data, then
data_has_tags, then tagarray_get_data). A status-returning alloc variant is
available when a module wants to handle the error itself, and a free-function
spelling ta_allocate(infos%dat, ...) exists for those who prefer it:
integer(c_int32_t) :: status
status = infos%dat%alloc(OQP_hf_hessian, (/ ncart, ncart /), hess_store, &
description=OQP_hf_hessian_comment)
if (status /= TA_OK) call show_message(get_status_message(status), WITH_ABORT)
Supported element types are real64/real32/int32/int64/complex(real64), pointer ranks 1–3.
Reading an existing record¶
To consume a record produced by an earlier stage, confirm it exists and bind a
typed pointer with tagarray_get_data:
use oqp_tagarray_driver, only: OQP_SM, data_has_tags, tagarray_get_data
real(kind=dp), contiguous, pointer :: smat(:)
call data_has_tags(infos%dat, [character(len=80) :: OQP_SM], &
module_name, subroutine_name, abort=.true.)
call tagarray_get_data(infos%dat, OQP_SM, smat)
Low-level operations¶
For records that alloc_or_die does not cover — an integer(8)-sized shape
(for example the nbf**4 in-core ERI tensor) or a tag that is filled on the C
side with no Fortran pointer — use the low-level container methods directly. The
create shape is integer(c_int64_t):
status = infos%dat%create(OQP_ERI_AO, TA_TYPE_REAL64, [nbf4], &
description=OQP_ERI_AO_comment, override=.true.)
call infos%dat%erase([character(len=80) :: OQP_QMAT]) ! invalidate a stale tag
Use the typed constants and comments in tagarray_driver.F90 instead of
hard-coded strings when adding stable records.
C Bridge¶
The native C interface exposes generic tag access through:
| Function | Purpose |
|---|---|
oqp_get(handle, code, type_id, ndims, dims, value) |
Return a pointer, type, dimensions, and data length for an existing tag. |
oqp_alloc(handle, code, type_id, ndims, dims, value) |
Allocate storage for a tag and return a writable pointer. |
oqp_del(handle, code) |
Delete a tag record. |
These are low-level functions. Callers must respect the returned type and dimensions.
Python Access¶
Python accesses tagarray records through Molecule.data:
td_energies = mol.data["OQP::td_energies"]
soc_eval = mol.data["OQP::soc_eval"]
Molecule also creates convenience getters for common tags. For example,
OQP::DM_A becomes mol.get_dm_a(), and OQP::td_energies becomes
mol.get_td_energies().
Contributor Checklist¶
When adding a new shared data record:
- Add a stable
OQP::...constant and comment insource/tagarray_driver.F90. - Create the record and bind its pointer in one call with
infos%dat%alloc_or_die(tag, shape, ptr, description=...)(or the low-levelcreateforinteger(8)shapes or C-filled tags), passing the shape that matches the pointer rank. - Read upstream records with
data_has_tags+tagarray_get_data. - Add it to Python result handling only if users or workflows need it.
- Add tests that check the tag is populated with the expected shape and data type.
- Document user-facing result tags in Results and Molecule Data.