@@ -296,19 +296,19 @@ def calculate(
296
296
system_changes = system_changes ,
297
297
)
298
298
299
+ ask_for_energy_gradient = (
300
+ "forces" in properties or "stress" in properties or "stresses" in properties
301
+ )
302
+ ask_for_energy = "energy" in properties or "energies" in properties
303
+
299
304
# In the next few lines, we decide which properties to calculate among energy,
300
305
# forces and stress. In addition to the requested properties, we calculate the
301
306
# energy if any of the three is requested, as it is an intermediate step in the
302
307
# calculation of the other two. We also calculate the forces if the stress is
303
308
# requested, and vice-versa. The overhead for the latter operation is also
304
309
# small, assuming that the majority of the model computes forces and stresses
305
310
# by backward propagation as opposed to forward-mode differentiation.
306
- calculate_energy = (
307
- "energy" in properties
308
- or "energies" in properties
309
- or "forces" in properties
310
- or "stress" in properties
311
- )
311
+ calculate_energy = ask_for_energy or ask_for_energy_gradient
312
312
calculate_energies = "energies" in properties
313
313
calculate_forces = "forces" in properties or "stress" in properties
314
314
calculate_stress = "stress" in properties
@@ -318,14 +318,28 @@ def calculate(
318
318
"periodic in all directions" ,
319
319
stacklevel = 2 ,
320
320
)
321
+
321
322
if "forces" in properties and atoms .pbc .all ():
322
323
# we have PBCs, and, since the user/integrator requested forces, we will run
323
324
# backward anyway, so let's do the stress as well for free (this saves
324
325
# another forward-backward call later if the stress is requested)
325
326
calculate_stress = True
327
+
326
328
if "stresses" in properties :
327
329
raise NotImplementedError ("'stresses' are not implemented yet" )
328
330
331
+ if ask_for_energy_gradient and not ask_for_energy :
332
+ # check if the user already computed energies in a previous call.
333
+ energy = self .get_property ("energy" , atoms = atoms , allow_calculation = False )
334
+ if energy is not None :
335
+ # when requesting energy first and then forces, the strategy above will
336
+ # force us to run the model twice
337
+ warnings .warn (
338
+ "forces or stress requested after having already computed the "
339
+ "energy, this is slower than requesting the forces/stress first" ,
340
+ stacklevel = 2 ,
341
+ )
342
+
329
343
with record_function ("ASECalculator::prepare_inputs" ):
330
344
outputs = self ._ase_properties_to_metatensor_outputs (properties )
331
345
outputs .update (self ._additional_output_requests )
0 commit comments