Example #1
0
/*******************************************************************************
 * Find separation vector between two pos vectors
 *******************************************************************************/
static PyObject*
separationVector(PyObject *self, PyObject *args)
{
    int length, *PBC;
    double *returnVector, *pos1, *pos2, *cellDims;
    PyArrayObject *PBCIn=NULL;
    PyArrayObject *returnVectorIn=NULL;
    PyArrayObject *pos1In=NULL;
    PyArrayObject *pos2In=NULL;
    PyArrayObject *cellDimsIn=NULL;
    int i;
    
    
    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "O!O!O!O!O!", &PyArray_Type, &returnVectorIn, &PyArray_Type, &pos1In, 
            &PyArray_Type, &pos2In, &PyArray_Type, &cellDimsIn, &PyArray_Type, &PBCIn))
        return NULL;
    
    if (not_intVector(PBCIn)) return NULL;
    PBC = pyvector_to_Cptr_int(PBCIn);
    
    if (not_doubleVector(pos1In)) return NULL;
    pos1 = pyvector_to_Cptr_double(pos1In);
    length = ((int) PyArray_DIM(pos1In, 0)) / 3;
    
    if (not_doubleVector(pos2In)) return NULL;
    pos2 = pyvector_to_Cptr_double(pos2In);
    
    if (not_doubleVector(returnVectorIn)) return NULL;
    returnVector = pyvector_to_Cptr_double(returnVectorIn);
    
    if (not_doubleVector(cellDimsIn)) return NULL;
    cellDims = pyvector_to_Cptr_double(cellDimsIn);
    
    /* loop */
    for (i = 0; i < length; i++)
    {
        double atomSepVec[3];
        
        atomSeparationVector(atomSepVec, pos1[3*i], pos1[3*i+1], pos1[3*i+2], pos2[3*i], pos2[3*i+1], pos2[3*i+2], 
                             cellDims[0], cellDims[4], cellDims[8], PBC[0], PBC[1], PBC[2]);
        
        returnVector[3*i] = atomSepVec[0];
        returnVector[3*i+1] = atomSepVec[1];
        returnVector[3*i+2] = atomSepVec[2];
    }
    
    return Py_BuildValue("i", 0);
}
Example #2
0
/*******************************************************************************
 ** Make scalars array for visible atoms
 *******************************************************************************/
static PyObject*
makeVisibleScalarArray(PyObject *self, PyObject *args)
{
    int NVisible;
    PyArrayObject *visibleAtoms=NULL;
    PyArrayObject *scalarsFull=NULL;

    int i;
    npy_intp numpydims[1];
    PyArrayObject *scalars=NULL;

    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "O!O!", &PyArray_Type, &visibleAtoms, &PyArray_Type, &scalarsFull))
        return NULL;

    if (not_intVector(visibleAtoms)) return NULL;
    NVisible = (int) PyArray_DIM(visibleAtoms, 0);

    if (not_doubleVector(scalarsFull)) return NULL;

    /* create radius array */
    numpydims[0] = (npy_intp) NVisible;
    scalars = (PyArrayObject *) PyArray_SimpleNew(1, numpydims, NPY_FLOAT64);

    /* populate array */
    for (i = 0; i < NVisible; i++)
    {
        int index;

        index = IIND1(visibleAtoms, i);
        DIND1(scalars, i) = DIND1(scalarsFull, index);
    }

    return PyArray_Return(scalars);
}
Example #3
0
/*******************************************************************************
 * Return the magnitude of given vector
 *******************************************************************************/
static PyObject*
magnitude(PyObject *self, PyObject *args)
{
    int length;
    double *pos;
    PyArrayObject *posIn=NULL;
    
    int i;
    double sum;
    
    
    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &posIn))
        return NULL;
    
    if (not_doubleVector(posIn)) return NULL;
    pos = pyvector_to_Cptr_double(posIn);
    length = (int) PyArray_DIM(posIn, 0);
    
    /* compute */
    sum = 0.0;
    for (i = 0; i < length; i++)
        sum += pos[i] * pos[i];
    
    return Py_BuildValue("d", sqrt(sum));
}
Example #4
0
/*******************************************************************************
 * return magnitude of separation vector between two pos vectors
 *******************************************************************************/
static PyObject*
separationMagnitude(PyObject *self, PyObject *args)
{
    int length, *PBC;
    double *pos1, *pos2, *cellDims;
    PyArrayObject *PBCIn=NULL;
    PyArrayObject *pos1In=NULL;
    PyArrayObject *pos2In=NULL;
    PyArrayObject *cellDimsIn=NULL;
    
    int i;
    double sum;
    
    
    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "O!O!O!O!", &PyArray_Type, &pos1In, &PyArray_Type, &pos2In, 
            &PyArray_Type, &cellDimsIn, &PyArray_Type, &PBCIn))
        return NULL;
    
    if (not_intVector(PBCIn)) return NULL;
    PBC = pyvector_to_Cptr_int(PBCIn);
    
    if (not_doubleVector(pos1In)) return NULL;
    pos1 = pyvector_to_Cptr_double(pos1In);
    length = ((int) PyArray_DIM(pos1In, 0)) / 3;
    
    if (not_doubleVector(pos2In)) return NULL;
    pos2 = pyvector_to_Cptr_double(pos2In);
    
    if (not_doubleVector(cellDimsIn)) return NULL;
    cellDims = pyvector_to_Cptr_double(cellDimsIn);
    
    /* loop */
    sum = 0;
    for (i = 0; i < length; i++ )
    {
        double r2;
        
        r2 = atomicSeparation2( pos1[3*i], pos1[3*i+1], pos1[3*i+2], pos2[3*i], pos2[3*i+1], pos2[3*i+2], cellDims[0], cellDims[4], cellDims[8], PBC[0], PBC[1], PBC[2]);
        
        sum += r2;
    }
    
    return Py_BuildValue("d", sqrt(sum));
}
Example #5
0
/*******************************************************************************
 ** Make points array for visible atoms
 *******************************************************************************/
static PyObject*
makeVisiblePointsArray(PyObject *self, PyObject *args)
{
    int NVisible;
    PyArrayObject *visibleAtoms=NULL;
    PyArrayObject *pos=NULL;

    int i;
    npy_intp numpydims[2];
    PyArrayObject *visiblePos=NULL;

    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "O!O!", &PyArray_Type, &visibleAtoms, &PyArray_Type, &pos))
        return NULL;

    if (not_intVector(visibleAtoms)) return NULL;
    NVisible = (int) PyArray_DIM(visibleAtoms, 0);

    if (not_doubleVector(pos)) return NULL;

    /* create radius array */
    numpydims[0] = (npy_intp) NVisible;
    numpydims[1] = 3;
    visiblePos = (PyArrayObject *) PyArray_SimpleNew(2, numpydims, NPY_FLOAT64);

    /* populate array */
    for (i = 0; i < NVisible; i++)
    {
        int index, index3, j;

        index = IIND1(visibleAtoms, i);
        index3 = index * 3;

        for (j = 0; j < 3; j++)
            DIND2(visiblePos, i, j) = DIND1(pos, index3 + j);
    }

    return PyArray_Return(visiblePos);
}
Example #6
0
/*******************************************************************************
 ** Make arrays for rendering bonds for displacment vectors
 *******************************************************************************/
static PyObject*
makeDisplacementVectorBondsArrays(PyObject *self, PyObject *args)
{
    int numBonds;
    PyArrayObject *visibleAtoms=NULL;
    PyArrayObject *scalarsArray=NULL;
    PyArrayObject *pos=NULL;
    PyArrayObject *drawBondArray=NULL;
    PyArrayObject *bondVectorsArray=NULL;
    PyObject *result=NULL;

    /* parse arguments from Python */
    if (PyArg_ParseTuple(args, "iO!O!O!O!O!", &numBonds, &PyArray_Type, &visibleAtoms, &PyArray_Type, &scalarsArray,
                         &PyArray_Type, &pos, &PyArray_Type, &drawBondArray, &PyArray_Type, &bondVectorsArray))
    {
        int i, count, numVisible;
        npy_intp numpydims[2];
        PyArrayObject *bondCoords = NULL;
        PyArrayObject *bondScalars = NULL;
        PyArrayObject *bondVectors = NULL;

        /* check arguments */
        if (not_intVector(visibleAtoms)) return NULL;
        numVisible = (int) PyArray_DIM(visibleAtoms, 0);
        if (not_doubleVector(scalarsArray)) return NULL;
        if (not_doubleVector(pos)) return NULL;
        if (not_intVector(drawBondArray)) return NULL;
        if (not_doubleVector(bondVectorsArray)) return NULL;

        /* create array for bond coordinates */
        numpydims[0] = (npy_intp) numBonds;
        numpydims[1] = 3;
        bondCoords = (PyArrayObject *) PyArray_SimpleNew(2, numpydims, NPY_FLOAT64);
        if (bondCoords == NULL)
        {
            PyErr_SetString(PyExc_MemoryError, "Could not allocate bondCoords");
            return NULL;
        }

        /* create array for bond vectors */
        numpydims[0] = (npy_intp) numBonds;
        numpydims[1] = 3;
        bondVectors = (PyArrayObject *) PyArray_SimpleNew(2, numpydims, NPY_FLOAT64);
        if (bondVectors == NULL)
        {
            PyErr_SetString(PyExc_MemoryError, "Could not allocate bondVectors");
            Py_DECREF(bondCoords);
            return NULL;
        }

        /* create array for bond scalars */
        numpydims[0] = (npy_intp) numBonds;
        bondScalars = (PyArrayObject *) PyArray_SimpleNew(1, numpydims, NPY_FLOAT64);
        if (bondScalars == NULL)
        {
            PyErr_SetString(PyExc_MemoryError, "Could not allocate bondScalars");
            Py_DECREF(bondCoords);
            Py_DECREF(bondVectors);
            return NULL;
        }

        /* loop over visible atoms */
        count = 0;
        for (i = 0; i < numVisible; i++)
        {
            /* check if we should be drawing this bond */
            if (IIND1(drawBondArray, i))
            {
                int j, i3 = 3 * i;
                int index3 = 3 * IIND1(visibleAtoms, i);

                /* store bond values */
                for (j = 0; j < 3; j++)
                {
                    DIND2(bondCoords, count, j) = DIND1(pos, index3 + j);
                    DIND2(bondVectors, count, j) = DIND1(bondVectorsArray, i3 + j);
                }
                DIND1(bondScalars, count) = DIND1(scalarsArray, i);
                count++;
            }
        }

        /* tuple for result */
        result = PyTuple_New(3);
        PyTuple_SetItem(result, 0, PyArray_Return(bondCoords));
        PyTuple_SetItem(result, 1, PyArray_Return(bondVectors));
        PyTuple_SetItem(result, 2, PyArray_Return(bondScalars));
    }

    return result;
}
Example #7
0
/*******************************************************************************
 ** Split visible atoms by specie (position and scalar)
 *******************************************************************************/
static PyObject*
splitVisAtomsBySpecie(PyObject *self, PyObject *args)
{
    int NVisible, *visibleAtoms, NSpecies, *specieArray, *specieCount, scalarType, heightAxis, vectorsLen;
    double *pos, *PE, *KE, *charge, *scalars;
    PyArrayObject *visibleAtomsIn=NULL;
    PyArrayObject *specieArrayIn=NULL;
    PyArrayObject *specieCountIn=NULL;
    PyArrayObject *posIn=NULL;
    PyArrayObject *PEIn=NULL;
    PyArrayObject *KEIn=NULL;
    PyArrayObject *chargeIn=NULL;
    PyArrayObject *scalarsIn=NULL;
    PyArrayObject *vectors=NULL;

    int i, j, index, specie, count;
    npy_intp numpyDims[2];
    double scalar;
    PyObject *list=NULL;


    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "O!iO!O!O!O!O!O!O!iiO!", &PyArray_Type, &visibleAtomsIn, &NSpecies, &PyArray_Type, &specieArrayIn,
                          &PyArray_Type, &specieCountIn, &PyArray_Type, &posIn, &PyArray_Type, &PEIn, &PyArray_Type, &KEIn, &PyArray_Type,
                          &chargeIn, &PyArray_Type, &scalarsIn, &scalarType, &heightAxis, &PyArray_Type, &vectors))
        return NULL;

    if (not_intVector(visibleAtomsIn)) return NULL;
    visibleAtoms = pyvector_to_Cptr_int(visibleAtomsIn);
    NVisible = (int) PyArray_DIM(visibleAtomsIn, 0);

    if (not_intVector(specieArrayIn)) return NULL;
    specieArray = pyvector_to_Cptr_int(specieArrayIn);

    if (not_intVector(specieCountIn)) return NULL;
    specieCount = pyvector_to_Cptr_int(specieCountIn);

    if (not_doubleVector(posIn)) return NULL;
    pos = pyvector_to_Cptr_double(posIn);

    if (not_doubleVector(PEIn)) return NULL;
    PE = pyvector_to_Cptr_double(PEIn);

    if (not_doubleVector(KEIn)) return NULL;
    KE = pyvector_to_Cptr_double(KEIn);

    if (not_doubleVector(chargeIn)) return NULL;
    charge = pyvector_to_Cptr_double(chargeIn);

    if (not_doubleVector(scalarsIn)) return NULL;
    scalars = pyvector_to_Cptr_double(scalarsIn);

    if (not_doubleVector(vectors)) return NULL;
    vectorsLen = (int) PyArray_DIM(vectors, 0);

    /* first pass to get counters, assume counter zeroed before */
    for (i = 0; i < NVisible; i++)
    {
        index = visibleAtoms[i];
        specie = specieArray[index];
        specieCount[specie]++;
    }

    /* create list for returning */
    list = PyList_New(NSpecies);

    /* loop over species */
    for (i = 0; i < NSpecies; i++)
    {
        PyArrayObject *speciePos = NULL;
        PyArrayObject *specieScalars = NULL;
        PyArrayObject *specieVectors = NULL;
        PyObject *tuple = NULL;

        /* allocate position array */
        numpyDims[0] = (npy_intp) specieCount[i];
        numpyDims[1] = 3;
        speciePos = (PyArrayObject *) PyArray_SimpleNew(2, numpyDims, NPY_FLOAT64);

        /* allocate position array */
        numpyDims[0] = (npy_intp) specieCount[i];
        specieScalars = (PyArrayObject *) PyArray_SimpleNew(1, numpyDims, NPY_FLOAT64);

        if (vectorsLen > 0)
        {
            /* allocate vectors array */
            numpyDims[0] = (npy_intp) specieCount[i];
            numpyDims[1] = 3;
            specieVectors = (PyArrayObject *) PyArray_SimpleNew(2, numpyDims, NPY_FLOAT64);
        }
        else
        {
            numpyDims[0] = 0;
            specieVectors = (PyArrayObject *) PyArray_SimpleNew(1, numpyDims, NPY_FLOAT64);
        }

        /* loop over atoms */
        count = 0;
        for (j = 0; j < NVisible; j++)
        {
            index = visibleAtoms[j];
            specie = specieArray[index];

            if (specie == i)
            {
                /* position */
                DIND2(speciePos, count, 0) = pos[3*index+0];
                DIND2(speciePos, count, 1) = pos[3*index+1];
                DIND2(speciePos, count, 2) = pos[3*index+2];

                /* scalar */
                if (scalarType == 0) scalar = specie;
                else if (scalarType == 1) scalar = pos[3*index+heightAxis];
                else if (scalarType == 2) scalar = KE[index];
                else if (scalarType == 3) scalar = PE[index];
                else if (scalarType == 4) scalar = charge[index];
                else scalar = scalars[j];

                DIND1(specieScalars, count) = scalar;

                if (vectorsLen > 0)
                {
                    /* vector */
                    DIND2(specieVectors, count, 0) = DIND2(vectors, index, 0);
                    DIND2(specieVectors, count, 1) = DIND2(vectors, index, 1);
                    DIND2(specieVectors, count, 2) = DIND2(vectors, index, 2);
                }

                count++;
            }
        }

        /* create tuple (setItem steals ownership of array objects!!??) */
        tuple = PyTuple_New(3);
        PyTuple_SetItem(tuple, 0, PyArray_Return(speciePos));
        PyTuple_SetItem(tuple, 1, PyArray_Return(specieScalars));
        PyTuple_SetItem(tuple, 2, PyArray_Return(specieVectors));

        /* store in list (setItem steals ownership of tuple!?) */
        PyList_SetItem(list, i, tuple);
    }

    return list;
}
Example #8
0
/*******************************************************************************
 ** Make arrays for rendering bonds
 *******************************************************************************/
static PyObject*
makeBondsArrays(PyObject *self, PyObject *args)
{
    PyArrayObject *visibleAtoms=NULL;
    PyArrayObject *scalarsArray=NULL;
    PyArrayObject *pos=NULL;
    PyArrayObject *numBondsArray=NULL;
    PyArrayObject *bondsArray=NULL;
    PyArrayObject *bondVectorsArray=NULL;
    PyObject *result=NULL;

    /* parse arguments from Python */
    if (PyArg_ParseTuple(args, "O!O!O!O!O!O!", &PyArray_Type, &visibleAtoms, &PyArray_Type, &scalarsArray,
                         &PyArray_Type, &pos, &PyArray_Type, &numBondsArray, &PyArray_Type, &bondsArray, &PyArray_Type,
                         &bondVectorsArray))
    {
        int i, numVisible, numBonds, count, bondCount;
        npy_intp numpydims[2];
        PyArrayObject *bondCoords = NULL;
        PyArrayObject *bondScalars = NULL;
        PyArrayObject *bondVectors = NULL;

        /* check arguments */
        if (not_intVector(visibleAtoms)) return NULL;
        numVisible = (int) PyArray_DIM(visibleAtoms, 0);
        if (not_doubleVector(scalarsArray)) return NULL;
        if (not_doubleVector(pos)) return NULL;
        if (not_intVector(numBondsArray)) return NULL;
        if (not_intVector(bondsArray)) return NULL;
        if (not_doubleVector(bondVectorsArray)) return NULL;

        /* calculate the number of bonds */
        numBonds = 0;
        for (i = 0; i < numVisible; i++) numBonds += IIND1(numBondsArray, i);
        /* multiply by two as there are two "bonds" drawn per real bond */
        numBonds *= 2;

        /* create array for bond coordinates */
        numpydims[0] = (npy_intp) numBonds;
        numpydims[1] = 3;
        bondCoords = (PyArrayObject *) PyArray_SimpleNew(2, numpydims, NPY_FLOAT64);
        if (bondCoords == NULL)
        {
            PyErr_SetString(PyExc_MemoryError, "Could not allocate bondCoords");
            return NULL;
        }

        /* create array for bond vectors */
        numpydims[0] = (npy_intp) numBonds;
        numpydims[1] = 3;
        bondVectors = (PyArrayObject *) PyArray_SimpleNew(2, numpydims, NPY_FLOAT64);
        if (bondVectors == NULL)
        {
            PyErr_SetString(PyExc_MemoryError, "Could not allocate bondVectors");
            Py_DECREF(bondCoords);
            return NULL;
        }

        /* create array for bond scalars */
        numpydims[0] = (npy_intp) numBonds;
        bondScalars = (PyArrayObject *) PyArray_SimpleNew(1, numpydims, NPY_FLOAT64);
        if (bondScalars == NULL)
        {
            PyErr_SetString(PyExc_MemoryError, "Could not allocate bondScalars");
            Py_DECREF(bondCoords);
            Py_DECREF(bondVectors);
            return NULL;
        }

        /* loop over visible atoms */
        count = 0;
        bondCount = 0;
        for (i = 0; i < numVisible; i++)
        {
            int j;
            int indexa = IIND1(visibleAtoms, i);
            int indexa3 = 3 * indexa;
            int numBondsForAtom = IIND1(numBondsArray, i);
            double xposa, yposa, zposa, scalara;

            /* atom position and scalar */
            xposa = DIND1(pos, indexa3    );
            yposa = DIND1(pos, indexa3 + 1);
            zposa = DIND1(pos, indexa3 + 2);
            scalara = DIND1(scalarsArray, i);

            /* loop over this atoms bonds */
            for (j = 0; j < numBondsForAtom; j++)
            {
                int cnt3 = count * 3;
                int visIndex = IIND1(bondsArray, count);
                int indexb3 = 3 * IIND1(visibleAtoms, visIndex);
                double xposb = DIND1(pos, indexb3    );
                double yposb = DIND1(pos, indexb3 + 1);
                double zposb = DIND1(pos, indexb3 + 2);
                double scalarb = DIND1(scalarsArray, visIndex);
                double bvecx = DIND1(bondVectorsArray, cnt3    );
                double bvecy = DIND1(bondVectorsArray, cnt3 + 1);
                double bvecz = DIND1(bondVectorsArray, cnt3 + 2);

                /* partial bond from atom a towards b */
                DIND2(bondCoords, bondCount, 0) = xposa;
                DIND2(bondCoords, bondCount, 1) = yposa;
                DIND2(bondCoords, bondCount, 2) = zposa;
                DIND2(bondVectors, bondCount, 0) = bvecx;
                DIND2(bondVectors, bondCount, 1) = bvecy;
                DIND2(bondVectors, bondCount, 2) = bvecz;
                DIND1(bondScalars, bondCount) = scalara;
                bondCount++;

                /* partial bond from atom b towards a */
                DIND2(bondCoords, bondCount, 0) = xposb;
                DIND2(bondCoords, bondCount, 1) = yposb;
                DIND2(bondCoords, bondCount, 2) = zposb;
                DIND2(bondVectors, bondCount, 0) = -1.0 * bvecx;
                DIND2(bondVectors, bondCount, 1) = -1.0 * bvecy;
                DIND2(bondVectors, bondCount, 2) = -1.0 * bvecz;
                DIND1(bondScalars, bondCount) = scalarb;
                bondCount++;

                count++;
            }
        }

        /* tuple for result */
        result = PyTuple_New(3);
        PyTuple_SetItem(result, 0, PyArray_Return(bondCoords));
        PyTuple_SetItem(result, 1, PyArray_Return(bondVectors));
        PyTuple_SetItem(result, 2, PyArray_Return(bondScalars));
    }

    return result;
}
Example #9
0
/*******************************************************************************
 ** Check if an object has been picked
 *******************************************************************************/
static PyObject*
pickObject(PyObject *self, PyObject *args)
{
    int visibleAtomsDim, *visibleAtoms, vacsDim, *vacs, intsDim, *ints, onAntsDim, *onAnts, splitsDim, *splits;
    int *PBC, *specie, *refSpecie;
    double *pickPos, *pos, *refPos, *cellDims, *specieCovRad, *refSpecieCovRad, *result;  
    PyArrayObject *visibleAtomsIn=NULL;
    PyArrayObject *vacsIn=NULL;
    PyArrayObject *intsIn=NULL;
    PyArrayObject *onAntsIn=NULL;
    PyArrayObject *splitsIn=NULL;
    PyArrayObject *pickPosIn=NULL;
    PyArrayObject *posIn=NULL;
    PyArrayObject *refPosIn=NULL;
    PyArrayObject *PBCIn=NULL;
    PyArrayObject *cellDimsIn=NULL;
    PyArrayObject *specieIn=NULL;
    PyArrayObject *refSpecieIn=NULL;
    PyArrayObject *specieCovRadIn=NULL;
    PyArrayObject *refSpecieCovRadIn=NULL;
    PyArrayObject *resultIn=NULL;
    
    int minSepIndex, minSepType;
    double approxBoxWidth, minSepRad, minSep2, minSep;
    
    
    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!O!O!O!O!O!O!O!O!", &PyArray_Type, &visibleAtomsIn, &PyArray_Type, &vacsIn, 
            &PyArray_Type, &intsIn, &PyArray_Type, &onAntsIn, &PyArray_Type, &splitsIn, &PyArray_Type, &pickPosIn, &PyArray_Type, 
            &posIn, &PyArray_Type, &refPosIn, &PyArray_Type, &PBCIn, &PyArray_Type, &cellDimsIn, &PyArray_Type, &specieIn,
            &PyArray_Type, &refSpecieIn, &PyArray_Type, &specieCovRadIn, &PyArray_Type, &refSpecieCovRadIn, &PyArray_Type,
            &resultIn))
        return NULL;
    
    if (not_intVector(visibleAtomsIn)) return NULL;
    visibleAtoms = pyvector_to_Cptr_int(visibleAtomsIn);
    visibleAtomsDim = (int) PyArray_DIM(visibleAtomsIn, 0);
    
    if (not_intVector(vacsIn)) return NULL;
    vacs = pyvector_to_Cptr_int(vacsIn);
    vacsDim = (int) PyArray_DIM(vacsIn, 0);
    
    if (not_intVector(intsIn)) return NULL;
    ints = pyvector_to_Cptr_int(intsIn);
    intsDim = (int) PyArray_DIM(intsIn, 0);
    
    if (not_intVector(onAntsIn)) return NULL;
    onAnts = pyvector_to_Cptr_int(onAntsIn);
    onAntsDim = (int) PyArray_DIM(onAntsIn, 0);
    
    if (not_intVector(splitsIn)) return NULL;
    splits = pyvector_to_Cptr_int(splitsIn);
    splitsDim = (int) PyArray_DIM(splitsIn, 0);
    
    if (not_doubleVector(pickPosIn)) return NULL;
    pickPos = pyvector_to_Cptr_double(pickPosIn);
    
    if (not_doubleVector(posIn)) return NULL;
    pos = pyvector_to_Cptr_double(posIn);
    
    if (not_doubleVector(refPosIn)) return NULL;
    refPos = pyvector_to_Cptr_double(refPosIn);
    
    if (not_doubleVector(cellDimsIn)) return NULL;
    cellDims = pyvector_to_Cptr_double(cellDimsIn);
    
    if (not_intVector(PBCIn)) return NULL;
    PBC = pyvector_to_Cptr_int(PBCIn);
    
    if (not_intVector(specieIn)) return NULL;
    specie = pyvector_to_Cptr_int(specieIn);
    
    if (not_intVector(refSpecieIn)) return NULL;
    refSpecie = pyvector_to_Cptr_int(refSpecieIn);
    
    if (not_doubleVector(specieCovRadIn)) return NULL;
    specieCovRad = pyvector_to_Cptr_double(specieCovRadIn);
    
    if (not_doubleVector(refSpecieCovRadIn)) return NULL;
    refSpecieCovRad = pyvector_to_Cptr_double(refSpecieCovRadIn);
    
    if (not_doubleVector(resultIn)) return NULL;
    result = pyvector_to_Cptr_double(resultIn);
    
    
    // this should be detected automatically depending on cell size...
    approxBoxWidth = 4.0;
    
    /* initialise */
    minSep2 = 9999999.0;
    minSepIndex = -1;
    minSepRad = 0.0;
    minSepType = 0;
    
    /* pick atoms (if there are any) */
    if (visibleAtomsDim > 0)
    {
        int i, boxIndex, boxNebList[27], boxstat;
        int boxNebListSize;
        double *visPos;
        struct Boxes *boxes;
        
#ifdef DEBUG
        printf("PICKC: Picking atoms\n");
#endif
        
        /* vis atoms pos */
        visPos = malloc(3 * visibleAtomsDim * sizeof(double));
        if (visPos == NULL)
        {
            PyErr_SetString(PyExc_RuntimeError, "Could not allocate visPos");
            return NULL;
        }
        
        for (i = 0; i < visibleAtomsDim; i++)
        {
            int i3 = 3 * i;
            int index = visibleAtoms[i];
            int index3 = 3 * index;
            visPos[i3    ] = pos[index3    ];
            visPos[i3 + 1] = pos[index3 + 1];
            visPos[i3 + 2] = pos[index3 + 2];
        }
        
        /* box vis atoms */
        boxes = setupBoxes(approxBoxWidth, PBC, cellDims);
        if (boxes == NULL)
        {
            free(visPos);
            return NULL;
        }
        boxstat = putAtomsInBoxes(visibleAtomsDim, visPos, boxes);
        if (boxstat)
        {
            free(visPos);
            return NULL;
        }
        
        /* box index of picked pos */
        boxIndex = boxIndexOfAtom(pickPos[0], pickPos[1], pickPos[2], boxes);
        if (boxIndex < 0)
        {
            free(visPos);
            freeBoxes(boxes);
            return NULL;
        }
        
        /* neighbouring boxes */
        boxNebListSize = getBoxNeighbourhood(boxIndex, boxNebList, boxes);
        
        /* loop over neighbouring boxes, looking for nearest atom */
        for (i = 0; i < boxNebListSize; i++)
        {
            int k;
            int checkBox = boxNebList[i];
            
            for (k = 0; k < boxes->boxNAtoms[checkBox]; k++)
            {
                int index, realIndex;
                double sep2, rad;
                
                index = boxes->boxAtoms[checkBox][k];
                
                /* atomic separation */
                sep2 = atomicSeparation2(pickPos[0], pickPos[1], pickPos[2], 
                                         visPos[3*index], visPos[3*index+1], visPos[3*index+2], 
                                         cellDims[0], cellDims[1], cellDims[2], 
                                         PBC[0], PBC[1], PBC[2]);
                
                /* need radius too */
                realIndex = visibleAtoms[index];
                rad = specieCovRad[specie[realIndex]];
                
                if (sep2 < minSep2)
                {
                    minSep2 = sep2;
                    minSepIndex = index;
                    minSepRad = rad;
                }
            }
        }
        
        /* free memory */
        free(visPos);
        freeBoxes(boxes);
    }
    
    /* now check defects (if there are any) */
    if (vacsDim + intsDim + onAntsDim + splitsDim > 0)
    {
        int i, NVis, count, boxNebListSize, minSepIsDefect;
        int boxIndex, boxNebList[27], boxstat;
        double *visPos, *visCovRad;
        struct Boxes *boxes;
        
#ifdef DEBUG
        printf("PICKC: Picking defect\n");
#endif
        
        /* build positions array of all defects */
        NVis = vacsDim + intsDim + onAntsDim + splitsDim;
        visPos = malloc(3 * NVis * sizeof(double));
        if (visPos == NULL)
        {
            PyErr_SetString(PyExc_RuntimeError, "Could not allocate visPos");
            return NULL;
        }
        
        visCovRad = malloc(NVis * sizeof(double));
        if (visCovRad == NULL)
        {
            PyErr_SetString(PyExc_RuntimeError, "Could not allocate visCovRad");
            free(visPos);
            return NULL;
        }
        
        /* add defects positions: vac then int then ant */
        count = 0;
        for (i = 0; i < vacsDim; i++)
        {
            int c3 = 3 * count;
            int index = vacs[i];
            int index3 = 3 * index;
            
            visPos[c3    ] = refPos[index3    ];
            visPos[c3 + 1] = refPos[index3 + 1];
            visPos[c3 + 2] = refPos[index3 + 2];
            
            visCovRad[count++] = refSpecieCovRad[refSpecie[index]] * 1.2; // * 0.75; // multiply by 0.75 because vacs aren't full size (rendering.py)
        }
        
        for (i = 0; i < intsDim; i++)
        {
            int c3 = 3 * count;
            int index = ints[i];
            int index3 = 3 * index;
            
            visPos[c3    ] = pos[index3    ];
            visPos[c3 + 1] = pos[index3 + 1];
            visPos[c3 + 2] = pos[index3 + 2];
            
            visCovRad[count++] = specieCovRad[specie[index]];
        }
        
        for (i = 0; i < onAntsDim; i++)
        {
            int c3 = 3 * count;
            int index = onAnts[i];
            int index3 = 3 * index;
            
            visPos[c3    ] = pos[index3    ];
            visPos[c3 + 1] = pos[index3 + 1];
            visPos[c3 + 2] = pos[index3 + 2];
            
            visCovRad[count++] = specieCovRad[specie[index]];
        }
        
        for (i = 0; i < splitsDim / 3; i++)
        {
            int i3 = 3 * i;
            int index, c3, index3;
            
            index = splits[i3    ];
            index3 = index * 3;
            c3 = count * 3;
            visPos[c3    ] = refPos[index3    ];
            visPos[c3 + 1] = refPos[index3 + 1];
            visPos[c3 + 2] = refPos[index3 + 2];
            visCovRad[count++] = refSpecieCovRad[refSpecie[index]];
            
            index = splits[i3 + 1];
            index3 = index * 3;
            c3 = count * 3;
            visPos[c3    ] = pos[index3    ];
            visPos[c3 + 1] = pos[index3 + 1];
            visPos[c3 + 2] = pos[index3 + 2];
            visCovRad[count++] = specieCovRad[specie[index]];
            
            index = splits[i3 + 2];
            index3 = index * 3;
            c3 = count * 3;
            visPos[c3    ] = pos[index3    ];
            visPos[c3 + 1] = pos[index3 + 1];
            visPos[c3 + 2] = pos[index3 + 2];
            visCovRad[count++] = specieCovRad[specie[index]];
        }
        
        /* box vis atoms */
        boxes = setupBoxes(approxBoxWidth, PBC, cellDims);
        if (boxes == NULL)
        {
            free(visPos);
            free(visCovRad);
            return NULL;
        }
        boxstat = putAtomsInBoxes(NVis, visPos, boxes);
        if (boxstat)
        {
            free(visPos);
            free(visCovRad);
            return NULL;
        }
        
        /* box index of picked pos */
        boxIndex = boxIndexOfAtom(pickPos[0], pickPos[1], pickPos[2], boxes);
        if (boxIndex < 0)
        {
            free(visPos);
            free(visCovRad);
            freeBoxes(boxes);
            return NULL;
        }
        
        /* neighbouring boxes */
        boxNebListSize = getBoxNeighbourhood(boxIndex, boxNebList, boxes);
        
        /* loop over neighbouring boxes, looking for nearest atom */
        minSepIsDefect = 0;
        for (i = 0; i < boxNebListSize; i++)
        {
            int k;
            int checkBox = boxNebList[i];
            
            for (k = 0; k < boxes->boxNAtoms[checkBox]; k++)
            {
                int index;
                double sep2, rad;
                
                index = boxes->boxAtoms[checkBox][k];
                
                /* atomic separation */
                sep2 = atomicSeparation2(pickPos[0], pickPos[1], pickPos[2], 
                                         visPos[3*index], visPos[3*index+1], visPos[3*index+2], 
                                         cellDims[0], cellDims[1], cellDims[2], 
                                         PBC[0], PBC[1], PBC[2]);
                
                /* need radius too */
                rad = visCovRad[index];
                
                if (sep2 < minSep2)
                {
                    minSep2 = sep2;
                    minSepIndex = index;
                    minSepRad = rad;
                    minSepIsDefect = 1;
                }
            }
        }
        
        if (minSepIsDefect)
        {
            /* picked type */
            if (minSepIndex < vacsDim)
            {
                minSepType = 1;
            }
            else if (minSepIndex < vacsDim + intsDim)
            {
                minSepIndex -= vacsDim;
                minSepType = 2;
            }
            else if (minSepIndex < vacsDim + intsDim + onAntsDim)
            {
                minSepIndex -= vacsDim + intsDim;
                minSepType = 3;
            }
            else
            {
                minSepIndex -= vacsDim + intsDim + onAntsDim;
                minSepIndex = (int) (minSepIndex / 3);
                minSepType = 4;
            }
        }
        
        /* free memory */
        freeBoxes(boxes);
        free(visPos);
        free(visCovRad);
    }
    
    /* min separation */
    minSep = sqrt(minSep2);
    /* if separation is greater than radius, subtract radius, 
     * otherwise set to zero (within radius is good enough for me)
     */
    minSep = (minSep > minSepRad) ? minSep - minSepRad : 0.0;
    
    /* store result */
    result[0] = minSepType;
    result[1] = minSepIndex;
    result[2] = minSep;
    
#ifdef DEBUG
    printf("PICKC: End\n");
#endif
    
    return Py_BuildValue("i", 0);
}
Example #10
0
/*******************************************************************************
 ** Calculate the radial distribution function for the given selections of
 ** visible atoms.
 ** 
 ** Inputs are:
 **     - visibleAtoms: indices of atoms that are to be used for the calculation
 **     - specie: array containing the species index for each atom
 **     - pos: array containing the positions of the atoms
 **     - specieID1: the species of the first selection of atoms
 **     - specieID2: the species of the second selection of atoms
 **     - cellDims: the size of the simulation cell
 **     - pbc: periodic boundary conditions
 **     - start: minimum separation to use when constructing the histogram
 **     - finish: maximum separation to use when constructing the histogram
 **     - interval: the interval between histogram bins
 **     - numBins: the number of histogram bins
 **     - rdf: the result is returned in this array
 *******************************************************************************/
static PyObject*
calculateRDF(PyObject *self, PyObject *args)
{
    int numVisible, *visibleAtoms, *specie, specieID1, specieID2, *pbc, numBins;
    int numAtoms;
    double *pos, *cellDims, start, finish, *rdf;
    PyArrayObject *visibleAtomsIn=NULL;
    PyArrayObject *specieIn=NULL;
    PyArrayObject *pbcIn=NULL;
    PyArrayObject *posIn=NULL;
    PyArrayObject *cellDimsIn=NULL;
    PyArrayObject *rdfIn=NULL;
    int i, status, *sel1, *sel2, sel1cnt, sel2cnt, duplicates;
    double interval;
    
    
    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "O!O!O!iiO!O!dddiO!", &PyArray_Type, &visibleAtomsIn, &PyArray_Type, &specieIn,
            &PyArray_Type, &posIn, &specieID1, &specieID2, &PyArray_Type, &cellDimsIn, &PyArray_Type, &pbcIn, &start,
            &finish, &interval, &numBins, &PyArray_Type, &rdfIn))
        return NULL;
    
    if (not_intVector(visibleAtomsIn)) return NULL;
    visibleAtoms = pyvector_to_Cptr_int(visibleAtomsIn);
    numVisible = (int) PyArray_DIM(visibleAtomsIn, 0);
    
    if (not_intVector(specieIn)) return NULL;
    specie = pyvector_to_Cptr_int(specieIn);
    numAtoms = (int) PyArray_DIM(specieIn, 0);
    
    if (not_doubleVector(posIn)) return NULL;
    pos = pyvector_to_Cptr_double(posIn);
    
    if (not_doubleVector(rdfIn)) return NULL;
    rdf = pyvector_to_Cptr_double(rdfIn);
    
    if (not_doubleVector(cellDimsIn)) return NULL;
    cellDims = pyvector_to_Cptr_double(cellDimsIn);
    
    if (not_intVector(pbcIn)) return NULL;
    pbc = pyvector_to_Cptr_int(pbcIn);
    
    /* initialise result array to zero */
    for (i = 0; i < numBins; i++) rdf[i] = 0.0;
    
    /* create the selections of atoms and check for number of duplicates */
    sel1 = malloc(numVisible * sizeof(int));
    if (sel1 == NULL)
    {
        PyErr_SetString(PyExc_MemoryError, "Could not allocate sel1");
        return NULL;
    }
    sel2 = malloc(numVisible * sizeof(int));
    if (sel2 == NULL)
    {
        PyErr_SetString(PyExc_MemoryError, "Could not allocate sel2");
        free(sel1);
        return NULL;
    }
    sel1cnt = 0;
    sel2cnt = 0;
    duplicates = 0;
    for (i = 0; i < numVisible; i++)
    {
        int index = visibleAtoms[i];
        
        /* check if this atom is in the first selection (negative means all species) */
        if (specieID1 < 0 || specie[index] == specieID1)
        {
            sel1[i] = 1;
            sel1cnt++;
        }
        else sel1[i] = 0;
        
        /* check if this atom is in the second selection (negative means all species) */
        if (specieID2 < 0 || specie[index] == specieID2)
        {
            sel2[i] = 1;
            sel2cnt++;
        }
        else sel2[i] = 0;
        
        /* count the number of atoms that are in both selections */
        if (sel1[i] && sel2[i]) duplicates++;
    }
    
    /* compute the histogram for the RDF */
    status = computeHistogram(numAtoms, numVisible, visibleAtoms, pos, pbc, cellDims, 
            sel1, sel2, start, finish, interval, rdf);
    
    /* free memory used for selections */
    free(sel1);
    free(sel2);
    
    /* return if there was an error */
    if (status) return NULL;
    
    /* normalise the rdf */
    normaliseRDF(numBins, sel1cnt, sel2cnt, duplicates, start, interval, cellDims, rdf);
    
    /* return None */
    Py_INCREF(Py_None);
    return Py_None;
}
Example #11
0
/*******************************************************************************
 ** Calculate the bond order parameters and filter atoms (if required).
 **
 ** Inputs:
 **     - visibleAtoms: the list of atoms that are currently visible
 **     - pos: positions of all the atoms
 **     - maxBondDistance: the maximum bond distance to consider
 **     - scalarsQ4: array to store the Q4 parameter value
 **     - scalarsQ6: array to store the Q6 parameter value
 **     - cellDims: simulation cell dimensions
 **     - PBC: periodic boundaries conditions
 **     - NScalars: the number of previously calculated scalar values
 **     - fullScalars: the full list of previously calculated scalars
 **     - NVectors: the number of previously calculated vector values
 **     - fullVectors: the full list of previously calculated vectors
 **     - filterQ4: filter atoms by the Q4 parameter
 **     - minQ4: the minimum Q4 for an atom to be visible
 **     - maxQ4: the maximum Q4 for an atom to be visible
 **     - filterQ6: filter atoms by the Q6 parameter
 **     - minQ6: the minimum Q6 for an atom to be visible
 **     - maxQ6: the maximum Q6 for an atom to be visible
 *******************************************************************************/
static PyObject*
bondOrderFilter(PyObject *self, PyObject *args)
{
    int NVisibleIn, *visibleAtoms, *PBC, NScalars, filterQ4Enabled, filterQ6Enabled;
    int NVectors;
    double maxBondDistance, *scalarsQ4, *scalarsQ6, *cellDims;
    double *pos, *fullScalars, minQ4, maxQ4, minQ6, maxQ6;
    PyArrayObject *posIn=NULL;
    PyArrayObject *visibleAtomsIn=NULL;
    PyArrayObject *PBCIn=NULL;
    PyArrayObject *scalarsQ4In=NULL;
    PyArrayObject *scalarsQ6In=NULL;
    PyArrayObject *cellDimsIn=NULL;
    PyArrayObject *fullScalarsIn=NULL;
    PyArrayObject *fullVectors=NULL;

    int i, NVisible, boxstat;
    double *visiblePos, maxSep2;
    struct Boxes *boxes;
    struct NeighbourList *nebList;
    struct AtomStructureResults *results;

    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "O!O!dO!O!O!O!iO!iddiddiO!", &PyArray_Type, &visibleAtomsIn, &PyArray_Type, &posIn, &maxBondDistance,
            &PyArray_Type, &scalarsQ4In, &PyArray_Type, &scalarsQ6In, &PyArray_Type, &cellDimsIn, &PyArray_Type, &PBCIn, &NScalars,
            &PyArray_Type, &fullScalarsIn, &filterQ4Enabled, &minQ4, &maxQ4, &filterQ6Enabled, &minQ6, &maxQ6, &NVectors,
            &PyArray_Type, &fullVectors))
        return NULL;

    if (not_intVector(visibleAtomsIn)) return NULL;
    visibleAtoms = pyvector_to_Cptr_int(visibleAtomsIn);
    NVisibleIn = (int) PyArray_DIM(visibleAtomsIn, 0);

    if (not_doubleVector(posIn)) return NULL;
    pos = pyvector_to_Cptr_double(posIn);

    if (not_doubleVector(scalarsQ4In)) return NULL;
    scalarsQ4 = pyvector_to_Cptr_double(scalarsQ4In);

    if (not_doubleVector(scalarsQ6In)) return NULL;
    scalarsQ6 = pyvector_to_Cptr_double(scalarsQ6In);

    if (not_doubleVector(cellDimsIn)) return NULL;
    cellDims = pyvector_to_Cptr_double(cellDimsIn);

    if (not_intVector(PBCIn)) return NULL;
    PBC = pyvector_to_Cptr_int(PBCIn);

    if (not_doubleVector(fullScalarsIn)) return NULL;
    fullScalars = pyvector_to_Cptr_double(fullScalarsIn);

    if (not_doubleVector(fullVectors)) return NULL;

    /* construct array of positions of visible atoms */
    visiblePos = malloc(3 * NVisibleIn * sizeof(double));
    if (visiblePos == NULL)
    {
        PyErr_SetString(PyExc_MemoryError, "Could not allocate visiblePos");
        return NULL;
    }
    for (i = 0; i < NVisibleIn; i++)
    {
        int index = visibleAtoms[i];
        int ind3 = 3 * index;
        int i3 = 3 * i;
        visiblePos[i3    ] = pos[ind3    ];
        visiblePos[i3 + 1] = pos[ind3 + 1];
        visiblePos[i3 + 2] = pos[ind3 + 2];
    }

    /* box visible atoms */
    boxes = setupBoxes(maxBondDistance, PBC, cellDims);
    if (boxes == NULL)
    {
        free(visiblePos);
        return NULL;
    }
    boxstat = putAtomsInBoxes(NVisibleIn, visiblePos, boxes);
    if (boxstat)
    {
        free(visiblePos);
        return NULL;
    }

    /* build neighbour list */
    maxSep2 = maxBondDistance * maxBondDistance;
    nebList = constructNeighbourList(NVisibleIn, visiblePos, boxes, cellDims, PBC, maxSep2);

    /* only required for building neb list */
    free(visiblePos);
    freeBoxes(boxes);

    /* return if failed to build the neighbour list */
    if (nebList == NULL) return NULL;

    /* allocate results structure */
    results = malloc(NVisibleIn * sizeof(struct AtomStructureResults));
    if (results == NULL)
    {
        PyErr_SetString(PyExc_MemoryError, "Could not allocate results");
        freeNeighbourList(nebList, NVisibleIn);
        return NULL;
    }

    /* first calc q_lm for each atom over all m values */
    complex_qlm(NVisibleIn, visibleAtoms, nebList, pos, cellDims, PBC, results);

    /* free neighbour list */
    freeNeighbourList(nebList, NVisibleIn);

    /* calculate Q4 and Q6 */
    calculate_Q(NVisibleIn, results);

    /* do filtering here, storing results along the way */
    NVisible = 0;
    for (i = 0; i < NVisibleIn; i++)
    {
        int j;
        double q4 = results[i].Q4;
        double q6 = results[i].Q6;

        /* skip if not within the valid range */
        if (filterQ4Enabled && (q4 < minQ4 || q4 > maxQ4))
            continue;
        if (filterQ6Enabled && (q6 < minQ6 || q6 > maxQ6))
            continue;

        /* store in visible atoms array */
        visibleAtoms[NVisible] = visibleAtoms[i];

        /* store calculated values */
        scalarsQ4[NVisible] = q4;
        scalarsQ6[NVisible] = q6;

        /* update full scalars/vectors arrays */
        for (j = 0; j < NScalars; j++)
        {
            int nj = j * NVisibleIn;
            fullScalars[nj + NVisible] = fullScalars[nj + i];
        }

        for (j = 0; j < NVectors; j++)
        {
            int nj = j * NVisibleIn;
            DIND2(fullVectors, nj + NVisible, 0) = DIND2(fullVectors, nj + i, 0);
            DIND2(fullVectors, nj + NVisible, 1) = DIND2(fullVectors, nj + i, 1);
            DIND2(fullVectors, nj + NVisible, 2) = DIND2(fullVectors, nj + i, 2);
        }

        NVisible++;
    }

    /* free results memory */
    free(results);

    return Py_BuildValue("i", NVisible);
}
Example #12
0
/*******************************************************************************
 * eliminate pbc flicker
 *******************************************************************************/
static PyObject*
eliminatePBCFlicker(PyObject *self, PyObject *args)
{
    int NAtoms, *pbc;
    double *pos, *previousPos, *cellDims;
    PyArrayObject *posIn=NULL;
    PyArrayObject *previousPosIn=NULL;
    PyArrayObject *cellDimsIn=NULL;
    PyArrayObject *pbcIn=NULL;
    
    int i, j, count;
    double sep, absSep, halfDims[3];
    
    
    /* parse and check arguments from Python */
    if (!PyArg_ParseTuple(args, "iO!O!O!O!", &NAtoms, &PyArray_Type, &posIn, &PyArray_Type, &previousPosIn, 
            &PyArray_Type, &cellDimsIn, &PyArray_Type, &pbcIn))
        return NULL;
    
    if (not_intVector(pbcIn)) return NULL;
    pbc = pyvector_to_Cptr_int(pbcIn);
    
    if (not_doubleVector(posIn)) return NULL;
    pos = pyvector_to_Cptr_double(posIn);
    
    if (not_doubleVector(previousPosIn)) return NULL;
    previousPos = pyvector_to_Cptr_double(previousPosIn);
    
    if (not_doubleVector(cellDimsIn)) return NULL;
    cellDims = pyvector_to_Cptr_double(cellDimsIn);
    
    /* half of cellDims */
    halfDims[0] = cellDims[0] * 0.5;
    halfDims[1] = cellDims[1] * 0.5;
    halfDims[2] = cellDims[2] * 0.5;
    
    /* loop over atoms */
    count = 0;
    for (i = 0; i < NAtoms; i++)
    {
        sep = atomicSeparation2(pos[3*i], pos[3*i+1], pos[3*i+2], previousPos[3*i], previousPos[3*i+1], previousPos[3*i+2], 
                                cellDims[0], cellDims[1], cellDims[2], pbc[0], pbc[1], pbc[2]);
        
        for (j = 0; j < 3; j++)
        {
            if (sep < 1.0 && pos[3*i+j] < 1.0)
            {
                absSep = fabs(pos[3*i+j] - previousPos[3*i+j]);
                if (absSep > halfDims[j])
                {
                    pos[3*i+j] += cellDims[j];
                    count++;
                }
            }
            
            else if (sep < 1.0 && fabs(cellDims[j] - pos[3*i+j]) < 1.0)
            {
                absSep = fabs(pos[3*i+j] - previousPos[3*i+j]);
                if (absSep > halfDims[j])
                {
                    pos[3*i+j] -= cellDims[j];
                    count++;
                }
            }
        }
    }
    
    return Py_BuildValue("i", count);
}