Skip to content

Commit fa14bdd

Browse files
mohanchenabacus_fixer
andauthored
DFT+U Refactor (#7538)
* format dftu_io.cpp * update output formats of DFT+U * update dftu, remove PARAM * fix read_occup_m function * DFT+U I/O: Fix multiple issues with onsite.dm format, precision, and MPI 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 * DFT+U I/O: Rename onsite.dm to dm_onsite.txt and adjust file paths 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 * remove some usage of PARAM * remove C++17 codes, reduce PARAM usage in dftu * update * remove all PARAM in dftu modules * fix a bug * fix bug about Yukawa potential * update * try fixing the bug? * update the directory --------- Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
1 parent ff5f570 commit fa14bdd

32 files changed

Lines changed: 613 additions & 498 deletions

File tree

docs/advanced/elec_properties/band.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ out_chg 1
88
```
99

1010
With this input parameter, the converged charge density will be output in the files such as `chgs1.cube`, `chgs2.cube`, etc.
11-
Then, one can use the same `STRU` file, pseudopotential files and atomic orbital files (and the local density matrix file onsite.dm if DFT+U is used) to do a non-self-consistent (NSCF) calculation. In this example, the potential is constructed from the ground-state charge density from the proceeding calculation. Now the INPUT file is like:
11+
Then, one can use the same `STRU` file, pseudopotential files and atomic orbital files (and the local density matrix file dm_onsite.txt if DFT+U is used) to do a non-self-consistent (NSCF) calculation. In this example, the potential is constructed from the ground-state charge density from the proceeding calculation. Now the INPUT file is like:
1212

1313
```
1414
INPUT_PARAMETERS

docs/advanced/elec_properties/dos.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ out_chg 1
1010
```
1111

1212
this will produce the converged charge density, which is contained in the file SPIN1_CHG.cube.
13-
Then, use the same `STRU` file, pseudopotential file and atomic orbital file (and the local density matrix file onsite.dm if DFT+U is used) to do a non-self-consistent calculation. In this example, the potential is constructed from the ground-state charge density from the proceeding calculation. Now the INPUT file is like:
13+
Then, use the same `STRU` file, pseudopotential file and atomic orbital file (and the local density matrix file dm_onsite.txt if DFT+U is used) to do a non-self-consistent calculation. In this example, the potential is constructed from the ground-state charge density from the proceeding calculation. Now the INPUT file is like:
1414

1515
```
1616
INPUT_PARAMETERS

docs/advanced/input_files/input-main.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3737,10 +3737,10 @@
37373737
- **Type**: Integer
37383738
- **Description**: The parameter controls the form of occupation matrix control used.
37393739
- 0: No occupation matrix control is performed, and the onsite density matrix will be calculated from wavefunctions in each SCF step.
3740-
- 1: The first SCF step will use an initial density matrix read from a file named initial_onsite.dm, but for later steps, the onsite density matrix will be updated.
3741-
- 2: The same onsite density matrix from initial_onsite.dm will be used throughout the entire calculation.
3740+
- 1: The first SCF step will use an initial density matrix read from a file named dm_onsite_ini.txt, but for later steps, the onsite density matrix will be updated.
3741+
- 2: The same onsite density matrix from dm_onsite_ini.txt will be used throughout the entire calculation.
37423742

3743-
> Note: The easiest way to create initial_onsite.dm is to run a DFT+U calculation, look for a file named onsite.dm in the OUT.prefix directory, and make replacements there. The format of the file is rather straight-forward.
3743+
> Note: The easiest way to create dm_onsite_ini.txt is to run a DFT+U calculation with out_chg=1, look for a file named dm_onsite.txt in the OUT.prefix directory, copy and rename it to dm_onsite_ini.txt. The file dm_onsite_ini.txt should be placed in the directory specified by read_file_dir. The format of the file is rather straight-forward.
37443744
- **Default**: 0
37453745

37463746
### onsite_radius

docs/parameters.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4389,10 +4389,10 @@ parameters:
43894389
description: |
43904390
The parameter controls the form of occupation matrix control used.
43914391
* 0: No occupation matrix control is performed, and the onsite density matrix will be calculated from wavefunctions in each SCF step.
4392-
* 1: The first SCF step will use an initial density matrix read from a file named initial_onsite.dm, but for later steps, the onsite density matrix will be updated.
4393-
* 2: The same onsite density matrix from initial_onsite.dm will be used throughout the entire calculation.
4392+
* 1: The first SCF step will use an initial density matrix read from a file named dm_onsite_ini.txt, but for later steps, the onsite density matrix will be updated.
4393+
* 2: The same onsite density matrix from dm_onsite_ini.txt will be used throughout the entire calculation.
43944394
4395-
[NOTE] The easiest way to create initial_onsite.dm is to run a DFT+U calculation, look for a file named onsite.dm in the OUT.prefix directory, and make replacements there. The format of the file is rather straight-forward.
4395+
[NOTE] The easiest way to create dm_onsite_ini.txt is to run a DFT+U calculation with out_chg=1, look for a file named dm_onsite.txt in the OUT.prefix directory, copy and rename it to dm_onsite_ini.txt. The file dm_onsite_ini.txt should be placed in the directory specified by read_file_dir. The format of the file is rather straight-forward.
43964396
default_value: "0"
43974397
unit: ""
43984398
availability: ""

interfaces/ASE_interface/abacuslite/core.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,8 @@ def fixed_density(self,
529529
'symmetry': 0,
530530
'out_band': 1,
531531
'kspacing': 0.0, # overwrite
532-
'gamma_only': False}) # overwrite
532+
'gamma_only': False,
533+
'read_file_dir': 'OUT.ABACUS'}) # overwrite
533534

534535
profile = self.profile if profile is None else profile
535536

source/source_esolver/esolver_ks_lcao.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ void ESolver_KS_LCAO<TK, TR>::iter_init(UnitCell& ucell, const int istep, const
372372
}
373373
#endif
374374

375-
init_dftu_lcao<TK>(istep, iter, PARAM.inp, &(this->dftu), this->dmat.dm, ucell, this->chr.rho, this->pw_rho->nrxx);
375+
init_dftu_lcao<TK>(istep, iter, PARAM.inp.dft_plus_u, &(this->dftu), this->dmat.dm, ucell, this->chr.rho, this->pw_rho->nrxx);
376376

377377
#ifdef __MLALGO
378378
// the density matrixes of DeePKS have been updated in each iter
@@ -483,7 +483,7 @@ void ESolver_KS_LCAO<TK, TR>::iter_finish(UnitCell& ucell, const int istep, int&
483483
const std::vector<std::vector<TK>>& dm_vec = this->dmat.dm->get_DMK_vector();
484484

485485
// 1) calculate the local occupation number matrix and energy correction in DFT+U
486-
finish_dftu_lcao<TK>(iter, conv_esolver, PARAM.inp, &(this->dftu), ucell, dm_vec, this->kv, this->p_chgmix->get_mixing_beta(), hamilt_lcao);
486+
finish_dftu_lcao<TK>(iter, conv_esolver, PARAM.inp.dft_plus_u, PARAM.inp.out_chg[0], &(this->dftu), ucell, dm_vec, this->kv, this->p_chgmix->get_mixing_beta(), hamilt_lcao, PARAM.globalv.global_out_dir, PARAM.inp.nspin, PARAM.globalv.npol);
487487

488488
// 2) for deepks, calculate delta_e, output labels during electronic steps
489489
this->deepks.delta_e(ucell, this->kv, this->orb_, this->pv, this->gd, dm_vec, this->pelec->f_en, PARAM.inp);

source/source_io/module_hs/write_vxc.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ void write_Vxc(const int nspin,
207207
&vxcs_R_ao[0],ucell,/*for paraV*/ kv, Hexxd, Hexxc, hamilt::Add_Hexx_Type::k);
208208
std::vector<std::vector<double>> e_orb_exx; // orbital energy (EXX)
209209
#endif
210-
hamilt::OperatorDFTU<hamilt::OperatorLCAO<TK, TR>> vdftu_op_ao(&vxc_k_ao, kv.kvec_d, nullptr, nullptr, kv.isk);
210+
hamilt::OperatorDFTU<hamilt::OperatorLCAO<TK, TR>> vdftu_op_ao(&vxc_k_ao, kv.kvec_d, nullptr, nullptr, kv.isk, PARAM.globalv.npol);
211211

212212
// 4. calculate and write the MO-matrix Exc
213213
Parallel_2D p2d;

source/source_io/module_parameter/input_conv.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ void Input_Conv::Convert()
212212

213213
if (PARAM.inp.dft_plus_u)
214214
{
215-
Plus_U::Yukawa = PARAM.inp.yukawa_potential;
216215
Plus_U::omc = PARAM.inp.omc;
217216
Plus_U::orbital_corr = PARAM.inp.orbital_corr;
218217
Plus_U::uramping = PARAM.globalv.uramping;

source/source_io/module_parameter/read_input_item_exx_dftu.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -834,10 +834,10 @@ void ReadInput::item_dftu()
834834
item.type = "Integer";
835835
item.description = R"(The parameter controls the form of occupation matrix control used.
836836
* 0: No occupation matrix control is performed, and the onsite density matrix will be calculated from wavefunctions in each SCF step.
837-
* 1: The first SCF step will use an initial density matrix read from a file named initial_onsite.dm, but for later steps, the onsite density matrix will be updated.
838-
* 2: The same onsite density matrix from initial_onsite.dm will be used throughout the entire calculation.
837+
* 1: The first SCF step will use an initial density matrix read from a file named dm_onsite_ini.txt, but for later steps, the onsite density matrix will be updated.
838+
* 2: The same onsite density matrix from dm_onsite_ini.txt will be used throughout the entire calculation.
839839
840-
[NOTE] The easiest way to create initial_onsite.dm is to run a DFT+U calculation, look for a file named onsite.dm in the OUT.prefix directory, and make replacements there. The format of the file is rather straight-forward.)";
840+
[NOTE] The easiest way to create dm_onsite_ini.txt is to run a DFT+U calculation with out_chg=1, look for a file named dm_onsite.txt in the OUT.prefix directory, copy and rename it to dm_onsite_ini.txt. The file dm_onsite_ini.txt should be placed in the directory specified by read_file_dir. The format of the file is rather straight-forward.)";
841841
item.default_value = "0";
842842
item.unit = "";
843843
item.availability = "";

source/source_lcao/FORCE_STRESS.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ void Force_Stress_LCAO<T>::getForceStress(UnitCell& ucell,
420420
std::vector<std::vector<double>>* dmk_d = nullptr;
421421
std::vector<std::vector<std::complex<double>>>* dmk_c = nullptr;
422422
assign_dmk_ptr<T>(dmat.dm, dmk_d, dmk_c, PARAM.globalv.gamma_only_local);
423-
dftu.force_stress(ucell, gd, dmk_d, dmk_c, pv, fsr_dftu, force_u, stress_u, kv);
423+
dftu.force_stress(ucell, gd, dmk_d, dmk_c, pv, fsr_dftu, force_u, stress_u, kv, PARAM.globalv.npol);
424424
}
425425
else
426426
{

0 commit comments

Comments
 (0)