Skip to content

Commit b13034d

Browse files
committed
Explicitly copying positions when building Cython CGF objects from Python variant
1 parent 7802a63 commit b13034d

File tree

7 files changed

+123
-120
lines changed

7 files changed

+123
-120
lines changed

COMPILATION.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,16 @@ To upload, run
3939

4040
```bash
4141
python -m twine upload wheelhouse/*
42+
```
43+
44+
## Editable install
45+
46+
```bash
47+
pip install -e .
48+
```
49+
50+
If the `.pyx` files have changed, you do need to recopmile with
51+
52+
```bash
53+
python setup.py build_ext --inplace
4254
```

pyqint/cgf.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ void CGF::add_gto(unsigned int type, // type of the orbital (see above for the
263263
}
264264

265265
/*
266-
* @fn add_GTO
266+
* @fn add_gto
267267
* @brief Add a GTO to the CGF
268268
*
269269
* @param double c coefficient
@@ -282,6 +282,32 @@ void CGF::add_gto(double c,
282282
this->gtos.push_back(GTO(c, this->r, alpha, l, m, n));
283283
}
284284

285+
/*
286+
* @fn add_gto_with_position
287+
* @brief Add a GTO to the CGF
288+
*
289+
* @param double c coefficient
290+
* @param double px px value
291+
* @param double py px value
292+
* @param double pz px value
293+
* @param double alpha alpha value
294+
* @param unsigned int l l angular momentum x
295+
* @param unsigned int m m angular momentum y
296+
* @param unsigned int n n angular momentum z
297+
*
298+
* @return void
299+
*/
300+
void CGF::add_gto_with_position(double c,
301+
double px,
302+
double py,
303+
double pz,
304+
double alpha,
305+
unsigned int l,
306+
unsigned int m,
307+
unsigned int n) {
308+
this->gtos.push_back(GTO(c, Vec3(px, py, pz), alpha, l, m, n));
309+
}
310+
285311
/*
286312
* @fn set_position
287313
* @brief Set a (new) center for the CGF

pyqint/cgf.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ class CGF { // Contracted Gaussian Function
378378
double c);
379379

380380
/*
381-
* @fn add_GTO
381+
* @fn add_gto
382382
* @brief Add a GTO to the CGF
383383
*
384384
* @param double c coefficient
@@ -395,6 +395,30 @@ class CGF { // Contracted Gaussian Function
395395
unsigned int m,
396396
unsigned int n);
397397

398+
/*
399+
* @fn add_gto_with_position
400+
* @brief Add a GTO to the CGF
401+
*
402+
* @param double c coefficient
403+
* @param double px px value
404+
* @param double py px value
405+
* @param double pz px value
406+
* @param double alpha alpha value
407+
* @param unsigned int l l angular momentum x
408+
* @param unsigned int m m angular momentum y
409+
* @param unsigned int n n angular momentum z
410+
*
411+
* @return void
412+
*/
413+
void add_gto_with_position(double c,
414+
double px,
415+
double py,
416+
double pz,
417+
double alpha,
418+
unsigned int l,
419+
unsigned int m,
420+
unsigned int n);
421+
398422
/*
399423
* @fn set_position
400424
* @brief Set a (new) center for the CGF

pyqint/cgf.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,21 @@ def add_gto(self, c, alpha, l, m, n):
4646
"""
4747
Add Gaussian Type Orbital to Contracted Gaussian Function
4848
"""
49+
# add GTO to the Python object
4950
self.gtos.append(GTO(c, self.p, alpha, l, m, n))
51+
52+
# also add GTO for the C++ object
5053
self.cgf.add_gto(c, alpha, l, m, n)
54+
55+
def add_gto_with_position(self, c, p, alpha, l, m, n):
56+
"""
57+
Add Gaussian Type Orbital to Contracted Gaussian Function
58+
"""
59+
# add GTO to the Python object
60+
self.gtos.append(GTO(c, p, alpha, l, m, n))
61+
62+
# also add GTO for the C++ object
63+
self.cgf.add_gto_with_position(c, p[0], p[1], p[2], alpha, l, m, n)
5164

5265
def add_spherical_gto(self, c, alpha, l, m):
5366
"""

pyqint/pyqint.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ cdef extern from "cgf.h":
3131
CGF() except +
3232
CGF(double, double, double) except +
3333
void add_gto(double, double, int, int, int) except +
34+
void add_gto_with_position(double, double, double, double, double, int, int, int) except +
3435
double get_amp(double, double, double) except +
3536
vector[double] get_grad(double, double, double) except +
3637

pyqint/pyqint.pyx

Lines changed: 44 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ cdef class PyCGF:
4040

4141
def add_gto(self, c:float, alpha:float, l:int, m:int, n:int):
4242
self.cgf.add_gto(c, alpha, l, m, n)
43+
44+
def add_gto_with_position(self, c:float, px:float, py:float, pz:float, alpha:float, l:int, m:int, n:int):
45+
self.cgf.add_gto_with_position(c, px, py, pz, alpha, l, m, n)
4346

4447
def get_amp_f(self, x:float, y:float, z:float):
4548
return self.cgf.get_amp(x, y, z)
@@ -89,6 +92,25 @@ cdef class PyQInt:
8992

9093
return compile_info
9194

95+
@staticmethod
96+
cdef CGF build_c_cgf(object cgf):
97+
"""
98+
Helper method to build a CGF object to be used in the Cython
99+
back-end; used by all CGF-level molecular integral functions
100+
"""
101+
cdef CGF c_cgf
102+
cdef object gto
103+
104+
c_cgf = CGF(cgf.p[0], cgf.p[1], cgf.p[2])
105+
for gto in cgf.gtos:
106+
c_cgf.add_gto_with_position(
107+
gto.c,
108+
gto.p[0], gto.p[1], gto.p[2],
109+
gto.alpha,
110+
gto.l, gto.m, gto.n
111+
)
112+
return c_cgf
113+
92114
def get_num_threads(self) -> int:
93115
"""
94116
Get the number of OpenMP threads
@@ -125,18 +147,8 @@ cdef class PyQInt:
125147
float: overlap integral
126148
"""
127149
128-
cdef CGF c_cgf1
129-
cdef CGF c_cgf2
130-
131-
# build cgf1
132-
c_cgf1 = CGF(cgf1.p[0], cgf1.p[1], cgf1.p[2])
133-
for gto in cgf1.gtos:
134-
c_cgf1.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
135-
136-
# build cgf2
137-
c_cgf2 = CGF(cgf2.p[0], cgf2.p[1], cgf2.p[2])
138-
for gto in cgf2.gtos:
139-
c_cgf2.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
150+
cdef CGF c_cgf1 = PyQInt.build_c_cgf(cgf1)
151+
cdef CGF c_cgf2 = PyQInt.build_c_cgf(cgf2)
140152
141153
return self.integrator.overlap(c_cgf1, c_cgf2)
142154
@@ -174,18 +186,8 @@ cdef class PyQInt:
174186
float: dipole integral in direction cc
175187
"""
176188
177-
cdef CGF c_cgf1
178-
cdef CGF c_cgf2
179-
180-
# build cgf1
181-
c_cgf1 = CGF(cgf1.p[0], cgf1.p[1], cgf1.p[2])
182-
for gto in cgf1.gtos:
183-
c_cgf1.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
184-
185-
# build cgf2
186-
c_cgf2 = CGF(cgf2.p[0], cgf2.p[1], cgf2.p[2])
187-
for gto in cgf2.gtos:
188-
c_cgf2.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
189+
cdef CGF c_cgf1 = PyQInt.build_c_cgf(cgf1)
190+
cdef CGF c_cgf2 = PyQInt.build_c_cgf(cgf2)
189191
190192
return self.integrator.dipole(c_cgf1, c_cgf2, cc, cref)
191193
@@ -202,18 +204,8 @@ cdef class PyQInt:
202204
float: derivate of overlap integral in cartesian direction coord
203205
"""
204206
205-
cdef CGF c_cgf1
206-
cdef CGF c_cgf2
207-
208-
# build cgf1
209-
c_cgf1 = CGF(cgf1.p[0], cgf1.p[1], cgf1.p[2])
210-
for gto in cgf1.gtos:
211-
c_cgf1.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
212-
213-
# build cgf2
214-
c_cgf2 = CGF(cgf2.p[0], cgf2.p[1], cgf2.p[2])
215-
for gto in cgf2.gtos:
216-
c_cgf2.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
207+
cdef CGF c_cgf1 = PyQInt.build_c_cgf(cgf1)
208+
cdef CGF c_cgf2 = PyQInt.build_c_cgf(cgf2)
217209
218210
return self.integrator.overlap_deriv(c_cgf1, c_cgf2, nuc[0], nuc[1], nuc[2], coord)
219211
@@ -247,18 +239,8 @@ cdef class PyQInt:
247239
float: kinetic integral
248240
"""
249241
250-
cdef CGF c_cgf1
251-
cdef CGF c_cgf2
252-
253-
# build cgf1
254-
c_cgf1 = CGF(cgf1.p[0], cgf1.p[1], cgf1.p[2])
255-
for gto in cgf1.gtos:
256-
c_cgf1.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
257-
258-
# build cgf2
259-
c_cgf2 = CGF(cgf2.p[0], cgf2.p[1], cgf2.p[2])
260-
for gto in cgf2.gtos:
261-
c_cgf2.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
242+
cdef CGF c_cgf1 = PyQInt.build_c_cgf(cgf1)
243+
cdef CGF c_cgf2 = PyQInt.build_c_cgf(cgf2)
262244
263245
return self.integrator.kinetic(c_cgf1, c_cgf2)
264246
@@ -274,19 +256,8 @@ cdef class PyQInt:
274256
Returns:
275257
float: kinetic integral derivative
276258
"""
277-
278-
cdef CGF c_cgf1
279-
cdef CGF c_cgf2
280-
281-
# build cgf1
282-
c_cgf1 = CGF(cgf1.p[0], cgf1.p[1], cgf1.p[2])
283-
for gto in cgf1.gtos:
284-
c_cgf1.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
285-
286-
# build cgf2
287-
c_cgf2 = CGF(cgf2.p[0], cgf2.p[1], cgf2.p[2])
288-
for gto in cgf2.gtos:
289-
c_cgf2.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
259+
cdef CGF c_cgf1 = PyQInt.build_c_cgf(cgf1)
260+
cdef CGF c_cgf2 = PyQInt.build_c_cgf(cgf2)
290261
291262
return self.integrator.kinetic_deriv(c_cgf1, c_cgf2, nuc[0], nuc[1], nuc[2], coord)
292263
@@ -322,19 +293,8 @@ cdef class PyQInt:
322293
Returns:
323294
float: nuclear integral
324295
"""
325-
326-
cdef CGF c_cgf1
327-
cdef CGF c_cgf2
328-
329-
# build cgf1
330-
c_cgf1 = CGF(cgf1.p[0], cgf1.p[1], cgf1.p[2])
331-
for gto in cgf1.gtos:
332-
c_cgf1.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
333-
334-
# build cgf2
335-
c_cgf2 = CGF(cgf2.p[0], cgf2.p[1], cgf2.p[2])
336-
for gto in cgf2.gtos:
337-
c_cgf2.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
296+
cdef CGF c_cgf1 = PyQInt.build_c_cgf(cgf1)
297+
cdef CGF c_cgf2 = PyQInt.build_c_cgf(cgf2)
338298
339299
return self.integrator.nuclear(c_cgf1, c_cgf2, rc[0], rc[1], rc[2], zc)
340300
@@ -352,19 +312,8 @@ cdef class PyQInt:
352312
Returns:
353313
float: nuclear derivative
354314
"""
355-
356-
cdef CGF c_cgf1
357-
cdef CGF c_cgf2
358-
359-
# build cgf1
360-
c_cgf1 = CGF(cgf1.p[0], cgf1.p[1], cgf1.p[2])
361-
for gto in cgf1.gtos:
362-
c_cgf1.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
363-
364-
# build cgf2
365-
c_cgf2 = CGF(cgf2.p[0], cgf2.p[1], cgf2.p[2])
366-
for gto in cgf2.gtos:
367-
c_cgf2.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
315+
cdef CGF c_cgf1 = PyQInt.build_c_cgf(cgf1)
316+
cdef CGF c_cgf2 = PyQInt.build_c_cgf(cgf2)
368317
369318
return self.integrator.nuclear_deriv(c_cgf1, c_cgf2, rc[0], rc[1], rc[2], zc, rd[0], rd[1], rd[2], coord)
370319
@@ -405,21 +354,10 @@ cdef class PyQInt:
405354
Returns:
406355
float: repulsion integral
407356
"""
408-
409-
cdef CGF c_cgf1
410-
cdef CGF c_cgf2
411-
cdef CGF c_cgf3
412-
cdef CGF c_cgf4
413-
414-
# build cgf1
415-
c_cgf1 = CGF(cgf1.p[0], cgf1.p[1], cgf1.p[2])
416-
for gto in cgf1.gtos:
417-
c_cgf1.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
418-
419-
# build cgf2
420-
c_cgf2 = CGF(cgf2.p[0], cgf2.p[1], cgf2.p[2])
421-
for gto in cgf2.gtos:
422-
c_cgf2.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
357+
cdef CGF c_cgf1 = PyQInt.build_c_cgf(cgf1)
358+
cdef CGF c_cgf2 = PyQInt.build_c_cgf(cgf2)
359+
cdef CGF c_cgf3 = PyQInt.build_c_cgf(cgf3)
360+
cdef CGF c_cgf4 = PyQInt.build_c_cgf(cgf4)
423361
424362
# build cgf3
425363
c_cgf3 = CGF(cgf3.p[0], cgf3.p[1], cgf3.p[2])
@@ -447,21 +385,10 @@ cdef class PyQInt:
447385
Returns:
448386
float: nuclear integral derivative
449387
"""
450-
451-
cdef CGF c_cgf1
452-
cdef CGF c_cgf2
453-
cdef CGF c_cgf3
454-
cdef CGF c_cgf4
455-
456-
# build cgf1
457-
c_cgf1 = CGF(cgf1.p[0], cgf1.p[1], cgf1.p[2])
458-
for gto in cgf1.gtos:
459-
c_cgf1.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
460-
461-
# build cgf2
462-
c_cgf2 = CGF(cgf2.p[0], cgf2.p[1], cgf2.p[2])
463-
for gto in cgf2.gtos:
464-
c_cgf2.add_gto(gto.c, gto.alpha, gto.l, gto.m, gto.n)
388+
cdef CGF c_cgf1 = PyQInt.build_c_cgf(cgf1)
389+
cdef CGF c_cgf2 = PyQInt.build_c_cgf(cgf2)
390+
cdef CGF c_cgf3 = PyQInt.build_c_cgf(cgf3)
391+
cdef CGF c_cgf4 = PyQInt.build_c_cgf(cgf4)
465392
466393
# build cgf3
467394
c_cgf3 = CGF(cgf3.p[0], cgf3.p[1], cgf3.p[2])

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def find_windows_versions():
113113
include_package_data=True,
114114
classifiers=[
115115
"Programming Language :: Python :: 3",
116-
"License :: OSI Approved :: MIT License",
116+
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
117117
"Operating System :: POSIX",
118118
],
119119
python_requires='>=3.5',

0 commit comments

Comments
 (0)