Пример #1
0
/*******************************************************************************
 * Construct neighbour lists for "ref" atoms where the neighbour lists contain
 * "input" atoms only. If separation is very close to 0 we don't add it.
 *******************************************************************************/
struct NeighbourList2 * constructNeighbourList2DiffPos(int NAtomsRef, double *refPos, int NAtomsInp, double *inpPos, double *cellDims, int *PBC, double maxSep)
{
    int i;
    int boxstat;
    double approxBoxWidth;
    double maxSep2 = maxSep * maxSep;
    double rxb, ryb, rzb, sep2;
    struct Boxes *boxes;
    struct NeighbourList2 *nebList;
    
    
    /* box input atoms */
    approxBoxWidth = maxSep;
    boxes = setupBoxes(approxBoxWidth, PBC, cellDims);
    if (boxes == NULL) return NULL;
    boxstat = putAtomsInBoxes(NAtomsInp, inpPos, boxes);
    if (boxstat) return NULL;
    
    /* allocate neb list */
    nebList = malloc(NAtomsRef * sizeof(struct NeighbourList2));
    if (nebList == NULL)
    {
        PyErr_SetString(PyExc_MemoryError, "Could not allocate nebList");
        freeBoxes(boxes);
        return NULL;
    }
    
    /* initialise */
    for (i = 0; i < NAtomsRef; i++)
    {
        nebList[i].chunk = 16;
        nebList[i].neighbourCount = 0;
        nebList[i].neighbour = NULL;
    }
    
    /* loop over ref atoms */
    for (i = 0; i < NAtomsRef; i++)
    {
        int i3 = 3 * i;
        int j, boxNebListSize, boxIndex, boxNebList[27];
        double rxa, rya, rza;
        
        /* atom position */
        rxa = refPos[i3    ];
        rya = refPos[i3 + 1];
        rza = refPos[i3 + 2];
        
        /* get box index of this atom */
        boxIndex = boxIndexOfAtom(rxa, rya, rza, boxes);
        if (boxIndex < 0)
        {
            freeNeighbourList2(nebList, NAtomsRef);
            freeBoxes(boxes);
            return NULL;
        }
        
        /* find neighbouring boxes */
        boxNebListSize = getBoxNeighbourhood(boxIndex, boxNebList, boxes);
        
        /* loop over box neighbourhood */
        for (j = 0; j < boxNebListSize; j++)
        {
            int k;
            
            boxIndex = boxNebList[j];
            
            /* loop over atoms in box */
            for (k = 0; k < boxes->boxNAtoms[boxIndex]; k++)
            {
                int indexb = boxes->boxAtoms[boxIndex][k];
                int indb3 = indexb * 3;
                
                /* atom position */
                rxb = inpPos[indb3    ];
                ryb = inpPos[indb3 + 1];
                rzb = inpPos[indb3 + 2];
                
                /* separation */
                sep2 = atomicSeparation2(rxa, rya, rza, rxb, ryb, rzb, cellDims[0], cellDims[1], cellDims[2], PBC[0], PBC[1], PBC[2]);
                
                /* check if neighbour */
                if (sep2 < maxSep2)
                {
                    if (fabs(sep2 - 0.0) > 1e-6)
                    {
                        int addstat;
                        double sep = sqrt(sep2);
                        
                        addstat = addAtomToNebList(i, indexb, sep, nebList);
                        if (addstat)
                        {
                            freeNeighbourList2(nebList, NAtomsRef);
                            freeBoxes(boxes);
                            return NULL;
                        }
                    }
                }
            }
        }
    }
    
    freeBoxes(boxes);
    
    return nebList;
}
Пример #2
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);
}
Пример #3
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);
}
Пример #4
0
/*******************************************************************************
 ** Compute the histogram for the RDF
 *******************************************************************************/
static int
computeHistogram(int NAtoms, int NVisible, int *visibleAtoms, double *pos, int *PBC, double *cellDims,
        int *sel1, int *sel2, double start, double finish, double interval, double *hist)
{
    int i, errorCount, boxstat;
    double *visiblePos, approxBoxWidth;
    const double start2 = start * start;
    const double finish2 = finish * finish;
    struct Boxes *boxes;
    
    
    /* positions of visible atoms */
    if (NAtoms == NVisible) visiblePos = pos;
    else
    {
        visiblePos = malloc(3 * NVisible * sizeof(double));
        if (visiblePos == NULL)
        {
            PyErr_SetString(PyExc_MemoryError, "Could not allocate visiblePos");
            return 1;
        }
        for (i = 0; i < NVisible; i++)
        {
            int index = visibleAtoms[i];
            int i3 = 3 * i;
            int ind3 = 3 * index;
            visiblePos[i3    ] = pos[ind3    ];
            visiblePos[i3 + 1] = pos[ind3 + 1];
            visiblePos[i3 + 2] = pos[ind3 + 2];
        }
    }
    
    /* spatial decomposition - box width must be at least `finish` */
    approxBoxWidth = finish;
    boxes = setupBoxes(approxBoxWidth, PBC, cellDims);
    if (boxes == NULL)
    {
        if (NAtoms != NVisible) free(visiblePos);
        return 2;
    }
    boxstat = putAtomsInBoxes(NVisible, visiblePos, boxes);
    if (NAtoms != NVisible) free(visiblePos);
    if (boxstat) return 3;
    
    /* loop over visible atoms */
    errorCount = 0;
    #pragma omp parallel for reduction(+: errorCount) num_threads(prefs_numThreads)
    for (i = 0; i < NVisible; i++)
    {
        int j, index, ind3, boxIndex, boxNebList[27], boxNebListSize;
        double rxa, rya, rza;
        
        /* skip if this atom is not in the first selection */
        if (!sel1[i]) continue;
        
        /* the index of this atom in the pos array */
        index = visibleAtoms[i];
        
        /* position of this atom and its box index */
        ind3 = index * 3;
        rxa = pos[ind3    ];
        rya = pos[ind3 + 1];
        rza = pos[ind3 + 2];
        boxIndex = boxIndexOfAtom(rxa, rya, rza, boxes);
        if (boxIndex < 0) errorCount++;
        
        if (!errorCount)
        {
            /* find neighbouring boxes */
            boxNebListSize = getBoxNeighbourhood(boxIndex, boxNebList, boxes);
            
            /* loop over the box neighbourhood */
            for (j = 0; j < boxNebListSize; j++)
            {
                int k;
                int checkBox = boxNebList[j];
                
                for (k = 0; k < boxes->boxNAtoms[checkBox]; k++)
                {
                    int visIndex, index2, ind23;
                    double sep2;
                    
                    /* the index of this atom in the visibleAtoms array */
                    visIndex = boxes->boxAtoms[checkBox][k];
                    
                    /* skip if this atom is not in the second selection */
                    if (!sel2[visIndex]) continue;
                    
                    /* atom index */
                    index2 = visibleAtoms[visIndex];
                    
                    /* skip if same atom */
                    if (index == index2) continue;
                    
                    /* atomic separation */
                    ind23 = index2 * 3;
                    sep2 = atomicSeparation2(rxa, rya, rza,
                                             pos[ind23], pos[ind23 + 1], pos[ind23 + 2],
                                             cellDims[0], cellDims[1], cellDims[2], 
                                             PBC[0], PBC[1], PBC[2]);
                    
                    /* put in bin */
                    if (sep2 >= start2 && sep2 < finish2)
                    {
                        int binIndex;
                        double sep;
                        
                        sep = sqrt(sep2);
                        binIndex = (int) ((sep - start) / interval);
                        #pragma omp atomic
                        hist[binIndex]++;
                    }
                }
            }
        }
    }
    
    /* free memory */
    freeBoxes(boxes);
    
    /* raise an exception if there were any errors */
    if (errorCount)
    {
        PyErr_SetString(PyExc_RuntimeError, 
                "computeHistogram failed; probably box index error (check stderr)");
        return 4;
    }
    
    return 0;
}
Пример #5
0
/*******************************************************************************
 * Search for defects and return the sub-system surrounding them
 *******************************************************************************/
int findDefects( int includeVacs, int includeInts, int includeAnts,
				 int* defectList, int* NDefectsByType,
				 int* vacancies, int* interstitials, int* antisites, int* onAntisites,
				 int inclSpecDim, int* inclSpec, int exclSpecInputDim, int* exclSpecInput, int exclSpecRefDim, int* exclSpecRef,
				 int NAtoms, char* specieList, int* specie, double* pos,
				 int refNAtoms, char* specieListRef, int* specieRef, double* refPos,
				 double *cellDims, int *PBC, double vacancyRadius, double inclusionRadius, double *minPos, double *maxPos,
                 int verboseLevel, int debugDefects)
{
    int i, exitLoop, k, j, index;
    double vacRad2, xpos, ypos, zpos;
    int boxNebList[27];
    char symtemp[3], symtemp2[3];
    int checkBox, refIndex, comp, boxIndex;
    double refxpos, refypos, refzpos;
    double sep2, incRad2, approxBoxWidth;
    int NDefects, NAntisites, NInterstitials, NVacancies;
    int *possibleVacancy, *possibleInterstitial;
    int *possibleAntisite, *possibleOnAntisite;
    int count, addToInt, skip;
    struct Boxes *boxes;

    if ( verboseLevel > 2)
    {
        printf("CLIB: finding defects\n");
        printf("  vac rad %f\n", vacancyRadius);
        printf("  inc rad %f\n", inclusionRadius);
    }

    /* approx width, must be at least vacRad */
    approxBoxWidth = 1.1 * vacancyRadius;

    /* box reference atoms */
    boxes = setupBoxes(approxBoxWidth, minPos, maxPos, PBC, cellDims);
    putAtomsInBoxes(refNAtoms, refPos, boxes);

    /* allocate local arrays for checking atoms */
    possibleVacancy = malloc( refNAtoms * sizeof(int) );
    if (possibleVacancy == NULL)
    {
        printf("ERROR: Boxes: could not allocate possibleVacancy\n");
        exit(1);
    }

    possibleInterstitial = malloc( NAtoms * sizeof(int) );
    if (possibleInterstitial == NULL)
    {
        printf("ERROR: Boxes: could not allocate possibleInterstitial\n");
        exit(1);
    }

    possibleAntisite = malloc( refNAtoms * sizeof(int) );
    if (possibleAntisite == NULL)
    {
        printf("ERROR: Boxes: could not allocate possibleAntisite\n");
        exit(1);
    }

    possibleOnAntisite = malloc( refNAtoms * sizeof(int) );
    if (possibleOnAntisite == NULL)
    {
        printf("ERROR: Boxes: could not allocate possibleOnAntisite\n");
        exit(1);
    }

    /* initialise arrays */
    for ( i=0; i<NAtoms; i++ )
    {
        possibleInterstitial[i] = 1;
    }
    for ( i=0; i<refNAtoms; i++ )
    {
        possibleVacancy[i] = 1;
        possibleAntisite[i] = 1;
    }

    /* build local specie list */

    vacRad2 = vacancyRadius * vacancyRadius;
    incRad2 = inclusionRadius * inclusionRadius;

    /* loop over all input atoms */
    for ( i=0; i<NAtoms; i++ )
    {
        int nboxes;

        xpos = pos[3*i];
        ypos = pos[3*i+1];
        zpos = pos[3*i+2];

        /* get box index of this atom */
        boxIndex = boxIndexOfAtom(xpos, ypos, zpos, boxes);

        /* find neighbouring boxes */
        nboxes = getBoxNeighbourhood(boxIndex, boxNebList, boxes);

        /* loop over neighbouring boxes */
        exitLoop = 0;
        for (j = 0; j < nboxes; j++)
        {
            if (exitLoop)
            {
                break;
            }

            checkBox = boxNebList[j];

            /* now loop over all reference atoms in the box */
            for ( k=0; k<boxes->boxNAtoms[checkBox]; k++ )
            {
                refIndex = boxes->boxAtoms[checkBox][k];

                /* if this vacancy has already been filled then skip to the next one */
                if ( possibleVacancy[refIndex] == 0 )
                {
                    continue;
                }

                refxpos = refPos[3*refIndex];
                refypos = refPos[3*refIndex+1];
                refzpos = refPos[3*refIndex+2];

                /* atomic separation of possible vacancy and possible interstitial */
                sep2 = atomicSeparation2(xpos, ypos, zpos, refxpos, refypos, refzpos,
                                         cellDims[0], cellDims[1], cellDims[2], PBC[0], PBC[1], PBC[2]);

                /* if within vacancy radius, is it an antisite or normal lattice point */
                if ( sep2 < vacRad2 )
                {
                    /* compare symbols */
                    symtemp[0] = specieList[2*specie[i]];
                    symtemp[1] = specieList[2*specie[i]+1];
                    symtemp[2] = '\0';

                    symtemp2[0] = specieListRef[2*specieRef[refIndex]];
                    symtemp2[1] = specieListRef[2*specieRef[refIndex]+1];
                    symtemp2[2] = '\0';

                    comp = strcmp( symtemp, symtemp2 );
                    if ( comp == 0 )
                    {
                        /* match, so not antisite */
                        possibleAntisite[refIndex] = 0;
                    }
                    else
                    {
                        possibleOnAntisite[refIndex] = i;
                    }

                    /* not an interstitial or vacancy */
                    possibleInterstitial[i] = 0;
                    possibleVacancy[refIndex] = 0;

                    /* no need to check further for this (no longer) possible interstitial */
                    exitLoop = 1;
                    break;
                }
            }
        }
    }

    /* free boxes structure */
    freeBoxes(boxes);

    /* now box input atoms, approx width must be at least incRad */
    approxBoxWidth = 1.1 * inclusionRadius;
    boxes = setupBoxes(approxBoxWidth, minPos, maxPos, PBC, cellDims);
    putAtomsInBoxes(NAtoms, pos, boxes);

    /* now classify defects */
    NVacancies = 0;
    NInterstitials = 0;
    NAntisites = 0;
    count = 0;
    for ( i=0; i<refNAtoms; i++ )
    {
        skip = 0;
        for (j=0; j<exclSpecRefDim; j++)
        {
            if (specieRef[i] == exclSpecRef[j])
            {
                skip = 1;
            }
        }

        if (skip == 1)
        {
            continue;
        }

        /* vacancies */
        if (possibleVacancy[i] == 1)
        {
            if (includeVacs == 1)
            {
                int nboxes;

                vacancies[NVacancies] = i;
                NVacancies++;

                /* find input atoms within inclusionRadius of this vacancy */
                refxpos = refPos[3*i];
                refypos = refPos[3*i+1];
                refzpos = refPos[3*i+2];
                boxIndex = boxIndexOfAtom(refxpos, refypos, refzpos, boxes);

                /* find neighbouring boxes */
                nboxes = getBoxNeighbourhood(boxIndex, boxNebList, boxes);

                for (j = 0; j < nboxes; j++ )
                {
                    checkBox = boxNebList[j];

                    /* loop over atoms in box */
                    for ( k=0; k<boxes->boxNAtoms[checkBox]; k++ )
                    {
                        index = boxes->boxAtoms[checkBox][k];

                        /* if already on defect list continue */
                        if (defectList[index] == 1)
                        {
                            continue;
                        }

                        /* if close to defect add to list */
                        xpos = pos[3*index];
                        ypos = pos[3*index+1];
                        zpos = pos[3*index+2];
                        sep2 = atomicSeparation2(xpos, ypos, zpos, refxpos, refypos, refzpos,
                                                 cellDims[0], cellDims[1], cellDims[2], PBC[0], PBC[1], PBC[2]);

                        if ( sep2 < incRad2 )
                        {
                            defectList[index] = 1;
                            count++;
                        }
                    }
                }
            }
        }

        /* antisites */
        else if ( (possibleAntisite[i] == 1) && (includeAnts == 1) )
        {
            int nboxes;

            antisites[NAntisites] = i;
            onAntisites[NAntisites] = possibleOnAntisite[i];
            NAntisites++;

            /* find input atoms within inclusionRadius of this antisite */
            refxpos = refPos[3*i];
            refypos = refPos[3*i+1];
            refzpos = refPos[3*i+2];
            boxIndex = boxIndexOfAtom(refxpos, refypos, refzpos, boxes);

            /* find neighbouring boxes */
            nboxes = getBoxNeighbourhood(boxIndex, boxNebList, boxes);

            for (j = 0; j < nboxes; j++)
            {
                checkBox = boxNebList[j];

                /* loop over atoms in box */
                for ( k=0; k<boxes->boxNAtoms[checkBox]; k++ )
                {
                    index = boxes->boxAtoms[checkBox][k];

                    /* if already on defect list continue */
                    if (defectList[index] == 1)
                    {
                        continue;
                    }

                    /* if close to defect add to list */
                    xpos = pos[3*index];
                    ypos = pos[3*index+1];
                    zpos = pos[3*index+2];
                    sep2 = atomicSeparation2(xpos, ypos, zpos, refxpos, refypos, refzpos,
                                             cellDims[0], cellDims[1], cellDims[2], PBC[0], PBC[1], PBC[2]);

                    if ( sep2 < incRad2 )
                    {
                        defectList[index] = 1;
                        count++;
                    }
                }
            }
        }
    }

    if (includeInts == 1)
    {
        for ( i=0; i<NAtoms; i++ )
        {
            skip = 0;
            for (j=0; j<exclSpecInputDim; j++)
            {
                if (specie[i] == exclSpecInput[j])
                {
                    skip = 1;
                    break;
                }
            }

            if (skip == 1)
            {
                continue;
            }

            addToInt = 0;
            for (j=0; j<inclSpecDim; j++)
            {
                if (specie[i] == inclSpec[j])
                {
                    addToInt = 1;
                    break;
                }
            }

            /* interstitials */
            if ( (possibleInterstitial[i] == 1) || (addToInt == 1) )
            {
                int nboxes;

                interstitials[NInterstitials] = i;
                NInterstitials++;
                defectList[i] = 1;
                count++;

                /* find input atoms within inclusionRadius of this interstitial */
                refxpos = pos[3*i];
                refypos = pos[3*i+1];
                refzpos = pos[3*i+2];
                boxIndex = boxIndexOfAtom(refxpos, refypos, refzpos, boxes);

                /* find neighbouring boxes */
                nboxes = getBoxNeighbourhood(boxIndex, boxNebList, boxes);

                for (j = 0; j < nboxes; j++)
                {
                    checkBox = boxNebList[j];

                    /* loop over atoms in box */
                    for ( k=0; k<boxes->boxNAtoms[checkBox]; k++ )
                    {
                        index = boxes->boxAtoms[checkBox][k];

                        /* if same atom continue */
                        if ( index == i )
                        {
                            continue;
                        }

                        /* if already on defect list continue */
                        if (defectList[index] == 1)
                        {
                            continue;
                        }

                        /* if close to defect add to list */
                        xpos = pos[3*index];
                        ypos = pos[3*index+1];
                        zpos = pos[3*index+2];
                        sep2 = atomicSeparation2(xpos, ypos, zpos, refxpos, refypos, refzpos,
                                                 cellDims[0], cellDims[1], cellDims[2], PBC[0], PBC[1], PBC[2]);

                        if ( sep2 < incRad2 )
                        {
                            defectList[index] = 1;
                            count++;
                        }
                    }
                }
            }
        }
    }

    /* shift indexes to zero */
    count = 0;
    for (i=0; i<NAtoms; i++)
    {
        if (defectList[i] == 1)
        {
            defectList[count] = i;
            count++;
        }
    }

    NDefects = NVacancies + NInterstitials + NAntisites;
    if ( verboseLevel > 2 )
    {
        printf("  found %d defects\n", NDefects);
        printf("    %d vacancies\n", NVacancies);
        printf("    %d interstitials\n", NInterstitials);
        printf("    %d antisites\n", NAntisites);
        printf("  including %d atoms in sub-system\n", count);
    }

    NDefectsByType[0] = NDefects;
    NDefectsByType[1] = NVacancies;
    NDefectsByType[2] = NInterstitials;
    NDefectsByType[3] = NAntisites;

    freeBoxes(boxes);
    free(possibleVacancy);
    free(possibleInterstitial);
    free(possibleAntisite);
    free(possibleOnAntisite);

    return count;
}