Skip to content

DFT+U Refactor#7538

Open
mohanchen wants to merge 13 commits into
deepmodeling:developfrom
mohanchen:2026-06-30
Open

DFT+U Refactor#7538
mohanchen wants to merge 13 commits into
deepmodeling:developfrom
mohanchen:2026-06-30

Conversation

@mohanchen

Copy link
Copy Markdown
Collaborator

DFT+U Refactor

@mohanchen mohanchen requested a review from lanshuyue June 30, 2026 09:36
@mohanchen mohanchen added DFT+U Issues related to DFT plus U function Refactor Refactor ABACUS codes labels Jun 30, 2026

@lanshuyue lanshuyue left a comment

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 think the direction of passing explicit parameters instead of letting lower-level DFT+U I/O code read from global PARAM is good. However, I see several issues that should be addressed before merging.

The main blocking issue is the onsite.dm format compatibility. This PR changes the format written by write_occup_m() to labels like Atom=, ORBITAL=, and spin=, but read_occup_m() still expects the
old tokens atoms, L, zeta, and spin. This means a newly written onsite.dm may not be readable by the current reader. Also, the writer now prints some indices as 1-based (iat+1, is+1), while the
reader uses parsed values as array indices, which could cause off-by-one or out-of-bounds errors.

This also affects dft_plus_u = 1 workflows. Although the main U-potential/Hamiltonian path for dft_plus_u = 1 goes through module_operator_lcao/DFTU<OperatorLCAO<...>>, Plus_U::output() is still called
in finish_dftu_lcao() for any nonzero dft_plus_u. So SCF -> NSCF/restart workflows using out_chg 1 followed by init_chg file, or workflows using omc / initial_onsite.dm, can still be broken.

A few other issues:

  1. The collinear diag=false output path no longer explicitly applies std::setprecision(8) << std::fixed when writing matrix values. Since onsite.dm is used as input/restart data, its numeric precision and
    format should remain stable.

  2. The new out_chg parameter is documented as controlling whether onsite.dm is written, but the implementation still checks if (!ofdftu) even when out_chg == false. This means out_chg = false can
    still lead to an error because the file stream was never opened. The check/write should probably be inside the out_chg && MY_RANK == 0 block.

  3. In MPI runs, only rank 0 opens onsite.dm, but all ranks appear to execute the if (!ofdftu) check. Non-root ranks may therefore see an unopened stream and report failure. The file-open check and write
    should be rank-0-only.

  4. dftu_lcao.h now uses std::string in the function signature but does not include <string> directly. It may compile through transitive includes, but the header should be self-contained.

  5. Some comments are now stale or incomplete. For example, init_dftu_lcao() still documents @param inp, while the parameter was changed to dft_plus_u; finish_dftu_lcao() adds global_out_dir, nspin,
    and npol but does not document them.

Suggested tests:

  • dft_plus_u = 1, out_chg = 1, then a following calculation with init_chg file
  • nspin = 1, nspin = 2, and nspin = 4
  • omc > 0 with initial_onsite.dm
  • out_chg = 0 should not fail due to an unopened onsite.dm
  • MPI run where only rank 0 writes onsite.dm

abacus_fixer and others added 10 commits July 12, 2026 11:13
This commit addresses several issues in the DFT+U I/O code related to the
onsite.dm file handling:

1. Format compatibility fix: Updated read_occup_m() to parse the new output format
   with labels Atom=, L=, ORBITAL=, and spin= instead of the old tokens atoms, L,
   zeta, and spin. The writer was already using the new format but the reader
   was not updated, causing new onsite.dm files to be unreadable.

2. Off-by-one fix: The writer outputs 1-based indices (iat+1, is+1) for human
   readability, but read_occup_m() was using these values directly as array
   indices. Added iat -= 1 and spin -= 1 to convert back to 0-based indices.

3. Precision fix: Added std::setprecision(8) << std::fixed for the collinear
   (nspin=1,2) diag=false output path in write_occup_m(). The eigenvalues path
   and SOC path already had this, but the matrix values path was missing it.
   This ensures stable numeric precision for restart data.

4. out_chg logic fix: The out_chg parameter is supposed to control whether
   onsite.dm is written, but the implementation was still checking if(!ofdftu)
   even when out_chg == false. Moved the file-open check and write operations
   inside the out_chg && MY_RANK == 0 block.

5. MPI fix: Only rank 0 opens the onsite.dm file, but all ranks were executing
   the if(!ofdftu) check and write_occup_m() call. Non-root ranks would see an
   unopened stream and potentially fail. Now all file operations are rank-0-only.

6. Header fix: Added missing #include <string> and #include <vector> to
   dftu_lcao.h. The header was using std::string and std::vector in function
   signatures but relying on transitive includes.

7. Documentation fix: Updated stale comments in dftu_lcao.h:
   - Changed @param inp to @param dft_plus_u in init_dftu_lcao()
   - Added documentation for global_out_dir, nspin, and npol parameters in
     finish_dftu_lcao()

8. Error handling: Replaced all exit(0) calls with ModuleBase::WARNING_QUIT()
   for consistent error handling across the codebase.

Files modified:
- source/source_lcao/module_dftu/dftu_io.cpp
- source/source_lcao/dftu_lcao.h
- source/source_lcao/dftu_lcao.cpp
This commit renames the DFT+U occupation matrix files and adjusts their read/write paths:

1. File name changes:
   - onsite.dm → dm_onsite.txt (output from DFT+U calculations)
   - initial_onsite.dm → dm_onsite_ini.txt (user-provided initial occupation matrix)

2. Path adjustments:
   - dm_onsite.txt: Both written and read from global_out_dir (OUT.prefix)
     - Previously read from global_readin_dir
     - This ensures the file is always in the output directory
   - dm_onsite_ini.txt: Read from global_readin_dir (set via read_file_dir parameter)
     - Previously read from global_out_dir
     - This allows users to place initial files in any directory

3. Code changes:
   - dftu_io.cpp: Updated output filename and error messages
   - dftu.cpp: Updated read paths for both files
   - dftu_lcao.h and module_operator_lcao/dftu_lcao.cpp: Updated comments

4. Documentation updates:
   - read_input_item_exx_dftu.cpp: Updated omc parameter description
   - parameters.yaml: Updated omc parameter description
   - input-main.md: Updated omc parameter description
   - band.md and dos.md: Updated file references
   - tests/17_DS_DFTU/README.md: Updated test documentation
   - tests/17_DS_DFTU/run_scf_nscf.sh: Updated copy logic for dm_onsite.txt

5. Backward compatibility:
   - The new format with labels Atom=, L=, ORBITAL=, spin= was already in the writer
   - This commit updates the reader to parse the new format
   - 1-based indices in output are converted to 0-based when reading

Files modified:
- source/source_lcao/module_dftu/dftu_io.cpp
- source/source_lcao/module_dftu/dftu.cpp
- source/source_lcao/dftu_lcao.h
- source/source_lcao/module_operator_lcao/dftu_lcao.cpp
- source/source_io/module_parameter/read_input_item_exx_dftu.cpp
- docs/parameters.yaml
- docs/advanced/input_files/input-main.md
- docs/advanced/elec_properties/band.md
- docs/advanced/elec_properties/dos.md
- tests/17_DS_DFTU/README.md
- tests/17_DS_DFTU/run_scf_nscf.sh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DFT+U Issues related to DFT plus U function Refactor Refactor ABACUS codes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants