Skip to content

Commit 58ea5a6

Browse files
author
abacus_fixer
committed
Phase A: extract output/write_occup_m as free functions in dftu_io namespace
- New files: source_pw/module_pwdft/dftu_output.h, dftu_output.cpp - declare and implement dftu_io::output and dftu_io::write_occup_m - first parameter is const Plus_U_Base&, accesses state via public getters - JacobiRotate and CalculateEigenvalues inline helpers migrated here - dftu_base.h: added public getters get_U_Yukawa / get_J_Yukawa; removed output/write_occup_m member declarations - dftu_base.cpp: removed output/write_occup_m implementations and the two Jacobi inline helpers (no longer referenced here) - Callers updated: - setup_dftu_pw.cpp: dftu.output(...) -> dftu_io::output(dftu, ...) - setup_dftu_lcao.cpp: dftu_ptr->output(...) -> dftu_io::output(*dftu_ptr, ...) - CMakeLists.txt and Makefile.Objects: added dftu_output.cpp/dftu_output.o All 4 dftu unit tests pass.
1 parent 7c4ad27 commit 58ea5a6

8 files changed

Lines changed: 378 additions & 313 deletions

File tree

source/Makefile.Objects

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ OBJS_SRCPW=h_ewald_pw.o\
742742
setup_pwwfc.o\
743743
update_cell_pw.o\
744744
dftu_base.o\
745+
dftu_output.o\
745746
dftu_pw.o\
746747
setup_dftu_pw.o\
747748
deltaspin_pw.o\

source/source_lcao/setup_dftu_lcao.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "setup_dftu_lcao.h"
22
#include "source_lcao/module_dftu/dftu.h"
3+
#include "source_pw/module_pwdft/dftu_output.h" // mohan add 2025-11-08
34
#include "source_estate/module_dm/density_matrix.h"
45
#include "source_lcao/hamilt_lcao.h"
56

@@ -67,7 +68,7 @@ void finish_dftu_lcao(const int iter,
6768
}
6869
dftu_ptr->cal_energy_correction(ucell, iter);
6970
}
70-
dftu_ptr->output(ucell, out_chg, global_out_dir, nspin, npol);
71+
dftu_io::output(*dftu_ptr, ucell, out_chg, global_out_dir, nspin, npol);
7172

7273
/// use the converged occupation matrix for next MD/Relax SCF calculation
7374
if (conv_esolver)

source/source_pw/module_pwdft/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ list(APPEND objects
1313
op_pw_exx_ace.cpp
1414
op_pw_exx_pot.cpp
1515
dftu_base.cpp
16+
dftu_output.cpp
1617
dftu_pw.cpp
1718
setup_pot.cpp
1819
setup_pwrho.cpp

source/source_pw/module_pwdft/dftu_base.cpp

Lines changed: 3 additions & 297 deletions
Original file line numberDiff line numberDiff line change
@@ -14,72 +14,9 @@
1414
#include <sstream>
1515
#include <vector>
1616

17-
// local inline helpers for eigenvalue calculation (mirrors dftu_io.cpp)
18-
inline void JacobiRotate(std::vector<std::vector<double>>& A, int p, int q, int n)
19-
{
20-
if (std::abs(A[p][q]) > 1e-10)
21-
{
22-
double r = (A[q][q] - A[p][p]) / (2.0 * A[p][q]);
23-
double t = 0.0;
24-
if (r >= 0)
25-
{
26-
t = 1.0 / (r + sqrt(1.0 + r * r));
27-
}
28-
else
29-
{
30-
t = -1.0 / (-r + sqrt(1.0 + r * r));
31-
}
32-
double c = 1.0 / sqrt(1.0 + t * t);
33-
double s = t * c;
34-
35-
A[p][p] -= t * A[p][q];
36-
A[q][q] += t * A[p][q];
37-
A[p][q] = A[q][p] = 0.0;
38-
39-
for (int k = 0; k < n; k++)
40-
{
41-
if (k != p && k != q)
42-
{
43-
double Akp = c * A[k][p] - s * A[k][q];
44-
double Akq = s * A[k][p] + c * A[k][q];
45-
A[k][p] = A[p][k] = Akp;
46-
A[k][q] = A[q][k] = Akq;
47-
}
48-
}
49-
}
50-
}
51-
52-
inline std::vector<double> CalculateEigenvalues(std::vector<std::vector<double>>& A, int n)
53-
{
54-
std::vector<double> eigenvalues(n);
55-
while (true)
56-
{
57-
int p = 0, q = 1;
58-
for (int i = 0; i < n; i++)
59-
{
60-
for (int j = i + 1; j < n; j++)
61-
{
62-
if (std::abs(A[i][j]) > std::abs(A[p][q]))
63-
{
64-
p = i;
65-
q = j;
66-
}
67-
}
68-
}
69-
70-
if (std::abs(A[p][q]) < 1e-10)
71-
{
72-
for (int i = 0; i < n; i++)
73-
{
74-
eigenvalues[i] = A[i][i];
75-
}
76-
break;
77-
}
78-
79-
JacobiRotate(A, p, q, n);
80-
}
81-
return eigenvalues;
82-
}
17+
// local inline helpers for eigenvalue calculation (JacobiRotate, CalculateEigenvalues)
18+
// have been migrated to dftu_output.cpp, where they are used by dftu_io::write_occup_m.
19+
// mohan refactored 2025-11-08
8320

8421
// static member definitions (mohan add 2025-11-06)
8522
double Plus_U_Base::energy_u = 0.0;
@@ -584,237 +521,6 @@ void Plus_U_Base::set_locale_flat(const int iat, const int l, const int spin,
584521
}
585522

586523

587-
void Plus_U_Base::output(const UnitCell& ucell,
588-
bool out_chg,
589-
const std::string& global_out_dir,
590-
int nspin,
591-
int npol)
592-
{
593-
ModuleBase::TITLE("Plus_U_Base", "output");
594-
595-
GlobalV::ofs_running << " >>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
596-
GlobalV::ofs_running << " | #DFT+U INFORMATION# |" << std::endl;
597-
GlobalV::ofs_running << " >>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
598-
599-
for (int T = 0; T < ucell.ntype; T++)
600-
{
601-
const int NL = ucell.atoms[T].nwl + 1;
602-
603-
for (int L = 0; L < NL; L++)
604-
{
605-
const int N = ucell.atoms[T].l_nchi[L];
606-
607-
if (L >= get_orbital_corr(T) && has_correlated_orbital(T))
608-
{
609-
if (L != get_orbital_corr(T))
610-
{
611-
continue;
612-
}
613-
614-
if (!Yukawa)
615-
{
616-
GlobalV::ofs_running << " Type=" << T+1 << " L=" << L << " ORBITAL=" << 0
617-
<< " U=" << this->U[T] * ModuleBase::Ry_to_eV << " eV" << std::endl;
618-
}
619-
else
620-
{
621-
for (int n = 0; n < N; n++)
622-
{
623-
if (n != 0)
624-
{
625-
continue;
626-
}
627-
double Ueff = (this->U_Yukawa[T][L][n] - this->J_Yukawa[T][L][n]) * ModuleBase::Ry_to_eV;
628-
GlobalV::ofs_running << " Type=" << T+1 << " L=" << L << " ORBITAL=" << n
629-
<< " U=" << this->U_Yukawa[T][L][n] * ModuleBase::Ry_to_eV << " eV"
630-
<< " J=" << this->J_Yukawa[T][L][n] * ModuleBase::Ry_to_eV << " eV"
631-
<< std::endl;
632-
}
633-
}
634-
}
635-
}
636-
}
637-
638-
GlobalV::ofs_running << " Local Occupation Matrices for each atom" << std::endl;
639-
this->write_occup_m(ucell, GlobalV::ofs_running, true, nspin, npol);
640-
641-
// Write dm_onsite.txt
642-
if (out_chg && GlobalV::MY_RANK == 0)
643-
{
644-
std::ofstream ofdftu;
645-
ofdftu.open(global_out_dir + "dm_onsite.txt");
646-
if (!ofdftu)
647-
{
648-
ModuleBase::WARNING_QUIT("Plus_U_Base::output", "Can't create file dm_onsite.txt");
649-
}
650-
this->write_occup_m(ucell, ofdftu, false, nspin, npol);
651-
ofdftu.close();
652-
}
653-
654-
GlobalV::ofs_running << " >>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
655-
GlobalV::ofs_running << " | # END DFT+U INFO |" << std::endl;
656-
GlobalV::ofs_running << " >>>>>>>>>>>>>>>>>>>>>>>" << std::endl << std::endl;
657-
658-
return;
659-
}
660-
661-
662-
void Plus_U_Base::write_occup_m(const UnitCell& ucell,
663-
std::ofstream& ofs,
664-
bool diag,
665-
int nspin,
666-
int npol)
667-
{
668-
ModuleBase::TITLE("Plus_U_Base", "write_occup_m");
669-
670-
if (GlobalV::MY_RANK != 0)
671-
{
672-
return;
673-
}
674-
675-
for (int T = 0; T < ucell.ntype; T++)
676-
{
677-
if (!has_correlated_orbital(T))
678-
{
679-
continue;
680-
}
681-
const int NL = ucell.atoms[T].nwl + 1;
682-
const int LC = get_orbital_corr(T);
683-
684-
for (int I = 0; I < ucell.atoms[T].na; I++)
685-
{
686-
const int iat = ucell.itia2iat(T, I);
687-
688-
for (int l = 0; l < NL; l++)
689-
{
690-
if (l != get_orbital_corr(T))
691-
{
692-
continue;
693-
}
694-
695-
const int N = ucell.atoms[T].l_nchi[l];
696-
697-
for (int n = 0; n < N; n++)
698-
{
699-
if (n != 0)
700-
{
701-
continue;
702-
}
703-
704-
ofs << "\n Atom= " << iat+1;
705-
ofs << " L= " << l;
706-
ofs << " ORBITAL= " << n << std::endl;
707-
708-
if (nspin == 1 || nspin == 2)
709-
{
710-
double sum0[2];
711-
for (int is = 0; is < 2; is++)
712-
{
713-
if (diag)
714-
{
715-
std::vector<std::vector<double>> A(2 * l + 1, std::vector<double>(2 * l + 1));
716-
for (int m0 = 0; m0 < 2 * l + 1; m0++)
717-
{
718-
for (int m1 = 0; m1 < 2 * l + 1; m1++)
719-
{
720-
A[m0][m1] = locale[iat][l][n][is](m0, m1);
721-
}
722-
}
723-
std::vector<double> eigenvalues = CalculateEigenvalues(A, 2 * l + 1);
724-
sum0[is] = 0.0;
725-
ofs << " Eigenvalues for spin=" << is+1 << std::endl;
726-
ofs << std::setprecision(8) << std::fixed;
727-
for (int i = 0; i < 2 * l + 1; i++)
728-
{
729-
ofs << std::setw(12) << eigenvalues[i];
730-
sum0[is] += eigenvalues[i];
731-
}
732-
ofs << std::endl;
733-
ofs << " sum is " << std::setw(12) << sum0[is] << std::endl;
734-
}
735-
ofs << " spin= " << is+1 << std::endl;
736-
ofs << std::setprecision(8) << std::fixed;
737-
for (int m0 = 0; m0 < 2 * l + 1; m0++)
738-
{
739-
for (int m1 = 0; m1 < 2 * l + 1; m1++)
740-
{
741-
ofs << std::setw(12)
742-
<< locale[iat][l][n][is](m0, m1);
743-
}
744-
ofs << std::endl;
745-
}
746-
}
747-
if (diag)
748-
{
749-
ofs << std::setw(12) << std::setprecision(8)
750-
<< std::fixed << " Magnetism for atom " << iat+1 << ": " << sum0[0] - sum0[1]
751-
<< std::endl;
752-
}
753-
}
754-
else if (nspin == 4) // SOC
755-
{
756-
if (diag)
757-
{
758-
double sum0[4];
759-
std::vector<std::vector<double>> A(2 * l + 1, std::vector<double>(2 * l + 1));
760-
int index = 0;
761-
for (int is = 0; is < 4; is++)
762-
{
763-
for (int m0 = 0; m0 < 2 * l + 1; m0++)
764-
{
765-
for (int m1 = 0; m1 < 2 * l + 1; m1++)
766-
{
767-
A[m0][m1] = locale[iat][l][n][0].c[index];
768-
index++;
769-
}
770-
}
771-
std::vector<double> eigenvalues = CalculateEigenvalues(A, 2 * l + 1);
772-
sum0[is] = 0.0;
773-
ofs << " Eigenvalues for is=" << is << std::endl;
774-
ofs << std::setprecision(8) << std::fixed;
775-
for (int i = 0; i < 2 * l + 1; i++)
776-
{
777-
ofs << std::setw(12) << eigenvalues[i];
778-
sum0[is] += eigenvalues[i];
779-
}
780-
ofs << std::endl;
781-
ofs << " sum is " << std::setw(12) << sum0[is] << std::endl;
782-
}
783-
ofs << std::setw(12) << std::setprecision(8)
784-
<< std::fixed << " Magnetism for atom " << iat + 1 << ": "
785-
<< sum0[1] << " " << sum0[2] << " " << sum0[3] << std::endl;
786-
}
787-
else
788-
{
789-
for (int m0 = 0; m0 < 2 * l + 1; m0++)
790-
{
791-
for (int ipol0 = 0; ipol0 < npol; ipol0++)
792-
{
793-
const int m0_all = m0 + (2 * l + 1) * ipol0;
794-
795-
for (int m1 = 0; m1 < 2 * l + 1; m1++)
796-
{
797-
for (int ipol1 = 0; ipol1 < npol; ipol1++)
798-
{
799-
int m1_all = m1 + (2 * l + 1) * ipol1;
800-
ofs << std::setw(12) << std::setprecision(8) << std::fixed
801-
<< locale[iat][l][n][0](m0_all, m1_all);
802-
}
803-
}
804-
ofs << std::endl;
805-
}
806-
}
807-
}
808-
}
809-
} // n
810-
} // l
811-
} // I
812-
} // T
813-
814-
return;
815-
}
816-
817-
818524
void Plus_U_Base::read_occup_m(const UnitCell& ucell,
819525
const std::string& fn,
820526
const std::string& init_chg,

source/source_pw/module_pwdft/dftu_base.h

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class Plus_U_Base
5555
static bool has_correlated_orbital(int it) { return orbital_corr[it] != -1; }
5656
static const int* get_orbital_corr_data() { return orbital_corr.data(); }
5757

58+
// mohan add 2025-11-08 for dftu_io::output free function
59+
double get_U_Yukawa(int it, int l, int n) const { return U_Yukawa[it][l][n]; }
60+
double get_J_Yukawa(int it, int l, int n) const { return J_Yukawa[it][l][n]; }
61+
5862
static double get_energy() { return energy_u; }
5963
static void set_energy(const double &e) { energy_u = e; }
6064
static void set_double_energy() { energy_u *= 2.0; }
@@ -187,22 +191,12 @@ class Plus_U_Base
187191
std::vector<std::vector<std::vector<std::vector<ModuleBase::matrix>>>> locale_save;
188192

189193
//=============================================================
190-
// In dftu_io.cpp
191-
// For reading/writing/broadcasting/copying relevant data structures
194+
// output() and write_occup_m() have been extracted to free functions
195+
// in source_pw/module_pwdft/dftu_output.cpp as dftu_io::output and
196+
// dftu_io::write_occup_m. They access Plus_U_Base via public getters.
197+
// mohan refactored 2025-11-08
192198
//=============================================================
193-
public:
194-
void output(const UnitCell& ucell,
195-
bool out_chg,
196-
const std::string& global_out_dir,
197-
int nspin,
198-
int npol);
199-
200199
protected:
201-
void write_occup_m(const UnitCell& ucell,
202-
std::ofstream& ofs,
203-
bool diag,
204-
int nspin,
205-
int npol);
206200
void read_occup_m(const UnitCell& ucell,
207201
const std::string& fn,
208202
const std::string& init_chg,

0 commit comments

Comments
 (0)