Skip to content

Refactor/merge openmp - #7446

Open
lijianing-sudo wants to merge 127 commits into
deepmodeling:developfrom
Audrey-777:refactor/merge-openmp
Open

Refactor/merge openmp#7446
lijianing-sudo wants to merge 127 commits into
deepmodeling:developfrom
Audrey-777:refactor/merge-openmp

Conversation

@lijianing-sudo

Copy link
Copy Markdown

PR: OpenMP Parallel Optimization for ABACUS MD Module and ML Potential Interfaces (NEP/DPMD/LJ)

Reminder

  • Have you linked an issue with this pull request?
  • Have you added adequate unit tests and/or case tests for your pull request?
  • Have you noticed possible changes of behavior below or in the linked issue?
  • Have you explained the changes of codes in core modules of ESolver, HSolver, ElecState, Hamilt, Operator or Psi? (ignore if not applicable)

Linked Issue

Fix #...

Unit Tests and/or Case Tests for my changes

  • A unit test is added for each new feature or bug fix.

Existing Unit Tests Pass:

  • MODULE_MD_LJ_pot (6 tests)
  • MODULE_MD_func (7 tests)
  • MODULE_MD_fire
  • MODULE_MD_verlet
  • MODULE_MD_nhc
  • MODULE_MD_msst
  • MODULE_MD_lgv

Test Infrastructure:

  • Introduced shared MD test fixtures (source/source_md/test/md_test_fixture.h) to eliminate duplicated SetUp/TearDown across 6 test files.

Microbenchmark Verification:

  • Independent C++ microbenchmarks were written for each optimized kernel (see Test/openmp_nep_basic_benchmark.cpp and companion scripts).
  • 2 million atoms, repeated 5 times, tested at 1/2/4/8/16 threads on Intel Xeon Platinum 8163.
  • All per-atom write loops produce bitwise-identical results (max_abs_diff = 0).
  • Reduction loops show floating-point differences at the 1e-10 to 1e-8 level due to summation order changes — expected and acceptable for MD trajectories.

What's changed?

This PR integrates OpenMP parallelization from three feature branches (refactor/md-factory, refactor/parallel-optimize, refactor/md-openmp-remainder) into the ABACUS MD module and ML potential interfaces. 22 parallel loops or worksharing regions are added across 12 source files (+3934/−342 lines total).

1. MD Base Loops (source/source_md/)

Function File Strategy
MD_base::update_pos() md_base.cpp #pragma omp parallel for schedule(static)
MD_base::update_vel() md_base.cpp #pragma omp parallel for schedule(static)
kinetic_energy() md_func.cpp reduction(+:ke)
force_virial() force copy md_func.cpp Parallel per-atom copy
temp_vector() md_func.cpp 9 scalar reductions instead of shared-matrix accumulation
rescale_vel() md_func.cpp schedule(static)

All loops use if (natom >= 256) to skip parallel overhead for small systems.

2. NEP Interface (source/source_esolver/esolver_nep.cpp/.h)

  • Added atom_type_index / atom_local_index index caches for flat iat-based parallel loops.
  • Parallelized: coordinate buffer fill, per-atom energy reduction, force copy-back with unit conversion, and 9-component per-atom virial reduction.
  • NEP virial: reorganized from 9 separate full-array scans into a single per-atom scan with 9 scalar reductions — algorithmic + parallel gains combined (14.24× speedup at 8 threads).
  • nep.compute() external library call remains serial.

3. DPMD Interface (source/source_esolver/esolver_dp.cpp/.h)

  • Added iat → (it, ia) index caches.
  • Parallelized: coordinate buffer fill and model force copy-back with unit conversion.
  • Introduced persistent member buffers (dp_cell, dp_coord, dp_model_force, dp_model_virial) to avoid repeated allocations.
  • dp.compute() external library call and 3×3 virial copy-back remain serial.

4. Thermostat and Barostat (source/source_md/)

Class Method File
Verlet thermalize() velocity rescaling verlet.cpp
MSST rescale() shock-direction velocity scaling msst.cpp
MSST vel_sum() velocity norm reduction msst.cpp
MSST propagate_vel() per-atom velocity propagation msst.cpp
NoseHoover particle_thermo() final velocity scaling nhchain.cpp
NoseHoover vel_baro() barostat velocity update nhchain.cpp

Thermostat chain recurrence integration and cell dilation remain serial.

5. FIRE Algorithm (source/source_md/fire.cpp)

FIRE::check_fire() parallelized in three phases:

  1. Three-scalar reduction for P, sumforce, normvel
  2. Parallel velocity-force mixing
  3. Parallel velocity zeroing (in P <= 0 branch)

Scalar state updates (alpha, negative_count, dt) remain serial.

6. LJ Interface (source/source_esolver/esolver_lj.cpp/.h)

  • Added global atom index cache.
  • Restructured nested type-iteration loops into flat iat-based loop.
  • schedule(dynamic, 32) to handle neighbor-count imbalance.
  • Thread-local potential and virial arrays with atomic (energy) and critical (virial) reduction at thread exit — no per-neighbor locks.

7. Code Quality Refactors

  • Extracted MD statistics helpers: calc_kinetic_state() / calc_stress_state() (md_func.h, md_statistics.h).
  • MD runner factory function: new/deletestd::unique_ptr (run_md.cpp).
  • Shared test fixture base classes to reduce duplication across 6 MD test files.

Performance Summary (Microbenchmark, 8 threads, 2M atoms, Xeon Platinum 8163)

Category Kernel Speedup Efficiency
MD Base update_pos 7.36× 92.0%
MD Base update_vel 7.19× 89.9%
MD Base kinetic_energy 6.98× 87.2%
MD Base temp_vector 7.38× 92.2%
NEP coord_fill 7.15× 89.4%
NEP energy_sum 8.03× 100.4%
NEP force_fill 6.99× 87.4%
NEP virial_sum 14.24× 177.9%*
DPMD coord_fill 5.50× 68.8%
DPMD force_copy 7.19× 89.9%
Verlet thermalize 7.80× 97.5%
MSST rescale 7.28× 91.1%
MSST propagate_vel 7.18× 89.7%
NHC particle_thermo 7.21× 90.2%
FIRE check_fire (mix) 7.64× 95.6%
LJ runner core loop 6.96× 87.0%

*NEP virial 14.24× includes loop reorganization benefits beyond pure 8-thread scaling.

Known Limitations & Future Work

  • End-to-end tests: NEP and DPMD optimizations lack end-to-end tests with real external model libraries (__NEP, deepmd).
  • LJ parallel path: existing LJ unit tests use 4 atoms (< 256 threshold), covering only the serial path.
  • MPI + OpenMP hybrid: microbenchmarks are single-process; oversubscription risks under mixed MPI/OpenMP have not been characterized.
  • Thread threshold: nat >= 256 is an empirical uniform threshold; per-kernel tuning (64/128/256/512) is recommended.
  • LJ scheduling: schedule(dynamic, 32) vs static and optimal chunk size have not been systematically benchmarked across different neighbor distributions.
  • Microbenchmark results ≠ end-to-end wall-time: excluded overheads include MPI communication, neighbor-list construction, file I/O, and external model computation.

Any changes of core modules? (ignore if not applicable)

The MD ESolver interface layer (esolver_nep.cpp, esolver_dp.cpp, esolver_lj.cpp) is modified to add index caches and parallel worksharing constructs. No changes to the ESolver base class virtual function signatures. All external library calls (nep.compute(), dp.compute()) remain serial and their calling convention is unchanged.

@mohanchen mohanchen added Refactor Refactor ABACUS codes MD & LAM MD and Larege Atomic Models project_learning and removed Refactor Refactor ABACUS codes labels Jun 7, 2026
Comment thread opt_logs/dpmd_interface_20260603.md Outdated

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.

this file is not needed

@mohanchen

Copy link
Copy Markdown
Collaborator

You may first remove unnecessary files, then add tests to show the effects of code refactoring.

@lijianing-sudo
lijianing-sudo force-pushed the refactor/merge-openmp branch from 56538dc to b0fccfa Compare June 26, 2026 11:43
@lijianing-sudo

Copy link
Copy Markdown
Author

Done. Removed unnecessary files (Planners/, Results/, Test/, opt_logs/). The PR now contains only 26 source files across source/source_md/ and source/source_esolver/, plus unit tests in source/source_md/test/. Please let me know if additional performance tests are needed.

You may first remove unnecessary files, then add tests to show the effects of code refactoring.

@lijianing-sudo
lijianing-sudo force-pushed the refactor/merge-openmp branch from b0fccfa to f4ebb41 Compare June 26, 2026 12:26
Add #pragma omp parallel for to major per-atom loops in MD module,
enabling multi-threaded execution for NEP/DPMD potentials and
thermostat/integrator operations.

Scope (23 files):
- source/source_md/: md_base, md_func, fire, msst, nhchain, verlet,
  run_md, md_statistics.h
- source/source_esolver/: esolver_nep, esolver_dp
- source/source_md/test/: 7 unit tests + md_test_fixture.h

Strategy: schedule(static) with if(nat>=256), reduction clauses,
atomic/critical for shared accumulators.
LJ esolver excluded (upstream refactored to UnitCellLite API).

Rebased onto deepmodeling/develop.

Co-Authored-By: Claude <noreply@anthropic.com>
@lijianing-sudo
lijianing-sudo force-pushed the refactor/merge-openmp branch from 4483678 to 72fa195 Compare June 26, 2026 12:52
@lijianing-sudo

Copy link
Copy Markdown
Author

Updated the PR: - Removed unnecessary non-code files (Planners/, Results/, Test/, opt_logs/)

  • Excluded LJ esolver (upstream refactored to UnitCellLite API, incompatible)
  • Rebased onto latest deepmodeling/develop
  • Fixed test CMakeLists.txt for the new module_neighlist dependencies
PR now focuses on 23 source files: core MD loops (md_base, md_func, fire, msst, nhchain, verlet, run_md) + NEP/DPMD 

esolver interfaces + unit tests. All #pragma omp directives follow the same strategy: schedule(static) with ▎ if(nat>=256), reduction clauses for energy/virial, atomic/critical for shared accumulators.

Please let me know if any further changes are needed.

@lijianing-sudo

Copy link
Copy Markdown
Author

All 16 CI checks are now passing.

Critsium-xy and others added 17 commits June 27, 2026 15:51
…encies (deepmodeling#7521)

* refactor(cell): remove dead source_lcao include from read_atom_species

read_atom_species.cpp included source_lcao/module_ri/serialization_cereal.h
(guarded by __EXX) but uses no cereal/serialization symbols. Removing it
cuts a source_cell -> source_lcao reverse dependency edge.

Add the direct <sstream> include the file actually needs (std::stringstream),
which was previously only available transitively through the cereal header.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(cell): move Magnetism from source_estate to source_cell

The Magnetism class only depends on source_base and is held by value as a
member of UnitCell (source_cell/unitcell.h). It is a fundamental property of
the unit cell, so it belongs in source_cell rather than source_estate.

This removes the unitcell.h -> source_estate header dependency (a core data
structure no longer reaches up into the electronic-state module) and breaks
one direction of the source_cell <-> source_estate cycle.

- git mv source_estate/magnetism.{h,cpp} -> source_cell/
- update all includers to source_cell/magnetism.h
- move the source file entry between CMakeLists and fix the unit-test path

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(base): move output print helpers from source_io to source_base

The `output` class (output.{h,cpp}) is a pure formatter that only operates on
source_base types (realArray, matrix, matrix3, ComplexMatrix). It was sitting
in source_io/module_output but has no dependency on anything above source_base,
so it belongs in source_base as a leaf utility.

Relocating it removes a batch of source_cell -> source_io (and source_pw/
source_psi -> source_io) reverse edges that existed only to reach this printer,
without changing any behavior or namespace.

- git mv source_io/module_output/output.{h,cpp} -> source_base/
- fix the relocated header's own includes (drop ../../source_base/ prefix)
- repoint all includers to source_base/output.h
- move the source entry from source_io to source_base CMakeLists and update
  the relative output.cpp paths in all affected unit-test CMakeLists

Verified: full abacus_basic_para executable builds and links cleanly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Add ASCII Art for ABACUS

* Align the title a bit

* remove original abacus title
…eepmodeling#7525)

* Toolchain: Block installation of prebuilt libtorch when enabling MKL

* Remove dead CMake logic
* fix: align module hs sparse output with threshold

* fix: stabilize module hs sparse output controls

* test: fix module hs regression test builds
…ay (deepmodeling#7536)

The HContainer copy constructor was unconditionally zeroing out the
data_array when wrapping existing memory. This caused getHR_vector()
to erase both spin channels' HR data for nspin=2, resulting in all-zero
HR output when out_mat_hs2 is enabled.

Fix: only zero memory when data_array is nullptr (fresh allocation);
preserve existing data when wrapping external memory.

Also add integration test scf_out_hsr_spin2 (nspin=2 + out_mat_hs2)
and update catch_properties.sh to compare hrs2_nao.csr for nspin=2.
…epmodeling#7513)

* fix: correct Pauli-to-spinor Hamiltonian conversion for nspin=4

Fix two bugs in LCAO non-collinear Hamiltonian construction:

1. Wrong sign in off-diagonal elements: H_{up,down} = B_x + i*B_y (wrong)
   should be B_x - i*B_y (correct), and vice versa for H_{down,up}.
   Fixed by correcting clx_j coefficients in merge_hr_part_to_hR().

2. Missing complex conjugate in lower triangle fill: H(-R) used transpose
   instead of conjugate transpose, breaking Hermiticity for complex matrices.
   Fixed by using std::conj() when filling lower triangle.

These errors caused the non-collinear Hamiltonian to be the complex conjugate
of the correct result, leading to incorrect spin textures in nspin=4 calculations.
The PW code path was not affected.

Add test case and verification script to validate:
- H(R=0) Hermiticity: max|H - H^dagger| < 1e-10
- Off-diagonal phase: Im(H_{up,down}) < 0 for m||+y direction

See tests/03_NAO_multik/verify_hamiltonian_convention/TEST_DESIGN.md for details.

* fix: correct Pauli-to-spinor conversion in DFT+U and DeltaSpin for nspin=4

Fix three critical bugs in non-collinear (nspin=4) LCAO calculations:

1. DFT+U transfer_vu (dftu_lcao.cpp): Fix sign error in Pauli-to-spinor
   conversion. The off-diagonal elements had wrong imaginary part sign:
   - Before: V_{up,down} = 0.5*(V_x + i*V_y)  (wrong)
   - After:  V_{up,down} = 0.5*(V_x - i*V_y)  (correct, from sigma_y)

2. DFT+U force/stress (dftu_force_stress.hpp): Convert VU from Pauli basis
   to spinor basis before force calculation. The old code incorrectly mixed
   Pauli-basis VU with spinor-basis DM.

3. DeltaSpin force/stress (dspin_force_stress.hpp): Convert lambda from
   Pauli basis to spinor basis. The constraint force F = lambda·dM/dR
   requires proper Pauli-to-spinor conversion:
   - lambda_spinor = (lambda_z, lambda_x, lambda_x, -lambda_z)
   for (uu, ud, du, dd) components.

These fixes ensure consistent Pauli-to-spinor conversion across all modules:
- H construction (gint_common.cpp): already fixed
- DFT+U Hamiltonian: fixed in this commit
- DFT+U force/stress: fixed in this commit
- DeltaSpin force/stress: fixed in this commit

Verified by scf_u_spin4 test (nspin=4 + DFT+U): SCF converges correctly.

* chore: remove .py and .md test files from PR

* fix: correct DFT+U force for nspin=4 - DM is stored in Pauli basis, not spinor basis

Two bugs fixed in dftu_force_stress.hpp:
1. Removed incorrect VU Pauli-to-spinor conversion: DM for nspin=4 is stored in
   Pauli basis (rho_0, rho_x, rho_y, rho_z) per func_xyz_to_updown(), so VU must
   also stay in Pauli basis for the force trace formula F = -Tr(VU * dDM/dR).
2. Removed force *= 2.0 for nspin=4: Pauli basis already includes all spin
   channels, unlike nspin=1 where the factor of 2 accounts for spin degeneracy.
Updated scf_u_spin4 result.ref accordingly.

* fix: remove force*=2.0 for nspin=4 in DeltaSpin - Pauli basis already covers all spin channels

* fix: add missing blacs_context to ELPA Constructor 1 for nspin=4 support

Constructor 1 of ELPA_Solver was missing elpa_set_integer("blacs_context", ...)
while Constructor 2 (otherParameter) already had it. Without blacs_context,
ELPA's internal MPI operations (e.g. MPI_Bcast in complex Cholesky and
invert_triangular) can fail with INVALID DATATYPE when using complex eigensolves.
Also update scf_angle_spin4 result.ref with corrected reference energy.

* fix: correct rho_y sign in spinor-to-Pauli DM conversion (func_xyz_to_updown)

For Pauli decomposition: rho = rho_0*I + rho_x*sigma_x + rho_y*sigma_y + rho_z*sigma_z
sigma_y = [[0,-i],[i,0]], so rho_updown = rho_x + i*rho_y, rho_downup = rho_x - i*rho_y
Thus rho_y = Im(rho_updown - rho_downup) = tmp[1].imag() - tmp[2].imag].

Previously the real version had -tmp[1].imag()+tmp[2].imag() = -2*rho_y (wrong sign),
and the complex version had i*(tmp[1].imag()-tmp[2].imag()) = 2i*rho_y (wrong formula).
This broke rotational invariance: mag along y gave wrong energy (~4 eV deviation vs x/z).

* test: update scf_angle_spin4 and scf_u_spin4 result.ref after DM rho_y fix

* chore: revert density_matrix.cpp rho_y fix (wrong branch) and remove verify_hamiltonian_convention test dir

- Revert density_matrix.cpp func_xyz_to_updown rho_y sign fix from
  commit 52ee608 (belongs on a separate DM-fix branch)
- Remove tests/03_NAO_multik/verify_hamiltonian_convention/ (debug helper)
- Update result.ref for scf_angle_spin4 and scf_u_spin4 to match
  current code (Pauli-to-spinor + ELPA fixes only)

* fix: restore density_matrix.cpp rho_y sign fix (paired with gint_common clx_j fix)

The gint_common.cpp fix corrects Pauli→spinor (H construction) and the
density_matrix.cpp fix corrects spinor→Pauli (DM Fourier transform).
Both must use the same σ_y convention for self-consistency.
Also update result.ref files for both test cases.

* fix: correct DFT+U force/stress reference values and clean up empty nspin=4 block

Both VU (from cal_v_of_u) and DMR are stored in Pauli basis for nspin=4,
so the Pauli-to-spinor conversion in force/stress calculation is NOT needed.
The previous result.ref for scf_u_spin4 (totalforceref=6.562) was incorrect
because it was generated with code that mixed Pauli-basis VU with incorrectly
converted values. The correct force is 11.33, consistent with the physical
Pauli-basis trace Tr(VU * dDM/dR).

Changes:
- Remove empty if(nspin==4) block in dftu_force_stress.hpp (no conversion needed)
- Update scf_u_spin4/result.ref: totalforceref 6.562 -> 11.332 (correct value)
- Update scf_angle_spin4/result.ref: energy/stress to match computed values
- Add scf_angle_spin4/threshold: relax energy threshold to 1e-5 eV for
  non-collinear calculation numerical reproducibility
- Update scf_out_dos_spin4/result.ref: force/stress to match computed values
…on and add unit test (deepmodeling#7539)

* Refactor: Share RT-TDDFT projector snap integration

* Docs: Comment RT-TDDFT projector snap integration
* Toolchain: Rely on installed CMake config file for Cereal and RapidJSON

* Remove FindLibxc.cmake

* CMake: Use interface target for feature dependencies

* Add "-Werror=dev" in CMake for "Test" workflow

* Follow-up CMake cleanups

* Document CMAKE_PREFIX_PATH and remove hints for LibXC_DIR

* Fix Libxc version issue and remove fatals that do not make sense

* Follow up to deepmodeling#7521

* CI: Build ABACUS with Ninja generator

* Sync abacus_disable_feature_definitions settings

* Guard every "apt" system package installation under "sudo"
Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
* Test: Refactor DeePKS unit tests

* Test: Address DeePKS unit test review comments
* refactor(cell): remove unused cross-module includes in read_atoms.cpp

Drop two dead includes that create needless reverse dependencies from
source_cell onto higher layers:
  - source_estate/read_orb.h  (elecstate::read_orb_file not used here;
    the real user is read_atoms_helper.cpp)
  - source_basis/module_ao/ORB_read.h  (ORB / LCAO_Orbitals not used here)

Verified by compiling the `cell` target with ENABLE_LCAO=ON so the
former `#ifdef __LCAO` block was actually exercised.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: remove dead cross-module includes on reverse-dependency edges

Static scan + per-target compile verification identified 9 unused
includes that create reverse/lateral dependency edges between modules.
Removing them weakens the coupling without any behavior change:

  io   -> md    input_conv.cpp        (md_func.h)
  estate -> lcao  elecstate_energy_terms.cpp, elecstate_print.cpp
                                       (module_deepks/LCAO_deepks.h)
  lcao -> pw    rdmft_tools.cpp (structure_factor.h),
                wavefunc_in_pw.cpp (soc.h)
  lcao -> io    FORCE_gamma.cpp, FORCE_k.cpp (module_hs/write_HS.h)
  pw   -> io    forces_cc.cpp, forces_scc.cpp (module_output/output_log.h)

Verified by building io_basic, elecstate, rdmft, hamilt_lcao and
module_pwdft (ENABLE_LCAO=ON) after removal; all link targets compile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(esolver): remove 29 dead io includes (esolver -> io hygiene)

Remove unused source_io includes across the esolver drivers. These are
on the allowed esolver->io direction, so this is include hygiene rather
than decoupling, but it trims 29 needless includes.

Verified three ways:
  1. `make esolver` (ENABLE_LCAO=ON) recompiles all 21 TUs, 0 errors.
  2. Feature-guarded headers checked explicitly since __RAPIDJSON,
     __EXX/__LIBRI and __MLALGO are OFF in this build: the json
     (init_info.h/output_info.h) and restart_exx_csr.h symbols are
     unused in their consumers (Json::add_output_scf_mag in
     esolver_ks.cpp comes from output_info.h, which is kept).
  3. Whole-file precise-symbol sweep (incl. all #ifdef blocks) finds
     no specific symbol of any removed header in its consumer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: remove 2 more dead cross-module includes

Two dead includes missed by the first reverse-edge pass:

  estate -> lcao   elecstate_energy_terms.cpp
                   (module_deltaspin/spin_constrain.h; SpinConstrain
                   is not referenced anywhere in the file)
  esolver -> io    esolver_double_xc.cpp
                   (module_hs/write_HS.h; only a comment mentions
                   ModuleIO::write_hsk(), no actual call)

Verified: no header symbol appears anywhere in the consumer (guards
included), and `make elecstate` / `make esolver` build cleanly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: update interfaces with ATAT

* feat: update path to PP&ORB

* feat: re-run the examples use pp&orb in tests/

* feat: update the validation of .orb/.upf extensions

* feat: update the validation of .orb/.upf extensions

---------

Co-authored-by: Zanthoxylum <chenshengjun@localhost.localdomain>
* Support NPZ output for LCAO HSR matrices

* Write NPZ outputs under OUT directory

* Run NPZ integration tests only with CNPY

---------

Co-authored-by: nscc-gz_pinchen_1 <nscc-gz_pinchen_1@users.noreply.github.com>
* Add FindKML.cmake and resolve FFTW3 issue

* FindKML: Add compiler check

* Detect fftwf only if ENABLE_FLOAT_FFTW
Flying-dragon-boxing and others added 30 commits July 31, 2026 19:32
…eling#7717)

Stress_PW::stress_exx only sums same-pool (ik, iq) pairs without the
same-spin restriction used in the EXX energy evaluation, and crashes
on GPU. Previously these combinations ran silently and produced wrong
stress or segfaulted. Now Input_Conv quits with an explicit message when
EXX stress is requested with:
- basis_type = pw and nspin != 1
- basis_type = pw and kpar > 1
- basis_type = pw and device = gpu
- basis_type = lcao_in_pw (EXX energy comes from Exx_Lip, but the
  stress would be evaluated with the pure PW formula)

The supported case (nspin = 1, kpar = 1, CPU) is unchanged.

Co-authored-by: Mohan Chen <mohanchen@pku.edu.cn>
* refactor: use BaseCell in ESolver interface

* fix: align LCAO others override with BaseCell

* fix: link BaseCell in MD unit tests

---------

Co-authored-by: Fei Yang <2501213217@stu.pku.edu.cn>
…deepmodeling#7707)

* Fix H/S matrix output documentation and tests

* Remove H/S matrix integration case

* feat: support folded H/S output for gamma-only

* feat: add unified H/S output options

* fix: align H/S output names and documentation
… for adding an SSH-based, GitHub-hosted control-plane workflow to run ABACUS GPU validation on the SAI Slurm cluster including a new multinode cuSolverMp RT-TDDFT smoke) (deepmodeling#7665)

* [skip ci] ci: add minimal SAI GPU validation

* [skip ci] ci: transfer source bundle in parallel

* [skip ci] ci: retry initial SAI connection

* ci: initialize Lmod preload state

* ci: retry MPI daemon startup once

* ci: retry SAI result download

* ci: stabilize SAI multinode launch and cleanup

* ci: export loaded modules to SAI job steps

* ci: retain SAI cleanup metadata on client failure

* ci: allow SAI results to comment on pull requests

* ci: expose one documented SAI run command

* ci: keep site credit in run summaries

* ci: allow PR result comment updates

* Update config.ini

* ci: provide defaults for local SAI runs

* ci: make remote GPU validation site-neutral

* docs: correct compute provider name

* ci: infer local run paths from the repository

* ci: summarize local GPU validation results

* ci: keep remote connection settings in config

* ci: credit the configured compute provider

* ci: update queued PR result comments in place

* ci: stream remote GPU validation progress

* ci: keep local GPU results outside source trees

* ci: keep transient local results in tmp

* ci: require explicit GPU validation opt-in

* ci: preserve active remote GPU runs

* ci: reuse source cache across sibling branches

* ci: simplify source cache retention

* docs: clarify GPU validation setup

* docs: avoid hard-wrapped prose

* ci: fix empty artifact link fallback

* ci: fail build on unresolved GPU dependencies

* ci: retry variable srun daemon failures
* move module_gint from source_lcao to source_hamilt

* update

* divide the hs_matrix_k.hpp to .h and .cpp files

* update

* move hs_matrix_k.h and .cpp to source_hamilt

* remove one useless header

* update

* update nonlocal.h and nonlocal.cpp, change nonlocal_dh.hpp to nonlocal_dh.cpp

* update nonlocal_fs.cpp

* update

* fix bug

* remove some hpp files

* some updates, change dftu_pw.cpp to setup_dftu_pw.cpp

* fix makefile

* update

* remove redundant output information when init_wfc is atomic but pseudopotentials do not have

---------

Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
* Fix(input): validate contradictory final parameters

* Fix(input): tighten stochastic band validation

* Fix(input): validate complete parallel configuration

* Fix(input): relax stochastic band limit
…#7732)

* ci: honor Triage role for GPU requests

* ci: retry transient Slurm accounting failures
Co-authored-by: Stardust0831 <stardust0831@users.noreply.github.com>
…ce (deepmodeling#7743)

The GPU path of Diago_DavSubspace::refresh() reads this->d_eigenvalue
which was last synchronized in cal_grad() — before diag_zhegvx()
computed the latest eigenvalues. This caused the restarted subspace
Hamiltonian to receive stale diagonal entries on GPU, leading to:
- Davidson eigenvalue oscillation and divergence
- Non-positive-definite overlap matrix
- zhegvx failure and zeroed wavefunctions

The CPU path already used the up-to-date eigenvalue_in_hsolver argument.
Fix the GPU path to re-sync d_eigenvalue from eigenvalue_in_hsolver.

Bug introduced by 8f7d319 (PR deepmodeling#6493).

Co-authored-by: dyzheng <zhengdy@bjaisi.com>
Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
* Fix JSON coordinate units

* Fix JSON cell units
Co-authored-by: Jiacheng Xu <169599847+Stardust0831@users.noreply.github.com>
* Fix(deltaspin): enable DeltaSpin constraint energy calculation for PW basis

- cal_escon(): replace is_Mi_converged gate with lambda_/Mi_ empty check
  to prevent segfault when uninitialized
- elecstate_pw: add get_spin_constrain_energy() override so PW basis
  computes DeltaSpin constraint energy (previously returned 0.0)
- elecstate_pw.h: declare get_spin_constrain_energy() override

Note: this fix enables escon computation for PW DeltaSpin but
lambda values from BFGS optimizer may differ from accel branch
due to energy functional convention differences. Full convergence
with accel requires lambda_loop.cpp migration.

* Fix(deltaspin): enable PW DeltaSpin constraint energy and update test refs

Source changes:
- cal_escon(): replace is_Mi_converged guard with lambda_/Mi_ empty check
  to prevent segfault when uninitialized (matching accel convention)
- elecstate_pw: add get_spin_constrain_energy() override so PW basis
  includes DeltaSpin constraint energy in total energy (was always 0)

Test refs regenerated for 7 cases with significant energy changes:
- 14_PW_DS_S4_XYZ, 15_PW_DS_S4_Z, 16_PW_DS_S4_XY
- 18_PW_DFTU_DS_S2_Z, 19_PW_DFTU_DS_S4_XY, 21_PW_DFTU_DS_S4_Z
- 41_PW_DS_S4_Thr10_XY

nspin=2 tests and ReadLam/Thr1e10 tests unchanged.

* Fix(deltaspin): fix pauli_to_moment My sign convention and enable PW escon

Source fixes:
- spin_constrain.h: fix My = -Im(occ1-occ2) → Im(occ1-occ2)
  The magnetic moment y-component had the wrong sign in the Pauli matrix
  transformation, causing incorrect Mi computation for nspin=4 DeltaSpin.
- cal_escon(): replace is_Mi_converged guard with lambda_/Mi_ empty check
- elecstate_pw: add get_spin_constrain_energy() for PW basis DeltaSpin

Refs regenerated for nspin=4 DeltaSpin cases: 14, 15, 16, 19, 21, 41
Test 18 unchanged, nspin=2 tests unchanged.

* Fix(build): link deltaspin sources into MODULE_ESTATE_elecstate_pw test

elecstate_pw.cpp now calls spinconstrain::SpinConstrain<
std::complex<double>>::getScInstance()/cal_escon() via the new
get_spin_constrain_energy() override. The MODULE_ESTATE_elecstate_pw
unit test compiles elecstate_pw.cpp directly but did not link the
deltaspin module, causing undefined-reference link errors in
BUILD_TESTING builds (test.yml and cuda.yml CI jobs).

Add spin_constrain.cpp to the test SOURCES, mirroring the existing
MODULE_LCAO_deltaspin_spin_constrain_test pattern.

* fix: add get_spin_constrain_energy stub to hsolver supplementary mock

ElecStatePW::get_spin_constrain_energy() is a new virtual override
that needs a definition in the vtable. Test targets (MODULE_HSOLVER_base,
MODULE_HSOLVER_pw, MODULE_HSOLVER_sdft) compile a mock implementation
of ElecStatePW methods instead of linking elecstate_pw.cpp, and were
missing a stub for this new method, causing:
  undefined reference to ElecStatePW::get_spin_constrain_energy()

---------

Co-authored-by: dyzheng <zhengdy@bjaisi.com>
* Fix(dftu-pw): correct Pauli-to-spin conversion signs and weight_eu for nspin=1

In cal_occ_pw():
- Swap the imaginary signs in the Pauli-to-spin conversion for nspin=4:
  index[1] (spin down-up): -i*vu_tmp[2] -> +i*vu_tmp[2]
  index[2] (spin up-down): +i*vu_tmp[2] -> -i*vu_tmp[2]
  The DFT+U vu array convention requires opposite sign from deeq_nc.

- Fix weight_eu for nspin=1: 0.25 -> 1.0
  nspin=1 has single occupancy, not the Pauli double-counting factor.

Verified with tests/17_DS_DFTU/08 and 09:
  08: -6792.33351671617 (ref -6792.33351670950, diff 6.7e-9 eV)
  09: -6364.26587638707 (ref -6364.26587639017, diff 3.1e-9 eV)

* Test: migrate PW DFT+U tests (08/09) from 17_DS_DFTU to 01_PW

815_PW_DFTU_S2_Z  — nspin=2 DFT+U, matches ref -6792.33351671614
816_PW_DFTU_S4_XY — nspin=4 DFT+U, matches ref -6364.26587638708

* Test: disable migrated 08/09 in 17_DS_DFTU CASES_CPU, enabled in 01_PW

* Test: regenerate 099_PW_DJ_SO reference for nspin=4 DFT+U sign fix

The nspin=4 Pauli-to-spin sign swap in cal_occ_pw changes the output of
all nspin=4 DFT+U PW tests, including the pre-existing 099_PW_DJ_SO whose
result.ref was not updated. Regenerate its etot/force/stress references:

  etot   -5662.3881388456420609 -> -5662.3908859903258417
  force     15.774740 -> 17.965510
  stress  100840.559090 -> 100582.607209

Without this, the 01_PW integrate suite fails on 099_PW_DJ_SO
(etot dev 2.7e-3 eV, force dev -2.19, stress dev 258).

* fix: add explicit nspin=4 to 816_PW_DFTU_S4_XY test INPUT

Commit b95f433 on develop removed the automatic nspin=4 reset
when noncolin/lspinorb is enabled, instead requiring explicit nspin=4.
Since the PR does not touch read_input_item_elec_stru.cpp, the CI merge
uses develop's validation code, causing ABACUS to quit with:
  nspin must be 4 when noncolin or lspinorb is enabled.

---------

Co-authored-by: dyzheng <zhengdy@bjaisi.com>
* remove parameter.h

* Remove unused G0/GT0/GGT0/invGGT0 members from UnitCell class

* Move print_cell from UnitCell member function to free function in unitcell namespace

* Move compare_atom_labels from UnitCell member function to free function in unitcell namespace

* add atom_in.h in read_pseudo.cpp

* add cell_tools class

* fix CMakeLists.txt

* Move deltaspin getters (get_target_mag/lambda/constrain) out of UnitCell into cell_tools

* Move if_atoms_can_move and if_cell_can_change out of UnitCell into cell_tools

* fix makefile

* remove useless step_ functions

* rename setup as setup_from_input

* fix cmake

* fix cmake

* refactor(cell): remove redundant UnitCell::atom_mass cache member, use atoms[it].mass directly

* remove atom label

* fix bug in json

* fix bug

* reduce a few lines from unitcell.h

---------

Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
* fix a bug when init_wfc=nao in pw basis for nspin=4

* update cell-relax output format, including rename the output STRU files

* remove useless words

* update documents

* update STRU output, the final one is named STRU_FINAL

* update out_stru command

* update

* update out_stru options (3 now)

* update fix bug in unitcell_test.cpp

* remove PARAM in relax_driver.cpp

* fix docs

* fix docs

* update docs

---------

Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
…7765)

Bumps [actions/checkout](https://github.com/actions/checkout) from 6.1.0 to 7.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](actions/checkout@v6.1.0...v7.0.1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* reformat the MD output energy, potential, T, P, etc.

* fix failures in unittests

* update json file style in source_io

---------

Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
Co-authored-by: Jiacheng Xu <169599847+Stardust0831@users.noreply.github.com>
…epmodeling#7753)

* ci(cuda): build only for CI runner GPU arch and raise parallelism

The CUDA CI built every .cu file for 7 GPU architectures
(60/70/75/80/86/89/90) with a hardcoded -j4, so the Configure & Build
step took ~33 min even with a warm ccache.

- Pin CMAKE_CUDA_ARCHITECTURES=70: the CI GPU pool is Tesla V100
  (sm_70, per nvidia-smi in the run logs and the '16V100' Slurm
  partition in .ci/slurm/config.ini). This cuts nvcc work by ~7x.
- Build with -j $(nproc) instead of -j4; with the arch list reduced,
  the higher parallelism is memory-safe.

Expected: Configure & Build ~33 min -> ~10 min on a cache-cold run.

* ci: auto-detect GPU arch via nvidia-smi at CMake configure time

Sister commit to e614a28. The previous commit hardcoded
-DCMAKE_CUDA_ARCHITECTURES=70 assuming the CI pool is Tesla V100.
Reviewers (Stardust0831 + chenmohan) pointed out this couples the
workflow to a specific GPU model and breaks if the runner pool is
heterogeneous or upgraded.

This commit moves the arch selection into CMakeLists.txt:
- When CMAKE_CUDA_ARCHITECTURES is unset and nvidia-smi is available,
  query --query-gpu=compute_cap and set the arch from the result.
  Map '7.0' -> 70, '8.0' -> 80, '8.9' -> 89, '9.0' -> 90, etc.
- Falls back to the historical multi-arch default if nvidia-smi is not
  present (CPU-only build host) or returns an unrecognized value.
- User-provided CMAKE_CUDA_ARCHITECTURES still takes precedence.

Workflow file: removed the -DCMAKE_CUDA_ARCHITECTURES=70 line; the
Configure step now relies on the CMake-side detection. Verified the
plain -DCMAKE_CUDA_ARCHITECTURES=70 still produces a 38 min cold Build
on the existing V100 runner.

* ci(cuda): revert broken auto-detect; use explicit sm_70 pin

The previous commit (167904f) tried to make the workflow adapt to
whatever GPU the runner has by auto-detecting compute capability at
CMake configure time. Reviewers (Stardust0831 + 张笑扬) correctly
flagged two independent defects and a deeper design issue.

Defects in the previous commit:
  1. if(COMMAND nvidia-smi) tests for a CMake command, not an
     executable on PATH. It was always false, so execute_process never
     ran. The correct check is find_program(NVIDIA_SMI_EXECUTABLE nvidia-smi).
  2. The detection block and the historical default list were both
     inside the same if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES) outer
     guard. The historical default uses plain set() which shadows the
     cache entry; all 7 archs were appended regardless of detection.
  3. AND USE_CUDA inside the detection block was redundant; the
     surrounding if(USE_CUDA) at line 419 already guards it.

Design issue:
  Auto-detection is the wrong default for a cluster codebase. ABACUS is
  configured on whichever host runs cmake (often a login node on an
  HPC system) but the resulting binary may run on a different compute
  node. Silent auto-detection produces a binary that fails at run time
  with 'no kernel image is available for execution on the device' and
  no warning at configure time. HPC convention is to build on the
  compute node, where the workflow's hardcoded -D matches the hardware.

Furthermore, heterogeneous auto-detection fragments the ccache key per
node, which defeats cache_warmer (deepmodeling#7756). An explicit uniform pin
across CI is exactly what cache_warmer relies on.

This commit:
  - Reverts the CMakeLists.txt auto-detect block.
  - Restores -DCMAKE_CUDA_ARCHITECTURES=70 in cuda.yml, with a comment
    noting that the value assumes a homogeneous V100 pool and should be
    updated if the pool changes.
  - Keeps -j $(nproc), which is the real win in e614a28 (~2x parallelism).

Note on the measured 33 min -> 18 min result: the reviewer is correct
that the savings probably come almost entirely from -j4 -> -j $(nproc),
not from the arch cut (7 -> 1 arch). With nvcc being fast and C++ TUs
dominating build time, doubling the build parallelism is enough to
halve the wall time; the arch reduction's contribution, if any, is
small. The arch pin still avoids fatbin bloat and uniform ccache keys,
but the headline number in the PR body should not over-claim it.

* Clean up comments in CUDA workflow

Removed comments explaining the CUDA architecture pinning process.
…mmit message for your changes. Lines starting

Resolve merge conflicts and fix Verlet CSVR test#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

MD & LAM MD and Larege Atomic Models project_learning Refactor Refactor ABACUS codes Tests/Examples Issues/PR related to unit tests and integrate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.