2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2007, The GROMACS development team.
6 * Copyright (c) 2013,2014, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
48 #include "gromacs/pbcutil/pbc.h"
49 #include "gromacs/legacyheaders/macros.h"
50 #include "gromacs/math/vec.h"
51 #include "gromacs/utility/smalloc.h"
60 #define UNSP_ICO_DOD 9
61 #define UNSP_ICO_ARC 10
65 int n_dot, ico_cube, last_n_dot = 0, last_densit = 0, last_unsp = 0;
68 #define FOURPI (4.*M_PI)
69 #define TORAD(A) ((A)*0.017453293)
72 #define UPDATE_FL __file__ = __FILE__, __line__ = __LINE__
73 const char * __file__; /* declared versions of macros */
74 int __line__; /* __FILE__ and __LINE__ */
79 #define ERROR UPDATE_FL, error
80 void error(const char *fmt, ...)
84 "\n---> ERROR when executing line %i in file %s !\n",
87 vfprintf(stderr, fmt, args);
89 fprintf(stderr, "\n---> Execution stopped !\n\n");
92 #define WARNING UPDATE_FL, warning2
93 void warning2(const char *fmt, ...)
97 "\n---> WARNING : line %i in file %s\n",
100 vfprintf(stderr, fmt, args);
102 fprintf(stderr, " ...!\n\n");
107 #define ASIN safe_asin
108 real safe_asin(real f)
110 if ( (fabs(f) < 1.00) )
114 if ( (fabs(f) - 1.00) <= DP_TOL)
116 ERROR("ASIN : invalid argument %f", f);
124 /* routines for dot distributions on the surface of the unit sphere */
127 void icosaeder_vertices(real *xus)
129 rh = sqrt(1.-2.*cos(TORAD(72.)))/(1.-cos(TORAD(72.)));
130 rg = cos(TORAD(72.))/(1.-cos(TORAD(72.)));
131 /* icosaeder vertices */
132 xus[ 0] = 0.; xus[ 1] = 0.; xus[ 2] = 1.;
133 xus[ 3] = rh*cos(TORAD(72.)); xus[ 4] = rh*sin(TORAD(72.)); xus[ 5] = rg;
134 xus[ 6] = rh*cos(TORAD(144.)); xus[ 7] = rh*sin(TORAD(144.)); xus[ 8] = rg;
135 xus[ 9] = rh*cos(TORAD(216.)); xus[10] = rh*sin(TORAD(216.)); xus[11] = rg;
136 xus[12] = rh*cos(TORAD(288.)); xus[13] = rh*sin(TORAD(288.)); xus[14] = rg;
137 xus[15] = rh; xus[16] = 0; xus[17] = rg;
138 xus[18] = rh*cos(TORAD(36.)); xus[19] = rh*sin(TORAD(36.)); xus[20] = -rg;
139 xus[21] = rh*cos(TORAD(108.)); xus[22] = rh*sin(TORAD(108.)); xus[23] = -rg;
140 xus[24] = -rh; xus[25] = 0; xus[26] = -rg;
141 xus[27] = rh*cos(TORAD(252.)); xus[28] = rh*sin(TORAD(252.)); xus[29] = -rg;
142 xus[30] = rh*cos(TORAD(324.)); xus[31] = rh*sin(TORAD(324.)); xus[32] = -rg;
143 xus[33] = 0.; xus[34] = 0.; xus[35] = -1.;
147 void divarc(real x1, real y1, real z1,
148 real x2, real y2, real z2,
149 int div1, int div2, real *xr, real *yr, real *zr)
152 real xd, yd, zd, dd, d1, d2, s, x, y, z;
153 real phi, sphi, cphi;
158 dd = sqrt(xd*xd+yd*yd+zd*zd);
161 ERROR("divarc: rotation axis of length %f", dd);
164 d1 = x1*x1+y1*y1+z1*z1;
167 ERROR("divarc: vector 1 of sq.length %f", d1);
169 d2 = x2*x2+y2*y2+z2*z2;
172 ERROR("divarc: vector 2 of sq.length %f", d2);
175 phi = ASIN(dd/sqrt(d1*d2));
176 phi = phi*((real)div1)/((real)div2);
177 sphi = sin(phi); cphi = cos(phi);
178 s = (x1*xd+y1*yd+z1*zd)/dd;
180 x = xd*s*(1.-cphi)/dd + x1 * cphi + (yd*z1-y1*zd)*sphi/dd;
181 y = yd*s*(1.-cphi)/dd + y1 * cphi + (zd*x1-z1*xd)*sphi/dd;
182 z = zd*s*(1.-cphi)/dd + z1 * cphi + (xd*y1-x1*yd)*sphi/dd;
183 dd = sqrt(x*x+y*y+z*z);
184 *xr = x/dd; *yr = y/dd; *zr = z/dd;
187 int ico_dot_arc(int densit) /* densit...required dots per unit sphere */
189 /* dot distribution on a unit sphere based on an icosaeder *
190 * great circle average refining of icosahedral face */
192 int i, j, k, tl, tl2, tn, tess;
193 real a, d, x, y, z, x2, y2, z2, x3, y3, z3;
194 real xij, yij, zij, xji, yji, zji, xik, yik, zik, xki, yki, zki,
195 xjk, yjk, zjk, xkj, ykj, zkj;
198 /* calculate tessalation level */
199 a = sqrt((((real) densit)-2.)/10.);
200 tess = (int) ceil(a);
201 n_dot = 10*tess*tess+2;
204 ERROR("ico_dot_arc: error in formula for tessalation level (%d->%d, %d)",
205 tess, n_dot, densit);
210 icosaeder_vertices(xus);
215 a = rh*rh*2.*(1.-cos(TORAD(72.)));
216 /* calculate tessalation of icosaeder edges */
217 for (i = 0; i < 11; i++)
219 for (j = i+1; j < 12; j++)
221 x = xus[3*i]-xus[3*j];
222 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
224 if (fabs(a-d) > DP_TOL)
228 for (tl = 1; tl < tess; tl++)
232 ERROR("ico_dot: tn exceeds dimension of xus");
234 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
235 xus[3*j], xus[1+3*j], xus[2+3*j],
236 tl, tess, &xus[3*tn], &xus[1+3*tn], &xus[2+3*tn]);
241 /* calculate tessalation of icosaeder faces */
242 for (i = 0; i < 10; i++)
244 for (j = i+1; j < 11; j++)
246 x = xus[3*i]-xus[3*j];
247 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
249 if (fabs(a-d) > DP_TOL)
254 for (k = j+1; k < 12; k++)
256 x = xus[3*i]-xus[3*k];
257 y = xus[1+3*i]-xus[1+3*k]; z = xus[2+3*i]-xus[2+3*k];
259 if (fabs(a-d) > DP_TOL)
263 x = xus[3*j]-xus[3*k];
264 y = xus[1+3*j]-xus[1+3*k]; z = xus[2+3*j]-xus[2+3*k];
266 if (fabs(a-d) > DP_TOL)
270 for (tl = 1; tl < tess-1; tl++)
272 divarc(xus[3*j], xus[1+3*j], xus[2+3*j],
273 xus[3*i], xus[1+3*i], xus[2+3*i],
274 tl, tess, &xji, &yji, &zji);
275 divarc(xus[3*k], xus[1+3*k], xus[2+3*k],
276 xus[3*i], xus[1+3*i], xus[2+3*i],
277 tl, tess, &xki, &yki, &zki);
279 for (tl2 = 1; tl2 < tess-tl; tl2++)
281 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
282 xus[3*j], xus[1+3*j], xus[2+3*j],
283 tl2, tess, &xij, &yij, &zij);
284 divarc(xus[3*k], xus[1+3*k], xus[2+3*k],
285 xus[3*j], xus[1+3*j], xus[2+3*j],
286 tl2, tess, &xkj, &ykj, &zkj);
287 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
288 xus[3*k], xus[1+3*k], xus[2+3*k],
289 tess-tl-tl2, tess, &xik, &yik, &zik);
290 divarc(xus[3*j], xus[1+3*j], xus[2+3*j],
291 xus[3*k], xus[1+3*k], xus[2+3*k],
292 tess-tl-tl2, tess, &xjk, &yjk, &zjk);
295 ERROR("ico_dot: tn exceeds dimension of xus");
297 divarc(xki, yki, zki, xji, yji, zji, tl2, tess-tl,
299 divarc(xkj, ykj, zkj, xij, yij, zij, tl, tess-tl2,
301 divarc(xjk, yjk, zjk, xik, yik, zik, tl, tl+tl2,
303 x = x+x2+x3; y = y+y2+y3; z = z+z2+z3;
304 d = sqrt(x*x+y*y+z*z);
316 ERROR("ico_dot: n_dot(%d) and tn(%d) differ", n_dot, tn);
318 } /* end of if (tess > 1) */
321 } /* end of routine ico_dot_arc */
323 int ico_dot_dod(int densit) /* densit...required dots per unit sphere */
325 /* dot distribution on a unit sphere based on an icosaeder *
326 * great circle average refining of icosahedral face */
328 int i, j, k, tl, tl2, tn, tess, j1, j2;
329 real a, d, x, y, z, x2, y2, z2, x3, y3, z3, ai_d, adod;
330 real xij, yij, zij, xji, yji, zji, xik, yik, zik, xki, yki, zki,
331 xjk, yjk, zjk, xkj, ykj, zkj;
333 /* calculate tesselation level */
334 a = sqrt((((real) densit)-2.)/30.);
335 tess = max((int) ceil(a), 1);
336 n_dot = 30*tess*tess+2;
339 ERROR("ico_dot_dod: error in formula for tessalation level (%d->%d, %d)",
340 tess, n_dot, densit);
345 icosaeder_vertices(xus);
348 /* square of the edge of an icosaeder */
349 a = rh*rh*2.*(1.-cos(TORAD(72.)));
350 /* dodecaeder vertices */
351 for (i = 0; i < 10; i++)
353 for (j = i+1; j < 11; j++)
355 x = xus[3*i]-xus[3*j];
356 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
358 if (fabs(a-d) > DP_TOL)
362 for (k = j+1; k < 12; k++)
364 x = xus[3*i]-xus[3*k];
365 y = xus[1+3*i]-xus[1+3*k]; z = xus[2+3*i]-xus[2+3*k];
367 if (fabs(a-d) > DP_TOL)
371 x = xus[3*j]-xus[3*k];
372 y = xus[1+3*j]-xus[1+3*k]; z = xus[2+3*j]-xus[2+3*k];
374 if (fabs(a-d) > DP_TOL)
378 x = xus[ 3*i]+xus[ 3*j]+xus[ 3*k];
379 y = xus[1+3*i]+xus[1+3*j]+xus[1+3*k];
380 z = xus[2+3*i]+xus[2+3*j]+xus[2+3*k];
381 d = sqrt(x*x+y*y+z*z);
382 xus[3*tn] = x/d; xus[1+3*tn] = y/d; xus[2+3*tn] = z/d;
391 /* square of the edge of an dodecaeder */
392 adod = 4.*(cos(TORAD(108.))-cos(TORAD(120.)))/(1.-cos(TORAD(120.)));
393 /* square of the distance of two adjacent vertices of ico- and dodecaeder */
394 ai_d = 2.*(1.-sqrt(1.-a/3.));
396 /* calculate tessalation of mixed edges */
397 for (i = 0; i < 31; i++)
399 j1 = 12; j2 = 32; a = ai_d;
404 for (j = j1; j < j2; j++)
406 x = xus[3*i]-xus[3*j];
407 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
409 if (fabs(a-d) > DP_TOL)
413 for (tl = 1; tl < tess; tl++)
417 ERROR("ico_dot: tn exceeds dimension of xus");
419 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
420 xus[3*j], xus[1+3*j], xus[2+3*j],
421 tl, tess, &xus[3*tn], &xus[1+3*tn], &xus[2+3*tn]);
426 /* calculate tessalation of pentakisdodecahedron faces */
427 for (i = 0; i < 12; i++)
429 for (j = 12; j < 31; j++)
431 x = xus[3*i]-xus[3*j];
432 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
434 if (fabs(ai_d-d) > DP_TOL)
439 for (k = j+1; k < 32; k++)
441 x = xus[3*i]-xus[3*k];
442 y = xus[1+3*i]-xus[1+3*k]; z = xus[2+3*i]-xus[2+3*k];
444 if (fabs(ai_d-d) > DP_TOL)
448 x = xus[3*j]-xus[3*k];
449 y = xus[1+3*j]-xus[1+3*k]; z = xus[2+3*j]-xus[2+3*k];
451 if (fabs(adod-d) > DP_TOL)
455 for (tl = 1; tl < tess-1; tl++)
457 divarc(xus[3*j], xus[1+3*j], xus[2+3*j],
458 xus[3*i], xus[1+3*i], xus[2+3*i],
459 tl, tess, &xji, &yji, &zji);
460 divarc(xus[3*k], xus[1+3*k], xus[2+3*k],
461 xus[3*i], xus[1+3*i], xus[2+3*i],
462 tl, tess, &xki, &yki, &zki);
464 for (tl2 = 1; tl2 < tess-tl; tl2++)
466 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
467 xus[3*j], xus[1+3*j], xus[2+3*j],
468 tl2, tess, &xij, &yij, &zij);
469 divarc(xus[3*k], xus[1+3*k], xus[2+3*k],
470 xus[3*j], xus[1+3*j], xus[2+3*j],
471 tl2, tess, &xkj, &ykj, &zkj);
472 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
473 xus[3*k], xus[1+3*k], xus[2+3*k],
474 tess-tl-tl2, tess, &xik, &yik, &zik);
475 divarc(xus[3*j], xus[1+3*j], xus[2+3*j],
476 xus[3*k], xus[1+3*k], xus[2+3*k],
477 tess-tl-tl2, tess, &xjk, &yjk, &zjk);
480 ERROR("ico_dot: tn exceeds dimension of xus");
482 divarc(xki, yki, zki, xji, yji, zji, tl2, tess-tl,
484 divarc(xkj, ykj, zkj, xij, yij, zij, tl, tess-tl2,
486 divarc(xjk, yjk, zjk, xik, yik, zik, tl, tl+tl2,
488 x = x+x2+x3; y = y+y2+y3; z = z+z2+z3;
489 d = sqrt(x*x+y*y+z*z);
501 ERROR("ico_dot: n_dot(%d) and tn(%d) differ", n_dot, tn);
503 } /* end of if (tess > 1) */
506 } /* end of routine ico_dot_dod */
508 int unsp_type(int densit)
512 while (10*i1*i1+2 < densit)
517 while (30*i2*i2+2 < densit)
521 if (10*i1*i1-2 < 30*i2*i2-2)
531 int make_unsp(int densit, int mode, int * num_dot, int cubus)
533 int *ico_wk, *ico_pt;
534 int ndot, ico_cube_cb, i, j, k, l, ijk, tn, tl, tl2;
548 if (mode == UNSP_ICO_ARC)
550 ndot = ico_dot_arc(densit);
552 else if (mode == UNSP_ICO_DOD)
554 ndot = ico_dot_dod(densit);
558 WARNING("make_unsp: mode %c%d not allowed", (k) ? '+' : '-', mode);
562 last_n_dot = ndot; last_densit = densit; last_unsp = mode;
563 *num_dot = ndot; if (k)
568 /* in the following the dots of the unit sphere may be resorted */
569 last_unsp = -last_unsp;
571 /* determine distribution of points in elementary cubes */
580 while (i*i*i*2 < ndot)
584 ico_cube = max(i-1, 0);
586 ico_cube_cb = ico_cube*ico_cube*ico_cube;
587 del_cube = 2./((real)ico_cube);
590 for (l = 0; l < ndot; l++)
592 i = max((int) floor((1.+xus[3*l])/del_cube), 0);
597 j = max((int) floor((1.+xus[1+3*l])/del_cube), 0);
602 k = max((int) floor((1.+xus[2+3*l])/del_cube), 0);
607 ijk = i+j*ico_cube+k*ico_cube*ico_cube;
611 snew(ico_wk, 2*ico_cube_cb+1);
613 ico_pt = ico_wk+ico_cube_cb;
614 for (l = 0; l < ndot; l++)
616 ico_wk[work[l]]++; /* dots per elementary cube */
619 /* reordering of the coordinate array in accordance with box number */
621 for (i = 0; i < ico_cube; i++)
623 for (j = 0; j < ico_cube; j++)
625 for (k = 0; k < ico_cube; k++)
629 ijk = i+ico_cube*j+ico_cube*ico_cube*k;
631 for (l = tl2; l < ndot; l++)
635 x = xus[3*l]; y = xus[1+3*l]; z = xus[2+3*l];
636 xus[3*l] = xus[3*tn];
637 xus[1+3*l] = xus[1+3*tn]; xus[2+3*l] = xus[2+3*tn];
638 xus[3*tn] = x; xus[1+3*tn] = y; xus[2+3*tn] = z;
639 ijk = work[l]; work[l] = work[tn]; work[tn] = ijk;
654 typedef struct _stwknb {
661 int nsc_dclm_pbc(const rvec *coords, real *radius, int nat,
662 int densit, int mode,
663 real *value_of_area, real **at_area,
665 real **lidots, int *nu_dots,
666 atom_id index[], int ePBC, matrix box)
668 int iat, i, ii, iii, ix, iy, iz, ixe, ixs, iye, iys, ize, izs, i_ac;
669 int jat, j, jj, jjj, jx, jy, jz;
672 int maxnei, nnei, last, maxdots = 0;
673 int *wkdot = NULL, *wkbox = NULL, *wkat1 = NULL, *wkatm = NULL;
675 int iii1, iii2, iiat, lfnr = 0, i_at, j_at;
676 real dx, dy, dz, dd, ai, aisq, ajsq, aj, as, a;
677 real xi, yi, zi, xs = 0., ys = 0., zs = 0.;
678 real dotarea, area, vol = 0.;
679 real *xus, *dots = NULL, *atom_area = NULL;
680 int nxbox, nybox, nzbox, nxy, nxyz;
681 real xmin = 0, ymin = 0, zmin = 0, xmax, ymax, zmax, ra2max, d;
683 /* Added DvdS 2006-07-19 */
688 distribution = unsp_type(densit);
689 if (distribution != -last_unsp || last_cubus != 4 ||
690 (densit != last_densit && densit != last_n_dot))
692 if (make_unsp(densit, (-distribution), &n_dot, 4))
699 dotarea = FOURPI/(real) n_dot;
704 fprintf(debug, "nsc_dclm: n_dot=%5d %9.3f\n", n_dot, dotarea);
707 /* start with neighbour list */
708 /* calculate neighbour list with the box algorithm */
711 WARNING("nsc_dclm: no surface atoms selected");
714 if (mode & FLAG_VOLUME)
718 if (mode & FLAG_DOTS)
720 maxdots = (3*n_dot*nat)/10;
721 /* should be set to NULL on first user call */
728 srenew(dots, maxdots);
733 if (mode & FLAG_ATOM_AREA)
735 /* should be set to NULL on first user call */
736 if (atom_area == NULL)
738 snew(atom_area, nat);
742 srenew(atom_area, nat);
746 /* Compute minimum size for grid cells */
747 ra2max = radius[index[0]];
748 for (iat_xx = 1; (iat_xx < nat); iat_xx++)
751 ra2max = max(ra2max, radius[iat]);
755 /* Added DvdS 2006-07-19 */
756 /* Updated 2008-10-09 */
759 set_pbc(&pbc, ePBC, box);
761 for (i = 0; (i < nat); i++)
764 copy_rvec(coords[iat], x[i]);
766 put_atoms_in_triclinic_unitcell(ecenterTRIC, box, nat, x);
767 nxbox = max(1, floor(norm(box[XX])/ra2max));
768 nybox = max(1, floor(norm(box[YY])/ra2max));
769 nzbox = max(1, floor(norm(box[ZZ])/ra2max));
772 fprintf(debug, "nbox = %d, %d, %d\n", nxbox, nybox, nzbox);
777 /* dimensions of atomic set, cell edge is 2*ra_max */
779 xmin = coords[iat][XX]; xmax = xmin; xs = xmin;
780 ymin = coords[iat][YY]; ymax = ymin; ys = ymin;
781 zmin = coords[iat][ZZ]; zmax = zmin; zs = zmin;
783 for (iat_xx = 1; (iat_xx < nat); iat_xx++)
787 xmin = min(xmin, *pco); xmax = max(xmax, *pco);
788 ymin = min(ymin, *(pco+1)); ymax = max(ymax, *(pco+1));
789 zmin = min(zmin, *(pco+2)); zmax = max(zmax, *(pco+2));
790 xs = xs+ *pco; ys = ys+ *(pco+1); zs = zs+ *(pco+2);
797 fprintf(debug, "nsc_dclm: n_dot=%5d ra2max=%9.3f %9.3f\n", n_dot, ra2max, dotarea);
800 d = xmax-xmin; nxbox = (int) max(ceil(d/ra2max), 1.);
801 d = (((real)nxbox)*ra2max-d)/2.;
802 xmin = xmin-d; xmax = xmax+d;
803 d = ymax-ymin; nybox = (int) max(ceil(d/ra2max), 1.);
804 d = (((real)nybox)*ra2max-d)/2.;
805 ymin = ymin-d; ymax = ymax+d;
806 d = zmax-zmin; nzbox = (int) max(ceil(d/ra2max), 1.);
807 d = (((real)nzbox)*ra2max-d)/2.;
808 zmin = zmin-d; zmax = zmax+d;
814 /* box number of atoms */
826 for (i = 0; (i < nat); i++)
828 mvmul(box_1, x[i], x_1);
829 ix = ((int)floor(x_1[XX]*nxbox) + 2*nxbox) % nxbox;
830 iy = ((int)floor(x_1[YY]*nybox) + 2*nybox) % nybox;
831 iz = ((int)floor(x_1[ZZ]*nzbox) + 2*nzbox) % nzbox;
832 j = ix + iy*nxbox + iz*nxbox*nybox;
835 fprintf(debug, "Atom %d cell index %d. x = (%8.3f,%8.3f,%8.3f) fc = (%8.3f,%8.3f,%8.3f)\n",
836 i, j, x[i][XX], x[i][YY], x[i][ZZ], x_1[XX], x_1[YY], x_1[ZZ]);
838 range_check(j, 0, nxyz);
845 /* Put the atoms in their boxes */
846 for (iat_xx = 0; (iat_xx < nat); iat_xx++)
850 i = (int) max(floor((pco[XX]-xmin)/ra2max), 0);
852 j = (int) max(floor((pco[YY]-ymin)/ra2max), 0);
854 l = (int) max(floor((pco[ZZ]-zmin)/ra2max), 0);
862 /* sorting of atoms in accordance with box numbers */
864 for (i = 1; i < nxyz; i++)
866 j = max(wkbox[i], j);
868 for (i = 1; i <= nxyz; i++)
870 wkbox[i] += wkbox[i-1];
873 /* maxnei = (int) floor(ra2max*ra2max*ra2max*0.5); */
874 maxnei = min(nat, 27*j);
876 for (iat_xx = 0; iat_xx < nat; iat_xx++)
879 range_check(wkat1[iat_xx], 0, nxyz);
880 wkatm[--wkbox[wkat1[iat_xx]]] = iat_xx;
883 fprintf(debug, "atom %5d on place %5d\n", iat, wkbox[wkat1[iat_xx]]);
889 fprintf(debug, "nsc_dclm: n_dot=%5d ra2max=%9.3f %9.3f\n",
890 n_dot, ra2max, dotarea);
891 fprintf(debug, "neighbour list calculated/box(xyz):%d %d %d\n",
892 nxbox, nybox, nzbox);
894 for (i = 0; i < nxyz; i++)
896 fprintf(debug, "box %6d : atoms %4d-%4d %5d\n",
897 i, wkbox[i], wkbox[i+1]-1, wkbox[i+1]-wkbox[i]);
899 for (i = 0; i < nat; i++)
901 fprintf(debug, "list place %5d by atom %7d\n", i, index[wkatm[i]]);
905 /* calculate surface for all atoms, step cube-wise */
906 for (iz = 0; iz < nzbox; iz++)
912 ize = min(iz+2, izs+nzbox);
917 ize = min(iz+2, nzbox);
919 for (iy = 0; iy < nybox; iy++)
925 iye = min(iy+2, iys+nybox);
930 iye = min(iy+2, nybox);
932 for (ix = 0; ix < nxbox; ix++)
944 ixe = min(ix+2, ixs+nxbox);
949 ixe = min(ix+2, nxbox);
952 /* make intermediate atom list */
953 for (jz = izs; jz < ize; jz++)
955 jjj = ((jz+nzbox) % nzbox)*nxy;
956 for (jy = iys; jy < iye; jy++)
958 jj = ((jy+nybox) % nybox)*nxbox+jjj;
959 for (jx = ixs; jx < ixe; jx++)
961 j = jj+((jx+nxbox) % nxbox);
962 for (jat = wkbox[j]; jat < wkbox[j+1]; jat++)
964 range_check(wkatm[jat], 0, nat);
965 range_check(iiat, 0, nat);
966 wkat1[iiat] = wkatm[jat];
968 } /* end of cycle "jat" */
969 } /* end of cycle "jx" */
970 } /* end of cycle "jy" */
971 } /* end of cycle "jz" */
972 for (iat = iii1; iat < iii2; iat++)
974 i_at = index[wkatm[iat]];
978 xi = pco[XX]; yi = pco[YY]; zi = pco[ZZ];
979 for (i = 0; i < n_dot; i++)
984 ctnb = wknb; nnei = 0;
985 for (j = 0; j < iiat; j++)
987 j_at = index[wkat1[j]];
997 /* Added DvdS 2006-07-19 */
1005 pbc_dx(&pbc,pco,xxi,ddx);*/
1006 pbc_dx(&pbc, coords[j_at], coords[i_at], ddx);
1017 dd = dx*dx+dy*dy+dz*dz;
1027 ctnb->dot = (dd+aisq-ajsq)/(2.*ai); /* reference dot product */
1031 /* check points on accessibility */
1035 for (l = 0; l < n_dot; l++)
1037 if (xus[3*l]*(wknb+last)->x+
1038 xus[1+3*l]*(wknb+last)->y+
1039 xus[2+3*l]*(wknb+last)->z <= (wknb+last)->dot)
1041 for (j = 0; j < nnei; j++)
1043 if (xus[3*l]*(wknb+j)->x+xus[1+3*l]*(wknb+j)->y+
1044 xus[2+3*l]*(wknb+j)->z > (wknb+j)->dot)
1055 } /* end of cycle j */
1056 } /* end of cycle l */
1061 for (l = 0; l < n_dot; l++)
1069 fprintf(debug, "i_ac=%d, dotarea=%8.3f, aisq=%8.3f\n",
1070 i_ac, dotarea, aisq);
1073 a = aisq*dotarea* (real) i_ac;
1075 if (mode & FLAG_ATOM_AREA)
1077 range_check(wkatm[iat], 0, nat);
1078 atom_area[wkatm[iat]] = a;
1080 if (mode & FLAG_DOTS)
1082 for (l = 0; l < n_dot; l++)
1087 if (maxdots <= 3*lfnr+1)
1089 maxdots = maxdots+n_dot*3;
1090 srenew(dots, maxdots);
1092 dots[3*lfnr-3] = ai*xus[3*l]+xi;
1093 dots[3*lfnr-2] = ai*xus[1+3*l]+yi;
1094 dots[3*lfnr-1] = ai*xus[2+3*l]+zi;
1098 if (mode & FLAG_VOLUME)
1100 dx = 0.; dy = 0.; dz = 0.;
1101 for (l = 0; l < n_dot; l++)
1110 vol = vol+aisq*(dx*(xi-xs)+dy*(yi-ys)+dz*(zi-zs)+ai* (real) i_ac);
1113 } /* end of cycle "iat" */
1114 } /* end of cycle "ix" */
1115 } /* end of cycle "iy" */
1116 } /* end of cycle "iz" */
1127 if (mode & FLAG_VOLUME)
1129 vol = vol*FOURPI/(3.* (real) n_dot);
1130 *value_of_vol = vol;
1132 if (mode & FLAG_DOTS)
1137 if (mode & FLAG_ATOM_AREA)
1139 *at_area = atom_area;
1141 *value_of_area = area;
1145 fprintf(debug, "area=%8.3f\n", area);
1157 real co[3*NAT], ra[NAT], area, volume, a, b, c;
1164 fp = fopen("nsc.txt", "w+");
1165 for (i = 1; i <= NAT; i++)
1179 if (i%3 == 0) b=0.5;
1183 ra[i-1] = (1.+j*0.5)*c;
1186 if (NSC(co, ra, NAT, 42, NULL, &area,
1188 if (NSC(co, ra, NAT, 42, NULL, &area,
1189 NULL, NULL, NULL, NULL))
1191 ERROR("error in NSC");
1194 fprintf(fp, "area : %8.3f\n", area);
1197 fprintf(fp, "next call\n");
1201 if (NSC(co, ra, NAT, 42, FLAG_VOLUME | FLAG_ATOM_AREA | FLAG_DOTS, &area,
1205 ERROR("error in NSC");
1209 fprintf(fp, "area : %8.3f\n", area);
1210 printf("area : %8.3f\n", area);
1211 fprintf(fp, "volume : %8.3f\n", volume);
1212 printf("volume : %8.3f\n", volume);
1213 fprintf(fp, "ndots : %8d\n", ndots);
1214 printf("ndots : %8d\n", ndots);
1216 for (i = 1; i <= NAT; i++)
1218 fprintf(fp, "%4d ATOM %7.2f %7.2f %7.2f ra=%4.1f area=%8.3f\n",
1219 i, co[3*i-3], co[3*i-2], co[3*i-1], ra[i-1], at_area[i-1]);
1222 fprintf(fp, "DOTS : %8d\n", ndots);
1223 for (i = 1; i <= ndots; i++)
1225 fprintf(fp, "%4d DOTS %8.2f %8.2f %8.2f\n",
1226 i, dots[3*i-3], dots[3*i-2], dots[3*i-1]);