Skip to content

Commit 00dd1af

Browse files
Merge pull request #251 from sayanbhowmik/master
2 parents 9069932 + 0286569 commit 00dd1af

3 files changed

Lines changed: 97 additions & 3 deletions

File tree

ChangeLog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
-Date
33
-Name
44
-changes
5+
--------------
6+
September 04, 2025
7+
Name: Sayan Bhowmik
8+
Changes: (src/md.c)
9+
1. Bug fix in minimum pairwise distance calculation - include PBC/MIC.
10+
511
--------------
612
September 03, 2025
713
Name: Tian Tian

src/initialization.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3722,7 +3722,7 @@ void write_output_init(SPARC_OBJ *pSPARC) {
37223722
}
37233723

37243724
fprintf(output_fp,"***************************************************************************\n");
3725-
fprintf(output_fp,"* SPARC (version September 03, 2025) *\n");
3725+
fprintf(output_fp,"* SPARC (version September 04, 2025) *\n");
37263726
fprintf(output_fp,"* Copyright (c) 2020 Material Physics & Mechanics Group, Georgia Tech *\n");
37273727
fprintf(output_fp,"* Distributed under GNU General Public License 3 (GPL) *\n");
37283728
fprintf(output_fp,"* Start time: %s *\n",c_time_str);

src/md.c

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@
1313
#include <string.h>
1414
#include <math.h>
1515

16+
#ifdef USE_MKL
17+
#include <mkl.h>
18+
#else
19+
#include <cblas.h>
20+
#include <lapacke.h>
21+
#endif
22+
1623
#include "md.h"
1724
#include "isddft.h"
1825
#include "orbitalElecDensInit.h"
@@ -2135,11 +2142,68 @@ void MD_QOI(SPARC_OBJ *pSPARC, double *avgvel, double *maxvel, double *mindis) {
21352142
//*avgdis = pow((pSPARC->range_x * pSPARC->range_y * pSPARC->range_z)/pSPARC->n_atom,1/3.0);
21362143
int atm2, ityp2, cc2, pairIndex;
21372144
cc = 0;
2145+
2146+
// Store the cell as a 3x3 lattice vector
2147+
double *lattice = (double *)calloc(sizeof(double), 9);
2148+
double cell[3] = {pSPARC->range_x, pSPARC->range_y, pSPARC->range_z};
2149+
double dr[3];
2150+
int row, col;
2151+
for (row = 0; row < 3; row++) {
2152+
lattice[row*3] = pSPARC->LatUVec[row*3] * cell[row];
2153+
lattice[row*3 + 1] = pSPARC->LatUVec[row*3 + 1] * cell[row];
2154+
lattice[row*3 + 2] = pSPARC->LatUVec[row*3 + 2] * cell[row];
2155+
}
2156+
2157+
// Calculate the inverse of lattice-vector
2158+
double LV_inv[9], U[9], S[3], VT[9], superb[2], temp_mat[9], LatVec[9];
2159+
double S_inv[9] = {0};
2160+
int m = 3;
2161+
2162+
for (int JJ = 0; JJ < 9; JJ++) {
2163+
LatVec[JJ] = lattice[JJ];
2164+
}
2165+
2166+
/* Calculating pinv(LatVec): This is necessary because for extremely skewed LV, the LV maybe close to singular */
2167+
// Compute SVD of LatVec(LV) first: LV = U * S * V^T
2168+
LAPACKE_dgesvd(LAPACK_ROW_MAJOR, 'A', 'A', m, m, LatVec, m, S, U, m, VT, m, superb);
2169+
2170+
// First compute S^{-1}
2171+
for (int i = 0; i < 3; i++) {
2172+
if (S[i] > 1e-12) S_inv[i * 3 + i] = 1.0/S[i];
2173+
}
2174+
2175+
// Compute LV^{-1} = V * S^{-1} * U^T
2176+
cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, m, m, m, 1.0, VT, m, S_inv, m, 0.0, temp_mat, m);
2177+
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, m, m, m, 1.0, temp_mat, m, U, m, 0.0, LV_inv, m);
2178+
21382179
for(ityp = 0; ityp < pSPARC->Ntypes; ityp++){
21392180
mindis[ityp] = 1000000000.0;
21402181
for(atm = 0; atm < pSPARC->nAtomv[ityp] - 1; atm++){
21412182
for(atm2 = atm + 1; atm2 < pSPARC->nAtomv[ityp]; atm2++){
2142-
temp = fabs(sqrt(pow(pSPARC->atom_pos[3 * (atm + cc)] - pSPARC->atom_pos[3 * (atm2 + cc)],2.0) + pow(pSPARC->atom_pos[3 * (atm + cc) + 1] - pSPARC->atom_pos[3 * (atm2 + cc) + 1],2.0) + pow(pSPARC->atom_pos[3 * (atm + cc) + 2] - pSPARC->atom_pos[3 * (atm2 + cc) + 2],2.0) ));
2183+
// temp = fabs(sqrt(pow(pSPARC->atom_pos[3 * (atm + cc)] - pSPARC->atom_pos[3 * (atm2 + cc)],2.0) + pow(pSPARC->atom_pos[3 * (atm + cc) + 1] - pSPARC->atom_pos[3 * (atm2 + cc) + 1],2.0) + pow(pSPARC->atom_pos[3 * (atm + cc) + 2] - pSPARC->atom_pos[3 * (atm2 + cc) + 2],2.0) ));
2184+
2185+
// Vector connecting atoms atm and atm2
2186+
dr[0] = pSPARC->atom_pos[3 * (atm + cc)] - pSPARC->atom_pos[3 * (atm2 + cc)];
2187+
dr[1] = pSPARC->atom_pos[3 * (atm + cc) + 1] - pSPARC->atom_pos[3 * (atm2 + cc) + 1];
2188+
dr[2] = pSPARC->atom_pos[3 * (atm + cc) + 2] - pSPARC->atom_pos[3 * (atm2 + cc) + 2];
2189+
2190+
double frac[3], dr_pbc[3];
2191+
2192+
// Minimum Image Convention (MIC) in fractional coordinates
2193+
// frac = LV^{-1} * dr
2194+
cblas_dgemv(CblasRowMajor, CblasNoTrans, m, m, 1.0, LV_inv, m, dr, 1, 0.0, frac, 1);
2195+
2196+
// Wrap into [-0.5, 0.5)
2197+
frac[0] -= round(frac[0]);
2198+
frac[1] -= round(frac[1]);
2199+
frac[2] -= round(frac[2]);
2200+
2201+
// dr_pbc = lattice * frac
2202+
cblas_dgemv(CblasRowMajor, CblasNoTrans, m, m, 1.0, lattice, 3, frac, 1, 0.0, dr_pbc, 1);
2203+
2204+
// Calculate distance
2205+
temp = sqrt(dr_pbc[0]*dr_pbc[0] + dr_pbc[1]*dr_pbc[1] + dr_pbc[2]*dr_pbc[2]);
2206+
21432207
if(temp < mindis[ityp])
21442208
mindis[ityp] = temp;
21452209
}
@@ -2155,7 +2219,30 @@ void MD_QOI(SPARC_OBJ *pSPARC, double *avgvel, double *maxvel, double *mindis) {
21552219
mindis[pairIndex] = 1000000000.0;
21562220
for(atm = 0; atm < pSPARC->nAtomv[ityp]; atm++){
21572221
for(atm2 = 0; atm2 < pSPARC->nAtomv[ityp2]; atm2++){
2158-
temp = fabs(sqrt(pow(pSPARC->atom_pos[3 * (atm + cc)] - pSPARC->atom_pos[3 * (atm2 + cc2)],2.0) + pow(pSPARC->atom_pos[3 * (atm + cc) + 1] - pSPARC->atom_pos[3 * (atm2 + cc2) + 1],2.0) + pow(pSPARC->atom_pos[3 * (atm + cc) + 2] - pSPARC->atom_pos[3 * (atm2 + cc2) + 2],2.0) ));
2222+
// temp = fabs(sqrt(pow(pSPARC->atom_pos[3 * (atm + cc)] - pSPARC->atom_pos[3 * (atm2 + cc2)],2.0) + pow(pSPARC->atom_pos[3 * (atm + cc) + 1] - pSPARC->atom_pos[3 * (atm2 + cc2) + 1],2.0) + pow(pSPARC->atom_pos[3 * (atm + cc) + 2] - pSPARC->atom_pos[3 * (atm2 + cc2) + 2],2.0) ));
2223+
2224+
// Vector connecting atoms atm and atm2
2225+
dr[0] = pSPARC->atom_pos[3 * (atm + cc)] - pSPARC->atom_pos[3 * (atm2 + cc2)];
2226+
dr[1] = pSPARC->atom_pos[3 * (atm + cc) + 1] - pSPARC->atom_pos[3 * (atm2 + cc2) + 1];
2227+
dr[2] = pSPARC->atom_pos[3 * (atm + cc) + 2] - pSPARC->atom_pos[3 * (atm2 + cc2) + 2];
2228+
2229+
double frac[3], dr_pbc[3];
2230+
2231+
// Minimum Image Convention (MIC) in fractional coordinates
2232+
// frac = LV^{-1} * dr
2233+
cblas_dgemv(CblasRowMajor, CblasNoTrans, m, m, 1.0, LV_inv, m, dr, 1, 0.0, frac, 1);
2234+
2235+
// Wrap into [-0.5, 0.5)
2236+
frac[0] -= round(frac[0]);
2237+
frac[1] -= round(frac[1]);
2238+
frac[2] -= round(frac[2]);
2239+
2240+
// dr_pbc = lattice * frac
2241+
cblas_dgemv(CblasRowMajor, CblasNoTrans, m, m, 1.0, lattice, 3, frac, 1, 0.0, dr_pbc, 1);
2242+
2243+
// Calculate distance
2244+
temp = sqrt(dr_pbc[0]*dr_pbc[0] + dr_pbc[1]*dr_pbc[1] + dr_pbc[2]*dr_pbc[2]);
2245+
21592246
if(temp < mindis[pairIndex])
21602247
mindis[pairIndex] = temp;
21612248
}
@@ -2165,6 +2252,7 @@ void MD_QOI(SPARC_OBJ *pSPARC, double *avgvel, double *maxvel, double *mindis) {
21652252
}
21662253
cc += pSPARC->nAtomv[ityp];
21672254
}
2255+
free(lattice);
21682256
}
21692257

21702258
/*

0 commit comments

Comments
 (0)