Skip to content

Commit eb328b5

Browse files
committed
fix:
1.update n_dl parameter type to float and add validation for positive values in energy fitting models 2.nufft_shift and ishift in energy and force calculation
1 parent fcb68fd commit eb328b5

5 files changed

Lines changed: 81 additions & 17 deletions

File tree

deepmd/pt/model/model/les_model.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Any,
44
)
55

6+
import math
67
import pytorch_finufft
78
import torch
89

@@ -29,6 +30,8 @@
2930
make_model,
3031
)
3132

33+
E2_PER_ANGSTROM_TO_EV = 14.3996454784255
34+
3235
LESEnergyModel_ = make_model(LESEnergyAtomicModel)
3336

3437

@@ -172,9 +175,18 @@ def _compute_les_frame_correction_bundle(
172175
).reshape(-1)[0]
173176
sigma = torch.clamp(sigma, min=torch.finfo(real_dtype).eps)
174177
remove_self_interaction = bool(fitting.remove_self_interaction)
175-
n_dl = int(fitting.n_dl)
178+
n_dl = float(fitting.n_dl)
179+
if (not math.isfinite(n_dl)) or n_dl <= 0.0:
180+
raise ValueError("`n_dl` should be a positive finite number.")
176181
pi_tensor = torch.tensor(torch.pi, dtype=real_dtype, device=runtime_device)
177182
two_pi = torch.tensor(2.0 * torch.pi, dtype=real_dtype, device=runtime_device)
183+
n_dl_tensor = torch.as_tensor(n_dl, dtype=real_dtype, device=runtime_device)
184+
k_sq_max = (two_pi / n_dl_tensor) ** 2
185+
coulomb_to_ev = torch.as_tensor(
186+
E2_PER_ANGSTROM_TO_EV,
187+
dtype=real_dtype,
188+
device=runtime_device,
189+
)
178190

179191
nf, nloc, _ = coord.shape
180192
corr = torch.zeros((nf, 1), dtype=real_dtype, device=runtime_device)
@@ -224,14 +236,17 @@ def _compute_les_frame_correction_bundle(
224236
cell_inv_group = cell_inv_all[frame_ids]
225237
g_cart_group = two_pi * torch.einsum("bik,k...->bi...", cell_inv_group, k_grid_int)
226238
k_sq_group = torch.sum(g_cart_group**2, dim=1)
239+
k_in_cutoff = k_sq_group <= k_sq_max
227240

228241
k_sq_safe_group = torch.where(
229-
zero_mask_expand,
242+
zero_mask_expand | (~k_in_cutoff),
230243
torch.ones_like(k_sq_group),
231244
k_sq_group,
232245
)
233246
kfac_group = torch.exp(-0.5 * (sigma**2) * k_sq_safe_group) / k_sq_safe_group
234-
kfac_group = kfac_group.to(dtype=real_dtype).masked_fill(zero_mask_expand, 0.0)
247+
kfac_group = kfac_group.to(dtype=real_dtype).masked_fill(
248+
zero_mask_expand | (~k_in_cutoff), 0.0
249+
)
235250

236251
for local_idx, ff in enumerate(frame_ids):
237252
r_raw = coord[ff]
@@ -253,6 +268,9 @@ def _compute_les_frame_correction_bundle(
253268
eps=1e-4,
254269
isign=-1,
255270
)
271+
# FINUFFT coefficients are returned in FFT order; align to centered
272+
# mode ordering (-nk..nk) used by k_grid_int/kfac/g_cart.
273+
recon = torch.fft.fftshift(recon, dim=(1, 2, 3))
256274

257275
rho_sq = recon.real.square() + recon.imag.square()
258276
corr[ff, 0] = (kfac.unsqueeze(0) * rho_sq).sum() * two_pi / volume
@@ -266,6 +284,8 @@ def _compute_les_frame_correction_bundle(
266284
grad_conv = (
267285
1j * g_cart.unsqueeze(1).to(dtype=complex_dtype)
268286
) * conv.unsqueeze(0)
287+
# Convert back to FINUFFT FFT order before type-2 evaluation.
288+
grad_conv = torch.fft.ifftshift(grad_conv, dim=(2, 3, 4))
269289
grad_field = pytorch_finufft.functional.finufft_type2(
270290
nufft_points,
271291
grad_conv,
@@ -288,8 +308,17 @@ def _compute_les_frame_correction_bundle(
288308
).reshape(nloc, 1, 9)
289309

290310
if remove_self_interaction:
291-
diag_sum = kfac.sum() * two_pi / volume
292-
corr[ff, 0] -= torch.sum(latent_charge[ff] ** 2) * diag_sum
311+
self_corr = torch.sum(latent_charge[ff] ** 2) / (
312+
sigma * torch.sqrt(two_pi)
313+
)
314+
corr[ff, 0] -= self_corr
315+
316+
# Convert electrostatic unit from e^2/A to eV.
317+
corr = corr * coulomb_to_ev
318+
if force_local is not None:
319+
force_local = force_local * coulomb_to_ev
320+
if virial_local is not None:
321+
virial_local = virial_local * coulomb_to_ev
293322

294323
out: dict[str, torch.Tensor] = {"corr_redu": corr}
295324
if force_local is not None:

deepmd/pt/model/model/sog_model.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Any,
44
)
55

6+
import math
67
import pytorch_finufft
78
import torch
89

@@ -29,6 +30,8 @@
2930
make_model,
3031
)
3132

33+
E2_PER_ANGSTROM_TO_EV = 14.3996454784255
34+
3235
SOGEnergyModel_ = make_model(SOGEnergyAtomicModel)
3336

3437

@@ -189,9 +192,18 @@ def _compute_sog_frame_correction_bundle(
189192
raise ValueError("Invalid SOG `amp` value in fitting net.")
190193
if bandwidth.ndim != 1 or bandwidth.numel() == 0:
191194
raise ValueError("Invalid SOG `bandwidth` in fitting net.")
192-
n_dl = int(fitting.n_dl)
195+
n_dl = float(fitting.n_dl)
196+
if (not math.isfinite(n_dl)) or n_dl <= 0.0:
197+
raise ValueError("`n_dl` should be a positive finite number.")
193198
pi_tensor = torch.tensor(torch.pi, dtype=real_dtype, device=runtime_device)
194199
two_pi = 2.0 * pi_tensor
200+
n_dl_tensor = torch.as_tensor(n_dl, dtype=real_dtype, device=runtime_device)
201+
k_sq_max = (two_pi / n_dl_tensor) ** 2
202+
coulomb_to_ev = torch.as_tensor(
203+
E2_PER_ANGSTROM_TO_EV,
204+
dtype=real_dtype,
205+
device=runtime_device,
206+
)
195207

196208
nf, nloc, _ = coord.shape
197209
corr = torch.zeros((nf, 1), dtype=real_dtype, device=runtime_device)
@@ -242,9 +254,12 @@ def _compute_sog_frame_correction_bundle(
242254
cell_inv_group = cell_inv_all[frame_ids]
243255
g_cart_group = two_pi * torch.einsum("bik,k...->bi...", cell_inv_group, k_grid_int)
244256
k_sq_group = torch.sum(g_cart_group**2, dim=1)
257+
k_in_cutoff = k_sq_group <= k_sq_max
245258

246259
kfac_group = amp * bw2 * torch.exp(-0.5 * bw2 * k_sq_group.unsqueeze(-1))
247-
kfac_group = kfac_group.sum(dim=-1).masked_fill(zero_mask_expand, 0.0)
260+
kfac_group = kfac_group.sum(dim=-1).masked_fill(
261+
zero_mask_expand | (~k_in_cutoff), 0.0
262+
)
248263

249264
for local_idx, ff in enumerate(frame_ids):
250265
r_raw = coord[ff]
@@ -266,6 +281,9 @@ def _compute_sog_frame_correction_bundle(
266281
eps=1e-4,
267282
isign=-1,
268283
)
284+
# FINUFFT coefficients are returned in FFT order; align to centered
285+
# mode ordering (-nk..nk) used by k_grid_int/kfac/g_cart.
286+
recon = torch.fft.fftshift(recon, dim=(1, 2, 3))
269287

270288
rho_sq = recon.real.square() + recon.imag.square()
271289
corr[ff, 0] = (kfac.unsqueeze(0) * rho_sq).sum() / (2.0 * volume)
@@ -279,6 +297,8 @@ def _compute_sog_frame_correction_bundle(
279297
grad_conv = (
280298
1j * g_cart.unsqueeze(1).to(dtype=complex_dtype)
281299
) * conv.unsqueeze(0)
300+
# Convert back to FINUFFT FFT order before type-2 evaluation.
301+
grad_conv = torch.fft.ifftshift(grad_conv, dim=(2, 3, 4))
282302
grad_field = pytorch_finufft.functional.finufft_type2(
283303
nufft_points,
284304
grad_conv,
@@ -304,6 +324,13 @@ def _compute_sog_frame_correction_bundle(
304324
diag_sum = kfac.sum() / (2.0 * volume)
305325
corr[ff, 0] -= torch.sum(latent_charge[ff] ** 2) * diag_sum
306326

327+
# Convert electrostatic unit from e^2/A to eV.
328+
corr = corr * coulomb_to_ev
329+
if force_local is not None:
330+
force_local = force_local * coulomb_to_ev
331+
if virial_local is not None:
332+
virial_local = virial_local * coulomb_to_ev
333+
307334
out: dict[str, torch.Tensor] = {"corr_redu": corr}
308335
if force_local is not None:
309336
out["force_local"] = force_local

deepmd/pt/model/task/les_energy_fitting.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class LESEnergyFittingNet(LRFittingNet):
9393
default_fparam: list[float], optional
9494
The default frame parameter. If set, when `fparam.npy` files are not included in the data system,
9595
this value will be used as the default value for the frame parameter in the fitting net.
96-
n_dl : int
96+
n_dl : float
9797
NUFFT long-range grid density control factor.
9898
remove_self_interaction : bool
9999
If True, remove self interaction term in long-range correction.
@@ -126,7 +126,7 @@ def __init__(
126126
use_aparam_as_mask: bool = False,
127127
default_fparam: list[float] | None = None,
128128
sigma: float | list[float] | torch.Tensor | None = None,
129-
n_dl: int = 1,
129+
n_dl: float | int = 1.0,
130130
remove_self_interaction: bool = False,
131131
**kwargs: Any,
132132
) -> None:
@@ -169,7 +169,11 @@ def __init__(
169169
min=torch.finfo(sigma_tensor.dtype).eps,
170170
)
171171

172-
self.n_dl = max(1, int(n_dl))
172+
n_dl_value = float(n_dl)
173+
if (not np.isfinite(n_dl_value)) or n_dl_value <= 0.0:
174+
raise ValueError("`n_dl` should be a positive finite number.")
175+
176+
self.n_dl = n_dl_value
173177
self.sigma = torch.nn.Parameter(
174178
sigma_tensor,
175179
requires_grad=bool(self.trainable),

deepmd/pt/model/task/sog_energy_fitting.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class SOGEnergyFittingNet(LRFittingNet):
101101
Base bandwidth used by SOG parameterization.
102102
M : int
103103
Number of geometric bandwidth levels.
104-
n_dl : int
104+
n_dl : float
105105
NUFFT long-range grid density control factor.
106106
remove_self_interaction : bool
107107
If True, remove self interaction term in long-range correction.
@@ -138,7 +138,7 @@ def __init__(
138138
b: float | torch.Tensor | None = None,
139139
sigma: float | torch.Tensor | None = None,
140140
M: int | None = None,
141-
n_dl: int = 1,
141+
n_dl: float | int = 1.0,
142142
remove_self_interaction: bool = False,
143143
**kwargs: Any,
144144
) -> None:
@@ -217,7 +217,11 @@ def __init__(
217217
if torch.any(bandwidth_tensor <= 0.0):
218218
raise ValueError("`bandwidth` values should be positive.")
219219

220-
self.n_dl = max(1, int(n_dl))
220+
n_dl_value = float(n_dl)
221+
if (not np.isfinite(n_dl_value)) or n_dl_value <= 0.0:
222+
raise ValueError("`n_dl` should be a positive finite number.")
223+
224+
self.n_dl = n_dl_value
221225
self.amp = torch.nn.Parameter(
222226
torch.tensor([amp_value], dtype=dtype, device=device),
223227
requires_grad=bool(self.trainable),

deepmd/utils/argcheck.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,9 +2263,9 @@ def fitting_sog_energy() -> list[Argument]:
22632263
),
22642264
Argument(
22652265
"n_dl",
2266-
int,
2266+
[float, int],
22672267
optional=True,
2268-
default=1,
2268+
default=1.0,
22692269
doc=doc_only_pt_supported + doc_n_dl,
22702270
),
22712271
Argument(
@@ -2426,9 +2426,9 @@ def fitting_les_energy() -> list[Argument]:
24262426
),
24272427
Argument(
24282428
"n_dl",
2429-
int,
2429+
[float, int],
24302430
optional=True,
2431-
default=1,
2431+
default=1.0,
24322432
doc=doc_only_pt_supported + doc_n_dl,
24332433
),
24342434
Argument(

0 commit comments

Comments
 (0)