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.
46 #include "gromacs/pbcutil/pbc.h"
47 #include "gromacs/legacyheaders/macros.h"
48 #include "gromacs/math/vec.h"
49 #include "gromacs/utility/smalloc.h"
58 #define UNSP_ICO_DOD 9
59 #define UNSP_ICO_ARC 10
63 int n_dot, ico_cube, last_n_dot = 0, last_densit = 0, last_unsp = 0;
66 #define FOURPI (4.*M_PI)
67 #define TORAD(A) ((A)*0.017453293)
70 #define UPDATE_FL __file__ = __FILE__, __line__ = __LINE__
71 const char * __file__; /* declared versions of macros */
72 int __line__; /* __FILE__ and __LINE__ */
77 #define ERROR UPDATE_FL, error
78 void error(const char *fmt, ...)
82 "\n---> ERROR when executing line %i in file %s !\n",
85 vfprintf(stderr, fmt, args);
87 fprintf(stderr, "\n---> Execution stopped !\n\n");
90 #define WARNING UPDATE_FL, warning2
91 void warning2(const char *fmt, ...)
95 "\n---> WARNING : line %i in file %s\n",
98 vfprintf(stderr, fmt, args);
100 fprintf(stderr, " ...!\n\n");
105 #define ASIN safe_asin
106 real safe_asin(real f)
108 if ( (fabs(f) < 1.00) )
112 if ( (fabs(f) - 1.00) <= DP_TOL)
114 ERROR("ASIN : invalid argument %f", f);
122 /* routines for dot distributions on the surface of the unit sphere */
125 void icosaeder_vertices(real *xus)
127 rh = sqrt(1.-2.*cos(TORAD(72.)))/(1.-cos(TORAD(72.)));
128 rg = cos(TORAD(72.))/(1.-cos(TORAD(72.)));
129 /* icosaeder vertices */
130 xus[ 0] = 0.; xus[ 1] = 0.; xus[ 2] = 1.;
131 xus[ 3] = rh*cos(TORAD(72.)); xus[ 4] = rh*sin(TORAD(72.)); xus[ 5] = rg;
132 xus[ 6] = rh*cos(TORAD(144.)); xus[ 7] = rh*sin(TORAD(144.)); xus[ 8] = rg;
133 xus[ 9] = rh*cos(TORAD(216.)); xus[10] = rh*sin(TORAD(216.)); xus[11] = rg;
134 xus[12] = rh*cos(TORAD(288.)); xus[13] = rh*sin(TORAD(288.)); xus[14] = rg;
135 xus[15] = rh; xus[16] = 0; xus[17] = rg;
136 xus[18] = rh*cos(TORAD(36.)); xus[19] = rh*sin(TORAD(36.)); xus[20] = -rg;
137 xus[21] = rh*cos(TORAD(108.)); xus[22] = rh*sin(TORAD(108.)); xus[23] = -rg;
138 xus[24] = -rh; xus[25] = 0; xus[26] = -rg;
139 xus[27] = rh*cos(TORAD(252.)); xus[28] = rh*sin(TORAD(252.)); xus[29] = -rg;
140 xus[30] = rh*cos(TORAD(324.)); xus[31] = rh*sin(TORAD(324.)); xus[32] = -rg;
141 xus[33] = 0.; xus[34] = 0.; xus[35] = -1.;
145 void divarc(real x1, real y1, real z1,
146 real x2, real y2, real z2,
147 int div1, int div2, real *xr, real *yr, real *zr)
150 real xd, yd, zd, dd, d1, d2, s, x, y, z;
151 real phi, sphi, cphi;
156 dd = sqrt(xd*xd+yd*yd+zd*zd);
159 ERROR("divarc: rotation axis of length %f", dd);
162 d1 = x1*x1+y1*y1+z1*z1;
165 ERROR("divarc: vector 1 of sq.length %f", d1);
167 d2 = x2*x2+y2*y2+z2*z2;
170 ERROR("divarc: vector 2 of sq.length %f", d2);
173 phi = ASIN(dd/sqrt(d1*d2));
174 phi = phi*((real)div1)/((real)div2);
175 sphi = sin(phi); cphi = cos(phi);
176 s = (x1*xd+y1*yd+z1*zd)/dd;
178 x = xd*s*(1.-cphi)/dd + x1 * cphi + (yd*z1-y1*zd)*sphi/dd;
179 y = yd*s*(1.-cphi)/dd + y1 * cphi + (zd*x1-z1*xd)*sphi/dd;
180 z = zd*s*(1.-cphi)/dd + z1 * cphi + (xd*y1-x1*yd)*sphi/dd;
181 dd = sqrt(x*x+y*y+z*z);
182 *xr = x/dd; *yr = y/dd; *zr = z/dd;
185 int ico_dot_arc(int densit) /* densit...required dots per unit sphere */
187 /* dot distribution on a unit sphere based on an icosaeder *
188 * great circle average refining of icosahedral face */
190 int i, j, k, tl, tl2, tn, tess;
191 real a, d, x, y, z, x2, y2, z2, x3, y3, z3;
192 real xij, yij, zij, xji, yji, zji, xik, yik, zik, xki, yki, zki,
193 xjk, yjk, zjk, xkj, ykj, zkj;
196 /* calculate tessalation level */
197 a = sqrt((((real) densit)-2.)/10.);
198 tess = (int) ceil(a);
199 n_dot = 10*tess*tess+2;
202 ERROR("ico_dot_arc: error in formula for tessalation level (%d->%d, %d)",
203 tess, n_dot, densit);
208 icosaeder_vertices(xus);
213 a = rh*rh*2.*(1.-cos(TORAD(72.)));
214 /* calculate tessalation of icosaeder edges */
215 for (i = 0; i < 11; i++)
217 for (j = i+1; j < 12; j++)
219 x = xus[3*i]-xus[3*j];
220 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
222 if (fabs(a-d) > DP_TOL)
226 for (tl = 1; tl < tess; tl++)
230 ERROR("ico_dot: tn exceeds dimension of xus");
232 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
233 xus[3*j], xus[1+3*j], xus[2+3*j],
234 tl, tess, &xus[3*tn], &xus[1+3*tn], &xus[2+3*tn]);
239 /* calculate tessalation of icosaeder faces */
240 for (i = 0; i < 10; i++)
242 for (j = i+1; j < 11; j++)
244 x = xus[3*i]-xus[3*j];
245 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
247 if (fabs(a-d) > DP_TOL)
252 for (k = j+1; k < 12; k++)
254 x = xus[3*i]-xus[3*k];
255 y = xus[1+3*i]-xus[1+3*k]; z = xus[2+3*i]-xus[2+3*k];
257 if (fabs(a-d) > DP_TOL)
261 x = xus[3*j]-xus[3*k];
262 y = xus[1+3*j]-xus[1+3*k]; z = xus[2+3*j]-xus[2+3*k];
264 if (fabs(a-d) > DP_TOL)
268 for (tl = 1; tl < tess-1; tl++)
270 divarc(xus[3*j], xus[1+3*j], xus[2+3*j],
271 xus[3*i], xus[1+3*i], xus[2+3*i],
272 tl, tess, &xji, &yji, &zji);
273 divarc(xus[3*k], xus[1+3*k], xus[2+3*k],
274 xus[3*i], xus[1+3*i], xus[2+3*i],
275 tl, tess, &xki, &yki, &zki);
277 for (tl2 = 1; tl2 < tess-tl; tl2++)
279 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
280 xus[3*j], xus[1+3*j], xus[2+3*j],
281 tl2, tess, &xij, &yij, &zij);
282 divarc(xus[3*k], xus[1+3*k], xus[2+3*k],
283 xus[3*j], xus[1+3*j], xus[2+3*j],
284 tl2, tess, &xkj, &ykj, &zkj);
285 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
286 xus[3*k], xus[1+3*k], xus[2+3*k],
287 tess-tl-tl2, tess, &xik, &yik, &zik);
288 divarc(xus[3*j], xus[1+3*j], xus[2+3*j],
289 xus[3*k], xus[1+3*k], xus[2+3*k],
290 tess-tl-tl2, tess, &xjk, &yjk, &zjk);
293 ERROR("ico_dot: tn exceeds dimension of xus");
295 divarc(xki, yki, zki, xji, yji, zji, tl2, tess-tl,
297 divarc(xkj, ykj, zkj, xij, yij, zij, tl, tess-tl2,
299 divarc(xjk, yjk, zjk, xik, yik, zik, tl, tl+tl2,
301 x = x+x2+x3; y = y+y2+y3; z = z+z2+z3;
302 d = sqrt(x*x+y*y+z*z);
314 ERROR("ico_dot: n_dot(%d) and tn(%d) differ", n_dot, tn);
316 } /* end of if (tess > 1) */
319 } /* end of routine ico_dot_arc */
321 int ico_dot_dod(int densit) /* densit...required dots per unit sphere */
323 /* dot distribution on a unit sphere based on an icosaeder *
324 * great circle average refining of icosahedral face */
326 int i, j, k, tl, tl2, tn, tess, j1, j2;
327 real a, d, x, y, z, x2, y2, z2, x3, y3, z3, ai_d, adod;
328 real xij, yij, zij, xji, yji, zji, xik, yik, zik, xki, yki, zki,
329 xjk, yjk, zjk, xkj, ykj, zkj;
331 /* calculate tesselation level */
332 a = sqrt((((real) densit)-2.)/30.);
333 tess = max((int) ceil(a), 1);
334 n_dot = 30*tess*tess+2;
337 ERROR("ico_dot_dod: error in formula for tessalation level (%d->%d, %d)",
338 tess, n_dot, densit);
343 icosaeder_vertices(xus);
346 /* square of the edge of an icosaeder */
347 a = rh*rh*2.*(1.-cos(TORAD(72.)));
348 /* dodecaeder vertices */
349 for (i = 0; i < 10; i++)
351 for (j = i+1; j < 11; j++)
353 x = xus[3*i]-xus[3*j];
354 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
356 if (fabs(a-d) > DP_TOL)
360 for (k = j+1; k < 12; k++)
362 x = xus[3*i]-xus[3*k];
363 y = xus[1+3*i]-xus[1+3*k]; z = xus[2+3*i]-xus[2+3*k];
365 if (fabs(a-d) > DP_TOL)
369 x = xus[3*j]-xus[3*k];
370 y = xus[1+3*j]-xus[1+3*k]; z = xus[2+3*j]-xus[2+3*k];
372 if (fabs(a-d) > DP_TOL)
376 x = xus[ 3*i]+xus[ 3*j]+xus[ 3*k];
377 y = xus[1+3*i]+xus[1+3*j]+xus[1+3*k];
378 z = xus[2+3*i]+xus[2+3*j]+xus[2+3*k];
379 d = sqrt(x*x+y*y+z*z);
380 xus[3*tn] = x/d; xus[1+3*tn] = y/d; xus[2+3*tn] = z/d;
389 /* square of the edge of an dodecaeder */
390 adod = 4.*(cos(TORAD(108.))-cos(TORAD(120.)))/(1.-cos(TORAD(120.)));
391 /* square of the distance of two adjacent vertices of ico- and dodecaeder */
392 ai_d = 2.*(1.-sqrt(1.-a/3.));
394 /* calculate tessalation of mixed edges */
395 for (i = 0; i < 31; i++)
397 j1 = 12; j2 = 32; a = ai_d;
402 for (j = j1; j < j2; j++)
404 x = xus[3*i]-xus[3*j];
405 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
407 if (fabs(a-d) > DP_TOL)
411 for (tl = 1; tl < tess; tl++)
415 ERROR("ico_dot: tn exceeds dimension of xus");
417 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
418 xus[3*j], xus[1+3*j], xus[2+3*j],
419 tl, tess, &xus[3*tn], &xus[1+3*tn], &xus[2+3*tn]);
424 /* calculate tessalation of pentakisdodecahedron faces */
425 for (i = 0; i < 12; i++)
427 for (j = 12; j < 31; j++)
429 x = xus[3*i]-xus[3*j];
430 y = xus[1+3*i]-xus[1+3*j]; z = xus[2+3*i]-xus[2+3*j];
432 if (fabs(ai_d-d) > DP_TOL)
437 for (k = j+1; k < 32; k++)
439 x = xus[3*i]-xus[3*k];
440 y = xus[1+3*i]-xus[1+3*k]; z = xus[2+3*i]-xus[2+3*k];
442 if (fabs(ai_d-d) > DP_TOL)
446 x = xus[3*j]-xus[3*k];
447 y = xus[1+3*j]-xus[1+3*k]; z = xus[2+3*j]-xus[2+3*k];
449 if (fabs(adod-d) > DP_TOL)
453 for (tl = 1; tl < tess-1; tl++)
455 divarc(xus[3*j], xus[1+3*j], xus[2+3*j],
456 xus[3*i], xus[1+3*i], xus[2+3*i],
457 tl, tess, &xji, &yji, &zji);
458 divarc(xus[3*k], xus[1+3*k], xus[2+3*k],
459 xus[3*i], xus[1+3*i], xus[2+3*i],
460 tl, tess, &xki, &yki, &zki);
462 for (tl2 = 1; tl2 < tess-tl; tl2++)
464 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
465 xus[3*j], xus[1+3*j], xus[2+3*j],
466 tl2, tess, &xij, &yij, &zij);
467 divarc(xus[3*k], xus[1+3*k], xus[2+3*k],
468 xus[3*j], xus[1+3*j], xus[2+3*j],
469 tl2, tess, &xkj, &ykj, &zkj);
470 divarc(xus[3*i], xus[1+3*i], xus[2+3*i],
471 xus[3*k], xus[1+3*k], xus[2+3*k],
472 tess-tl-tl2, tess, &xik, &yik, &zik);
473 divarc(xus[3*j], xus[1+3*j], xus[2+3*j],
474 xus[3*k], xus[1+3*k], xus[2+3*k],
475 tess-tl-tl2, tess, &xjk, &yjk, &zjk);
478 ERROR("ico_dot: tn exceeds dimension of xus");
480 divarc(xki, yki, zki, xji, yji, zji, tl2, tess-tl,
482 divarc(xkj, ykj, zkj, xij, yij, zij, tl, tess-tl2,
484 divarc(xjk, yjk, zjk, xik, yik, zik, tl, tl+tl2,
486 x = x+x2+x3; y = y+y2+y3; z = z+z2+z3;
487 d = sqrt(x*x+y*y+z*z);
499 ERROR("ico_dot: n_dot(%d) and tn(%d) differ", n_dot, tn);
501 } /* end of if (tess > 1) */
504 } /* end of routine ico_dot_dod */
506 int unsp_type(int densit)
510 while (10*i1*i1+2 < densit)
515 while (30*i2*i2+2 < densit)
519 if (10*i1*i1-2 < 30*i2*i2-2)
529 int make_unsp(int densit, int mode, int * num_dot, int cubus)
531 int *ico_wk, *ico_pt;
532 int ndot, ico_cube_cb, i, j, k, l, ijk, tn, tl, tl2;
546 if (mode == UNSP_ICO_ARC)
548 ndot = ico_dot_arc(densit);
550 else if (mode == UNSP_ICO_DOD)
552 ndot = ico_dot_dod(densit);
556 WARNING("make_unsp: mode %c%d not allowed", (k) ? '+' : '-', mode);
560 last_n_dot = ndot; last_densit = densit; last_unsp = mode;
561 *num_dot = ndot; if (k)
566 /* in the following the dots of the unit sphere may be resorted */
567 last_unsp = -last_unsp;
569 /* determine distribution of points in elementary cubes */
578 while (i*i*i*2 < ndot)
582 ico_cube = max(i-1, 0);
584 ico_cube_cb = ico_cube*ico_cube*ico_cube;
585 del_cube = 2./((real)ico_cube);
588 for (l = 0; l < ndot; l++)
590 i = max((int) floor((1.+xus[3*l])/del_cube), 0);
595 j = max((int) floor((1.+xus[1+3*l])/del_cube), 0);
600 k = max((int) floor((1.+xus[2+3*l])/del_cube), 0);
605 ijk = i+j*ico_cube+k*ico_cube*ico_cube;
609 snew(ico_wk, 2*ico_cube_cb+1);
611 ico_pt = ico_wk+ico_cube_cb;
612 for (l = 0; l < ndot; l++)
614 ico_wk[work[l]]++; /* dots per elementary cube */
617 /* reordering of the coordinate array in accordance with box number */
619 for (i = 0; i < ico_cube; i++)
621 for (j = 0; j < ico_cube; j++)
623 for (k = 0; k < ico_cube; k++)
627 ijk = i+ico_cube*j+ico_cube*ico_cube*k;
629 for (l = tl2; l < ndot; l++)
633 x = xus[3*l]; y = xus[1+3*l]; z = xus[2+3*l];
634 xus[3*l] = xus[3*tn];
635 xus[1+3*l] = xus[1+3*tn]; xus[2+3*l] = xus[2+3*tn];
636 xus[3*tn] = x; xus[1+3*tn] = y; xus[2+3*tn] = z;
637 ijk = work[l]; work[l] = work[tn]; work[tn] = ijk;
652 typedef struct _stwknb {
659 int nsc_dclm_pbc(const rvec *coords, real *radius, int nat,
660 int densit, int mode,
661 real *value_of_area, real **at_area,
663 real **lidots, int *nu_dots,
664 atom_id index[], int ePBC, matrix box)
666 int iat, i, ii, iii, ix, iy, iz, ixe, ixs, iye, iys, ize, izs, i_ac;
667 int jat, j, jj, jjj, jx, jy, jz;
670 int maxnei, nnei, last, maxdots = 0;
671 int *wkdot = NULL, *wkbox = NULL, *wkat1 = NULL, *wkatm = NULL;
673 int iii1, iii2, iiat, lfnr = 0, i_at, j_at;
674 real dx, dy, dz, dd, ai, aisq, ajsq, aj, as, a;
675 real xi, yi, zi, xs = 0., ys = 0., zs = 0.;
676 real dotarea, area, vol = 0.;
677 real *xus, *dots = NULL, *atom_area = NULL;
678 int nxbox, nybox, nzbox, nxy, nxyz;
679 real xmin = 0, ymin = 0, zmin = 0, xmax, ymax, zmax, ra2max, d;
681 /* Added DvdS 2006-07-19 */
686 distribution = unsp_type(densit);
687 if (distribution != -last_unsp || last_cubus != 4 ||
688 (densit != last_densit && densit != last_n_dot))
690 if (make_unsp(densit, (-distribution), &n_dot, 4))
697 dotarea = FOURPI/(real) n_dot;
702 fprintf(debug, "nsc_dclm: n_dot=%5d %9.3f\n", n_dot, dotarea);
705 /* start with neighbour list */
706 /* calculate neighbour list with the box algorithm */
709 WARNING("nsc_dclm: no surface atoms selected");
712 if (mode & FLAG_VOLUME)
716 if (mode & FLAG_DOTS)
718 maxdots = (3*n_dot*nat)/10;
719 /* should be set to NULL on first user call */
726 srenew(dots, maxdots);
731 if (mode & FLAG_ATOM_AREA)
733 /* should be set to NULL on first user call */
734 if (atom_area == NULL)
736 snew(atom_area, nat);
740 srenew(atom_area, nat);
744 /* Compute minimum size for grid cells */
745 ra2max = radius[index[0]];
746 for (iat_xx = 1; (iat_xx < nat); iat_xx++)
749 ra2max = max(ra2max, radius[iat]);
753 /* Added DvdS 2006-07-19 */
754 /* Updated 2008-10-09 */
757 set_pbc(&pbc, ePBC, box);
759 for (i = 0; (i < nat); i++)
762 copy_rvec(coords[iat], x[i]);
764 put_atoms_in_triclinic_unitcell(ecenterTRIC, box, nat, x);
765 nxbox = max(1, floor(norm(box[XX])/ra2max));
766 nybox = max(1, floor(norm(box[YY])/ra2max));
767 nzbox = max(1, floor(norm(box[ZZ])/ra2max));
770 fprintf(debug, "nbox = %d, %d, %d\n", nxbox, nybox, nzbox);
775 /* dimensions of atomic set, cell edge is 2*ra_max */
777 xmin = coords[iat][XX]; xmax = xmin; xs = xmin;
778 ymin = coords[iat][YY]; ymax = ymin; ys = ymin;
779 zmin = coords[iat][ZZ]; zmax = zmin; zs = zmin;
781 for (iat_xx = 1; (iat_xx < nat); iat_xx++)
785 xmin = min(xmin, *pco); xmax = max(xmax, *pco);
786 ymin = min(ymin, *(pco+1)); ymax = max(ymax, *(pco+1));
787 zmin = min(zmin, *(pco+2)); zmax = max(zmax, *(pco+2));
788 xs = xs+ *pco; ys = ys+ *(pco+1); zs = zs+ *(pco+2);
795 fprintf(debug, "nsc_dclm: n_dot=%5d ra2max=%9.3f %9.3f\n", n_dot, ra2max, dotarea);
798 d = xmax-xmin; nxbox = (int) max(ceil(d/ra2max), 1.);
799 d = (((real)nxbox)*ra2max-d)/2.;
800 xmin = xmin-d; xmax = xmax+d;
801 d = ymax-ymin; nybox = (int) max(ceil(d/ra2max), 1.);
802 d = (((real)nybox)*ra2max-d)/2.;
803 ymin = ymin-d; ymax = ymax+d;
804 d = zmax-zmin; nzbox = (int) max(ceil(d/ra2max), 1.);
805 d = (((real)nzbox)*ra2max-d)/2.;
806 zmin = zmin-d; zmax = zmax+d;
812 /* box number of atoms */
824 for (i = 0; (i < nat); i++)
826 mvmul(box_1, x[i], x_1);
827 ix = ((int)floor(x_1[XX]*nxbox) + 2*nxbox) % nxbox;
828 iy = ((int)floor(x_1[YY]*nybox) + 2*nybox) % nybox;
829 iz = ((int)floor(x_1[ZZ]*nzbox) + 2*nzbox) % nzbox;
830 j = ix + iy*nxbox + iz*nxbox*nybox;
833 fprintf(debug, "Atom %d cell index %d. x = (%8.3f,%8.3f,%8.3f) fc = (%8.3f,%8.3f,%8.3f)\n",
834 i, j, x[i][XX], x[i][YY], x[i][ZZ], x_1[XX], x_1[YY], x_1[ZZ]);
836 range_check(j, 0, nxyz);
843 /* Put the atoms in their boxes */
844 for (iat_xx = 0; (iat_xx < nat); iat_xx++)
848 i = (int) max(floor((pco[XX]-xmin)/ra2max), 0);
850 j = (int) max(floor((pco[YY]-ymin)/ra2max), 0);
852 l = (int) max(floor((pco[ZZ]-zmin)/ra2max), 0);
860 /* sorting of atoms in accordance with box numbers */
862 for (i = 1; i < nxyz; i++)
864 j = max(wkbox[i], j);
866 for (i = 1; i <= nxyz; i++)
868 wkbox[i] += wkbox[i-1];
871 /* maxnei = (int) floor(ra2max*ra2max*ra2max*0.5); */
872 maxnei = min(nat, 27*j);
874 for (iat_xx = 0; iat_xx < nat; iat_xx++)
877 range_check(wkat1[iat_xx], 0, nxyz);
878 wkatm[--wkbox[wkat1[iat_xx]]] = iat_xx;
881 fprintf(debug, "atom %5d on place %5d\n", iat, wkbox[wkat1[iat_xx]]);
887 fprintf(debug, "nsc_dclm: n_dot=%5d ra2max=%9.3f %9.3f\n",
888 n_dot, ra2max, dotarea);
889 fprintf(debug, "neighbour list calculated/box(xyz):%d %d %d\n",
890 nxbox, nybox, nzbox);
892 for (i = 0; i < nxyz; i++)
894 fprintf(debug, "box %6d : atoms %4d-%4d %5d\n",
895 i, wkbox[i], wkbox[i+1]-1, wkbox[i+1]-wkbox[i]);
897 for (i = 0; i < nat; i++)
899 fprintf(debug, "list place %5d by atom %7d\n", i, index[wkatm[i]]);
903 /* calculate surface for all atoms, step cube-wise */
904 for (iz = 0; iz < nzbox; iz++)
910 ize = min(iz+2, izs+nzbox);
915 ize = min(iz+2, nzbox);
917 for (iy = 0; iy < nybox; iy++)
923 iye = min(iy+2, iys+nybox);
928 iye = min(iy+2, nybox);
930 for (ix = 0; ix < nxbox; ix++)
942 ixe = min(ix+2, ixs+nxbox);
947 ixe = min(ix+2, nxbox);
950 /* make intermediate atom list */
951 for (jz = izs; jz < ize; jz++)
953 jjj = ((jz+nzbox) % nzbox)*nxy;
954 for (jy = iys; jy < iye; jy++)
956 jj = ((jy+nybox) % nybox)*nxbox+jjj;
957 for (jx = ixs; jx < ixe; jx++)
959 j = jj+((jx+nxbox) % nxbox);
960 for (jat = wkbox[j]; jat < wkbox[j+1]; jat++)
962 range_check(wkatm[jat], 0, nat);
963 range_check(iiat, 0, nat);
964 wkat1[iiat] = wkatm[jat];
966 } /* end of cycle "jat" */
967 } /* end of cycle "jx" */
968 } /* end of cycle "jy" */
969 } /* end of cycle "jz" */
970 for (iat = iii1; iat < iii2; iat++)
972 i_at = index[wkatm[iat]];
976 xi = pco[XX]; yi = pco[YY]; zi = pco[ZZ];
977 for (i = 0; i < n_dot; i++)
982 ctnb = wknb; nnei = 0;
983 for (j = 0; j < iiat; j++)
985 j_at = index[wkat1[j]];
995 /* Added DvdS 2006-07-19 */
1003 pbc_dx(&pbc,pco,xxi,ddx);*/
1004 pbc_dx(&pbc, coords[j_at], coords[i_at], ddx);
1015 dd = dx*dx+dy*dy+dz*dz;
1025 ctnb->dot = (dd+aisq-ajsq)/(2.*ai); /* reference dot product */
1029 /* check points on accessibility */
1033 for (l = 0; l < n_dot; l++)
1035 if (xus[3*l]*(wknb+last)->x+
1036 xus[1+3*l]*(wknb+last)->y+
1037 xus[2+3*l]*(wknb+last)->z <= (wknb+last)->dot)
1039 for (j = 0; j < nnei; j++)
1041 if (xus[3*l]*(wknb+j)->x+xus[1+3*l]*(wknb+j)->y+
1042 xus[2+3*l]*(wknb+j)->z > (wknb+j)->dot)
1053 } /* end of cycle j */
1054 } /* end of cycle l */
1059 for (l = 0; l < n_dot; l++)
1067 fprintf(debug, "i_ac=%d, dotarea=%8.3f, aisq=%8.3f\n",
1068 i_ac, dotarea, aisq);
1071 a = aisq*dotarea* (real) i_ac;
1073 if (mode & FLAG_ATOM_AREA)
1075 range_check(wkatm[iat], 0, nat);
1076 atom_area[wkatm[iat]] = a;
1078 if (mode & FLAG_DOTS)
1080 for (l = 0; l < n_dot; l++)
1085 if (maxdots <= 3*lfnr+1)
1087 maxdots = maxdots+n_dot*3;
1088 srenew(dots, maxdots);
1090 dots[3*lfnr-3] = ai*xus[3*l]+xi;
1091 dots[3*lfnr-2] = ai*xus[1+3*l]+yi;
1092 dots[3*lfnr-1] = ai*xus[2+3*l]+zi;
1096 if (mode & FLAG_VOLUME)
1098 dx = 0.; dy = 0.; dz = 0.;
1099 for (l = 0; l < n_dot; l++)
1108 vol = vol+aisq*(dx*(xi-xs)+dy*(yi-ys)+dz*(zi-zs)+ai* (real) i_ac);
1111 } /* end of cycle "iat" */
1112 } /* end of cycle "ix" */
1113 } /* end of cycle "iy" */
1114 } /* end of cycle "iz" */
1125 if (mode & FLAG_VOLUME)
1127 vol = vol*FOURPI/(3.* (real) n_dot);
1128 *value_of_vol = vol;
1130 if (mode & FLAG_DOTS)
1135 if (mode & FLAG_ATOM_AREA)
1137 *at_area = atom_area;
1139 *value_of_area = area;
1143 fprintf(debug, "area=%8.3f\n", area);
1155 real co[3*NAT], ra[NAT], area, volume, a, b, c;
1162 fp = fopen("nsc.txt", "w+");
1163 for (i = 1; i <= NAT; i++)
1177 if (i%3 == 0) b=0.5;
1181 ra[i-1] = (1.+j*0.5)*c;
1184 if (NSC(co, ra, NAT, 42, NULL, &area,
1186 if (NSC(co, ra, NAT, 42, NULL, &area,
1187 NULL, NULL, NULL, NULL))
1189 ERROR("error in NSC");
1192 fprintf(fp, "area : %8.3f\n", area);
1195 fprintf(fp, "next call\n");
1199 if (NSC(co, ra, NAT, 42, FLAG_VOLUME | FLAG_ATOM_AREA | FLAG_DOTS, &area,
1203 ERROR("error in NSC");
1207 fprintf(fp, "area : %8.3f\n", area);
1208 printf("area : %8.3f\n", area);
1209 fprintf(fp, "volume : %8.3f\n", volume);
1210 printf("volume : %8.3f\n", volume);
1211 fprintf(fp, "ndots : %8d\n", ndots);
1212 printf("ndots : %8d\n", ndots);
1214 for (i = 1; i <= NAT; i++)
1216 fprintf(fp, "%4d ATOM %7.2f %7.2f %7.2f ra=%4.1f area=%8.3f\n",
1217 i, co[3*i-3], co[3*i-2], co[3*i-1], ra[i-1], at_area[i-1]);
1220 fprintf(fp, "DOTS : %8d\n", ndots);
1221 for (i = 1; i <= ndots; i++)
1223 fprintf(fp, "%4d DOTS %8.2f %8.2f %8.2f\n",
1224 i, dots[3*i-3], dots[3*i-2], dots[3*i-1]);