From 2d64ebd4270a2eef1c66ab53eeeb80f4b7788574 Mon Sep 17 00:00:00 2001 From: richardjgowers Date: Wed, 25 Jul 2018 13:35:41 -0500 Subject: [PATCH 1/8] added Cython pbc --- package/MDAnalysis/lib/_cutil.pxd | 3 +- package/MDAnalysis/lib/_cutil.pyx | 12 +- package/MDAnalysis/lib/new_distances.pyx | 43 +++++ package/MDAnalysis/lib/pbc.pxd | 20 ++ package/MDAnalysis/lib/pbc.pyx | 234 +++++++++++++++++++++++ 5 files changed, 305 insertions(+), 7 deletions(-) create mode 100644 package/MDAnalysis/lib/new_distances.pyx create mode 100644 package/MDAnalysis/lib/pbc.pxd create mode 100644 package/MDAnalysis/lib/pbc.pyx diff --git a/package/MDAnalysis/lib/_cutil.pxd b/package/MDAnalysis/lib/_cutil.pxd index 5efc82f6d5d..48ab3a79258 100644 --- a/package/MDAnalysis/lib/_cutil.pxd +++ b/package/MDAnalysis/lib/_cutil.pxd @@ -1,3 +1,4 @@ cdef float _dot(float *, float *) cdef void _cross(float *, float *, float *) -cdef float _norm(float *) \ No newline at end of file +cdef float _norm(float *) +cdef float norm2(float *) diff --git a/package/MDAnalysis/lib/_cutil.pyx b/package/MDAnalysis/lib/_cutil.pyx index dec11c68ea7..f2965c43cfe 100644 --- a/package/MDAnalysis/lib/_cutil.pyx +++ b/package/MDAnalysis/lib/_cutil.pyx @@ -305,9 +305,9 @@ cdef float _norm(float * a): """ Calculates the magnitude of the vector """ - cdef float result - cdef ssize_t n - result = 0.0 - for n in range(3): - result += a[n]*a[n] - return sqrt(result) \ No newline at end of file + return sqrt(norm2(a)) + + +cdef float norm2(float* a): + """Square of norm""" + return a[0] * a[0] + a[1] * a[1] + a[2] * a[2] diff --git a/package/MDAnalysis/lib/new_distances.pyx b/package/MDAnalysis/lib/new_distances.pyx new file mode 100644 index 00000000000..973b913c747 --- /dev/null +++ b/package/MDAnalysis/lib/new_distances.pyx @@ -0,0 +1,43 @@ +import cython +import numpy as np + +from numpy.math import sqrtf as sqrt +from ._cutil cimport norm2 +from pbc cimport PBC, minimum_image + + +@cython.boundscheck(False) +@cython.wraparound(False) +cdef void inner_distance_array(const float[:, :] a, const float[:, :] b, + PBC box, float[:, :] result): + """C level of distance_array""" + cdef int i, j + cdef float[3] dx + + for i in range(a.shape[0]): + for j in range(b.shape[0]): + dx[0] = a[i, 0] - b[j, 0] + dx[1] = a[i, 1] - b[j, 1] + dx[2] = a[i, 2] - b[j, 2] + + minimum_image(dx, box) + + result[i, j] = sqrt(norm2(dx)) + + +def distance_array(coords1, coords2, box): + cdef PBC cbox + cdef float[:, :] a, b + cdef float[:, :] result_view + + a = np.asarray(coords1, dtype=np.float32) + b = np.asarray(coords2, dtype=np.float32) + box = np.asarray(box, dtype=np.float32) + + cbox = PBC(box) + result = np.zeros((a.shape[0], b.shape[0]), dtype=np.float32) + result_view = result[:] + + inner_distance_array(a, b, cbox, result_view) + + return result diff --git a/package/MDAnalysis/lib/pbc.pxd b/package/MDAnalysis/lib/pbc.pxd new file mode 100644 index 00000000000..7eadb8b1c9a --- /dev/null +++ b/package/MDAnalysis/lib/pbc.pxd @@ -0,0 +1,20 @@ +cdef class PBC: + # Cymem Memory pool, takes care of heap memory allocation + cdef Pool mem + # Triclinic vector representation of box + cdef float** box + # Full box diagonal + cdef float* fbox_diag + # Half box diagonal + cdef float* hbox_diag + # Minus half box diagonal + cdef float* mhbox_diag + # Maximum cutoff squared + cdef float max_cutoff2 + # What type of periodic boundaries [ORTHO, TRICLINIC, NONE] + cdef int pbc_type + # triclinic vectors to search for minimum image + cdef int ntric_vec + cdef float **tric_vec + +cdef void minimum_image(float*, PBC) \ No newline at end of file diff --git a/package/MDAnalysis/lib/pbc.pyx b/package/MDAnalysis/lib/pbc.pyx new file mode 100644 index 00000000000..bc1ad7f0e17 --- /dev/null +++ b/package/MDAnalysis/lib/pbc.pyx @@ -0,0 +1,234 @@ +import cython + +from cymem.cymem cimport Pool +from libc.math cimport fabs +from numpy.math cimport deg2radf, sinf as sin, cosf as cos, sqrtf as sqrt + +from _cutil cimport norm2 + +DEF MAX_NTRICVEC=12 +DEF EPSILON=1e-5 +DEF BOX_MARGIN=1.0010 + +cdef enum PBC_TYPES: + ORTHO = 1 + TRICLINIC = 2 + NONE = 3 + + +cdef class PBC: + """Cython class representing periodic boundaries in system + + Used for minimum_image function + """ + def __cinit__(self, float[:] box): + self.mem = None + self.box = NULL + self.fbox_diag = NULL + self.hbox_diag = NULL + self.mhbox_diag = NULL + self.tric_vec = NULL + + def __init__(self, float[:] box): + self.mem = Pool() + self.box = self.mem.alloc(3, sizeof(float*)) + for i in range(3): + self.box[i] = self.mem.alloc(3, sizeof(float)) + self.fbox_diag = self.mem.alloc(3, sizeof(float)) + self.hbox_diag = self.mem.alloc(3, sizeof(float)) + self.mhbox_diag = self.mem.alloc(3, sizeof(float)) + self.tric_vec = self.mem.alloc(MAX_NTRICVEC, sizeof(float*)) + for i in range(MAX_NTRICVEC): + self.tric_vec[i] = self.mem.alloc(3, sizeof(float)) + self.ntric_vec = 0 + + self.define_box(box) + + @cython.boundscheck(False) + @cython.wraparound(False) + cdef void define_box(self, float[:] box): + # turn box into triclinic vectors + cdef bint triclinic + + triclinic = False + for i in range(3): + if fabs(box[i] - 90.0) > EPSILON: + triclinic = True + + if triclinic: + self.pbc_type = TRICLINIC + self.triclinic_define(box) + else: + self.pbc_type = ORTHO + self.ortho_define(box) + + self.fbox_diag[0] = box[0] + self.fbox_diag[1] = box[1] + self.fbox_diag[2] = box[2] + + self.hbox_diag[0] = 0.5 * self.fbox_diag[0] + self.hbox_diag[1] = 0.5 * self.fbox_diag[1] + self.hbox_diag[2] = 0.5 * self.fbox_diag[2] + + self.mhbox_diag[0] = - self.hbox_diag[0] + self.mhbox_diag[1] = - self.hbox_diag[1] + self.mhbox_diag[2] = - self.hbox_diag[2] + + self.max_cutoff2 = self.calc_max_cutoff2() + + @cython.boundscheck(False) + @cython.wraparound(False) + cdef void ortho_define(self, float[:] box): + self.box[0][0] = box[0] + self.box[0][1] = 0.0 + self.box[0][2] = 0.0 + + self.box[1][0] = 0.0 + self.box[1][1] = box[1] + self.box[1][2] = 0.0 + + self.box[2][0] = 0.0 + self.box[2][1] = 0.0 + self.box[2][2] = box[2] + + @cython.boundscheck(False) + @cython.wraparound(False) + @cython.cdivision(True) + cdef void triclinic_define(self, float[:] box): + cdef float alpha, beta, gamma + + alpha = deg2radf(box[3]) + beta = deg2radf(box[4]) + gamma = deg2radf(box[5]) + + self.box[0][0] = box[0] + self.box[0][1] = 0.0 + self.box[0][2] = 0.0 + + self.box[1][0] = box[1] * cos(gamma) + self.box[1][1] = box[1] * sin(gamma) + self.box[1][2] = 0.0 + + self.box[2][0] = box[2] * cos(beta) + self.box[2][1] = box[2] * (cos(alpha) - cos(beta) * cos(gamma) / sin(gamma)) + self.box[2][2] = box[2] * sqrt(box[2] * box[2] - self.box[2][0] ** 2 - self.box[2][1] ** 2) + + cdef void find_triclinic_shifts(self): + cdef int[3] order + cdef int i, j, k, dd, d, shift + cdef float[3] trial, pos + cdef float d2old, d2new, d2new_c + cdef bint use + + order[0] = 0 + order[1] = -1 + order[2] = 1 + + for k in order: + for j in order: + for i in order: + if j != 0 or k != 0: + d2old = 0.0 + d2new = 0.0 + + for d in range(3): + trial[d] = i * self.box[0][d] + j * self.box[1][d] + k * self.box[2][d] + if d == 3: + trial[d] = 0.0 + pos[d] = 0.0 + else: + if trial[d] < 0: + pos[d] = min(self.hbox_diag[d], -trial[d]) + else: + pos[d] = max(self.hbox_diag[d], -trial[d]) + + d2old += pos[d] * pos[d] + d2new += (pos[d] + trial[d]) * (pos[d] + trial[d]) + + if BOX_MARGIN * d2new < d2old: + use = True + + for dd in range(3): # for d in [i, j, k]: + if dd == 0: + shift = i + elif dd == 1: + shift = j + else: + shift = k + + if shift: + d2new_c = 0 + for d in range(3): + d2new_c += (pos[d] + trial[d] - shift * self.box[dd][d])**2 + + if d2new_c <= BOX_MARGIN * d2new: + use = False + + if use: # Accept this shift vector. + for d in range(3): + self.tric_vec[self.ntric_vec][d] = trial[d] + self.ntric_vec += 1 + + @cython.boundscheck(False) + @cython.wraparound(False) + cdef float calc_max_cutoff2(self): + cdef float min_hv2, min_ss + + min_hv2 = 0.25 * min(norm2(self.box[0]), + norm2(self.box[1]), + norm2(self.box[2])) + + min_ss = min(self.box[0][0], fabs(self.box[1][1] - self.box[2][1]), self.box[2][2]) + + return min(min_hv2, min_ss * min_ss) + + +cdef void minimum_image(float* dx, PBC pbc): + """Apply minimum image convention to a vector *dx* + + Parameters + ---------- + float* dx + a single 3d separation + PBC pbc + PBC object representing the box + + Modifies dx in place + """ + cdef int i, j + cdef float d2min, d2trial + cdef float[3] dx_start, trial + + if pbc.pbc_type == TRICLINIC: + for i in range(2, -1, -1): + while (dx[i] > pbc.hbox_diag[i]): + for j in range(i, -1, -1): + dx[j] -= pbc.box[i][j] + while (dx[i] <= pbc.mhbox_diag[i]): + for j in range(i, -1, -1): + dx[j] += pbc.box[i][j] + d2min = norm2(dx) + if d2min > pbc.max_cutoff2: + for j in range(3): + dx_start[j] = dx[j] + + i = 0 + while (d2min > pbc.max_cutoff2) and (i < pbc.ntric_vec): + for j in range(3): + trial[j] = dx_start[j] + pbc.tric_vec[i][j] + d2trial = norm2(trial) + if d2trial < d2min: + for j in range(3): + dx[j] = trial[j] + d2min = d2trial + i += 1 + + elif pbc.pbc_type == ORTHO: + for i in range(3): + while (dx[i] > pbc.hbox_diag[i]): + dx[i] -= pbc.fbox_diag[i] + while (dx[i] <= pbc.mhbox_diag[i]): + dx[i] += pbc.fbox_diag[i] + + elif pbc.pbc_type == NONE: + pass From 6763d8ed76e3cdece527c3fb9883f865d6fb0102 Mon Sep 17 00:00:00 2001 From: richardjgowers Date: Thu, 26 Jul 2018 15:54:28 -0500 Subject: [PATCH 2/8] fixed PBC installation --- package/MDAnalysis/lib/new_distances.pyx | 12 ++++++------ package/MDAnalysis/lib/pbc.pxd | 12 ++++++++++-- package/MDAnalysis/lib/pbc.pyx | 2 +- package/setup.py | 14 +++++++++++++- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/package/MDAnalysis/lib/new_distances.pyx b/package/MDAnalysis/lib/new_distances.pyx index 973b913c747..611d8aa34c1 100644 --- a/package/MDAnalysis/lib/new_distances.pyx +++ b/package/MDAnalysis/lib/new_distances.pyx @@ -1,7 +1,7 @@ import cython import numpy as np -from numpy.math import sqrtf as sqrt +from numpy.math cimport sqrtf as sqrt from ._cutil cimport norm2 from pbc cimport PBC, minimum_image @@ -25,18 +25,18 @@ cdef void inner_distance_array(const float[:, :] a, const float[:, :] b, result[i, j] = sqrt(norm2(dx)) -def distance_array(coords1, coords2, box): +def distance_array(coords1, coords2, box, result=None, backend=None): cdef PBC cbox - cdef float[:, :] a, b - cdef float[:, :] result_view + cdef float[:, :] a, b, result_view a = np.asarray(coords1, dtype=np.float32) b = np.asarray(coords2, dtype=np.float32) box = np.asarray(box, dtype=np.float32) + if result is None: + result = np.zeros((a.shape[0], b.shape[0]), dtype=np.float32) cbox = PBC(box) - result = np.zeros((a.shape[0], b.shape[0]), dtype=np.float32) - result_view = result[:] + result_view = result inner_distance_array(a, b, cbox, result_view) diff --git a/package/MDAnalysis/lib/pbc.pxd b/package/MDAnalysis/lib/pbc.pxd index 7eadb8b1c9a..61bee73be6b 100644 --- a/package/MDAnalysis/lib/pbc.pxd +++ b/package/MDAnalysis/lib/pbc.pxd @@ -1,3 +1,5 @@ +from cymem.cymem cimport Pool + cdef class PBC: # Cymem Memory pool, takes care of heap memory allocation cdef Pool mem @@ -12,9 +14,15 @@ cdef class PBC: # Maximum cutoff squared cdef float max_cutoff2 # What type of periodic boundaries [ORTHO, TRICLINIC, NONE] - cdef int pbc_type + cdef public int pbc_type # triclinic vectors to search for minimum image cdef int ntric_vec cdef float **tric_vec -cdef void minimum_image(float*, PBC) \ No newline at end of file + cdef void define_box(self, float[:] box) + cdef void ortho_define(self, float[:] box) + cdef void triclinic_define(self, float[:] box) + cdef void find_triclinic_shifts(self) + cdef float calc_max_cutoff2(self) + +cdef void minimum_image(float* dx, PBC pbc) diff --git a/package/MDAnalysis/lib/pbc.pyx b/package/MDAnalysis/lib/pbc.pyx index bc1ad7f0e17..440213caee9 100644 --- a/package/MDAnalysis/lib/pbc.pyx +++ b/package/MDAnalysis/lib/pbc.pyx @@ -52,7 +52,7 @@ cdef class PBC: triclinic = False for i in range(3): - if fabs(box[i] - 90.0) > EPSILON: + if fabs(box[i + 3] - 90.0) > EPSILON: triclinic = True if triclinic: diff --git a/package/setup.py b/package/setup.py index 6e9a7b381c0..6119efd5d37 100755 --- a/package/setup.py +++ b/package/setup.py @@ -305,6 +305,18 @@ def extensions(config): include_dirs=include_dirs + ['MDAnalysis/lib/formats/include'], define_macros=define_macros, extra_compile_args=extra_compile_args) + pbc = MDAExtension('MDAnalysis.lib.pbc', + ['MDAnalysis/lib/pbc' + source_suffix], + include_dirs=include_dirs, + libraries=mathlib, + define_macros=define_macros, + extra_compile_args=extra_compile_args) + new_distances = MDAExtension('MDAnalysis.lib.new_distances', + ['MDAnalysis/lib/new_distances' + source_suffix], + include_dirs=include_dirs, + libraries=mathlib, + define_macros=define_macros, + extra_compile_args=extra_compile_args) distances = MDAExtension('MDAnalysis.lib.c_distances', ['MDAnalysis/lib/c_distances' + source_suffix], include_dirs=include_dirs + ['MDAnalysis/lib/include'], @@ -380,7 +392,7 @@ def extensions(config): libraries=mathlib, define_macros=define_macros, extra_compile_args=extra_compile_args) - pre_exts = [libdcd, distances, distances_omp, qcprot, + pre_exts = [libdcd, pbc, new_distances, distances, distances_omp, qcprot, transformation, libmdaxdr, util, encore_utils, ap_clustering, spe_dimred, cutil, augment] From edb95e4796fcbd51a4a20c44aed10bc189e66ba1 Mon Sep 17 00:00:00 2001 From: richardjgowers Date: Thu, 26 Jul 2018 15:54:37 -0500 Subject: [PATCH 3/8] started tests for new distance_array --- testsuite/MDAnalysisTests/utils/test_distances.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/testsuite/MDAnalysisTests/utils/test_distances.py b/testsuite/MDAnalysisTests/utils/test_distances.py index fa57a16d0ac..366d39ffce0 100644 --- a/testsuite/MDAnalysisTests/utils/test_distances.py +++ b/testsuite/MDAnalysisTests/utils/test_distances.py @@ -22,6 +22,8 @@ from __future__ import division, absolute_import import MDAnalysis import MDAnalysis.lib.distances +from MDAnalysis.lib.distances import distance_array as da_old +from MDAnalysis.lib.new_distances import distance_array as da_new import numpy as np import pytest @@ -33,7 +35,7 @@ @pytest.fixture() def ref_system(): - box = np.array([1., 1., 2.], dtype=np.float32) + box = np.array([1., 1., 2., 90., 90., 90.], dtype=np.float32) points = np.array( [ [0, 0, 0], [1, 1, 2], [1, 0, 2], # identical under PBC @@ -56,7 +58,7 @@ def _dist(x, ref): def test_noPBC(self, backend, ref_system): box, points, ref, conf = ref_system - d = MDAnalysis.lib.distances.distance_array(ref, points, backend=backend) + d = da_old(ref, points, backend=backend) assert_almost_equal(d, np.array([[ self._dist(points[0], ref[0]), @@ -65,10 +67,11 @@ def test_noPBC(self, backend, ref_system): self._dist(points[3], ref[0])] ])) - def test_PBC(self, backend, ref_system): + @pytest.mark.parametrize('da', [da_old, da_new]) + def test_PBC(self, da, backend, ref_system): box, points, ref, conf = ref_system - d = MDAnalysis.lib.distances.distance_array(ref, points, box=box, backend=backend) + d = da(ref, points, box=box, backend=backend) assert_almost_equal(d, np.array([[0., 0., 0., self._dist(points[3], ref=[1, 1, 2])]])) From 8dbb23135d73dc7727c76eed2b7aa1d5bb5af619 Mon Sep 17 00:00:00 2001 From: richardjgowers Date: Thu, 26 Jul 2018 16:02:24 -0500 Subject: [PATCH 4/8] PBC object handles no periodic boundaries --- package/MDAnalysis/lib/new_distances.pyx | 5 +++-- package/MDAnalysis/lib/pbc.pyx | 13 +++++++++---- .../MDAnalysisTests/utils/test_distances.py | 16 +++++++++------- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/package/MDAnalysis/lib/new_distances.pyx b/package/MDAnalysis/lib/new_distances.pyx index 611d8aa34c1..a8da9ad228b 100644 --- a/package/MDAnalysis/lib/new_distances.pyx +++ b/package/MDAnalysis/lib/new_distances.pyx @@ -25,13 +25,14 @@ cdef void inner_distance_array(const float[:, :] a, const float[:, :] b, result[i, j] = sqrt(norm2(dx)) -def distance_array(coords1, coords2, box, result=None, backend=None): +def distance_array(coords1, coords2, box=None, result=None, backend=None): cdef PBC cbox cdef float[:, :] a, b, result_view a = np.asarray(coords1, dtype=np.float32) b = np.asarray(coords2, dtype=np.float32) - box = np.asarray(box, dtype=np.float32) + if not box is None: + box = np.asarray(box, dtype=np.float32) if result is None: result = np.zeros((a.shape[0], b.shape[0]), dtype=np.float32) diff --git a/package/MDAnalysis/lib/pbc.pyx b/package/MDAnalysis/lib/pbc.pyx index 440213caee9..d8125e95607 100644 --- a/package/MDAnalysis/lib/pbc.pyx +++ b/package/MDAnalysis/lib/pbc.pyx @@ -13,7 +13,7 @@ DEF BOX_MARGIN=1.0010 cdef enum PBC_TYPES: ORTHO = 1 TRICLINIC = 2 - NONE = 3 + NOPBC = 3 cdef class PBC: @@ -29,7 +29,7 @@ cdef class PBC: self.mhbox_diag = NULL self.tric_vec = NULL - def __init__(self, float[:] box): + def __init__(self, box): self.mem = Pool() self.box = self.mem.alloc(3, sizeof(float*)) for i in range(3): @@ -42,7 +42,12 @@ cdef class PBC: self.tric_vec[i] = self.mem.alloc(3, sizeof(float)) self.ntric_vec = 0 - self.define_box(box) + if box is None: + self.pbc_type = NOPBC + else: + if not box.shape == (6,): + raise ValueError('Wrong shaped box') + self.define_box(box) @cython.boundscheck(False) @cython.wraparound(False) @@ -230,5 +235,5 @@ cdef void minimum_image(float* dx, PBC pbc): while (dx[i] <= pbc.mhbox_diag[i]): dx[i] += pbc.fbox_diag[i] - elif pbc.pbc_type == NONE: + elif pbc.pbc_type == NOPBC: pass diff --git a/testsuite/MDAnalysisTests/utils/test_distances.py b/testsuite/MDAnalysisTests/utils/test_distances.py index 366d39ffce0..28893ebd9b4 100644 --- a/testsuite/MDAnalysisTests/utils/test_distances.py +++ b/testsuite/MDAnalysisTests/utils/test_distances.py @@ -55,10 +55,11 @@ def _dist(x, ref): r = x - ref return np.sqrt(np.dot(r, r)) - def test_noPBC(self, backend, ref_system): + @pytest.mark.parametrize('da', [da_old, da_new]) + def test_noPBC(self, da, backend, ref_system): box, points, ref, conf = ref_system - d = da_old(ref, points, backend=backend) + d = da(ref, points, backend=backend) assert_almost_equal(d, np.array([[ self._dist(points[0], ref[0]), @@ -348,14 +349,15 @@ def test_pbc_dist(self, S_mol, boxV, backend): assert_almost_equal(dists, results, self.prec, err_msg="distance_array failed to retrieve PBC distance") - def test_pbc_wrong_wassenaar_distance(self, backend): + @pytest.mark.parametrize('da', [da_old, da_new]) + def test_pbc_wrong_wassenaar_distance(self, da, backend): from MDAnalysis.lib.distances import distance_array - box = MDAnalysis.lib.mdamath.triclinic_vectors([2, 2, 2, 60, 60, 60]) - a, b, c = box + box = np.array([2, 2, 2, 60, 60, 60], dtype=np.float32) + a, b, c = MDAnalysis.lib.mdamath.triclinic_vectors(box) point_a = a + b point_b = .5 * point_a - dist = distance_array(point_a[np.newaxis, :], point_b[np.newaxis, :], - box=box, backend=backend) + dist = da(point_a[np.newaxis, :], point_b[np.newaxis, :], + box=box, backend=backend) assert_almost_equal(dist[0, 0], 1) # check that our distance is different then the wassenaar distance as # expected. From f57fd3ae093d22d76b94fff9dcc69dbb22ca87cd Mon Sep 17 00:00:00 2001 From: richardjgowers Date: Thu, 26 Jul 2018 18:40:16 -0500 Subject: [PATCH 5/8] added nogil to cython pbc --- package/MDAnalysis/lib/_cutil.pxd | 2 +- package/MDAnalysis/lib/_cutil.pyx | 2 +- package/MDAnalysis/lib/new_distances.pyx | 5 +++-- package/MDAnalysis/lib/pbc.pxd | 2 +- package/MDAnalysis/lib/pbc.pyx | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package/MDAnalysis/lib/_cutil.pxd b/package/MDAnalysis/lib/_cutil.pxd index 48ab3a79258..f7e97a74e64 100644 --- a/package/MDAnalysis/lib/_cutil.pxd +++ b/package/MDAnalysis/lib/_cutil.pxd @@ -1,4 +1,4 @@ cdef float _dot(float *, float *) cdef void _cross(float *, float *, float *) cdef float _norm(float *) -cdef float norm2(float *) +cdef float norm2(float *) nogil diff --git a/package/MDAnalysis/lib/_cutil.pyx b/package/MDAnalysis/lib/_cutil.pyx index f2965c43cfe..9eeb53288cd 100644 --- a/package/MDAnalysis/lib/_cutil.pyx +++ b/package/MDAnalysis/lib/_cutil.pyx @@ -308,6 +308,6 @@ cdef float _norm(float * a): return sqrt(norm2(a)) -cdef float norm2(float* a): +cdef float norm2(float* a) nogil: """Square of norm""" return a[0] * a[0] + a[1] * a[1] + a[2] * a[2] diff --git a/package/MDAnalysis/lib/new_distances.pyx b/package/MDAnalysis/lib/new_distances.pyx index a8da9ad228b..41c632b9acb 100644 --- a/package/MDAnalysis/lib/new_distances.pyx +++ b/package/MDAnalysis/lib/new_distances.pyx @@ -9,7 +9,7 @@ from pbc cimport PBC, minimum_image @cython.boundscheck(False) @cython.wraparound(False) cdef void inner_distance_array(const float[:, :] a, const float[:, :] b, - PBC box, float[:, :] result): + PBC box, float[:, :] result) nogil: """C level of distance_array""" cdef int i, j cdef float[3] dx @@ -39,6 +39,7 @@ def distance_array(coords1, coords2, box=None, result=None, backend=None): cbox = PBC(box) result_view = result - inner_distance_array(a, b, cbox, result_view) + with nogil: + inner_distance_array(a, b, cbox, result_view) return result diff --git a/package/MDAnalysis/lib/pbc.pxd b/package/MDAnalysis/lib/pbc.pxd index 61bee73be6b..5f1037092bc 100644 --- a/package/MDAnalysis/lib/pbc.pxd +++ b/package/MDAnalysis/lib/pbc.pxd @@ -25,4 +25,4 @@ cdef class PBC: cdef void find_triclinic_shifts(self) cdef float calc_max_cutoff2(self) -cdef void minimum_image(float* dx, PBC pbc) +cdef void minimum_image(float* dx, PBC pbc) nogil diff --git a/package/MDAnalysis/lib/pbc.pyx b/package/MDAnalysis/lib/pbc.pyx index d8125e95607..66b187934ee 100644 --- a/package/MDAnalysis/lib/pbc.pyx +++ b/package/MDAnalysis/lib/pbc.pyx @@ -188,7 +188,7 @@ cdef class PBC: return min(min_hv2, min_ss * min_ss) -cdef void minimum_image(float* dx, PBC pbc): +cdef void minimum_image(float* dx, PBC pbc) nogil: """Apply minimum image convention to a vector *dx* Parameters From 0919fe484c5bbaf027299ea454e5634e25389963 Mon Sep 17 00:00:00 2001 From: richardjgowers Date: Thu, 26 Jul 2018 18:43:39 -0500 Subject: [PATCH 6/8] added cymem dependency --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 957cbb219d0..47c0dbfea6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ env: - MAIN_CMD="pytest ${PYTEST_LIST}" - SETUP_CMD="${PYTEST_FLAGS}" - BUILD_CMD="pip install -v package/ && pip install testsuite/" - - CONDA_MIN_DEPENDENCIES="mmtf-python mock six biopython networkx cython joblib matplotlib scipy griddataformats hypothesis gsd codecov" + - CONDA_MIN_DEPENDENCIES="mmtf-python mock six biopython networkx cython joblib matplotlib scipy griddataformats hypothesis gsd codecov cymem" - CONDA_DEPENDENCIES="${CONDA_MIN_DEPENDENCIES} seaborn>=0.7.0 clustalw=2.1 netcdf4 scikit-learn" - CONDA_CHANNELS='biobuilds conda-forge' - CONDA_CHANNEL_PRIORITY=True From 078ae0caec18104e067c69ace1c43d1593d1e5e9 Mon Sep 17 00:00:00 2001 From: richardjgowers Date: Sat, 28 Jul 2018 10:02:01 -0500 Subject: [PATCH 7/8] use libc trig? --- package/MDAnalysis/lib/pbc.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/MDAnalysis/lib/pbc.pyx b/package/MDAnalysis/lib/pbc.pyx index 66b187934ee..a5f383c3a93 100644 --- a/package/MDAnalysis/lib/pbc.pyx +++ b/package/MDAnalysis/lib/pbc.pyx @@ -1,8 +1,8 @@ import cython from cymem.cymem cimport Pool -from libc.math cimport fabs -from numpy.math cimport deg2radf, sinf as sin, cosf as cos, sqrtf as sqrt +from libc.math cimport fabs, sin, cos, sqrt +from numpy.math cimport deg2radf #, sinf as sin, cosf as cos, sqrtf as sqrt from _cutil cimport norm2 From 1aeabe01b60a35849227a5d58819b9347bd420bd Mon Sep 17 00:00:00 2001 From: richardjgowers Date: Sun, 29 Jul 2018 16:06:57 -0500 Subject: [PATCH 8/8] libc sqrt --- package/MDAnalysis/lib/new_distances.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/MDAnalysis/lib/new_distances.pyx b/package/MDAnalysis/lib/new_distances.pyx index 41c632b9acb..d4fd075c9da 100644 --- a/package/MDAnalysis/lib/new_distances.pyx +++ b/package/MDAnalysis/lib/new_distances.pyx @@ -1,7 +1,7 @@ import cython import numpy as np -from numpy.math cimport sqrtf as sqrt +from libc.math import sqrt from ._cutil cimport norm2 from pbc cimport PBC, minimum_image