Skip to content

Commit 0fc456f

Browse files
Merge pull request #246 from sayanbhowmik/hubbard_and_atom
2 parents 555110b + d166563 commit 0fc456f

31 files changed

+513
-399
lines changed

ChangeLog

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@
33
-Name
44
-changes
55

6+
--------------
7+
June 03, 2025
8+
Name: Sayan Bhowmik
9+
Changes: README.md, doc/.LaTeX/Introduction.tex, doc/.LaTeX/System.tex, doc/Manual.pdf,
10+
src/atom/initializationAtom.c, src/atom/sparcAtom.c, src/include/isddft.h,
11+
src/initialization.c, src/readfiles.c, src/xc/hubbard/hubbardForce.c,
12+
src/xc/hubbard/hubbardStress.c, src/xc/locOrbRoutines.c,
13+
src/xc/hubbard/occupationMatrix.c, tests/MoO3_hubbard/,
14+
tests/NiO_spin_kpts_non_ortho_hubbard/, tests/TiCrO4_kpt_hubbard/
15+
1. Changed i/o format for DFT+U.
16+
2. Fixed minor bug in atom code.
17+
3. Updated doc.
18+
619
--------------
720
June 02, 2025
821
Name: Lucas Timmerman

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ SPARC is an open-source software package for the accurate, effcient, and scalabl
1212
* Spin-orbit coupling (SOC).
1313
* Noncollinear spin.
1414
* Dispersion interactions through DFT-D3, vdW-DF1, and vdW-DF2.
15+
* DFT+U through Dudarev's formulation.
1516
* Symmetry-adaption for cyclic and/or helical symmetries (Cyclix-DFT).
1617
* O(N) Spectral Quadrature (SQ) method.
1718
* On-the-fly machine-learned force field (MLFF) molecular dynamics (MD) simulations.

doc/.LaTeX/Introduction.tex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
\item \textbf{Boqin Zhang}: vdW-DF, DFT-D3, meta-GGA (SCAN) \\
3434
\item \textbf{Shashikant Kumar}: Testing framework, NLCC, MLFF \\
3535
\item \textbf{Mostafa Faghih Shojaei}: SPMS table of pseudopotentials \\
36-
\item \textbf{Sayan Bhowmik\footnotemark{}}: Atom code, DFT+U (Dudarev) \\
36+
\item \textbf{Sayan Bhowmik\footnotemark}: Atom code, DFT+U (Dudarev) \\
3737
\item \textbf{Swarnava Ghosh}: Preliminary development \\
3838
\item \textbf{Deepa Phanish}: Initial development
3939
\end{itemize}
@@ -282,6 +282,7 @@
282282
\hyperlink{COORD_FRAC}{\texttt{COORD\_FRAC}} $\vert$
283283
\hyperlink{RELAX}{\texttt{RELAX}} $\vert$
284284
\hyperlink{SPIN}{\texttt{SPIN}} $\vert$
285+
\hyperlink{HUBBARD_FLAG}{\texttt{HUBBARD\_FLAG}} $\vert$
285286
\hyperlink{HUBBARD}{\texttt{HUBBARD}} $\vert$
286287
\hyperlink{U_ATOM_TYPE}{\texttt{U\_ATOM\_TYPE}} $\vert$
287288
\hyperlink{U_VAL}{\texttt{U\_VAL}}

doc/.LaTeX/System.tex

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,40 @@
777777
\end{frame}
778778
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779779

780+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
781+
\begin{frame}[allowframebreaks]{\texttt{HUBBARD\_FLAG}} \label{HUBBARD_FLAG}
782+
\vspace*{-12pt}
783+
\begin{columns}
784+
\column{0.4\linewidth}
785+
\begin{block}{Type}
786+
0 or 1
787+
\end{block}
788+
789+
\begin{block}{Default}
790+
\texttt{0}
791+
\end{block}
792+
793+
\column{0.4\linewidth}
794+
\begin{block}{Unit}
795+
No unit
796+
\end{block}
797+
798+
\begin{block}{Example}
799+
\texttt{HUBBARD\_FLAG}: \texttt{1}
800+
\end{block}
801+
\end{columns}
802+
803+
\begin{block}{Description}
804+
Flag for adding hubbard correction on top of the \hyperlink{EXCHANGE_CORRELATION}{\texttt{EXCHANGE\_CORRELATION}}.
805+
\end{block}
806+
807+
\begin{block}{Remark}
808+
Usually used along with LDA, GGA or SCAN type functionals.
809+
\end{block}
810+
811+
\end{frame}
812+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813+
780814

781815
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
782816
\begin{frame}[allowframebreaks,c]{} \label{System:ion}
@@ -1053,13 +1087,17 @@
10531087

10541088
\begin{block}{Example}
10551089
\texttt{HUBBARD: \\}
1056-
\texttt{U\_ATOM\_TYPE: Ni \\}
1057-
\texttt{U\_VAL:} 0 0 0.05 0 \\
1090+
% \texttt{U\_ATOM\_TYPE: Ni \\}
1091+
% \texttt{U\_VAL:} 0 0 0.05 0 \\
10581092
\end{block}
10591093
\end{columns}
10601094

10611095
\begin{block}{Description}
1062-
Triggers a DFT+U calculation on top of the \hyperlink{EXCHANGE_CORRELATION}{\texttt{EXCHANGE\_CORRELATION}} specified in the \texttt{.inpt} file. Must be followed by specifying the atoms on which a U correction is desired along with value of U as per Dudarev's scheme.
1096+
Start of the DFT+U parameter block. Must be followed by specifying the atoms on which a U correction is desired along with value of U as per Dudarev's scheme.
1097+
\end{block}
1098+
1099+
\begin{block}{Remark}
1100+
\hyperlink{HUBBARD_FLAG}{HUBBARD\_FLAG} must be specified to 1 in \texttt{.inpt} file.
10631101
\end{block}
10641102

10651103
\end{frame}

doc/Manual.pdf

3.5 KB
Binary file not shown.

src/atom/initializationAtom.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ void copy_PSP_atom(SPARC_ATOM_OBJ *pSPARC_ATOM, SPARC_OBJ *pSPARC, int ityp) {
249249
for (int l = 0; l <= pSPARC_ATOM->psd->lmax; l++) {
250250
pSPARC_ATOM->psd->rc[l] = pSPARC->psd[ityp].rc[l];
251251
pSPARC_ATOM->psd->ppl[l] = pSPARC->psd[ityp].ppl[l];
252-
lpos[l+1] = lpos[l] + pSPARC->psd->ppl[l];
252+
lpos[l+1] = lpos[l] + pSPARC_ATOM->psd->ppl[l];
253253
}
254254
int nproj = lpos[lmax+1];
255255

src/atom/sparcAtom.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ void sparc_atom(SPARC_OBJ *pSPARC, int ityp, SPARC_INPUT_OBJ *pSPARC_Input) {
3434
electronicGroundState_atom(&pSPARC_ATOM);
3535

3636
// Printing
37-
if (!pSPARC->is_hubbard){
37+
if (!pSPARC_Input->is_hubbard){
3838
printResultsAtom(&pSPARC_ATOM);
3939
}
4040

4141
// Copy solution
42-
if (pSPARC->is_hubbard) copyAtomSolution(&pSPARC_ATOM, pSPARC, ityp);
42+
if (pSPARC_Input->is_hubbard) copyAtomSolution(&pSPARC_ATOM, pSPARC, ityp);
4343

4444
// Free memory
4545
Finalize_Atom(&pSPARC_ATOM);

src/include/isddft.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,6 +1471,9 @@ typedef struct _SPARC_INPUT_OBJ{
14711471
double exx_frac; // hybrid mixing coefficient
14721472
int ExxMethod; // method for solving poissons equation, kronecker product way or FFT
14731473

1474+
/* DFT+U */
1475+
int is_hubbard; // DFT+U flag
1476+
14741477
/* SQ methods */
14751478
int sqAmbientFlag; // Flag of SQ method
14761479
// int SQ_highT_gauss_mem; // Memory option for gauss quadrature

src/initialization.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555
#define min(x,y) ((x)<(y)?(x):(y))
5656
#define max(x,y) ((x)>(y)?(x):(y))
5757

58-
//#define N_MEMBR 209
59-
#define N_MEMBR 208
58+
#define N_MEMBR 209
59+
// #define N_MEMBR 208
6060

6161

6262
/**
@@ -300,8 +300,8 @@ void Initialize(SPARC_OBJ *pSPARC, int argc, char *argv[]) {
300300
t1 = MPI_Wtime();
301301
#endif
302302

303-
// broadcast hubbard flag
304-
MPI_Bcast(&pSPARC->is_hubbard, 1, MPI_INT, 0, MPI_COMM_WORLD);
303+
// // broadcast hubbard flag
304+
// MPI_Bcast(&pSPARC->is_hubbard, 1, MPI_INT, 0, MPI_COMM_WORLD);
305305

306306
// broadcast Ntypes read from ion file
307307
MPI_Ibcast(&pSPARC->Ntypes, 1, MPI_INT, 0, MPI_COMM_WORLD, &req);
@@ -341,8 +341,8 @@ void Initialize(SPARC_OBJ *pSPARC, int argc, char *argv[]) {
341341
t2 = MPI_Wtime();
342342
if (rank == 0) printf("Broadcasting the input parameters took %.3f ms\n",(t2-t1)*1000);
343343
#endif
344-
// broadcast hubbard flag
345-
MPI_Bcast(&pSPARC->is_hubbard, 1, MPI_INT, 0, MPI_COMM_WORLD);
344+
// // broadcast hubbard flag
345+
// MPI_Bcast(&pSPARC->is_hubbard, 1, MPI_INT, 0, MPI_COMM_WORLD);
346346

347347
// broadcast Ntypes read from ion file
348348
MPI_Ibcast(&pSPARC->Ntypes, 1, MPI_INT, 0, MPI_COMM_WORLD, &req);
@@ -967,6 +967,9 @@ void set_defaults(SPARC_INPUT_OBJ *pSPARC_Input, SPARC_OBJ *pSPARC) {
967967
// read in initial density
968968
pSPARC_Input->readInitDens = 0;
969969

970+
// DFT+U
971+
pSPARC_Input->is_hubbard = 0;
972+
970973
/* Default socket options
971974
Note to future developers: please keep the USE_SOCKET macro
972975
as the LAST PART of the initialization function!!
@@ -1571,6 +1574,7 @@ void SPARC_copy_input(SPARC_OBJ *pSPARC, SPARC_INPUT_OBJ *pSPARC_Input) {
15711574
pSPARC->OFDFT_tol = pSPARC_Input->OFDFT_tol;
15721575
pSPARC->OFDFT_lambda = pSPARC_Input->OFDFT_lambda;
15731576
pSPARC->twist = pSPARC_Input->twist;
1577+
pSPARC->is_hubbard = pSPARC_Input->is_hubbard; // DFT+U
15741578

15751579
// char type values
15761580
strncpy(pSPARC->MDMeth , pSPARC_Input->MDMeth,sizeof(pSPARC->MDMeth));
@@ -3716,7 +3720,7 @@ void write_output_init(SPARC_OBJ *pSPARC) {
37163720
}
37173721

37183722
fprintf(output_fp,"***************************************************************************\n");
3719-
fprintf(output_fp,"* SPARC (version May 29, 2025) *\n");
3723+
fprintf(output_fp,"* SPARC (version June 3, 2025) *\n");
37203724
fprintf(output_fp,"* Copyright (c) 2020 Material Physics & Mechanics Group, Georgia Tech *\n");
37213725
fprintf(output_fp,"* Distributed under GNU General Public License 3 (GPL) *\n");
37223726
fprintf(output_fp,"* Start time: %s *\n",c_time_str);
@@ -3777,6 +3781,8 @@ void write_output_init(SPARC_OBJ *pSPARC) {
37773781
fprintf(output_fp,"EXX_RANGE_FOCK: %.6f\n", pSPARC->hyb_range_fock);
37783782
fprintf(output_fp,"EXX_RANGE_PBE: %.6f\n", pSPARC->hyb_range_pbe);
37793783
}
3784+
// DFT+U
3785+
fprintf(output_fp, "HUBBARD_FLAG: %d\n", pSPARC->is_hubbard);
37803786
if (pSPARC->sqAmbientFlag == 1 || pSPARC->sqHighTFlag == 1) {
37813787
if (pSPARC->sqAmbientFlag) fprintf(output_fp,"SQ_AMBIENT_FLAG: %d\n", pSPARC->sqAmbientFlag);
37823788
if (pSPARC->sqHighTFlag) fprintf(output_fp,"SQ_HIGHT_FLAG: %d\n", pSPARC->sqHighTFlag);
@@ -4056,6 +4062,7 @@ void write_output_init(SPARC_OBJ *pSPARC) {
40564062
pSPARC->stress_rel_scale[4], pSPARC->stress_rel_scale[5]);
40574063
fprintf(output_fp, "MLFF_DFT_FQ: %d\n", pSPARC->MLFF_DFT_fq);
40584064
}
4065+
40594066

40604067
fprintf(output_fp,"VERBOSITY: %d\n",pSPARC->Verbosity);
40614068
fprintf(output_fp,"PRINT_FORCES: %d\n",pSPARC->PrintForceFlag);
@@ -4329,7 +4336,7 @@ void SPARC_Input_MPI_create(MPI_Datatype *pSPARC_INPUT_MPI) {
43294336
MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT,
43304337
MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT,
43314338
MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT,
4332-
MPI_INT, MPI_INT, MPI_INT, /* int array */
4339+
MPI_INT, MPI_INT, MPI_INT, MPI_INT, /* int array */
43334340

43344341
MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
43354342
MPI_DOUBLE, MPI_DOUBLE,
@@ -4373,7 +4380,7 @@ void SPARC_Input_MPI_create(MPI_Datatype *pSPARC_INPUT_MPI) {
43734380
1, 1, 1, 1, 1,
43744381
1, 1, 1, 1, 1,
43754382
1, 1, 1, 1, 1,
4376-
1, 1, 1, /* int */
4383+
1, 1, 1, 1, /* int */
43774384
9, 3, L_QMASS, L_kpoint, L_kpoint,
43784385
L_kpoint, 6, /* double array */
43794386
1, 1, 1, 1, 1,
@@ -4520,6 +4527,7 @@ void SPARC_Input_MPI_create(MPI_Datatype *pSPARC_INPUT_MPI) {
45204527
MPI_Get_address(&sparc_input_tmp.N_rgrid_MLFF, addr + i++);
45214528
MPI_Get_address(&sparc_input_tmp.MLFF_DFT_fq, addr + i++);
45224529
MPI_Get_address(&sparc_input_tmp.REFERENCE_CUTOFF_FAC, addr + i++);
4530+
MPI_Get_address(&sparc_input_tmp.is_hubbard, addr + i++);
45234531

45244532
// double array type
45254533
MPI_Get_address(&sparc_input_tmp.LatVec, addr + i++);

src/readfiles.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,8 @@ void read_input(SPARC_INPUT_OBJ *pSPARC_Input, SPARC_OBJ *pSPARC) {
10121012
} else if(strcmpi(str,"PRINT_ENERGY_DENSITY:") == 0) {
10131013
fscanf(input_fp,"%d",&pSPARC_Input->PrintEnergyDensFlag);
10141014
fscanf(input_fp, "%*[^\n]\n");
1015+
} else if(strcmpi(str,"HUBBARD_FLAG:") == 0) {
1016+
fscanf(input_fp,"%d",&pSPARC_Input->is_hubbard);
10151017
} else {
10161018
printf("\nCannot recognize input variable identifier: \"%s\"\n",str);
10171019
exit(EXIT_FAILURE);
@@ -1848,7 +1850,7 @@ void read_ion(SPARC_INPUT_OBJ *pSPARC_Input, SPARC_OBJ *pSPARC) {
18481850

18491851
//////////////////////////// HUBBARD BLOCK ///////////////////////////////////
18501852
// @author: Sayan Bhowmik ([email protected])
1851-
pSPARC->is_hubbard = 0;
1853+
// pSPARC->is_hubbard = 0;
18521854
fseek(ion_fp, 0L, SEEK_SET);
18531855

18541856
/* Identify atom types for which radial solve is desired */
@@ -1869,9 +1871,13 @@ void read_ion(SPARC_INPUT_OBJ *pSPARC_Input, SPARC_OBJ *pSPARC) {
18691871
#ifdef DEBUG
18701872
printf("Found Hubbard block.\n");
18711873
#endif
1874+
if (pSPARC_Input->is_hubbard == 0) {
1875+
printf("Please specify HUBBARD_FALG: 1 in the .inpt file.\n");
1876+
exit(EXIT_FAILURE);
1877+
}
18721878
pSPARC->atomSolvSpinFlag = 0;
18731879
atm_flag = 1;
1874-
pSPARC->is_hubbard = 1;
1880+
// pSPARC->is_hubbard = 1;
18751881
pSPARC->AtmU = (HUB_DUDAREV_OBJ *)malloc(pSPARC->Ntypes*sizeof(HUB_DUDAREV_OBJ)); // initialise the AtmU object
18761882
fscanf(ion_fp, "%*[^\n]\n");
18771883
} else if (strcmpi(str, "U_ATOM_TYPE:") == 0) {
@@ -1896,7 +1902,8 @@ void read_ion(SPARC_INPUT_OBJ *pSPARC_Input, SPARC_OBJ *pSPARC) {
18961902
} else {
18971903
typcnt++;
18981904
if (pSPARC->atom_solve_flag != NULL) {
1899-
pSPARC->atom_solve_flag[typcnt] = 1;
1905+
// pSPARC->atom_solve_flag[typcnt] = 1;
1906+
pSPARC->atom_solve_flag[id_OG] = 1;
19001907
} else {
19011908
printf("Check if you have indicated start of the HUBBARD block...\n");
19021909
printf("Include the following line to indicate start of the block\n");
@@ -1907,8 +1914,10 @@ void read_ion(SPARC_INPUT_OBJ *pSPARC_Input, SPARC_OBJ *pSPARC) {
19071914

19081915
free(local_str);
19091916
} else if(strcmpi(str, "U_VAL:") == 0) {
1910-
Uval_count = fscanf(ion_fp,"%lf %lf %lf %lf",&pSPARC->AtmU[typcnt].U[0], &pSPARC->AtmU[typcnt].U[1],
1911-
&pSPARC->AtmU[typcnt].U[2], &pSPARC->AtmU[typcnt].U[3]);
1917+
// Uval_count = fscanf(ion_fp,"%lf %lf %lf %lf",&pSPARC->AtmU[typcnt].U[0], &pSPARC->AtmU[typcnt].U[1],
1918+
// &pSPARC->AtmU[typcnt].U[2], &pSPARC->AtmU[typcnt].U[3]);
1919+
Uval_count = fscanf(ion_fp,"%lf %lf %lf %lf",&pSPARC->AtmU[id_OG].U[0], &pSPARC->AtmU[id_OG].U[1],
1920+
&pSPARC->AtmU[id_OG].U[2], &pSPARC->AtmU[id_OG].U[3]);
19121921
if (Uval_count != 4) {
19131922
printf("\nError: U_VAL must have exactly 4 values corresponding to s p d f orbitals. Found %d values.\n", Uval_count);
19141923
exit(EXIT_FAILURE);
@@ -1923,7 +1932,7 @@ void read_ion(SPARC_INPUT_OBJ *pSPARC_Input, SPARC_OBJ *pSPARC) {
19231932
}
19241933

19251934
// checks
1926-
if ((pSPARC->is_hubbard == 1) && (typcnt+1 == 0)) {
1935+
if ((pSPARC_Input->is_hubbard == 1) && (typcnt+1 == 0)) {
19271936
printf("\nPlease specify atoms where you want to apply hubbard corrections.\n");
19281937
exit(EXIT_FAILURE);
19291938
}

0 commit comments

Comments
 (0)