@@ -1121,45 +1121,50 @@ class JeeIOrbitalSoA : public WaveFunctionComponent
1121
1121
1122
1122
inline GradType evalGradSource (ParticleSet& P, ParticleSet& source, int isrc) override
1123
1123
{
1124
- ParticleSet::ParticleGradient tempG;
1125
- ParticleSet::ParticleLaplacian tempL;
1126
- tempG.resize (P.getTotalNum ());
1127
- tempL.resize (P.getTotalNum ());
1128
- QTFull::RealType delta = 0.00001 ;
1129
- QTFull::RealType c1 = 1.0 / delta / 2.0 ;
1130
- QTFull::RealType c2 = 1.0 / delta / delta;
1131
-
1132
- GradType g_return (0.0 );
1133
- // GRAD TEST COMPUTATION
1134
- PosType rI = source.R [isrc];
1135
- for (int iondim = 0 ; iondim < 3 ; iondim++)
1136
- {
1137
- source.R [isrc][iondim] = rI[iondim] + delta;
1138
- source.update ();
1139
- P.update ();
1140
-
1141
- LogValue log_p = evaluateLog (P, tempG, tempL);
1124
+ constexpr valT czero (0 );
1125
+ constexpr valT cone (1 );
1126
+ constexpr valT cminus (-1 );
1127
+ constexpr valT ctwo (2 );
1128
+ constexpr valT lapfac = OHMMS_DIM - cone;
1142
1129
1143
- source.R [isrc][iondim] = rI[iondim] - delta;
1144
- source.update ();
1145
- P.update ();
1146
- LogValue log_m = evaluateLog (P, tempG, tempL);
1130
+ const auto & ee_table = P.getDistTableAA (ee_Table_ID_);
1131
+ const auto & ee_dists = ee_table.getDistances ();
1132
+ const auto & ee_displs = ee_table.getDisplacements ();
1147
1133
1148
- QTFull::RealType log_p_r (0.0 ), log_m_r (0.0 );
1134
+ TinyVector<RealType, 3 > u3grad;
1135
+ Tensor<RealType, 3 > u3hess;
1136
+ const int iat = isrc;
1149
1137
1150
- log_p_r = log_p.real ();
1151
- log_m_r = log_m.real ();
1152
- // symmetric finite difference formula for gradient.
1153
- g_return[iondim] = c1 * (log_p_r - log_m_r);
1138
+ posT ion_deriv (0 );
1139
+ const int ig = Ions.GroupID [iat];
1140
+ for (int jg = 0 ; jg < eGroups; ++jg)
1141
+ for (int jind = 0 ; jind < elecs_inside (jg, iat).size (); jind++)
1142
+ {
1143
+ const int jel = elecs_inside (jg, iat)[jind];
1144
+ const valT r_Ij = elecs_inside_dist (jg, iat)[jind];
1145
+ const posT disp_Ij = cminus * elecs_inside_displ (jg, iat)[jind];
1146
+ const valT r_Ij_inv = cone / r_Ij;
1154
1147
1155
- // reset everything to how it was.
1156
- source.R [isrc][iondim] = rI[iondim];
1157
- }
1158
- // this last one makes sure the distance tables and internal neighbourlist correspond to unperturbed source.
1159
- source.update ();
1160
- P.update ();
1161
- build_compact_list (P);
1162
- return g_return;
1148
+ for (int kg = 0 ; kg < eGroups; ++kg)
1149
+ for (int kind = 0 ; kind < elecs_inside (kg, iat).size (); kind++)
1150
+ {
1151
+ const FT& feeI (*F (ig, jg, kg));
1152
+ const int kel = elecs_inside (kg, iat)[kind];
1153
+ if (kel < jel)
1154
+ {
1155
+ const valT r_Ik = elecs_inside_dist (kg, iat)[kind];
1156
+ const posT disp_Ik = cminus * elecs_inside_displ (kg, iat)[kind];
1157
+ const valT r_Ik_inv = cone / r_Ik;
1158
+
1159
+ const valT r_jk = ee_dists[jel][kel];
1160
+ const posT disp_jk = ee_displs[jel][kel];
1161
+ const valT r_jk_inv = cone / r_jk;
1162
+ feeI.evaluate (r_jk, r_Ij, r_Ik, u3grad, u3hess);
1163
+ ion_deriv += u3grad[1 ] * disp_Ij * r_Ij_inv + u3grad[2 ] * disp_Ik * r_Ik_inv;
1164
+ }
1165
+ }
1166
+ }
1167
+ return ion_deriv;;
1163
1168
}
1164
1169
1165
1170
inline GradType evalGradSource (ParticleSet& P,
@@ -1168,55 +1173,106 @@ class JeeIOrbitalSoA : public WaveFunctionComponent
1168
1173
TinyVector<ParticleSet::ParticleGradient, OHMMS_DIM>& grad_grad,
1169
1174
TinyVector<ParticleSet::ParticleLaplacian, OHMMS_DIM>& lapl_grad) override
1170
1175
{
1171
- ParticleSet::ParticleGradient Gp, Gm, dG;
1172
- ParticleSet::ParticleLaplacian Lp, Lm, dL;
1173
- Gp.resize (P.getTotalNum ());
1174
- Gm.resize (P.getTotalNum ());
1175
- dG.resize (P.getTotalNum ());
1176
- Lp.resize (P.getTotalNum ());
1177
- Lm.resize (P.getTotalNum ());
1178
- dL.resize (P.getTotalNum ());
1179
-
1180
- QTFull::RealType delta = 0.00001 ;
1181
- QTFull::RealType c1 = 1.0 / delta / 2.0 ;
1182
- QTFull::RealType c2 = 1.0 / delta / delta;
1183
- GradType g_return (0.0 );
1184
- // GRAD TEST COMPUTATION
1185
- PosType rI = source.R [isrc];
1186
- for (int iondim = 0 ; iondim < 3 ; iondim++)
1187
- {
1188
- Lp = 0 ;
1189
- Gp = 0 ;
1190
- Lm = 0 ;
1191
- Gm = 0 ;
1192
- source.R [isrc][iondim] = rI[iondim] + delta;
1193
- source.update ();
1194
- P.update ();
1195
-
1196
- LogValue log_p = evaluateLog (P, Gp, Lp);
1197
-
1198
- source.R [isrc][iondim] = rI[iondim] - delta;
1199
- source.update ();
1200
- P.update ();
1201
- LogValue log_m = evaluateLog (P, Gm, Lm);
1202
- QTFull::RealType log_p_r (0.0 ), log_m_r (0.0 );
1203
-
1204
- log_p_r = log_p.real ();
1205
- log_m_r = log_m.real ();
1206
- dG = Gp - Gm;
1207
- dL = Lp - Lm;
1208
- // symmetric finite difference formula for gradient.
1209
- g_return[iondim] = c1 * (log_p_r - log_m_r);
1210
- grad_grad[iondim] += c1 * dG;
1211
- lapl_grad[iondim] += c1 * dL;
1212
- // reset everything to how it was.
1213
- source.R [isrc][iondim] = rI[iondim];
1214
- }
1215
- // this last one makes sure the distance tables and internal neighbourlist correspond to unperturbed source.
1216
- source.update ();
1217
- P.update ();
1218
- build_compact_list (P);
1219
- return g_return;
1176
+ constexpr valT czero (0 );
1177
+ constexpr valT cone (1 );
1178
+ constexpr valT cminus (-1 );
1179
+ constexpr valT ctwo (2 );
1180
+ constexpr valT lapfac = OHMMS_DIM - cone;
1181
+
1182
+ const auto & ee_table = P.getDistTableAA (ee_Table_ID_);
1183
+ const auto & ee_dists = ee_table.getDistances ();
1184
+ const auto & ee_displs = ee_table.getDisplacements ();
1185
+
1186
+ ParticleSet::ParticleGradient G;
1187
+ ParticleSet::ParticleLaplacian L;
1188
+ G.resize (4 );
1189
+ L.resize (4 );
1190
+
1191
+ TinyVector<RealType, 3 > grad;
1192
+ Tensor<RealType, 3 > hess;
1193
+ TinyVector<Tensor<RealType, 3 >, 3 > d3;
1194
+
1195
+ TinyVector<RealType, 3 > e1 (1 , 0 , 0 );
1196
+ TinyVector<RealType, 3 > e2 (0 , 1 , 0 );
1197
+ TinyVector<RealType, 3 > e3 (0 , 0 , 1 );
1198
+
1199
+ TinyVector<TinyVector<RealType, 3 >, 3 > identmat (e1 , e2 , e3 );
1200
+
1201
+ const int iat = isrc;
1202
+
1203
+ posT ion_deriv (0 );
1204
+ const int ig = Ions.GroupID [iat];
1205
+ for (int jg = 0 ; jg < eGroups; ++jg)
1206
+ for (int jind = 0 ; jind < elecs_inside (jg, iat).size (); jind++)
1207
+ {
1208
+ const int jel = elecs_inside (jg, iat)[jind];
1209
+ const valT r_Ij = elecs_inside_dist (jg, iat)[jind];
1210
+ const posT disp_Ij = cminus * elecs_inside_displ (jg, iat)[jind];
1211
+ const valT r_Ij_inv = cone / r_Ij;
1212
+ const posT disp_Ij_unit = disp_Ij * r_Ij_inv;
1213
+
1214
+ for (int kg = 0 ; kg < eGroups; ++kg)
1215
+ for (int kind = 0 ; kind < elecs_inside (kg, iat).size (); kind++)
1216
+ {
1217
+ const FT& feeI (*F (ig, jg, kg));
1218
+ const int kel = elecs_inside (kg, iat)[kind];
1219
+ if (kel < jel)
1220
+ {
1221
+ const valT r_Ik = elecs_inside_dist (kg, iat)[kind];
1222
+ const posT disp_Ik = cminus * elecs_inside_displ (kg, iat)[kind];
1223
+ const valT r_Ik_inv = cone / r_Ik;
1224
+ const posT disp_Ik_unit = disp_Ik * r_Ik_inv;
1225
+
1226
+ const valT r_jk = ee_dists[jel][kel];
1227
+ const posT disp_jk = ee_displs[jel][kel];
1228
+ const valT r_jk_inv = cone / r_jk;
1229
+ const posT disp_jk_unit = disp_jk * r_jk_inv;
1230
+
1231
+ const valT dot_ujk_uIj = dot (disp_jk_unit, disp_Ij_unit);
1232
+ const valT dot_ujk_uIk = dot (disp_jk_unit, disp_Ik_unit);
1233
+ grad = 0.0 ;
1234
+ hess = 0.0 ;
1235
+ d3 = 0.0 ;
1236
+ feeI.evaluate (r_jk, r_Ij, r_Ik, grad, hess, d3);
1237
+ ion_deriv += grad[1 ] * disp_Ij * r_Ij_inv + grad[2 ] * disp_Ik * r_Ik_inv;
1238
+
1239
+ for (int idim = 0 ; idim < OHMMS_DIM; idim++)
1240
+ {
1241
+ const posT igrad_r_Ij_unit =
1242
+ -(identmat[idim] * r_Ij_inv - disp_Ij * disp_Ij[idim] * r_Ij_inv * r_Ij_inv * r_Ij_inv);
1243
+ const posT igrad_r_Ik_unit =
1244
+ -(identmat[idim] * r_Ik_inv - disp_Ik * disp_Ik[idim] * r_Ik_inv * r_Ik_inv * r_Ik_inv);
1245
+ const posT igrad_g0 = -(hess (0 , 1 ) * disp_Ij_unit[idim] + hess (0 , 2 ) * disp_Ik_unit[idim]);
1246
+ const posT igrad_g1 = -(hess (1 , 1 ) * disp_Ij_unit[idim] + hess (1 , 2 ) * disp_Ik_unit[idim]);
1247
+ const posT igrad_g2 = -(hess (1 , 2 ) * disp_Ij_unit[idim] + hess (2 , 2 ) * disp_Ik_unit[idim]);
1248
+
1249
+ const posT igrad_h00 =
1250
+ -(d3[0 ](0 , 1 ) * disp_Ij[idim] * r_Ij_inv + d3[0 ](0 , 2 ) * disp_Ik[idim] * r_Ik_inv);
1251
+ const posT igrad_h11 =
1252
+ -(d3[1 ](1 , 1 ) * disp_Ij[idim] * r_Ij_inv + d3[1 ](1 , 2 ) * disp_Ik[idim] * r_Ik_inv);
1253
+ const posT igrad_h22 =
1254
+ -(d3[1 ](2 , 2 ) * disp_Ij[idim] * r_Ij_inv + d3[2 ](2 , 2 ) * disp_Ik[idim] * r_Ik_inv);
1255
+ const posT igrad_h01 =
1256
+ -(d3[0 ](1 , 1 ) * disp_Ij[idim] * r_Ij_inv + d3[0 ](1 , 2 ) * disp_Ik[idim] * r_Ik_inv);
1257
+ const posT igrad_h02 =
1258
+ -(d3[0 ](1 , 2 ) * disp_Ij[idim] * r_Ij_inv + d3[0 ](2 , 2 ) * disp_Ik[idim] * r_Ik_inv);
1259
+ const posT igrad_dot_ujk_uIj = -(disp_jk_unit[idim] - dot_ujk_uIj * disp_Ij_unit) * r_Ij_inv;
1260
+ const posT igrad_dot_ujk_uIk = -(disp_jk_unit[idim] - dot_ujk_uIk * disp_Ik_unit) * r_Ik_inv;
1261
+
1262
+ grad_grad[idim][jel] -= igrad_g1 * disp_Ij_unit + grad[1 ] * igrad_r_Ij_unit - igrad_g0 * disp_jk_unit;
1263
+ grad_grad[idim][kel] -= igrad_g2 * disp_Ik_unit + grad[2 ] * igrad_r_Ik_unit + igrad_g0 * disp_jk_unit;
1264
+
1265
+ lapl_grad[idim][jel] -= igrad_h00[idim] + lapfac * igrad_g0[idim] * r_jk_inv -
1266
+ ctwo * (igrad_h01[idim] * dot_ujk_uIj + hess (0 , 1 ) * igrad_dot_ujk_uIj[idim]) + igrad_h11[idim] +
1267
+ lapfac * (igrad_g1[idim] * r_Ij_inv - grad[1 ] * r_Ij_inv * r_Ij_inv * (-disp_Ij_unit[idim]));
1268
+ lapl_grad[idim][kel] -= igrad_h00[idim] + lapfac * igrad_g0[idim] * r_jk_inv +
1269
+ ctwo * (igrad_h02[idim] * dot_ujk_uIk + hess (0 , 2 ) * igrad_dot_ujk_uIk[idim]) + igrad_h22[idim] +
1270
+ lapfac * (igrad_g2[idim] * r_Ik_inv - grad[2 ] * r_Ik_inv * r_Ik_inv * (-disp_Ik_unit[idim]));
1271
+ }
1272
+ }
1273
+ }
1274
+ }
1275
+ return ion_deriv;;
1220
1276
}
1221
1277
};
1222
1278
0 commit comments