Skip to content

Add fixed-cell i-PI socket driver with validated property responses - #7609

Open
Phorbol wants to merge 27 commits into
deepmodeling:developfrom
Phorbol:feature/fixed-cell-ipi-socket
Open

Add fixed-cell i-PI socket driver with validated property responses#7609
Phorbol wants to merge 27 commits into
deepmodeling:developfrom
Phorbol:feature/fixed-cell-ipi-socket

Conversation

@Phorbol

@Phorbol Phorbol commented Jul 7, 2026

Copy link
Copy Markdown

What's changed?

Add an opt-in, persistent fixed-cell i-PI socket client for repeated external energy, force, and stress evaluations. ABACUS uses calculation scf with socket_driver true; Relax_Driver dispatches to Socket_Driver. Atomic positions can change, but cell, species, atom count, and electronic-structure settings must remain fixed.

The client reads results directly from the completed ESolver frame, not from output files. POSDATA updates positions and runs SCF, then publishes energy, enabled derivatives, and convergence metadata together. GETFORCE consumes and clears that frame. Input validation covers finite values, atom counts, cell conditioning and inverse consistency, including ASE's inverse-cell layout. Wire integers use int32.

Energy is always computed. cal_force and cal_stress independently enable derivatives; disabled fields are protocol padding, with presence declared in abacus.socket.properties.v1 extras. SCF nonconvergence is reported as scf_converged=false; available results are returned and the caller chooses an acceptance policy. Stress is supported at a fixed cell; variable-cell updates, NPT, and cell optimization are excluded.

The ASE AbacusSocketIO adapter validates metadata and results, preserves atom ordering, enables requested properties, and restarts the client if a later request expands the property set. New requests clear cached results and convergence metadata; only fully validated responses are published.

Usage and compatibility

INPUT_PARAMETERS
calculation scf
socket_driver true
cal_force true
cal_stress false

Set ABACUS_SOCKET_ADDRESS=localhost:31415 for TCP or ABACUS_SOCKET_ADDRESS=/tmp/ipi_abacus:UNIX for a UNIX socket. AbacusSocketIO selects the endpoint automatically. No additional C++ socket library is required.

Generic i-PI clients must explicitly enable all derivatives they consume: omitted force/stress switches are disabled. Clients ignoring extras cannot distinguish padding from a physical zero or read the convergence flag. AbacusSocketIO requires presence metadata for force/stress; legacy empty extras are accepted only for energy-only results. This is not unconditional backward compatibility with older ABACUS socket binaries.

INPUT Parameter Changes

  • Add socket_driver, restricted to calculation scf.
  • In socket mode, chg_extrap default selects first-order.
  • cal_force is not forced on; force and stress switches remain independent.
  • Updated docs/parameters.yaml, docs/advanced/input_files/input-main.md, and ASE documentation.

Core Module Impact

Socket code is in source/source_relax, registered in both CMake and Makefile object lists. KS runner publishes its current convergence state after SCF; LCAO output receives the current convergence argument while retaining the upstream EXX interface. These shared solver changes require CI regression coverage beyond socket tests.

The fixed-cell hardening branch is integrated, including inverse-layout compatibility and frame-consistency fixes. Unrelated ELPA reports and historical design documents are excluded.

Exact Verification Performed

Local CMake build: GNU C++, MPI enabled for the repository test configuration, LCAO/ELPA/libXC disabled, installed FFTW/BLAS/ScaLAPACK and GTest. GTest requires C++17; production socket/parser sources were additionally checked under C++11.

cmake --build /tmp/abacus-pr7609-check/build --target \
  MODULE_RELAX_socket_ipi_test MODULE_RELAX_socket_frame_test \
  MODULE_RELAX_socket_driver_test MODULE_IO_read_item_serial -j 4

OMP_NUM_THREADS=1 ctest --test-dir /tmp/abacus-pr7609-check/build \
  --output-on-failure \
  -R 'MODULE_RELAX_socket_(ipi|frame|driver)_test|MODULE_IO_read_item_serial'

PYTHONPATH=interfaces/ASE_interface \
  /home/gengjianrui/bin/abacus-variable-cell-runtime/venv/bin/python \
  -m unittest abacuslite.core.TestAbacusCalculator -k socket -v

g++ -std=c++11 -fsyntax-only -Isource \
  -Isource/source_base/module_container \
  -I/opt/devtools/fftw/fftw-3.3.10/include \
  source/source_relax/socket_frame.cpp \
  source/source_relax/socket_ipi.cpp \
  source/source_relax/socket_driver.cpp \
  source/source_io/module_parameter/read_inp_sys.cpp

python3 tools/03_code_analysis/agent_governance_check.py \
  --base upstream/develop --head HEAD --format text
git diff --check

Results: 4/4 CTest targets passed; 10/10 ASE socket tests passed; C++11 syntax checks passed. Expanded the actual Makefile OBJS_ABACUS list and verified socket_driver.o, socket_ipi.o, and socket_frame.o appear exactly once. Governance reports header-dependency warnings only.

Regression coverage includes two different consecutive geometries with corresponding energy/force/virial/convergence changes, duplicate GETFORCE rejection, invalid-next-frame rejection, nonorthogonal ASE cell layout, optional properties, and clearing stale ASE results after a failed response. The stale-cache regression failed before the fix and passed afterward.

Limits: driver tests use a fake solver and serial socket execution. No fresh full Intel build, multi-rank socket runtime test, or real-DFT socket-versus-independent-frame comparison was completed for this integrated revision. Full build/integration CI is pending; prior branch numerical results are not evidence for this revision.

Linked Issue

No linked issue; this introduces an optional external-driver interface.

Governance

New headers use standard-library types required by their public declarations and value members. No new default arguments or third-party dependency. Input docs and both build paths are updated. No global-dependency budget blocker was reported; no exception is requested.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Comment thread source/source_relax/socket_ipi.h
Comment thread source/source_main/driver_run.cpp Outdated
{
ModuleBase::TITLE("Driver", "driver_run");

const std::string cal = PARAM.inp.calculation;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not a good idea to add new function here,

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in the later refactor. driver_run.cpp no longer contains socket-specific helper logic. The normal calculation dispatch remains calculation-based, and socket mode is handled inside Relax_Driver through the separate input flag socket_driver.

Comment thread source/source_main/driver_ipi.cpp Outdated
return GlobalV::MY_RANK == IPI_RANK_ROOT;
}

void bcast_int(int& value)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have 'bcast_int' function that can be used without writing a new one

@Phorbol Phorbol Jul 20, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in the refactor. The old driver_ipi.cpp path was removed. The current socket driver uses Parallel_Common::bcast_int for integer broadcast. A small socket-local wrapper remains only to centralize MPI/non-MPI handling and to support string/header broadcast.

Comment thread source/source_main/driver_ipi.cpp Outdated
const std::string message = bcast_string(root_message);
if (root_failed != 0)
{
throw std::runtime_error(message.empty() ? "i-PI socket I/O failed" : message);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use WARNING_QUIT

@Phorbol Phorbol Jul 20, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed at the driver level. Socket_Driver now reports fatal socket failures through ModuleBase::WARNING_QUIT. The lower-level IpiSocket class still uses exceptions internally for syscall/read/write/connect failures, which are caught by Socket_Driver and converted to WARNING_QUIT.

Comment thread source/source_main/driver_ipi.cpp Outdated
CalculationModeGuard calculation_guard("scf");

UnitCell ucell;
ucell.setup(PARAM.inp.latname, PARAM.inp.ntype, PARAM.inp.lmaxmax, PARAM.inp.init_vel, PARAM.inp.fixed_axes);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest not using PARAM (global variable)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed for the socket-specific path. Socket_Driver now receives the needed state explicitly through ESolver, UnitCell, Input_para, and ofs_running, and socket_driver.cpp no longer depends directly on the global PARAM object. Some existing ABACUS driver/relax infrastructure still uses PARAM, but the socket-specific implementation does not introduce the previous broad PARAM dependency.

@mohanchen mohanchen added Feature Discussed The features will be discussed first but will not be implemented soon Refactor Refactor ABACUS codes Interfaces Interfaces with other packages labels Jul 8, 2026
jianrui geng and others added 3 commits July 9, 2026 09:24
Route calculation=socket through Relax_Driver, keep ESolver lifecycle in driver_run, and add source_relax socket transport tests.
@Phorbol
Phorbol force-pushed the feature/fixed-cell-ipi-socket branch from 341a302 to fe2c2a3 Compare July 9, 2026 03:15
Comment thread source/source_main/driver_run.cpp Outdated
const bool socket_mode = (socket_esolver_inp.calculation == "socket");
if (socket_mode)
{
socket_esolver_inp.calculation = "scf";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, but here it seems not appropriate to set the calculation as 'socket' first and then change it to 'scf', it may better to design another variable other than calculation

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed. The socket mode is no longer represented by calculation="socket". The input now keeps calculation="scf" and enables the independent boolean option socket_driver. The input checker rejects socket_driver with non-scf calculations.

Comment thread source/source_relax/CMakeLists.txt Outdated
relax
OBJECT
relax_data.cpp
ipi_socket.cpp

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems better to name the file name as socket_ipi.cpp, consistent with the socket_driver.cpp

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed. The files were renamed to socket_ipi.cpp/socket_ipi.h, and source_relax/CMakeLists.txt now builds socket_ipi.cpp.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you provide some examples in the 'interface' directory to demonstrate that the function can run successfully?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed. Added interfaces/ASE_interface/examples/socketio.py. It runs ABACUS through AbacusSocketIO, compares socket SCF energy/forces with normal FileIO SCF, and benchmarks repeated force evaluations. I also added documentation in docs/advanced/interface/ase.md.

* relax: perform structure relaxation calculations, the relax_nmax parameter depicts the maximal number of ionic iterations
* cell-relax: perform cell relaxation calculations
* md: perform molecular dynamics simulations
* socket: run as a socket client for external drivers using the i-PI protocol

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have an example to demonstrate how to use this feature?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed. The usage is now documented in docs/advanced/interface/ase.md, including AbacusSocketIO setup, ABACUS_SOCKET_ADDRESS endpoint formats, Unix socket vs TCP behavior, fixed-cell limitation, immutable INPUT/STRU settings, and atom-order handling.

@mohanchen

Copy link
Copy Markdown
Collaborator

Thanks @Phorbol for your contribution? Could you kindly reply to my questions?

@Phorbol

Phorbol commented Jul 20, 2026

Copy link
Copy Markdown
Author

@mohanchen I have pushed follow-up changes and replied to the review threads.

The current implementation now:

  • uses calculation="scf" with a separate socket_driver boolean input, instead of introducing calculation="socket";
  • moves socket execution out of driver_run.cpp into the relax/socket driver path;
  • renames the i-PI socket files to socket_ipi.*;
  • adds ASE AbacusSocketIO support with an interface example in interfaces/ASE_interface/examples/socketio.py;
  • documents ABACUS_SOCKET_ADDRESS endpoint formats, fixed-cell behavior, immutable INPUT/STRU settings, atom ordering, MPI/GPU notes, and socket running_scf.log behavior;
  • regenerates input-main.md from parameters.yaml to keep the docs CI check in sync.

A few behavior details are worth noting:

  • In socket mode, ABACUS still writes OUT.ABACUS/running_scf.log because calculation remains scf. Since one ABACUS client process is kept alive, multiple socket SCF evaluations from the same AbacusSocketIO instance are appended to the same running_scf.log. The per-step energy/force results are returned through the i-PI socket to ASE; running_scf.log should be treated mainly as the diagnostic log for the socket client. This is documented in docs/advanced/interface/ase.md.
  • The i-PI POSDATA message does not carry element symbols. AbacusSocketIO handles this by sorting the internal socket atoms consistently with the STRU species grouping and mapping returned forces back to the original ASE Atoms order. This avoids silent force/atom mismatches for structures read from CIF/extxyz/POSCAR-like formats, and is documented and covered by a unit test.
  • The intended use case is high-throughput fixed-cell force/energy evaluation from external drivers, especially ASE workflows(active learning for MLIP or TS search such as ATST) where many structures share the same ABACUS input setup. It can also serve finite-displacement force-evaluation workflows before phonon/thermal-conductivity post-processing, while force-constant fitting/post-processing remains handled by tools such as Phonopy/Phono3py.

Please let me know if any thread still needs further changes.

@Phorbol

Phorbol commented Jul 20, 2026

Copy link
Copy Markdown
Author

This PR intentionally implements fixed-cell socket evaluations first. The i-PI POSDATA message carries cell data, but changing the ABACUS cell safely would require reinitializing cell-dependent state such as basis/grid/k-points/neighbors and possibly electronic-structure setup. To avoid silent incorrect results, AbacusSocketIO rejects cell changes on the ASE side, and the ABACUS socket driver also checks incoming POSDATA cells against the initial STRU cell and exits if they differ.

The currently supported scope is repeated energy/force evaluation for structures with the same cell, atom count, species, pseudopotentials, basis, k-points, spin setting, and other core INPUT/STRU parameters. Changing any of these requires creating a new AbacusSocketIO instance and launching a new ABACUS client process.

@mohanchen

Copy link
Copy Markdown
Collaborator

Thanks for your contribution, but I still have some questions. It would be easier to chat in another way, could you write an email to me? (mohanchen@pku.edu.cn) @Phorbol

@Phorbol Phorbol changed the title Add fixed-cell i-PI socket driver Add fixed-cell i-PI socket driver with validated property responses Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature Discussed The features will be discussed first but will not be implemented soon Interfaces Interfaces with other packages Refactor Refactor ABACUS codes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants