/******************************************************************************* * 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); }
/******************************************************************************* ** 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); }
/******************************************************************************* * 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)); }
/******************************************************************************* * 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)); }
/******************************************************************************* ** 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); }
/******************************************************************************* ** 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; }
/******************************************************************************* ** 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; }
/******************************************************************************* ** 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; }
/******************************************************************************* ** 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); }
/******************************************************************************* ** 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; }
/******************************************************************************* ** 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); }
/******************************************************************************* * 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); }