@@ -191,48 +191,49 @@ def compute_dpdr(self, atoms, atom_ids=None):
191191 p_list = np .zeros ((self .natoms , self .ncoefs ), dtype = np .float64 )
192192 dp_list = np .zeros ((self .natoms , self .natoms , self .ncoefs , 3 ), dtype = np .float64 )
193193
194- # get expansion coefficients and derivatives
195- cs , dcs = compute_dcs (self .neighborlist , self .nmax , self .lmax , self .rcut , self .alpha , self ._cutoff_function )
194+ if len (self .neighborlist ) > 0 :
195+ # get expansion coefficients and derivatives
196+ cs , dcs = compute_dcs (self .neighborlist , self .nmax , self .lmax , self .rcut , self .alpha , self ._cutoff_function )
196197
197- # weight cs and dcs
198- cs *= self .atomic_weights [:, np .newaxis , np .newaxis , np .newaxis ]
199- dcs *= self .atomic_weights [:, np .newaxis , np .newaxis , np .newaxis , np .newaxis ]
200- cs = np .einsum ('inlm,l->inlm' , cs , self .norm )
201- dcs = np .einsum ('inlmj,l->inlmj' , dcs , self .norm )
202- #print('cs, dcs', self.neighbor_indices, cs.shape, dcs.shape)
198+ # weight cs and dcs
199+ cs *= self .atomic_weights [:, np .newaxis , np .newaxis , np .newaxis ]
200+ dcs *= self .atomic_weights [:, np .newaxis , np .newaxis , np .newaxis , np .newaxis ]
201+ cs = np .einsum ('inlm,l->inlm' , cs , self .norm )
202+ dcs = np .einsum ('inlmj,l->inlmj' , dcs , self .norm )
203+ #print('cs, dcs', self.neighbor_indices, cs.shape, dcs.shape)
203204
204- # Assign cs and dcs to P and dP
205- # cs: (N_ij, n, l, m) => P (N_i, N_des)
206- # dcs: (N_ij, n, l, m, 3) => dP (N_i, N_j, N_des, 3)
207- # (n, l, m) needs to be merged to 1 dimension
205+ # Assign cs and dcs to P and dP
206+ # cs: (N_ij, n, l, m) => P (N_i, N_des)
207+ # dcs: (N_ij, n, l, m, 3) => dP (N_i, N_j, N_des, 3)
208+ # (n, l, m) needs to be merged to 1 dimension
208209
209- for i in range (len (atoms )):
210- # find atoms for which i is the center
211- centers = self .neighbor_indices [:, 0 ] == i
210+ for i in range (len (atoms )):
211+ # find atoms for which i is the center
212+ centers = self .neighbor_indices [:, 0 ] == i
212213
213- if len (self .neighbor_indices [centers ]) > 0 :
214- # total up the c array for the center atom
215- ctot = cs [centers ].sum (axis = 0 ) #(n, l, m)
214+ if len (self .neighbor_indices [centers ]) > 0 :
215+ # total up the c array for the center atom
216+ ctot = cs [centers ].sum (axis = 0 ) #(n, l, m)
216217
217- # power spectrum P = c*c_conj
218- # eq_3 (n, n', l) eliminate m
219- P = np .einsum ('ijk, ljk->ilj' , ctot , np .conj (ctot )).real
220- p_list [i ] = P [self .tril_indices ].flatten ()
218+ # power spectrum P = c*c_conj
219+ # eq_3 (n, n', l) eliminate m
220+ P = np .einsum ('ijk, ljk->ilj' , ctot , np .conj (ctot )).real
221+ p_list [i ] + = P [self .tril_indices ].flatten ()
221222
222- # gradient of P for each neighbor, eq_26
223- # (N_ijs, n, n', l, 3)
224- # dc * c_conj + c * dc_conj
225- dP = np .einsum ('wijkn,ljk->wiljn' , dcs [centers ], np .conj (ctot ))
226- dP += np .conj (np .transpose (dP , axes = [0 , 2 , 1 , 3 , 4 ]))
227- dP = dP .real
223+ # gradient of P for each neighbor, eq_26
224+ # (N_ijs, n, n', l, 3)
225+ # dc * c_conj + c * dc_conj
226+ dP = np .einsum ('wijkn,ljk->wiljn' , dcs [centers ], np .conj (ctot ))
227+ dP += np .conj (np .transpose (dP , axes = [0 , 2 , 1 , 3 , 4 ]))
228+ dP = dP .real
228229
229- #print("shape of P/dP", P.shape, dP.shape)#; import sys; sys.exit()
230+ #print("shape of P/dP", P.shape, dP.shape)#; import sys; sys.exit()
230231
231- # QZ: to check
232- ijs = self .neighbor_indices [centers ]
233- for _id , j in enumerate (ijs [:, 1 ]):
234- dp_list [i , j , :, :] += dP [_id ][self .tril_indices ].flatten ().reshape (self .ncoefs , 3 )
235- dp_list [i , i , :, :] -= dP [_id ][self .tril_indices ].flatten ().reshape (self .ncoefs , 3 )
232+ # QZ: to check
233+ ijs = self .neighbor_indices [centers ]
234+ for _id , j in enumerate (ijs [:, 1 ]):
235+ dp_list [i , j , :, :] += dP [_id ][self .tril_indices ].flatten ().reshape (self .ncoefs , 3 )
236+ dp_list [i , i , :, :] -= dP [_id ][self .tril_indices ].flatten ().reshape (self .ncoefs , 3 )
236237
237238 return dp_list , p_list
238239
@@ -242,7 +243,6 @@ def compute_dpdr_5d(self, atoms):
242243
243244 Args:
244245 atoms: ase atoms object
245- atom_ids: optional list of atomic indices
246246
247247 Returns:
248248 dpdr array (N, N, M, 3, 27) and p array (N, M)
@@ -270,31 +270,31 @@ def compute_dpdr_5d(self, atoms):
270270 for i in range (len (atoms )):
271271 # find atoms for which i is the center
272272 pair_ids = neigh_ids [self .neighbor_indices [:, 0 ] == i ]
273-
274- # loop over each pair
275- for pair_id in pair_ids :
276- (_ , j , x , y , z ) = self .neighbor_indices [pair_id ]
277- # map from (x, y, z) to (0, 27)
278- cell_id = (x + 1 ) * 9 + (y + 1 ) * 3 + z + 1
279-
273+ if len (pair_ids ) > 0 :
274+ ctot = cs [pair_ids ].sum (axis = 0 ) #(n, l, m)
280275 # power spectrum P = c*c_conj
281276 # eq_3 (n, n', l) eliminate m
282- P = np .einsum ('ijk, ljk->ilj' , cs [ pair_id ] , np .conj (cs [ pair_id ] )).real
283- p_list [i ] = P [self .tril_indices ].flatten ()
277+ P = np .einsum ('ijk, ljk->ilj' , ctot , np .conj (ctot )).real
278+ p_list [i ] + = P [self .tril_indices ].flatten ()
284279
285- # gradient of P for each neighbor, eq_26
286- # (N_ijs, n, n', l, 3)
287- # dc * c_conj + c * dc_conj
288- dP = np .einsum ('ijkn, ljk->iljn' , dcs [pair_id ], np .conj (cs [pair_id ]))
289- dP += np .conj (np .transpose (dP , axes = [1 , 0 , 2 , 3 ]))
290- dP = dP .real [self .tril_indices ].flatten ().reshape (self .ncoefs , 3 )
291- #print(cs[pair_id].shape, dcs[pair_id].shape, dP.shape)
280+ # loop over each pair
281+ for pair_id in pair_ids :
282+ (_ , j , x , y , z ) = self .neighbor_indices [pair_id ]
283+ # map from (x, y, z) to (0, 27)
284+ cell_id = (x + 1 ) * 9 + (y + 1 ) * 3 + z + 1
292285
293- dp_list [i , j , :, :, cell_id ] += dP
294- dp_list [i , i , :, :, cell_id ] -= dP
286+ # gradient of P for each neighbor, eq_26
287+ # (N_ijs, n, n', l, 3)
288+ # dc * c_conj + c * dc_conj
289+ dP = np .einsum ('ijkn, ljk->iljn' , dcs [pair_id ], np .conj (ctot ))
290+ dP += np .conj (np .transpose (dP , axes = [1 , 0 , 2 , 3 ]))
291+ dP = dP .real [self .tril_indices ].flatten ().reshape (self .ncoefs , 3 )
292+ #print(cs[pair_id].shape, dcs[pair_id].shape, dP.shape)
295293
296- return dp_list , p_list
294+ dp_list [i , j , :, :, cell_id ] += dP
295+ dp_list [i , i , :, :, cell_id ] -= dP
297296
297+ return dp_list , p_list
298298
299299
300300 def calculate (self , atoms , atom_ids = None , derivative = False ):
@@ -696,5 +696,6 @@ def compute_dcs(pos, nmax, lmax, rcut, alpha, cutoff):
696696 print (f )
697697 print ('x' , x ['x' ])
698698 #print('dxdr', x['dxdr'])
699- print ('calculation time {}' .format (start2 - start1 ))
700- print (f .compute_p (test ))
699+ p = f .compute_p (test ); print ('from P' , p )
700+ dp , p = f .compute_dpdr (test ); print ('from dP' , p )
701+ dp , p = f .compute_dpdr_5d (test ); print ('from dP5d' , p )
0 commit comments