Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -: 0:Source:cq_uni.c
- -: 0:Graph:cq_uni.gcno
- -: 0:Data:cq_uni.gcda
- -: 0:Runs:2
- -: 0:Programs:1
- -: 1:/**************************************************************************
- -: 2: chibigq.c A simple program to compute the CHI index for an
- -: 3: alpha-quartz crystal lattice.
- -: 4:
- -: 5: mdf 2002-12-04 15:56 UTC Created
- -: 6: tjl 2003-02-20 Implimented IEEE-80 floating point
- -: 7: changed data type real from double to long double
- -: 8: changed Math Lib function calls to their long
- -: 9: equivalents.
- -: 10: ams 2003-05-21 Modified for alpha-quartz crystal lattice.
- -: 11: tjl 2003-05-21 Eliminated program timer, recompiled.
- -: 12: ams 2004-11-28 Modified for benzil crystal lattice, no hydrogens
- -: 13: amm 2005-11-24 Modified for speed by AM Merritt.
- -: 14: ams 2007-08-02 Modified for full benzil unit cell, 78 atoms
- -: 15: ams 2009-06-20 Modified for P3(2) gamma-glycine, 30 atoms
- -: 16: ams 2009-11-12 Modified for P3(2)21 quartz, 9 atoms
- -: 17: smd 2009-12-19 Rewritten in ANSI C for speed (and ease of ASM'ing later)
- -: 18: smd 2009-12-21 Modified for pthread
- -: 19: ***************************************************************************/
- -: 20:
- -: 21:#include <stdio.h>
- -: 22:#include <stdlib.h>
- -: 23:#include <math.h>
- -: 24://#include <pthread.h>
- -: 25:
- -: 26:#define THREADS 4
- -: 27:
- -: 28:/* 18 digits of precision in a long double */
- -: 29:typedef long double real;
- -: 30:
- -: 31:/* bool type */
- -: 32:typedef char boolean;
- -: 33:#define TRUE 1
- -: 34:#define FALSE 0
- -: 35:
- -: 36:/* jacobi transformation of a symmetric 3x3 matrix */
- -: 37:/* this code ripped from my personal library (making it specific to 3x3
- -: 38: matrices, with no eigenvectors), which is in turn ripped from
- -: 39: Numerical Recipies oh so long ago, which was in turn probably ripped
- -: 40: from EISPACK, whose authors no doubt ripped it Jacobi himself,
- -: 41: who ultimately extracted it from the intellectual aether in 1846. */
- 18: 42:void jacobi3(real **A, real (*dest)[3]) {
- -: 43: int i, j, its, p, q;
- -: 44: real sm, g, h, c, s, tau, dp, dq, t, th;
- -: 45: real d[3];
- -: 46: real a[3][3];
- -: 47: real b[3], z[3];
- -: 48:
- -: 49: /* setup initial result */
- 72: 50: for (i = 0; i < 3; ++i)
- 216: 51: for (j = 0; j < 3; ++j)
- 162: 52: a[i][j] = A[i][j];
- -: 53:
- -: 54: /* update vectors */
- 72: 55: for (i = 0; i < 3; ++i) {
- 54: 56: b[i] = d[i] = a[i][i];
- 54: 57: z[i] = 0.0;
- -: 58: }
- -: 59:
- -: 60: /* sweeps */
- 36: 61: for (its = 1; its < 50; ++its) {
- -: 62: /* done? */
- 36: 63: sm = 0.0;
- 108: 64: for (i = 0; i < 2; ++i)
- 180: 65: for (j = i + 1; j < 3; ++j)
- 108: 66: sm += fabsl(a[i][j]);
- -: 67:
- 36: 68: if (sm == 0.0) {
- 18: 69: for (i = 0; i < 3; ++i) (*dest)[i] = d[i];
- -: 70: return;
- -: 71: }
- -: 72:
- -: 73: /* nuke the off-diagonals */
- 54: 74: for (p = 0; p < 2; ++p) {
- 90: 75: for (q = p + 1; q < 3; ++q) {
- 54: 76: g = 100.0 * fabsl(a[p][q]);
- 54: 77: dp = d[p];
- 54: 78: dq = d[q];
- 54: 79: h = dq - dp;
- 54: 80: if ((fabsl(h) + g) != fabsl(h)) {
- 54: 81: th = 0.5 * h / a[p][q];
- 54: 82: t = 1.0 / (fabsl(th) + sqrtl(1.0 + th * th));
- 54: 83: if (th < 0.0) t = -t;
- #####: 84: } else t = a[p][q] / h;
- 54: 85: c = 1.0 / sqrtl(1.0 + t * t);
- 54: 86: s = t * c;
- 54: 87: tau = s / (1.0 + c);
- 54: 88: h = t * a[p][q];
- 54: 89: z[p] -= h;
- 54: 90: z[q] += h;
- 54: 91: d[p] -= h;
- 54: 92: d[q] += h;
- 54: 93: a[p][q] = 0.0;
- 54: 94: for (j = 0; j < p - 1; ++j) {
- #####: 95: g = a[j][p];
- #####: 96: h = a[j][q];
- #####: 97: a[j][p] = g - s * (h + g * tau);
- #####: 98: a[j][q] = h + s * (g - h * tau);
- -: 99: }
- -: 100:
- 54: 101: for (j = p + 1; j < q - 1; ++j) {
- #####: 102: g = a[p][j];
- #####: 103: h = a[j][q];
- #####: 104: a[p][j] = g - s * (h + g * tau);
- #####: 105: a[j][q] = h + s * (g - h * tau);
- -: 106: }
- -: 107:
- 72: 108: for (j = q + 1; j < 3; ++j) {
- 18: 109: g = a[p][j];
- 18: 110: h = a[q][j];
- 18: 111: a[p][j] = g - s * (h + g * tau);
- 18: 112: a[q][j] = h + s * (g - h * tau);
- -: 113: }
- -: 114: }
- -: 115: }
- -: 116:
- 72: 117: for (p = 0; p < 3; ++p) {
- 54: 118: d[p] = (b[p] += z[p]);
- 54: 119: z[p] = 0.0;
- -: 120: }
- -: 121: }
- #####: 122: printf("oh man!\n");
- #####: 123: exit(EXIT_FAILURE);
- -: 124:}
- -: 125:
- -: 126:
- -: 127:/* sums of integers from lo to hi (inclusive) raised to powers 0, 1, and 2 */
- -: 128:#define SUM0(lo, hi) ((real) ((hi) - (lo) + 1))
- -: 129:#define SUM1(lo, hi) (0.5 * (real) ((hi) + (lo)) * SUM0((lo), (hi)))
- -: 130:#define _SUM2(l, h, n) (((n) + 1.0) * (l) * (l) + (l) * ((n) + 1.0) * (n) + (n) * ((n) + 1.0) * (2.0 * (n) + 1.0) / 6.0)
- -: 131:#define SUM2(l, h) _SUM2((l), (h), (h) - (l))
- -: 132:
- -: 133:
- -: 134:/* Print usage info */
- #####: 135:void usage() {
- #####: 136: fprintf(stderr, " Usage: chi base step radius ring \n");
- #####: 137: fprintf(stderr, " Where ring is 0-false or 1-true \n");
- #####: 138:}
- -: 139:
- -: 140:
- 8: 141:void chiqz(real base, real step, real to, real *ANS_A, real *ANS_B, real *ANS_C) {
- -: 142: real dd, S0, S1, S2, dz, temp1, temp2, oN, chi;
- -: 143: real d[3];
- -: 144: int i, j, k, p, nsp;
- -: 145: real r;
- -: 146:
- -: 147: /**************** Lattice *****************/
- -: 148: int lat_i, lat_lo, lat_hi;
- -: 149: real lat_X0, lat_X1;
- -: 150: /* the atom sequencer */
- -: 151: int lat_ia, lat_ib;
- -: 152: int lat_ia_lo, lat_ia_hi, lat_ib_lo, lat_ib_hi;
- -: 153: /* lattice specifics */
- -: 154: real lat_d0, lat_d1;
- -: 155: /**************** Lattice *****************/
- -: 156:
- -: 157: /********** sposes **********/
- -: 158: real *_N; /* atom counter (good to 2^63) long double tjl */
- -: 159: real **_UX; /* mean */
- -: 160: real ***_U; /* the mixed tensor */
- -: 161: /********** sposes **********/
- -: 162:
- -: 163: /* an alpha-quartz crystal lattice generator */
- -: 164: /* lat_R == radius of sphere */
- -: 165: /* lattice specifics */
- 8: 166: const real lat_a = 4.9137;
- 8: 167: const real lat_c = 5.4047;
- 8: 168: const real lat_c0 = -0.50;
- 8: 169: const real lat_c1 = sqrtl(0.750);
- -: 170:
- 8: 171: real lat_atx[9] = {0.4697, 0.0000, -0.4697, 0.4133, -0.2672, -0.1461, 0.2672, 0.1461, -0.4133};
- 8: 172: real lat_aty[9] = {0.0000, 0.4697, -0.4697, 0.2672, 0.1461, -0.4133, 0.4133, -0.2672, -0.1461};
- -: 173: real lat_atz[9] = {1.0 / 6.0, 5.0 / 6.0, 0.5000, 0.1188 + 1.0 / 6.0, 0.1188 + 5.0 / 6.0, 0.6188,
- 8: 174: -0.1188 - 1.0 / 6.0, 1.0 / 6.0 - 0.1188, 0.3812};
- -: 175:
- 8: 176: const real lat_R = to; /* radius */
- 8: 177: const real lat_RR = lat_R * lat_R;
- 8: 178: const real lat_aa = lat_a * lat_a;
- -: 179:
- -: 180: /* fill the spheres */
- 8: 181: nsp = (int) ceill((to - base) / step);
- -: 182: /* Prepare heap for sposes */
- -: 183:
- 8: 184: _N = (real *) malloc(nsp*sizeof(real));
- 8: 185: _UX = (real **) malloc(nsp*sizeof(real*));
- 8: 186: _U = (real ***) malloc(nsp*sizeof(real**));
- 26: 187: for (i = 0; i < nsp; ++i) {
- 18: 188: _UX[i] = (real *) malloc(3*sizeof(real));
- 18: 189: _U[i] = (real **) malloc(3*sizeof(real*));
- 72: 190: for (j = 0; j < 3; ++j) {
- 54: 191: _U[i][j] = (real *) malloc(3*sizeof(real));
- 54: 192: for (k = 0; k < 3; ++k) _U[i][j][k] = 0;
- -: 193: }
- 18: 194: _N[i] = 0.0;
- -: 195: }
- -: 196: /* rewind the generator */
- 8: 197: lat_i = -1;
- 8: 198: lat_ib = lat_ia = lat_ib_hi = lat_ia_hi = 0;
- -: 199: for (;;) {
- -: 200: /* return next line through the lattice */
- -: 201: /* false is returned if there are no more lines */
- 43293500: 202: if (++lat_ib > lat_ib_hi) {
- 67700: 203: if (++lat_ia > lat_ia_hi) {
- 80: 204: if (++lat_i >= 9) break; /* end? */
- -: 205: /* new range for x */
- 72: 206: dd = lat_R / (lat_a * lat_c1);
- 72: 207: lat_ia_hi = (int) floorl(dd - lat_atx[lat_i]);
- 72: 208: lat_ia = (int) ceill(-dd - lat_atx[lat_i]); /* lat_ia_lo */
- -: 209: }
- -: 210: /* precompute coordinate */
- -: 211: lat_d0 = (real) lat_ia + lat_atx[lat_i],
- -: 212: /* new range for y */
- 67692: 213: dd = sqrtl(lat_RR / lat_aa - lat_c1 * lat_c1 * lat_d0 * lat_d0);
- 67692: 214: lat_ib_hi = (int) floorl(-lat_d0 * lat_c0 + dd - lat_aty[lat_i]);
- 67692: 215: lat_ib = (int) ceill(-lat_d0 * lat_c0 - dd - lat_aty[lat_i]); /* lat_ib_lo */
- -: 216: }
- -: 217: /* precompute coordinate */
- 43293492: 218: lat_d1 = (real) lat_ib + lat_aty[lat_i];
- -: 219: /* precompute atom x/y position */
- 43293492: 220: lat_X0 = lat_a * lat_d0 + lat_a * lat_d1 * lat_c0;
- 43293492: 221: lat_X1 = lat_a * lat_d1 * lat_c1;
- -: 222:
- 140700912: 223: for (i = nsp - 1; i >= 0; --i) {
- 97413888: 224: if (i + 1 == nsp) {
- 43293492: 225: r = to;
- -: 226: } else {
- 54120396: 227: r = base + step * (real) (i + 1);
- -: 228: }
- -: 229: /* given a sphere radius, compute the cell endpoints. return false if none. */
- -: 230: /* new range for 'z' */
- 97413888: 231: dd = r * r - lat_X0 * lat_X0 - lat_X1 * lat_X1;
- 97413888: 232: if (dd < 0.0) break;
- 97407420: 233: dd = sqrtl(dd) / lat_c;
- 97407420: 234: lat_lo = (int) ceill(-dd - lat_atz[lat_i]);
- 97407420: 235: lat_hi = (int) floorl(dd - lat_atz[lat_i]);
- -: 236: /* add a line of atoms along the z-axis of the crystal */
- -: 237: /* fill_Spose */
- 97407420: 238: S0 = SUM0(lat_lo, lat_hi);
- 97407420: 239: S1 = SUM1(lat_lo, lat_hi);
- 97407420: 240: S2 = SUM2(lat_lo, lat_hi);
- 97407420: 241: dz = lat_c * lat_atz[lat_i];
- 97407420: 242: temp1 = S0 * lat_X0;
- 97407420: 243: temp2 = S0 * lat_X1;
- 97407420: 244: _N[i] += S0;
- 97407420: 245: _UX[i][0] += temp1;
- 97407420: 246: _UX[i][1] += temp2;
- 97407420: 247: _UX[i][2] += S0 * dz + S1 * lat_c;
- 97407420: 248: _U[i][0][0] += temp1 * lat_X0;
- 97407420: 249: _U[i][0][1] += temp1 * lat_X1;
- 97407420: 250: _U[i][0][2] += temp1 * dz + S1 * lat_X0 * lat_c;
- 97407420: 251: _U[i][1][1] += temp2 * lat_X1;
- 97407420: 252: _U[i][1][2] += temp2 * dz + S1 * lat_X1 * lat_c;
- 97407420: 253: _U[i][2][2] += S0 * dz * dz + 2.0 * lat_c * dz * S1 + lat_c * lat_c * S2;
- -: 254: }
- -: 255: }
- -: 256: /* emit answers */
- 26: 257: for (i = 0; i < nsp; ++i) {
- -: 258: /* declare the input done: finalize the U tensor */
- -: 259: /* centre the U */
- 18: 260: oN = (_N[i] == 0.0) ? 0.0 : 1.0 / _N[i];
- 18: 261: _U[i][0][0] -= oN * _UX[i][0] * _UX[i][0];
- 18: 262: _U[i][1][0] = (_U[i][0][1] -= oN * _UX[i][0] * _UX[i][1]);
- 18: 263: _U[i][2][0] = (_U[i][0][2] -= oN * _UX[i][0] * _UX[i][2]);
- 18: 264: _U[i][1][1] -= oN * _UX[i][1] * _UX[i][1];
- 18: 265: _U[i][2][1] = (_U[i][1][2] -= oN * _UX[i][1] * _UX[i][2]);
- 18: 266: _U[i][2][2] -= oN * _UX[i][2] * _UX[i][2];
- -: 267: /* compute the CHI for the crystal against its 3D enantiomer */
- 18: 268: p = 0;
- 18: 269: jacobi3(_U[i], &d); /* extract eigenvalues */
- 18: 270: for (j = 1; j < 3; ++j) if (d[j] < d[p]) p = j; /* find the smallest */
- 18: 271: chi = 3.0 * d[p] / (_U[i][0][0] + _U[i][1][1] + _U[i][2][2]); /* the CHI is: */
- -: 272:
- -: 273: //printf("%10.3Lf %20.14Lg %20.18Lf\n", (i + 1 == nsp) ? to : base + step * (real) (i + 1), _N[i], chi);
- 18: 274: ANS_A[i] = (i + 1 == nsp) ? to : base + step * (real) (i + 1);
- 18: 275: ANS_B[i] = _N[i];
- 18: 276: ANS_C[i] = chi;
- -: 277: }
- -: 278:
- 8: 279:}
- -: 280:
- -: 281:
- 2: 282:int main(int argc, char **argv) { /* handle the command line */
- -: 283: int i;
- -: 284: real base, to, step;
- -: 285: boolean ring;
- -: 286: int idx;
- -: 287: int nsp;
- -: 288: /* Units per thread */
- -: 289: real t_step, t_base;
- -: 290:
- -: 291: /* Answers */
- -: 292: real *ANS_A, *ANS_B, *ANS_C;
- -: 293:
- -: 294: /* enforce the Rules and Regulations */
- 2: 295: if (argc != 5) {
- #####: 296: usage();
- #####: 297: return EXIT_FAILURE;
- -: 298: }
- -: 299:
- 2: 300: base = atof(argv[1]);
- 2: 301: step = atof(argv[2]);
- 2: 302: to = atof(argv[3]);
- 2: 303: ring = (boolean) atoi(argv[4]);
- -: 304:
- 2: 305: printf("\n");
- -: 306:
- -: 307: /* desired computation */
- 2: 308: if (ring) {
- -: 309: //chiqz(base, step, to);
- 2: 310: nsp = (int) ceill((to - base) / step);
- 2: 311: ANS_A = (real *) malloc(nsp*sizeof(real));
- 2: 312: ANS_B = (real *) malloc(nsp*sizeof(real));
- 2: 313: ANS_C = (real *) malloc(nsp*sizeof(real));
- 2: 314: t_step = (nsp / THREADS) * step;
- 2: 315: t_base = base;
- -: 316: /*
- -: 317: printf("nsp=%d\n", nsp);
- -: 318: printf("THREADS=%d\n", THREADS);
- -: 319: printf("step=%10.3Lf\n", step);
- -: 320: printf("t_step=%10.3Lf\n", t_step);
- -: 321: */
- -: 322:
- 8: 323: for (i = 0; i < THREADS - 1; i++) {
- -: 324: /* printf("t#%d: base=%10.3Lf to=%10.3Lf\n", i, t_base, t_base + t_step); */
- 6: 325: idx = (nsp / THREADS)*i;
- 6: 326: chiqz(t_base, step, t_base + t_step, &(ANS_A[idx]), &(ANS_B[idx]), &(ANS_C[idx]));
- 6: 327: t_base += t_step;
- -: 328: };
- -: 329: /* printf("t#%d: base=%10.3Lf to=%10.3Lf\n", THREADS, t_base, to); */
- 2: 330: idx = (nsp / THREADS)*i;
- 2: 331: chiqz(t_base, step, to, &(ANS_A[idx]), &(ANS_B[idx]), &(ANS_C[idx]));
- -: 332:
- 20: 333: for (i = 0; i < nsp; i++) {
- 18: 334: printf("%10.3Lf %20.14Lg %20.18Lf\n", ANS_A[i], ANS_B[i], ANS_C[i]);
- -: 335: }
- -: 336:
- -: 337: } else { /* just one */
- -: 338: //chiqz(to - step, step, to);
- -: 339: }
- 2: 340: return EXIT_SUCCESS;
- -: 341:}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement