Skip to content

Commit 8a7e795

Browse files
committed
Fix dangling pointers when running multiple FF calculations in a row.
1 parent 2d8c126 commit 8a7e795

10 files changed

Lines changed: 68 additions & 2 deletions

File tree

‎examples/pyridineDensOverlap/example_pyridine_density_overlap.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def example_pyridine_density_overlap():
3232

3333
generate_conv_rho("-s CHGCAR.xsf -t tip/density_CO.xsf -B 1.0 -E".split())
3434
generate_elff("-i LOCPOT.xsf --tip_dens tip/density_CO.xsf --Rcore 0.7 -E --doDensity".split())
35-
generate_dftd3("-i LOCPOT.xsf --df_name PBE --energy".split())
35+
generate_dftd3("-i LOCPOT.xsf --df_name PBE".split())
3636

3737
relaxed_scan("-k 0.25 -q 1.0 --noLJ --Apauli 18.0 --bDebugFFtot".split()) # Note the --noLJ for loading separate Pauli and vdW instead of LJ force field
3838
plot_results("-k 0.25 -q 1.0 -a 2.0 --df".split())

‎ppafm/HighLevel.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/python
22

33
import sys
4+
import weakref
45

56
import numpy as np
67

@@ -191,6 +192,9 @@ def perform_relaxation(
191192
PPdisp = None
192193
if verbose > 0:
193194
print("<<<END: perform_relaxation()")
195+
196+
core.deleteFF_Fpointer()
197+
194198
return fzs, PPpos, PPdisp, lvecScan
195199

196200

@@ -204,11 +208,14 @@ def prepareArrays(FF, Vpot, parameters):
204208
gridN = parameters.gridN
205209
FF = np.zeros((gridN[2], gridN[1], gridN[0], 3))
206210
else:
207-
parameters.gridN = np.shape(FF)
211+
gridN = np.shape(FF)
212+
parameters.gridN = gridN
208213
core.setFF_Fpointer(FF)
214+
weakref.finalize(FF, lambda: core.deleteFF_Fpointer()) # Set array pointer to NULL when garbage collector runs.
209215
if Vpot:
210216
V = np.zeros((gridN[2], gridN[1], gridN[0]))
211217
core.setFF_Epointer(V)
218+
weakref.finalize(FF, lambda: core.deleteFF_Epointer())
212219
else:
213220
V = None
214221
return FF, V
@@ -455,3 +462,5 @@ def subtractCoreDensities(
455462
print("sum(RHO), Nelec: ", rho.sum(), rho.sum() * dV) # check sum
456463
if bSaveDebugDens:
457464
io.saveXSF("rho_subCoreChg.xsf", rho, lvec, head=head)
465+
466+
core.deleteFF_Epointer()

‎ppafm/cli/conv_rho.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#!/usr/bin/python
2+
import gc
3+
24
import numpy as np
35

46
from .. import common, fieldFFT, io
@@ -69,6 +71,10 @@ def main(argv=None):
6971
force_field = io.packVecGrid(f_x * args.Apauli, f_y * args.Apauli, f_z * args.Apauli)
7072
io.save_vec_field("FF" + namestr, force_field, lvec_sample, data_format=args.output_format, head=head_sample)
7173

74+
# Make sure that the energy and force field pointers are deleted so that they don't interfere if any other force fields are computed after this.
75+
del energy, force_field
76+
gc.collect()
77+
7278

7379
if __name__ == "__main__":
7480
main()

‎ppafm/cli/generateDFTD3.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env python3
22

3+
import gc
34
import sys
45

56
from ppafm.defaults import d3
@@ -50,6 +51,9 @@ def main(argv=None):
5051

5152
computeDFTD3(args.input, df_params=df_params, geometry_format=args.input_format, save_format=args.output_format, compute_energy=args.energy, parameters=parameters)
5253

54+
# Make sure that the energy and force field pointers are deleted so that they don't interfere if any other force fields are computed after this.
55+
gc.collect()
56+
5357

5458
if __name__ == "__main__":
5559
main()

‎ppafm/cli/generateElFF.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/python
2+
import gc
23
import sys
34
from pathlib import Path
45

@@ -161,6 +162,10 @@ def main(argv=None):
161162
if args.energy:
162163
io.save_scal_field("Eel", e_electrostatic, lvec_samp, data_format=args.output_format, head=head_samp, atomic_info=(atoms_samp[:4], lvec_samp))
163164

165+
# Make sure that the energy and force field pointers are deleted so that they don't interfere if any other force fields are computed after this.
166+
del e_electrostatic, ff_electrostatic
167+
gc.collect()
168+
164169

165170
if __name__ == "__main__":
166171
main()

‎ppafm/cli/generateElFF_point_charges.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/python
22

3+
import gc
4+
35
from .. import common
46
from ..HighLevel import computeELFF_pointCharge
57

@@ -13,6 +15,9 @@ def main(argv=None):
1315

1416
computeELFF_pointCharge(args.input, geometry_format=args.input_format, tip=args.tip, save_format=args.output_format, computeVpot=args.energy, parameters=parameters)
1517

18+
# Make sure that the energy and force field pointers are deleted so that they don't interfere if any other force fields are computed after this.
19+
gc.collect()
20+
1621

1722
if __name__ == "__main__":
1823
main()

‎ppafm/cli/generateLJFF.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/python
2+
import gc
23
from pathlib import Path
34

45
from .. import common
@@ -22,6 +23,9 @@ def main(argv=None):
2223
parameters=parameters,
2324
)
2425

26+
# Make sure that the energy and force field pointers are deleted so that they don't interfere if any other force fields are computed after this.
27+
gc.collect()
28+
2529

2630
if __name__ == "__main__":
2731
main()

‎ppafm/core.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,24 @@ def setFF_Epointer(gridE):
8787
lib.setFF_Epointer(gridE)
8888

8989

90+
# void deleteFF_Fpointer()
91+
lib.deleteFF_Fpointer.argtypes = []
92+
lib.deleteFF_Fpointer.restype = None
93+
94+
95+
def deleteFF_Fpointer():
96+
lib.deleteFF_Fpointer()
97+
98+
99+
# void deleteFF_Epointer()
100+
lib.deleteFF_Epointer.argtypes = []
101+
lib.deleteFF_Epointer.restype = None
102+
103+
104+
def deleteFF_Epointer():
105+
lib.deleteFF_Epointer()
106+
107+
90108
def setFF(cell=None, gridF=None, gridE=None, parameters=None):
91109
n_ = None
92110
if gridF is not None:

‎ppafm/cpp/ProbeParticle.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,16 @@ DLLEXPORT void setFF_Epointer( double * gridE_ ){
344344
gridE = gridE_;
345345
}
346346

347+
// set force field array pointer to NULL
348+
DLLEXPORT void deleteFF_Fpointer(){
349+
gridF = NULL;
350+
}
351+
352+
// set energy array pointer to NULL
353+
DLLEXPORT void deleteFF_Epointer(){
354+
gridE = NULL;
355+
}
356+
347357
// set forcefield grid dimension "n"
348358
DLLEXPORT void setGridN( int * n ){
349359
//gridShape.n.set( *(Vec3i*)n );

‎tests/_test_vdw.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
Compare the C++ and OpenCL implementations of the vdW calculation and check that they are consistent.
55
"""
66

7+
import gc
8+
79
import numpy as np
810
import pyopencl as cl
911

@@ -102,3 +104,6 @@ def test_dftd3():
102104
assert np.allclose(coeffs_ocl, coeffs_cpp)
103105
assert np.allclose(FF_ocl[..., :3], FF_cpp, rtol=1e-4, atol=1e-6)
104106
assert np.allclose(FF_ocl[..., 3], E_cpp, rtol=1e-4, atol=1e-6)
107+
108+
del E_cpp, FF_cpp
109+
gc.collect()

0 commit comments

Comments
 (0)