/* Copyright (C) 1989, California Institute of Technology */ /* All rights reserved. U. S. Government Sponsorship under */ /* NASA Contract NAS7-918 is acknowledged. */ /* Herbert M. Pickett, 20 March 1989 */ /* 18 Aug. 2003: code cleanup, @comment@ is for splint */ #include #include #include #include #include "calpgm.h" #include "ftran.h" #include "readopt.h" #define MYDEBUG 0 #define MYDEBUG_EIG 0 #define NLABL 10 #define NFT 20 #define MPE 1 /* potntial egy multiplied by -0.5 */ #define MWN 2 /* wave number units */ #define MREV 4 /* primary operator has vx = 1 */ #define MV12 8 /* operator abs(nv) >= 25 */ #define MHAM 16 /* parameter is in hamiltonian */ #define ND2TOP 7 #define ODD(x) (((x) & 1) != 0) typedef struct sxpec { /*@owned@*/ /*@null@*/ double *xpec; /* vector of expectation values */ double xval; /* sum of parameter values used in Hamiltonian */ int nval, mval, kdel, ixvib, isunit; /* for first element, nval = nsym, mval = max(m)/nsym, kdel = number of parameters in Hamiltonian ixvib = number of extra vibrations isunit = number of parameter types */ } SXPEC; typedef /*@out@*/ SXPEC *PSXPEC; typedef struct spar { /*@dependent@*/ /*@null@*/ SXPEC *ptxpec, *ptxpecx; double parval, parerr; long idval; int offset, ksym, flg; char labl[NLABL + 1]; } SIPAR; typedef /*@out@ */ SIPAR *PSIPAR; typedef struct seig { double rhok[9]; /*@owned@*/ /*@notnull@*/ double *eigvec; /*@dependent@*/ int *morg; int irhok; } SEIG; typedef /*@out@*/ SEIG *PSEIG; typedef struct s2top { int ix1, ix2, iqv, iqsig, inew; } S2TOP; static double zero = 0.; static double eps = 1.e-35; static double tiny = 1.e-12; static double clight = 29979.2458; static double rthalf =0.707; static int morgsym[10]; int iamdiag( /*@null@*/ FILE * lu, int nvib, SXPEC ** pxpecv, /*@out@*/ SEIG * eig, /*@out@*/ double *egy, int ioff); int expec(int ityp, int indx, PSXPEC *pxpecv, int nvib, SEIG *eig, SEIG *eigp, int nxpec, int *isym); int getparv(int nv, int mv, int iv, int nvib2, /*@out@*/ SIPAR *parp, PSXPEC *pxpecv); int ideqv(long *idtmp, /*@out@*/ double *fac); int init2top(FILE *lu, int nvib2, int nsym, int nvib, int nvtot, int nsig, short *kmap, S2TOP *vmap, /*@out@*/int *sigma2, /*@out@*/int *ivtop); int get2top(SIPAR *ppar,/*@out@*/ double *xpec2, int nvtot, int nft, int nsym, int *vmapsym, int *ivtop, int nvtop); int wrpar(/*@null@*/FILE * lu, double *id, int nid, int isdip, int kflg, double *t, int nft, char *labl, int nfmt, double drhok); int ftanal(int flg, int nft, double *xpec, /*@out@ */ double *fc); int ksign(int kdel, int nft, double *xpec, /*@out@ */ double *fc); void ftfix(int nftp2, int nftp, double *pxfc); void dneg(int n, double *dx, int incx); void sxpec_alloc( /*@out@*/ PSXPEC *pxpecv, const int nvec); void spar_alloc(/*@out@*/ SIPAR *parwk, /*@out@*/ PSIPAR *par, const int nvec); void seig_alloc(PSEIG eigv, const int nvec, const size_t nfill, /*@dependent@*/ int *pmorgwk, const int nvib); /* program to calculate expectation values for iam basis */ /* input file: name.iam */ /* first line => rho, nsym, maxm, nvib, maxfc */ /* abs(nsym) = symmetry of basis (zero for no K series) */ /* (negative nsym for calculation at K = 0 only) */ /* maxm = maximum value of m for the basis */ /* abs(nvib) = number of vibrational states to include in the output*/ /* (neg nvib for no FC) */ /* abs(maxfc) = maximum number of sample points in (rho * K) */ /* rounded up so mod(maxfc, abs(nsym)) = 0 */ /* (negative maxfc for sampling of K) */ /* other lines => ityp, nf, nm, value */ /* nf = coefficient in Fourier series in tau */ /* (negative for sin, positive for cosine) */ /* if |nf| >= 25 then nf = nf mod 25 and is special potential term */ /* ityp, nm= 99,0 for V delta K=0 */ /* 99,2 for F delta K=0 */ /* 1099,0 for A - (B+C)/2 delta K=0 */ /* 199,0 for (B+C)/2 delta K=0 */ /* 40099,0 for (B-C)/4 delta K=2 */ /* 210099,0 for D_bc delta K=2 */ /* 410099,0 for D_ac delta K=1 */ /* 610099,0 for D_ab delta K=1 */ /* 1,0 for mu_a delta K=0 */ /* 2,0 for mu_b delta K=1 */ /* 3,0 for mu_c delta K=1 */ /* 200099,1 for Pa delta K=0 */ /* 400099,1 for Pb (RAM) delta K=1 */ /* 600099,1 for Pc (PAM) delta K=1 */ /* if nm >= 100, nmp = nm - 100 and define as dipole */ /* output file name.par */ /* rho */ /* V_n */ /* Kinetic energy */ /* expectation for ityp=2..10 (all Fourier series in tau combined) */ int main(int argc, char **argv); int main(argc, argv) int argc; char *argv[]; { #define LIN 0 #define LPAR 1 #define LOUT #define LINT 3 #define LBAK 4 #define NFILE 5 #define NRHOK 5 static double dval[8], rhokv[NRHOK * 9], rhov[10], drhokv[9]; static double *eigref[9]; static int krhok[NRHOK], ilink[9]; static const char *cext[NFILE] = { "iam", "par", "out", "int", "bak"}; enum efile {eiam, epar, eout, eint, ebak}; char *cfil[NFILE+1]; static char card[82], title[82]; FILE *luin, *lupar, *luout, *luint, *lubak, *lu; /*@owned@*/ SXPEC **pxpecv; /*@owned@*/ SXPEC *pxpecpwk; SXPEC *pxpecp; /*@owned@*/ SIPAR **par; /*@owned@*/ SIPAR *parwk; SIPAR *parp, *parq, *parr; SEIG *eigp, *eig, *eig0; /*@owned@*/ SEIG *eigv; /*@owned@*/ S2TOP *vmap; /*@owned@*/ double *eigval, *eigvalk, *eigvalk2, *xfc, *rhokdif, *xpec2top; double *egy, *egyp, *egywk, *eigvec0, *eigvec1, *eigvec0p, *eigvec1p, *pdtmp; double *pxfc, *pxfc1, *eigvec; /*@owned@*/ double *txpec; /*@owned@*/ int *sigma, *isym, *pmorgwk, *ioffv, *ixeig, *ixpt0, *ivtop; /*@owned@*/ int *sigma2, *vmapsym; /*@owned@*/ short *kmap; int *pmorg; char *pstr, *pbgn; double rho, drhok, val, voff, vref, vmin, vmax, didtmp, valm[2], zval; double rhoang, ang, ang0, amp; size_t nl; long idtyp, idtmp, idtst, nnpar; /*@owned@*/ double *didtmpv; int nsize_p, iend, kflg, ipar, nvibsq, maxm, npar, nvib, ift, ncalc, nxvib; int ityp, nsym, ntyp, i, k, nbasis, negy, nvfac, nrhok, nft, nft2, nftp, m; int nvfac2, kd, kk, iv, ivp, ivv, ivvp, mv, nv, nkk, neig, nxpec, ldel; int isig, isigp, ivx, ivxp, nvs, nvp, kdel, kdel0, kmax, kmax0, ktest, ntyp0; int neigp, nhalf, nsymb, isymtau, ksymtau, kdoff, nsin, mbasis, nsig, nvtot2; int kflg0, kflgm, nprn, isdip, nvtot, nvtotsq, nvtot0, nxrho, ncalcm, nvt2; int ixv, nxblks, nxdim, isigx, ixvv, nnblk, ndip, nvib2, nvt, nvtsq, nsymsq; int nvib0, mm, nsigsq, ii, nline2, vtmax, nvtop, ndtop, ndmtop, nneg; short iv1,iv2; char cval; BOOL hsym, negrho, nomorg, nofc, isoffd, headok, lsym, rezero; nsize_p = maxmem(&nl); rthalf = sqrt(0.5); filget(argc, argv, NFILE, cfil, cext); luin = fopenq(cfil[eiam], "r"); luout = fopenq(cfil[eout], "w"); kflg0 = 0; kflgm = -1; /* read input */ if (fgetstr(card, 82, luin) <= 0) exit(EXIT_FAILURE); dval[0] = 0.; dval[1] = 1.; dval[2] = 30.; dval[3] = 1.; dval[4] = NFT; dval[5] = 0; dval[6] = -1.; pcard(card, dval, 6, NULL); rho = dval[0]; nsym = (int) dval[1]; maxm = (int) dval[2]; nvib = (int) dval[3]; nft = (int) dval[4]; nline2 = (int) dval[5]; ktest = (int) dval[6]; dcopy(10, &rho, 0, rhov, 1); ktest = ktest + ktest + 1; negrho = FALSE; nomorg = FALSE; nofc = FALSE; kmax = -1; kmax0 = nhalf = 0; if (nvib < 0) { nofc = TRUE; nvib = -nvib; ktest = 0; fputs(".par file does not use Fourier coefficients\n",luout); } if (nsym > 0) { nrhok = NRHOK; kflg = 100 + nsym; if (nft < 0) { kmax = -nft; if (kmax > 49) kmax = 49; kmax0 = kmax; nft = kmax + kmax + 1; drhok = rho; voff = 1. / (double) nft; nhalf = kmax; fputs("sampling at integer K\n",luout); } else { if (nft > 99) nft = 99; drhok = (double) nsym / nft; voff = rho / nsym; negrho = (rho < 0.); fputs("sampling for periodic rho K\n",luout); } } else { nrhok = 1; nsym = -nsym; if (nsym == 0) nsym = 1; nft = 1; drhok = rho; voff = rho / nsym; kflg = 100; fputs("single sample in low rho K limit\n",luout); } lsym = (nsym > 1); if (ktest > nft) ktest = nft; ftfix(0, 0, &voff); for (k = 0; k < 9; ++k) { morgsym[k] = 0; ilink[k] = k; } nsymb = -10000; if ((nsym & 1) == 0) nsymb = nsym >> 1; nsymsq = nsym * nsym; nl = (size_t) (nline2 * ND2TOP + 1); /* save 2-top info */ kmap = (short *)mallocq (nl * sizeof(short)); kmap[0] = (short) nline2; ivv = 1; nsig = 1; vtmax = 0; nvib2 = 0; iv1 = 0; iv2 = 0; for (k = 0; k < nline2; ++k, ivv += ND2TOP){ if (fgetstr(card, 82, luin) < 1) break; dcopy(ND2TOP, &zero, 0, dval,1); if (pcard(card, dval, ND2TOP, NULL) < 1) continue; for (kk = 0; kk < ND2TOP; ++kk) { kmap[ivv + kk] = (short) dval[kk]; } /* find nsig */ if (k == 0) { iv1 = kmap[ivv + 5]; iv2 = kmap[ivv + 6]; } else if (kmap[ivv + 5] == iv1 && kmap[ivv + 6] == iv2) { ++nsig; } kk = (int) kmap[ivv] + 1; if (nvib2 < kk) nvib2 = kk; kk = (int) kmap[ivv + 5] + 1; if (vtmax < kk) vtmax = kk; kk = (int) kmap[ivv + 6] + 1; if (vtmax < kk) vtmax = kk; } nvt2 = 0; nvtot2 = 0; nvtop = 0; if (nvib2 > 0) { nvt2 = (nvib2 - 1) / nsig + 1; nvib2 = nvt2 * nsig; nvtot2 = nvib2; vtmax *= nsym; if (nvib < vtmax) nvib = vtmax; } /* scan for number of parameters */ npar = 1; ndip = 0; ntyp = 1; nxvib = 0; isoffd = FALSE; nxrho = 0; ivx = 0; ivxp = 0; while (fgetstr(card, 82, luin) > 0) { if (pcard(card, dval, 5, NULL) < 4) continue; idtmp = (long) dval[0]; nv = (int) dval[1]; mv = (int) dval[2]; if (idtmp < 0) idtmp = -idtmp; if (idtmp < 9L && mv < 100) { mv += 100; idtmp += 990; } iv = 0; if (mv >= 100) { ++ndip; ivv = (int)(idtmp / 10); idtmp -= ivv * 10; } else { ivv = (int)(idtmp % 100L); idtmp += 99 - ivv; } ivp = ivv / 10; iv = ivv - 10 * ivp; if (iv < ivp) { i = ivp; ivp = iv; iv = i; } if (ivv != 99) { if (iv >= 9) continue; if (nxvib < iv) nxvib = iv; } if (nv < 0) nv = -nv; if (nv >= 25) nv -= 25; if (lsym && (nv % nsym) != 0) lsym = FALSE; if (ivp != iv && idtmp == 99L && mv == 0) { isoffd = TRUE; if (nsymb > 1 && ilink[ivp] != ilink[iv]) { i = (nsym - nv) % nsym; if (i < 0) i += nsym; kk = ilink[iv]; for (k = 1; k <= nxvib; ++k) { if (ilink[k] == kk) { ilink[k] = ilink[ivp]; morgsym[k] = (morgsym[k] + i) % nsym; } } } } if (idtmp == 910099L) { if (ivp == iv && iv < 9) { rhov[ivv] = dval[3]; ++nxrho; } continue; } ++npar; ++ntyp; if (ivv == 99) { ++ivx; ++ivxp; } else if (iv != ivp) { ++npar; ++ntyp; } if (ideqv(&idtmp, &val) != 0){ ++npar; ++ntyp; if (ivv == 99) { ++ivx; } else if (iv != ivp) { ++npar; ++ntyp; } } } npar += nxvib * ivx; ntyp += nxvib * (ivxp + nrhok); ++nxvib; nxblks = nxvib; nxdim = 1; if (isoffd) { nxblks = 1; nxdim = nxvib; } if (nxrho > 0) { nxrho = 0; for (k = 1; k < nxvib; ++k) { if (fabs(rhov[k] - rhov[0]) > 1.e-10) { if (isoffd) { rhov[k] = rhov[0]; fputs(" warning: rho values for ixv = ", luout); fprintf(luout, "%d set to rho for ixv = 0\n", k); } else { ++nxrho; } } } } if (kmax0 > 0) /* integer K sampling */ dcopy(nxvib, rhov, 1, drhokv, 1); else dcopy(nxvib, &drhok, 0, drhokv, 1); if (npar < 2) { puts(" bad parameter file"); exit(EXIT_FAILURE); } rewind(luin); nftp = nft | 1; nsin = nft >> 1; for (k = 0; k < nrhok; ++k) { /* offsets for overlaps */ kk = (k + 1) >> 1; /* i = 0,1,1,2,2 */ i = kk; if (ODD(k)) i = -i; krhok[k] = i; /* i = 0,-1,1,-2,2 */ if (nhalf > 0 && ODD(kk)) ++i;/* i = 0,0,2,-2,2 */ rhokv[k] = 0.5 * i * rhov[0]; for (ixv = 1; ixv < nxvib; ++ixv) rhokv[k + ixv * nrhok] = 0.5 * i * rhov[ixv]; } if (maxm < 0) { maxm = -maxm; nomorg = TRUE; } maxm = (maxm - 1) / nsym + 1; mbasis = maxm + maxm + 1; nbasis = mbasis; nvt = (nvib - 1) / nsym + 1; if (nvt > nbasis) nvt = nbasis; nvib = nvt * nsym; nvtsq = nvt * nvt; nbasis *= nxdim; nvib0 = nvib; if (nvib0 > nvib) nvib0 = nvib; if (nxvib != 2 || isoffd || nsym > 3) nvib2 = 0; nnblk = nxdim * nvib; nvtot = nvib * nxvib; nvtot0 = nvib0 * nxvib; nvibsq = nvib * nvib; nvtotsq = nvtot * nvtot; if (nvib2 <= 0) { nsig = nsym; nvtot2 = nvtot; nvtop = 1; } else { nsymb = -nsig; nvtot0 = nvib2; nvtop = ((nvt + 1) * (nvt + 2)) >> 1; } nvfac = 10; if (nvtot2 > 9) nvfac = 100; nvfac2 = nvfac * nvfac; nsigsq = nsig * nsig; nl = nvtot2 * sizeof(int); sigma2 = (int *)mallocq(nl); nl = (nvib2 + 1) * sizeof(S2TOP); vmap = (S2TOP *)mallocq(nl); ivtop = (int *)mallocq((size_t) nvtop * sizeof(int)); nvtop = init2top(luout, nvib2, nsym, nvib, nvtot2, nsig, kmap, vmap, sigma2, ivtop); free(kmap); ndtop = 0; ndmtop = 0; /* allocate space for eigenvalues */ negy = nft * nvtot; nl = (size_t) (negy + nvtot) * sizeof(double); eigval = (double *) mallocq(nl); eigval[0] = 0.; eigvalk = NULL; eigvalk2 = NULL; /* allocate space for eigenvector structures */ neig = nft * nrhok; neigp = neig + 1; nl = (size_t) neigp * sizeof(SEIG); eigv = (SEIG *) mallocq(nl); /* allocate space for sigma */ nl = (size_t) nvtot * sizeof(int); sigma = (int *) mallocq(nl); sigma[0] = 0; /* allocate space for morg + isym */ isym = (int *) mallocq(nl); isym[0] = 0; for (k = 1; k < nvtot; ++k) isym[k] = 0; nl *= (size_t) neigp; pmorgwk = (int *) mallocq(nl); pmorgwk[0] = 0; nl = (size_t) nbasis; nl *= (size_t) nvtot * sizeof(double); /* eigenvector size */ /* allocate space for eigenvectors */ seig_alloc(eigv, neig, nl, pmorgwk, nvtot); eig = &eigv[0]; kd = 0; for (ift = 0; ift < nft; ++ift) { k = ift; kk = nft - ift; if (k > kk) k -= nft; val = (double) k; for (kd = 0; kd < nrhok; ++kd) { for (ixv = 0; ixv < nxvib; ++ixv) { eig->rhok[ixv] = rhokv[kd + nrhok * ixv] + val * drhokv[ixv]; } eig->irhok = kd; ++eig; } } val = 0.5 * nsym; dcopy(nxvib, &val, 0, eig->rhok, 1); eig->irhok = 0; eig = NULL; vref = -0.5 + 0.5 * tiny / nsym; for (k = 0; k < nsym; ++k) { /* set up sigma values */ kk = k + 1; isig = kk >> 1; if (ODD(kk)) { isig = -isig; /* isig = 0,+1,-1,.. */ } for (iv = k; iv < nvtot; iv += nsym) sigma[iv] = isig; eig = &eigv[0]; for (kk = 0; kk <= neig; ++kk) { /* set up morg values for each sigma value */ ixvv = 0; for (ixv = 0; ixv < nxvib; ++ixv) { if (isoffd && ixv > 0) { kd = kd + morgsym[ixv] - morgsym[ixv - 1]; } else { /* abs(rhok - morg) < 0.5 * nsym */ val = (eig->rhok[ixv] - isig) / nsym; kd = (int) floor(val + 0.5); val -= kd; /* abs(val) <= 0.5 */ if (val < vref) { --kd; val += 1.; } if (nomorg) { val += kd; kd = 0; } kd = isig + nsym * kd; } pmorg = eig->morg; for (iv = k; iv < nvib; iv += nsym) pmorg[iv + ixvv] = kd; ixvv += nvib; } ++eig; } } eig = NULL; if (nvib2 == 0){ for (k = 0; k < nvtot; ++k) sigma2[k] = sigma[k]; } /* allocate space for ioffv + ixeig + ipt0 */ ncalcm = neig * nsym * nxblks; ncalc = ncalcm + nxblks; nl = (size_t)ncalc * sizeof(int); ioffv = (int *) mallocq(nl); ioffv[0] = 0; ixeig = (int *) mallocq(nl); ixeig[0] = 0; ixpt0 = (int *) mallocq(nl); ixpt0[0] = 0; nl = (size_t)ncalc * sizeof(double); rhokdif = (double *) mallocq(nl); rhokdif[0] = 0.; kk = 0; for (isigx = 0; isigx < nsym; ++isigx) { eig = &eigv[0]; for (k = 0; k < neig; ++k) { ixvv = 0; for (ixv = 0; ixv < nxblks; ++ixv) { isig = isigx + ixvv; ioffv[kk] = isig; ixeig[kk] = k; ixpt0[kk] = kk; val = fabs(eig->rhok[ixv] - eig->morg[isig]); if (val < tiny) val = 0.; rhokdif[kk] = val / nsym; ++kk; ixvv += nvib; } ++eig; } } ixvv = 0; for (ixv = 0; ixv < nxblks; ++ixv) { ioffv[kk] = ixvv; ixeig[kk] = neig; ixpt0[kk] = kk; rhokdif[kk] = 0.5; ++kk; ixvv += nvib; } ixvv = 0; for (ixv = 0; ixv < nxblks; ++ixv) { /* sort rhokdif */ for (i = ixv + nxblks; i < ncalc; i += nxblks) { kk = i; vmin = rhokdif[i]; for (k = i + nxblks; k < ncalc; k += nxblks) { val = rhokdif[k]; if (val < vmin) { vmin = val; kk = k; } } if (kk > i) { isig = ioffv[kk]; ioffv[kk] = ioffv[i]; ioffv[i] = isig; kd = ixeig[kk]; ixeig[kk] = ixeig[i]; ixeig[i] = kd; rhokdif[kk] = rhokdif[i]; rhokdif[i] = vmin; } kk = ixpt0[i - nxblks]; val = rhokdif[kk]; if (fabs(val - vmin) > tiny) { ixpt0[i] = i; continue; } ixpt0[i] = kk; ivp = eigv[ixeig[kk]].irhok; iv = eigv[ixeig[ i]].irhok; if (ivp < iv) continue; if (ivp == iv && ioffv[kk] <= ioffv[i]) continue; isig = ioffv[kk]; ioffv[kk] = ioffv[i]; ioffv[i] = isig; kd = ixeig[kk]; ixeig[kk] = ixeig[i]; ixeig[i] = kd; } ixvv += nvib; } fgetstr(card, 82, luin); for (k = 0; k < nline2; ++k) fgetstr(card, 82, luin); /* allocate structures for parameters */ nl = (size_t) npar * sizeof(SIPAR *); par = (SIPAR **) mallocq(nl); /* allocate vector of parameter pointers */ nl = (size_t) npar * sizeof(SIPAR); parwk = (SIPAR *) mallocq(nl); /* allocate parameter structures */ par[0] = parwk; spar_alloc(parwk, par, npar); nl = (size_t) (ntyp + 1) * sizeof(SXPEC *); pxpecv = (SXPEC **) mallocq(nl); /* allocate vector of expectation pointers */ nl = (size_t) (ntyp + 1) * sizeof(SXPEC); pxpecpwk = (SXPEC *) mallocq(nl); /* allocate expectation structures */ pxpecv[0] = pxpecpwk; pxpecpwk->xpec = NULL; sxpec_alloc(pxpecv, ntyp); pxpecp = pxpecv[0]; pxpecp->mval = maxm; pxpecp->nval = nsym; pxpecp->kdel = 0; ivx = nxvib; if (isoffd) ivx = -ivx; pxpecp->ixvib = ivx; ntyp0 = ntyp; pxpecp->isunit = ntyp; pxpecp = NULL; par[0]->idval = 0; idtmp = 0; kdel0 = -1; for (ipar = 0; ipar < npar; ++ipar) { /* read parameters */ if (fgetstr(card, 82, luin) <= 0) break; dval[4] = 1.e+36; if (pcard(card, dval, 5, NULL) < 4) { --ipar; continue; } idtmp = (long) dval[0]; idtst = idtmp; nv = (int) dval[1]; mv = (int) dval[2]; if (idtst < 0) idtst = -idtst; if (idtst < 9L && mv < 100) { mv += 100; idtst += 990; } else if (idtst > 800000L && idtst <= 899099L) { k = (int) (idtst / 1000L) - 800; if (k > kmax) kmax = k; idtmp = 800099L; } else if (idtst == 910099L) { --ipar; continue; } if (mv >= 100) { ivv = (int)(idtst / 10); idtst -= ivv * 10; } else { ivv = (int)(idtst % 100); idtst += 99 - ivv; } ivp = ivv / 10; iv = ivv - 10 * ivp; if (ivp > iv) { ivv = ivp; ivp = iv; iv = ivv; ivv = iv + ivp * 10; } ivvp = ivp + iv * 10; if (iv >= 9 && ivv != 99) { --ipar; continue; } if (idtmp > 0) { idtmp = idtst; } else { idtmp = -idtst; } parp = par[ipar]; parp->offset = 0; parp->parval = dval[3]; parp->parerr = dval[4]; parp->flg = 0; if (idtst == 99L && mv == 0 && nv > 0 && nv < 25 && ivp == iv) { parp->parval *= -0.5; parp->flg |= MPE; } if (parp->parerr < -eps) { parp->parerr *= -clight; parp->parval *= clight; } pstr = strchr(card, '/'); if (pstr == NULL) { parp->labl[0] = '\0'; } else { memcpy(parp->labl, pstr + 1, NLABL); parp->labl[NLABL] = '\0'; } ivp = ivv; if (ivv == 99) ivp = 0; parp->idval = idtmp; ntyp = getparv(nv, mv, ivp, nvib2, parp, pxpecv); kdel = ideqv(&idtmp, &val); k = mv; if (nv < 0) ++k; if (nvib2 > 0 && nv <= -25) ++k; parp->ksym = k; if (ivv == 99) { for (ixv = 1; ixv < nxvib; ++ixv) { parr = par[++ipar]; memcpy(parr, parp, sizeof(SIPAR)); if (parr->idval > 0) parr->idval = -parr->idval; ivp = ixv * 11; ntyp = getparv(nv, mv, ivp, nvib2, parr, pxpecv); } } else if (ivv != ivvp) { parr = par[++ipar]; memcpy(parr, parp, sizeof(SIPAR)); if (parr->idval > 0) parr->idval = -parr->idval; ntyp = getparv(nv, mv, ivvp, nvib2, parr, pxpecv); } if (kdel != 0) { /* add parameters for complementary operators */ parq = par[++ipar]; memcpy(parq, parp, sizeof(SIPAR)); parq->parval *= val; parq->parerr *= fabs(val); parq->idval = idtmp; parq->offset = 1; parq->ksym = k + 1; if (ivv == 99) { for (ixv = 1; ixv < nxvib; ++ixv) { parr = par[++ipar]; memcpy(parr, parq, sizeof(SIPAR)); if (parq->idval > 0) parq->idval = -parq->idval; ivp = ixv * 11; ntyp = getparv(nv, mv, ivp, nvib2, parr, pxpecv); } } else if (ivv != ivvp) { parr = par[++ipar]; memcpy(parr, parq, sizeof(SIPAR)); if (parr->idval > 0) parr->idval = -parr->idval; ntyp = getparv(nv, mv, ivvp, nvib2, parr, pxpecv); } } if (parp->idval < 0 && kdel != kdel0) parp->idval = -parp->idval; kdel0 = kdel; } fclose(luin); if (kmax >= 0) { nl = (size_t)(kmax + 1) * sizeof(double); eigvalk = (double *) mallocq((size_t) nvtot * nl); eigvalk[0] = 0.; eigvalk2 = (double *) mallocq((size_t) nvtot2 * nl); eigvalk2[0] = 0.; } pxpecp = pxpecv[0]; pxpecp->nval = nsym; parp = parq = NULL; /* allocate space for expectation matrices */ nxpec = nft * nvtotsq; for (ityp = 1; ityp <= ntyp; ++ityp) { pxpecp = pxpecv[ityp]; nv = nxpec; kdel = pxpecp->kdel; if (kdel > 0) { nv = nv << 1; } else if (kdel < 0) { pxpecp->kdel = 0; } if (pxpecp->xpec == NULL) pxpecp->xpec = (double *) mallocq((size_t)nv * sizeof(double)); dcopy(nv, &zero, 0, pxpecp->xpec, 1); } pxpecp = NULL; nl = (size_t) (nsigsq * nftp + nftp + 1) * sizeof(double); xfc = (double *) mallocq(nl); nl = (size_t) nsigsq * sizeof(double); didtmpv = (double *) mallocq(nl); didtmpv[0] = 0.; fputs("ipar, idpar, vv, n, m, kd, ip, par\n", luout); if (par[0]->idval < 0) par[0]->idval = -par[0]->idval; for (ipar = 0; ipar < npar; ++ipar) { /* print out parameters */ parp = par[ipar]; idtyp = parp->idval; pxpecp = parp->ptxpec; if ((parp->flg & MREV) != 0) pxpecp = parp->ptxpecx; if (pxpecp == NULL) continue; kdel = pxpecp->kdel; val = parp->parval; if ((parp->flg & MPE) != 0) { val *= -2.; } cval = ((parp->flg & MHAM) == 0)? ' ':'*'; ixv = pxpecp->ixvib; fprintf(luout, "%4d %8ld %3d %3d %3d %3d %3d%c %15.5E %15.5E %s\n", ipar, idtyp, ixv, pxpecp->nval, pxpecp->mval, kdel, parp->offset, cval, val, parp->parerr, parp->labl); if (parp->offset != 0) parp->offset = nxpec; pxpecp = parp->ptxpec; if (pxpecp != NULL) { if (pxpecp->nval >= 25) { pxpecp->nval -= 25; parp->flg |= MV12; } else if (pxpecp->nval <= -25) { pxpecp->nval += 25; parp->flg |= MV12; } } pxpecp = parp->ptxpecx; if (pxpecp != NULL) { if (pxpecp->nval >= 25) { pxpecp->nval -= 25; parp->flg |= MV12; } else if (pxpecp->nval <= -25) { pxpecp->nval += 25; parp->flg |= MV12; } } if (idtyp > 0) idtyp = -idtyp; nkk = ipar + 1; for (iend = nkk; iend < npar; ++iend) { /* sort related operators */ parq = par[iend]; idtmp = parq->idval; if (idtmp > 0) break; if (idtmp == idtyp) { for (k = iend; k > nkk; --k) { par[k] = par[k - 1]; } par[nkk] = parq; break; } } } pxpecp = NULL; parp = parq = NULL; if (nxrho == 0) { fprintf(luout, " rho = %15.10f\n", rho); } else { for (i = 0; i < nxvib; ++i) fprintf(luout, " rho (%1d) = %15.10f\n", i, rhov[i]); } egywk = &eigval[negy]; egy = egyp = egywk; eig = eigv; eigvec0 = eig->eigvec; for (ixv = 0; ixv < nxblks; ++ixv) { eigref[ixv] = NULL; } for (i = 0; i < ncalc; ++i) { /* calculate eigenvectors in order of rho K*/ isig = ioffv[i]; ixv = isig / nvib; isigx = isig - ixv * nvib; kk = ixeig[i]; eig = &eigv[kk]; m = eig->morg[isig]; val = eig->rhok[ixv] - m; if (val < 0.) rhokdif[i] = -rhokdif[i]; lu = NULL; egy = egywk; k = eig->irhok; if (k == 0) { ift = kk / nrhok; if (ift < nft) egy = &eigval[nvtot * ift]; if (isigx == 0) lu = luout; } eigvec0 = eig->eigvec; iv = ixpt0[i]; if (iv == i) { printf(" rhoK = %9.6f, %2d %2d \n", val, krhok[k], sigma[isigx]); egyp = egy; fflush(stdout); eig->rhok[ixv] = fabs(val); eig->morg[isig] = 0; iamdiag(lu, nvib, pxpecv, eig, egy, isig); eig->rhok[ixv] = val + m; eig->morg[isig] = m; eigvec1 = eigref[ixv]; for (iv = 0; iv < nnblk; iv += nsym) { ivv = (iv + isig) * nbasis; ivvp = iv * nbasis; if (eigvec1 != NULL) { val = ddot(nbasis, &eigvec1[ivvp], 1, &eigvec0[ivv], 1); if (val < 0.) { dneg(nbasis, &eigvec0[ivv], 1); } } } eigref[ixv] = &eigvec0[isig * nbasis]; } else { isigp = ioffv[iv]; kk = ixeig[iv]; eigp = &eigv[kk]; if (eigp->irhok == 0) { for (iv = 0; iv < nnblk; iv += nsym) { egy[iv + isig] = egyp[iv + isigp]; } } eigvec1 = eigp->eigvec; for (iv = 0; iv < nnblk; iv += nsym) { ivv = (iv + isig) * nbasis; ivvp = (iv + isigp) * nbasis; dcopy(nbasis, &eigvec1[ivvp], 1, &eigvec0[ivv], 1); } } } ivv = iv = 0; hsym = FALSE; vmax = 0.; nneg = 0; eigp = &eigv[neig]; eigvec1p = eigp->eigvec; eig = &eigv[0]; eigvec0p = eig->eigvec; fputs(" v, sym, symmetry at 0 and mid rhoK\n", luout); for (ivp = ivvp = 0; ivp < nvtot; ++ivp, ivvp += nbasis) { if (sigma[ivp] == 0) { iv = ivp; /* determine symmetry for rhoK = 0.5 * nsym and 0 */ eigvec0 = eigvec0p + ivvp; eigvec1 = eigvec1p + ivvp; ivv = 0; valm[0] = 0.; valm[1] = 0.; vmax = 0; for (ixv = 0; ixv < nxdim; ++ixv) { if (ixv > 0) { eigvec0 += mbasis; eigvec1 += mbasis; ivv += nvib; } mv = -(eig->morg[ivv] << 1) / nsym; eigvec = eigvec0; for (kk = 0; kk <= 1; ++kk) { if (ODD(mv)) { mv = maxm + ((mv + 1) >> 1); mm = mv - 1; k = (mv > maxm)? maxm: mv; vref = 0.; for (m = 1; m <= k; ++m) { /* mv - 1, mv */ vref += eigvec[mv - m] * eigvec[mm + m]; } nneg = k; } else { mv = maxm + (mv >> 1); k = (mv > maxm)? maxm: mv; vref = 0.5 * eigvec[mv] * eigvec[mv]; for (m = 1; m <= k; ++m) { vref += eigvec[mv - m] * eigvec[mv + m]; } nneg = k + 1; } valm[kk] += vref; if (kk != 0) break; nl = idamax(nneg, &eigvec[mv], 1) + mv; vref = eigvec[nl]; if (fabs(vref) > fabs(vmax)) vmax = vref; mv = 1 - (eigp->morg[ivv] << 1) / nsym; eigvec = eigvec1; } } nneg = 0; if (vmax < 0.) nneg = 1; val = 2.* valm[0]; vref = 2. * valm[1]; isym[iv] = 0; if (val < 0.) isym[iv] = 3; if (vref < 0.) isym[iv] ^= 1; fprintf(luout, "%3d %3d %9.6f %9.6f\n", iv, isym[iv] & 3, val, vref); } else { if (sigma[ivp] < 0) { isym[ivp - 1] = isym[iv] + 4; isym[ivp] = isym[iv] + 8; } else { isym[ivp] = isym[iv] + 12; } } if (ODD(isym[ivp])) { /* correct for translation symmetry */ hsym = TRUE; eig = &eigv[0]; for (k = 0; k < neig; ++k) { kk = eig->morg[ivp] / nsym + nneg; if (ODD(kk)) { eigvec1 = eig->eigvec + ivvp; dneg(nbasis, eigvec1, 1); } ++eig; } } else if (nneg != 0) { eig = &eigv[0]; for (k = 0; k < neig; ++k) { eigvec1 = eig->eigvec + ivvp; dneg(nbasis, eigvec1, 1); ++eig; } } } for (i = 1; i < ncalc; ++i) { /* fix negative rhoK */ if (rhokdif[i] >= 0.) continue; isig = ioffv[i]; ixv = isig / nvib; isigx = isig - ixv * nvib; kk = ixeig[i]; eig = &eigv[kk]; eigvec0 = eig->eigvec; for (ii = 0; ii < nnblk; ii += nsym) { iv = ii + isig; eigvec = &eigvec0[iv * nbasis]; if ((isym[iv] & 2) != 0) { dneg(nbasis, eigvec, 1); } ivv = isigx; for (ixv = 0; ixv < nxdim; ++ixv) { if (ixv > 0) { eigvec += mbasis; } if (morgsym[ixv] != 0) { mv = maxm; mm = mv - 1; for (m = 1; m <= mv; ++m) { /* mv - 1, mv */ vref = eigvec[mv - m]; eigvec[mv - m] = eigvec[mm + m]; eigvec[mm + m] = vref; } } else { mv = maxm; for (m = 1; m <= mv; ++m) { vref = eigvec[mv - m]; eigvec[mv - m] = eigvec[mv + m]; eigvec[mv + m] = vref; } } } } } egyp = NULL; eigvec1 = NULL; egy = NULL; if (eigvalk != NULL) { /* need energy vs K */ egy = eigvalk; kk = (kmax0 + 1) * nvtot; dcopy(kk, eigval, 1, egy, 1); if (kmax0 < kmax) { egy += kk; eig = &eigv[neig]; eig->irhok = 0; pmorg = eig->morg; for (kk = kmax0 + 1; kk <= kmax; ++kk) { for (ixv = 0; ixv < nxblks; ++ixv) { isig = ixv * nvib; for (isigx = 0; isigx < nsym; ++isigx) { val = kk * rhov[ixv]; eig->rhok[ixv] = val; val = (val - sigma[isigx]) / nsym; pmorg[isig] = sigma[isigx] + nsym * (int)floor(val + 0.5); iamdiag(luout, nvib, pxpecv, eig, egy, isig); ++isig; } } printf(" K = %3d, egy = %12.5e\n", kk, egy[0]); egy += nvib; } } if (eigvalk2 != NULL) { if (nvib2 > 0) { egy = eigvalk; egyp = eigvalk2; for (kk = 0; kk <= kmax; ++kk) { for (k = 0; k < nvtot2; ++k) { iv = vmap[k].ix1; ivp = vmap[k].ix2; egyp[k] = egy[iv] + egy[ivp]; } egy += nvtot; egyp += nvtot2; } egy = NULL; egyp = NULL; } else { kk = nvtot * (kmax + 1); dcopy(kk, eigvalk, 1, eigvalk2, 1); } } free(eigvalk); eigvalk = NULL; if (eigvalk2 != NULL) { egy = eigvalk2; for (kk = 0; kk <= kmax; ++kk) { for (isig = 0; isig < nsig; ++isig) { if (sigma2[isig] < 0) { for (k = isig; k < nvtot2; k += nsym) { egy[k] = 0.5 * (egy[k - 1] - egy[k]); egy[k - 1] -= egy[k]; } } } egy += nvtot2; } egy = NULL; } } egywk = NULL; iamdiag(NULL, 0, pxpecv, eigv, eigval, -1); /* free store */ #if MYDEBUG /* test for good overlap */ for (i = 1; i < ncalc; ++i) { /* sort rhokdif */ kk = i; vmin = rhokdif[i]; for (k = i + 1; k < ncalc; ++k) { val = rhokdif[k]; if (val < vmin) { vmin = val; kk = k; } } if (kk > i) { isig = ioffv[kk]; ioffv[kk] = ioffv[i]; ioffv[i] = isig; kd = ixeig[kk]; ixeig[kk] = ixeig[i]; ixeig[i] = kd; rhokdif[kk] = rhokdif[i]; rhokdif[i] = vmin; } } eig = &eigv[0]; isig = 0; for (i = 1; i <= ncalc; ++i) { isigp = isig; eigp = eig; if (i < ncalc) { isig = ioffv[i]; kk = ixeig[i]; val = rhokdif[i]; if (kk == neig) continue; } else { isig = kk = 0; val = 0.; } eig = &eigv[kk]; eigvec1 = eig->eigvec; eigvec0 = eigp->eigvec; for (iv = 0; iv < nvtot; iv += nsym) { ivv = nbasis * (iv + isig); ivvp = nbasis * (iv + isigp); vref = ddot(nbasis, &eigvec0[ivvp], 1, &eigvec1[ivv], 1); if (ODD(isym[iv])) { kk = (eig->morg[iv] - eigp->morg[iv]) / nsym; if (ODD(kk)) vref = -vref; } fprintf(luout, " rhoK = %9.6f,v = %2d, %10.6f\n", val, iv + isig, vref); } } eigvec1 = NULL; #endif /* end test */ for (ixv = 0; ixv < nxblks; ++ixv) eigref[ixv] = NULL; eigvec0 = NULL; if (nrhok == 1) { nft = 1; nftp = 1; } eig0 = &eigv[0]; for (kk = 0; kk < nft; ++kk) { /* calculate expectation values */ eig = eigp = eig0; kd = 0; nkk = kk * nvtotsq; for (ityp = 1; ityp <= ntyp; ++ityp) { k = pxpecv[ityp]->kdel; if (kd < k) { kd = k; k = k << 1; if (k < nrhok) { eigp = eig0 + k; eig = eigp - 1; } else { eig = eigp = eig0; } } expec(ityp, nkk, pxpecv, nvib, eig, eigp, nxpec, isym); } eig0 += nrhok; } eig0 = NULL; eigp = NULL; free(ioffv); free(ixeig); free(rhokdif); free(ixpt0); for (i = 0; i <= neig; ++i) { eig = &eigv[i]; if (eig->eigvec != NULL) { free(eig->eigvec); eig->eigvec = NULL; } } eig = eigp = NULL; free(pmorgwk); free(eigv); lupar = fopen(cfil[epar], "r"); lubak = fopenq(cfil[ebak], "w"); headok = FALSE; if (lupar != NULL) { if (fgetstr(card, 82, lupar) > 0) { fputs(card, lubak); fputc('\n', lubak); if (fgetstr(card, 82, lupar) > 0) { fputs(card, lubak); fputc('\n', lubak); mm = 0; for (;;) {/* read option cards */ if (fgetstr(card, 82, lupar) < 0) break; fputs(card, lubak); fputc('\n', lubak); if (readopt(card, dval, 8) <= 0) break; m = (int) dval[0]; if (mm == 0) mm = m; if (dval[7] > -0.5) break; } headok = TRUE; if (nvtot2 != mm) printf("%s (%3d) does not match .iam (%3d)\n", "WARNING: # states in .par file", mm, nvtot2); } } fclose(lupar); } luint = NULL; if (ndip > 0) luint = fopen(cfil[eint], "r"); if (luint != NULL){ if (fgetstr(title, 82, luint) > 0 && fgetstr(card, 82, luint) > 0) { fclose(luint); luint = fopen(cfil[eint], "w"); if (luint != NULL) { fputs(title, luint); fputc('\n', luint); fputs(card, luint); fputc('\n', luint); } } else if (luint != NULL) { fclose(luint); luint = NULL; } } if (luint == NULL && ndip > 0) luint = fopenq(cfil[eint], "w"); nnpar = 0; nl = (size_t) (2 * nft) * sizeof(double); txpec = (double *) mallocq(nl); txpec[0] = 0.; /* print out rho */ if (kmax0 > 0 && !nofc) { val = 3. / nft; drhok = 1.; } else { val = fabs(3. * rho / nsym); } rhoang = val * acos(-0.5); /* 2*pi/3 */ pstr = " 0. / rho"; if (kmax0 > 0 && hsym) { hsym = FALSE; for (iv = 0; iv < nvtot; ++iv) isym[iv] &= 0x7ffe; } if (hsym && !nofc) nxrho = 1; if (nxrho > 0) { ivv = 0; for (ixv = 0; ixv < nxvib; ++ixv) { val = rhov[ixv]; for (iv = 0; iv < nvib; ++iv) { txpec[0] = val; if (ODD(isym[ivv])) txpec[0] = -txpec[0]; didtmp = 9100. * (double) nvfac2 + ivv * (nvfac + 1); nnpar += wrpar(lubak, &didtmp, 1, 0, kflg0, txpec, 1, pstr, 0, drhok); ++ivv; } } } else { idtyp = 910099L; if (nvfac == 100) idtyp = idtyp * nvfac + 99; txpec[0] = val; didtmp = (double) idtyp; nnpar += wrpar(lubak, &didtmp, 1, 0, kflg0, txpec, 1, pstr, 0, drhok); } /* print out Fourier transform of energies */ txpec[0] = par[0]->parval; idtyp = 0; didtmp = 0.; fputs("Fourier transform of energies\n", luout); wrpar(luout, &didtmp, 1, 0, kflg0, txpec, 1, "", 0, drhok); idtyp = 99; for (iv = 0; iv < nvtot2; ++iv) { if (nvib2 > 0) { ivx = vmap[iv].ix1; ivxp = vmap[iv].ix2 + nvib; for (k = 0; k < nft; ++k) { txpec[k] = eigval[ivx] + eigval[ivxp]; ivx += nvtot; ivxp += nvtot; } } else { dcopy(nft, &eigval[iv], nvtot, txpec, 1); } ftanal(0, nft, txpec, xfc); didtmp = iv * (double)(nvfac + 1); wrpar(luout, &didtmp, 1, 0, kflgm, xfc, nftp, " Egy", nvfac2, drhok); } fputs("expectation values\n", luout); pstr = NULL; pbgn = NULL; rezero = !isoffd; if (nvib2 > 0) { ndmtop = nsymsq * (nvtop >> 1); vmapsym = (int *)mallocq((size_t) ndmtop * sizeof(int)); vmapsym[0] = 0; for (k = 1; k < ndmtop; ++k) vmapsym[k] = 0; for (k = 0; k < nvtot2; ++k) { if (vmap[k].iqv < 0) continue; i = vmap[k].inew; vmapsym[i] = (vmap[k].iqsig & 3) + (vmap[k].iqv << 2); } nvtotsq = ndmtop * ndmtop; nxpec = nvtotsq * nft; } else { vmapsym = (int *) mallocq(sizeof(int)); vmapsym[0] = 0; } xpec2top = (double *) mallocq(sizeof(double)); xpec2top[0] = 0.; /* assemble expectation values */ nprn = nftp; strcpy(card, " 0.0 / egy"); pbgn = strchr(card, '/') - 1; pstr = pbgn + 2; for (ipar = 0; ipar < npar; ipar = iend + 1) { zval = 0.; amp = 0.; kflgm = -1; parp = par[ipar]; idtyp = parp->idval; isdip = 0; lu = lubak; if (idtyp < 0) { idtyp = -idtyp; if (idtyp < 99) { isdip = 1; lu = luint; } } else { if (idtyp < 99) { kflgm = -2; isdip = 1; lu = luint; } sprintf(card,"%12.4E /%s", parp->parerr, parp->labl); pbgn = strchr(card, '/') - 1; pstr = pbgn + 2; txpec[0] = parp->parval; pxpecp = parp->ptxpec; if (pxpecp == NULL) break; if (isdip > 0) { didtmp = 9900.; mv = 99; if (nvfac == 100) didtmp = didtmp * 100 + 99.; } else { if ((parp->flg & MPE) != 0) txpec[0] *= -2.; didtmp = (double)(idtyp / 100); nv = pxpecp->nval; mv = pxpecp->mval; if (nv != 0) { if (nv < 0) { nv = -nv; if ((parp->flg & MV12) != 0) nv += 25; i = (nv + 9) / 10; } else { if ((parp->flg & MV12) != 0) nv += 25; i = (nv - 1) / 10; } nv += i * 10; didtmp += nv * 1.e+07; } if (nvfac == 100) { didtmp = didtmp * 100 + mv; mv = 99; } else { mv = mv * 10 + 9; } } nnpar += wrpar(lu, &didtmp, 1, isdip, kflg0, txpec, 1, card, mv, drhok); } ksymtau = parp->ksym << 1; idtst = -idtyp; if (idtyp == 800099L) idtst = -99L; iend = ipar; for (i = ipar + 1; i < npar && idtst == par[i]->idval; ++i) iend = i; if (idtyp == 990099L) continue; if (idtyp == 800099L) { if (eigvalk2 == NULL) continue; for (iv = 0; iv < nvtot2; ++iv) { val = 0.; egy = &eigvalk2[iv]; if (sigma2[iv] >= 0 && iv > 0) { val = egy[0]; txpec[0] = val; didtmp = (double)(-iv * (nvfac + 1)); nnpar += wrpar(lu, &didtmp, 1, 0, kflg0, txpec, 1, pbgn, 0, drhok); } for (kk = 1; kk <= kmax; ++kk) { egy += nvtot2; txpec[0] = (*egy) - val; didtmp = ((8000. + kk * 10.) * nvfac + iv) * nvfac + iv; didtmp = -didtmp; nnpar += wrpar(lu, &didtmp, 1, 0, kflg0, txpec, 1, pbgn, 0, drhok); } } continue; } pxpecp = parp->ptxpec; kdel = -2; if (pxpecp != NULL) kdel = pxpecp->kdel; if (nvib2 > 0) { k = iend - ipar + 1; if (kdel > 0) ++k; if (k > ndtop) { free(xpec2top); ndtop = k; nl = (size_t) nxpec; nl = nl * ndtop * sizeof(double); xpec2top = (double *)mallocq(nl); } pdtmp = xpec2top; xpec2top[0] = 0.; for (k = ipar; k <= iend; ++k) { if (k > ipar) pdtmp += nxpec; parq = par[k]; get2top(parq, pdtmp, nvtot, nft, nsym, vmapsym, ivtop, nvtop); } pdtmp = NULL; } voff = vref = 0.; for (ivx = 0; ivx < nvtot2; ivx += nsig) { for (ivxp = 0; ivxp <= ivx; ivxp += nsig) { if (nvib2 > 0) { isymtau = ksymtau ^ isym[vmap[ivx].ix1] ^ isym[vmap[ivxp].ix1] ^ isym[vmap[ivx].ix2] ^ isym[vmap[ivxp].ix2]; } else { isymtau = ksymtau ^ isym[ivx] ^ isym[ivxp]; } pxfc = pxfc1 = xfc; xfc[0] = 0.; nvs = 0; nv = ivx + nsig - 1; for (iv = ivx; iv <= nv; ++iv) { nvp = ivxp + nsig - 1; if (nvp > iv) nvp = iv; for (ivp = ivxp; ivp <= nvp; ++ivp) { /* loops over sigma within torsion state */ isig = sigma2[iv]; isigp = sigma2[ivp]; val = 0.; if (iv == ivp) val = voff; dcopy(nft, &val, 0, txpec, 1); for (k = ipar; k <= iend; ++k) { parp = par[k]; pxpecp = parp->ptxpec; if (pxpecp == NULL) continue; val = parp->parval; idtmp = parp->idval; if (nvib2 > 0) { nl = (size_t) ndmtop * vmap[iv].inew + vmap[ivp].inew; nl += nxpec * (k - ipar); daxpy(nft, val, &xpec2top[nl], nvtotsq, txpec, 1); } else { pdtmp = pxpecp->xpec; if (pdtmp == NULL) continue; pdtmp += (iv + ivp * nvtot + parp->offset); daxpy(nft, val, pdtmp, nvtotsq, txpec, 1); } } pxpecp = NULL; pdtmp = NULL; kdoff = 0; if (nofc) { nprn = ksign(kdel, nft, txpec, pxfc); nft2 = nft; } else { if (nhalf > 0 && ODD(kdel)) { kdoff = 1; txpec[nhalf] = 0.5 * (txpec[nhalf - 1] + txpec[nhalf + 1]); } nft2 = ftanal(isymtau, nft, txpec, pxfc); if (kdoff != 0) { ftfix(nft2, nftp, pxfc); } } if (negrho){ dneg(nsin, &pxfc[2], 2); } parp = NULL; if (isig == nsymb) isig = 0; if (isigp == nsymb) isigp = 0; ldel = isigp - isig; idtmp = ivp * nvfac + iv; if (ldel < 0) idtmp = iv * nvfac + ivp; didtmp = (double) idtmp; if (isdip > 0) { didtmp = didtmp * 10 + (double)(idtyp % 10); } else if (idtyp > 99) { didtmp += nvfac2 * (double)(idtyp / 100); } else if (idtmp == 0) { /* idtyp == 99 */ voff = -txpec[0]; xfc[0] += voff; for (k = 0; k < nft; ++k) { txpec[k] += voff; } vref = xfc[0]; didtmp = -99.; if (nvfac == 100) didtmp = -9999.; nnpar += wrpar(lu, &didtmp, 1, 0, kflgm, xfc, 1, pbgn, nvfac2, drhok); didtmp = 0; } wrpar(luout, &didtmp, 1, isdip, kflg, txpec, nft, pbgn, nft, drhok); if (iv == ivp) pxfc[0] -= vref; if (ktest > 0 && nft2 == nft && dnrm2(nft, pxfc, 1) > tiny) { fputs("begin K prediction\n",luout); egy = txpec + nft; for (k = 0; k < ktest; ++k){ kk = k; if ((k + k) >= ktest) kk -= ktest; ang0 = (double)kk; if (ODD(kdel)) ang0 += 0.5; ang0 *= rhoang; ang = ang0; val = pxfc[0]; for (kk = 1; kk < nft; kk += 2) { val += pxfc[kk] * cos(ang) + pxfc[kk + 1] * sin(ang); ang += ang0; } egy[k] = val; } pbgn[0] = '/'; pbgn[1] = ':'; nnpar += wrpar(luout, &didtmp, 1, isdip, kflg, egy, ktest, pbgn, ktest, 1.); pbgn[0] = ' '; pbgn[1] = '/'; } if (lsym && ldel != 0) continue; didtmpv[nvs] = -didtmp; if (ldel == 0) { if (isig >= 0) { pxfc1 = pxfc; } else { for (k = 0; k < nprn; ++k) { pxfc[k] = 0.5 * (pxfc1[k] - pxfc[k]); pxfc1[k] -= pxfc[k]; } if (nvib2 == 0) { k = isymtau & 2; val = dnrm2(nprn, pxfc, 1) + tiny; if (val > amp) amp = val; val = 0; for (; k < nprn; k += 2) { val += fabs(pxfc[k]); if (rezero) pxfc[k] = 0.; if (k == 0) --k; } val /= amp; if (zval < val) zval = val; } } if (isig <= 0 && nvib2 == 0) { k = 2 - (isymtau & 2); val = dnrm2(nprn, pxfc, 1) + tiny; if (val > amp) amp = val; val = 0; for (; k < nprn; k += 2) { val += fabs(pxfc1[k]); if (rezero) pxfc1[k] = 0.; if (k == 0) --k; } val /= amp; if (zval < val) zval = val; } } if (iv < nvtot0) { ++nvs; pxfc += nprn; } } /*ivp loop */ } /* iv loop */ nnpar += wrpar(lu, didtmpv, nvs, isdip, kflgm, xfc, nprn, pbgn, -nvfac2, drhok); pxfc1 = NULL; pxfc = NULL; kflgm = -1; } /*ivxp loop */ } /* ivx loop */ if (nvib2 == 0) fprintf(luout,"%3d zero test = %e\n", ipar, zval); } /* par loop */ if (luint != NULL) fclose(luint); fclose(lubak); fclose(luout); lubak = fopen(cfil[ebak], "r"); if (lubak == NULL) exit(EXIT_FAILURE); lupar = fopen(cfil[epar], "w"); if (lupar == NULL) { fclose(lubak); exit(EXIT_FAILURE); } if (fgetstr(card, 82, lubak) > 0) { fputs(card, lupar); fputc('\n', lupar); /* title */ if (fgetstr(card, 82, lubak) > 0) { k = readint(card); if (headok) { fprintf(lupar,"%8ld%s\n", nnpar, &card[k]); } else { fputs(card, lupar); fputc('\n', lupar); } for (;;) {/* read */ if (fgetstr(card, 82, lubak) < 0) break; fputs(card, lupar); fputc('\n', lupar); } } } fclose(lubak); fclose(lupar); parp = NULL; free(eigval); free(eigvalk2); free(didtmpv); free(xfc); ityp = 0; for (ityp = 1; ityp <= ntyp; ++ityp) { pxpecp = pxpecv[ityp]; if (pxpecp->xpec != NULL) free(pxpecp->xpec); pxpecp->xpec = NULL; } pxpecp = NULL; free(pxpecv); pxpecv = NULL; free(pxpecpwk); pxpecpwk = NULL; free(xpec2top); free(vmapsym); free(ivtop); vmapsym = NULL; free(par); par = NULL; free(vmap); free(sigma2); free(isym); free(sigma); return 0; } /* main */ int iamdiag(lu, nvib, pxpecv, eig, egy, ioff) FILE *lu; int nvib; SXPEC **pxpecv; SEIG *eig; double *egy; int ioff; { SXPEC *pxpec0; /*@only@*/ static double *t, *tv, *tegy, *twk; /*@only@*/ static short *iassgn, *idx; static short ibkptr[2]; static double c, egy0, fval[9]; static int init = 0; static int mbgn, nsym, nbasis, mbasis, nf, np; static int nsq, isdgn0, nxvib, nxdim, nxall; double *pt, *ptt; double vsym, val, rhokx, tmp, pmix, cv, sv; int i, iv, ivp, k, icol, nv, nlim, m, ivdgn, minv, isdgn, mm, ixvib; int iend, ixv, ixvp, isig, nvib0, kk, knt, kd, kmix, kkp; size_t nl; pxpec0 = *pxpecv; if (init == 0) { /* initialize */ if (nbasis > 0) { free(iassgn); iassgn = NULL; free(idx); idx = NULL; free(tegy); tegy = NULL; free(twk); twk = NULL; free(t); t = NULL; free(tv); tv = NULL; } nbasis = 0; kkp = 0; if (nvib == 0) return 0; nxvib = pxpec0->ixvib; nxdim = 1; nxall = nxvib; if (nxvib < 0) { nxdim = -nxvib; nxall = nxdim; } nsym = pxpec0->nval; m = pxpec0->mval; mbgn = -m * nsym; mbasis = m + m + 1; nbasis = mbasis * nxdim; ibkptr[0] = 0; ibkptr[1] = (short) nbasis; np = nbasis + 1; nl = (size_t) np * sizeof(short); iassgn = (short *) mallocq(nl); iassgn[0] = 0; idx = (short *) mallocq(nl); idx[0] = 0; nl = (size_t) nbasis * sizeof(double); tegy = (double *) mallocq(nl); twk = (double *) mallocq(nl); nsq = nbasis * nbasis; nl = (size_t) nsq * sizeof(double); t = (double *) mallocq(nl); if (nxvib > 1) nl *= nxvib; tv = (double *) mallocq(nl); dcopy(nxall, &zero, 0, fval, 1); dcopy(nsq, &zero, 0, tv, 1); for (k = 1; k < nxvib; ++k) dcopy(nsq, &zero, 0, &tv[k * nsq], 1); nf = 0; minv = 1024; iend = pxpec0->kdel; for (i = 1; i <= iend; ++i) { val = pxpecv[i]->xval; nv = pxpecv[i]->nval; iv = pxpecv[i]->ixvib; if (nv >= 25) continue; if (pxpecv[i]->mval == 0) { /* calculate potential terms */ if (nv > 0 && nv < minv && (iv % 11) == 0) minv = nv; if (nv > 0) val *= 0.5; k = nv / nsym; if (iv == 0) { pt = tv; ivp = 0; } else { ivp = iv / 10; iv -= ivp * 10; /* iv >= ivp */ if (iv < ivp) continue; if (nxvib < 0) ixv = (iv + ivp * nbasis) * mbasis; else ixv = nsq * iv; pt = &tv[ixv]; } kd = 0; if (iv != ivp ) { if ((nsym & 1) == 0) { kk = morgsym[ivp] - morgsym[iv] - nv; k = kk / nsym; if (kk != k * nsym) continue; kd = (kk + nv + nv) / nsym; } else { kd = k; k = -k; } } for (knt = 0; knt < 2; ++knt) { ixv = k; if (k < 0) { k = -k; ixv = k * nbasis; } for (kk = k; kk < mbasis; ++kk) { pt[ixv] += val; ixv += np; } if (nv == 0 || iv == ivp) break; k = kd; nv = 0; } if (nv == 0) continue; val *= -2.; ixv = 0; for (kk = 0; kk < mbasis; ++kk) { pt[ixv] += val; ixv += np; } } else { /* isolate allowed F values */ iv = iv / 11; fval[iv] += val; } } isdgn0 = minv; if (nsym >= 3 || minv < 3) isdgn0 = 0; c = 29979.2458; } /* begin normal computation */ if (nvib <= 0) return -1; if (nxdim == 1) { ixvib = ioff / nvib; isig = ioff - nvib * ixvib; iend = ioff + nvib; } else { ixvib = 0; isig = ioff; iend = nvib * nxdim; } nvib0 = nvib / nsym; pt = tv; if (ixvib > 0) pt = &tv[ixvib * nsq]; dcopy(nsq, pt, 1, t, 1); /* calculate kinetic energy */ rhokx = eig->morg[ioff] - eig->rhok[ixvib]; isdgn = 0; if (init <= 0 || fabs(rhokx - 0.5 * nsym) < tiny) isdgn = isdgn0; kd = 0; kk = 0; iv = 0; nv = mbasis; for (ixv = 0; ixv < nxdim; ++ixv) { val = fval[ixv + ixvib]; m = mbgn; for (k = 0; k < nv; ++k) { tmp = m + rhokx; t[iv] += val * tmp * tmp; #if MYDEBUG_EIG if (lu != 0) { kkp = kk; for (i = kk; i < nbasis; ++i) { pmix = t[iv + i - kkp]; if (fabs(pmix) < tiny) continue; fprintf(lu, " %4d%4d%15.6e", i, kk, pmix); if (++kd > 4) { fputc('\n',lu); kd = 0; } } } #endif m += nsym; iv += np; ++kk; } rhokx += morgsym[ixv + 1] - morgsym[ixv]; } #if MYDEBUG_EIG if (lu != 0) fputc('\n',lu); #endif /* diagonalize */ m = hdiag(nbasis, nbasis, t, tegy, twk, iassgn); ordblk(nbasis, nbasis, iassgn, t, tegy, ibkptr, twk, idx); m = pxpec0->mval; ivp = 0; nlim = nvib0; ixv = 0; for (iv = ioff; iv < iend; iv += nsym) { /* loop over states */ val = tegy[ivp]; pt = &t[ivp * nbasis]; pmix = twk[ivp]; #if MYDEBUG_EIG if (lu != 0) { kd = 0; fprintf(lu, "eignvector %3d\n", iv); for (i = 0; i < nbasis; ++i) { tmp = pt[i]; fprintf(lu, " %3d%15.6e", i, tmp); if (++kd > 4) { fputc('\n',lu); kd = 0; } } fputc('\n',lu); } #endif pmix = 0.; kmix = 0; ptt = pt; for (ixvp = 0; ixvp < nxdim; ++ixvp) { if (ixvp > 0) ptt += mbasis; vsym = ddot(mbasis, ptt, 1, ptt, 1); if (vsym > pmix) { kmix = ixvp; pmix = vsym; } } ixvp = ixv; ++ivp; if (ivp >= nlim) { ++ixv; nlim = ivp + nvib0; } ivdgn = -1; if (isdgn != 0 && nxvib > 0) { vsym = (1.e-10) * fabs(val); i = ivp; /* find energy degeneracy */ if (fabs(tegy[ivp] - val) < vsym) { ivdgn = ivp; ptt = &t[ivdgn * nbasis]; mm = m; if (init > 0) --mm; vsym = 0.; sv = 0.; for (i = 1; i <= m; ++i) { vsym += pt[mm + i] * pt[m - i]; sv += pt[mm + i] * ptt[m - i] + ptt[mm + i] * pt[m - i]; } i = iv; if (m == mm) { i += iv / isdgn; vsym = 2. * vsym + pt[m] * pt[m]; sv += pt[m] * ptt[m]; } cv = 1. - vsym; tmp = sqrt(cv * cv + sv * sv); cv /= tmp; sv /= tmp; if ((i & 1) == 0) { tmp = cv; cv = sv; sv = -tmp; } drot(nbasis, ptt, 1, pt, 1, cv, sv); } } if (init == 0) { init = -1; egy0 = val; if (lu != NULL) fprintf(lu, " v, rho*K, vmix, pmix, energy relative to %15.6f\n", egy0 / c); } val -= egy0; if (lu != NULL) fprintf(lu, "%3d %9.6f %2d %9.6f %15.6f\n", iv, eig->rhok[ixvib], kmix, pmix, val / c); egy[iv] = val; icol = iv * nbasis; dcopy(nbasis, pt, 1, eig->eigvec + icol, 1); } init = 1; return 0; } /* iamdiag */ int expec(ityp, indx, pxpecv, nvib, eigm, eigp, noff, isym) int ityp, indx; SXPEC **pxpecv; int nvib; SEIG *eigm, *eigp; int noff, *isym; { static double facv[] = { 1.0, 0.5, 0.5, 0.25 }; static double sumv[4]; SXPEC *pxpecp, *pxpec0; SEIG *eigbra, *eigket; double *result; double *eigvbra, *eigvket; double pabra, paket, vtmp1, vtmp2, tmp, fac; int idel, nsym, i, nbasis, mbra, mket, maxm, isin, nxvib; int state, state0, nv, nv0, mv, m, nx, iv1, iv2, kd, isum, nvtot, nvcmp; int iv1s, iv2s, iv1d, iv2d, ivv, nn, mbasis, ixv1, ixv2, ixv1p, ixv2p; int nblk,ibgn1, ibgn2, ixv1m, ixv2m, iend1, iend2, nlim, iv1z, iv2z; int ivv0, isig1, isig2; /* state=0 */ /* state=1 */ /* state=2 */ /* state=3 */ pxpec0 = pxpecv[0]; nsym = pxpec0->nval; maxm = pxpec0->mval; nxvib = pxpec0->ixvib; mbasis = maxm + maxm + 1; nbasis = mbasis; if (nxvib < 0) nbasis *= -nxvib; maxm *= nsym; pxpecp = pxpecv[ityp]; result = pxpecp->xpec + indx; nv0 = pxpecp->nval; mv = pxpecp->mval; kd = pxpecp->kdel; ixv1 = pxpecp->ixvib; ixv2 = ixv1 / 10; ixv1 -= 10 * ixv2; if (nxvib > 0) { nblk = nvib; nvtot = nblk * nxvib; ibgn1 = ixv1 * nblk; ixv1p = 0; ixv1m = 0; ibgn2 = ixv2 * nblk; ixv2p = 0; ixv2m = 0; } else { nblk = -nxvib * nvib; nvtot = nblk; ibgn1 = 0; ixv1p = ixv1 * mbasis; ixv1m = ixv1 * nvib; ibgn2 = 0; ixv2p = ixv2 * mbasis; ixv2m = ixv2 * nvib; } iend1 = ibgn1 + nblk - 1; iend2 = ibgn2 + nblk - 1; isin = 0; if (nv0 < 0) { isin = 1; nv0 = -nv0; } state0 = 0; if (kd != 0) state0 = 2; if (nv0 != 0) ++state0; nvcmp = nv0 % nsym; fac = facv[state0]; iv1z = ibgn1; iv2z = ibgn2; nv = nv0; /* loop through vibrational states */ for (iv2s = ibgn2; iv2s <= iend2; ++iv2s) { iv2d = (int) isym[iv2s] >> 2; if (iv2d == 0) iv2z = iv2s; isig2 = iv2s - iv2z; nlim = (iend1 < iv2s)? iend1: iv2s; ivv0 = iv2s * nvtot; for (iv1s = ibgn1; iv1s <= nlim; ++iv1s) { /* iv1s <= iv2s */ iv1d = (int) isym[iv1s] >> 2; if (iv1d == 0) iv1z = iv1s; isig1 = iv1s - iv1z; if (nvcmp == 0 && isig1 != isig2) continue; eigbra = eigp; eigket = eigm; iv1 = iv1s; iv2 = iv2s; isum = 0; for (state = state0; state >= 0; --state) { if (state == 1) { if (nv0 == 0) state = 0; iv1 = iv1z + isig2; iv2 = iv2z + isig1; eigbra = eigm; eigket = eigp; } nv = nv0; if ((state & 1) == 0) nv = -nv; sumv[state] = 0.; mbra = eigbra->morg[ixv1m + iv1 - iv1z]; mket = eigket->morg[ixv2m + iv2 - iv2z]; idel = nv + mket - mbra; if (nsym > 1) { if ((idel % nsym) == 0) { /* check for good symmetry */ idel /= nsym; } else { continue; } } if (idel > 0) { nx = mbasis - idel; if (nx <= 0) continue; eigvbra = eigbra->eigvec + (iv1 * nbasis + ixv1p + idel); eigvket = eigket->eigvec + (iv2 * nbasis + ixv2p); mbra += idel * nsym; } else { nx = mbasis + idel; if (nx <= 0) continue; eigvbra = eigbra->eigvec + (iv1 * nbasis + ixv1p); eigvket = eigket->eigvec + (iv2 * nbasis + ixv2p - idel); mket -= idel * nsym; } if (mv == 0) { tmp = ddot(nx, eigvbra, 1, eigvket, 1); } else { /* mv > 0 */ pabra = (mbra - maxm) - eigbra->rhok[ixv1]; paket = (mket - maxm) - eigket->rhok[ixv2]; if (mv == 2 && nv == 0 && iv1s == 2 && iv2s == 2 && kd == 0) tmp = 0.; tmp = 0.; for (i = 0; i < nx; ++i) { vtmp1 = 0.5 * eigvbra[i] * eigvket[i]; vtmp2 = vtmp1; for (m = 0; m < mv; ++m) { vtmp1 *= pabra; vtmp2 *= paket; } tmp += vtmp1 + vtmp2; pabra += nsym; paket += nsym; } } sumv[state] = tmp; isum += nx; } /* state loop */ if (isum == 0) continue; if (isin != 0) { sumv[0] -= sumv[1]; if (state0 == 3) sumv[2] -= sumv[3]; } else if (nv != 0) { sumv[0] += sumv[1]; if (state0 == 3) sumv[2] += sumv[3]; } ivv = ivv0 + iv1s; if (state0 >= 2) { tmp = sumv[2] - sumv[0]; sumv[0] += sumv[2]; if (isin != 0) tmp = -tmp; result[ivv + noff] = fac * tmp; } result[ivv] = fac * sumv[0]; } /* iv1 loop */ nn = nlim - ibgn1; ivv = iv2s + nvtot * ibgn1; ivv0 += ibgn1; if (state0 >= 2) dcopy(nn, &result[ivv0 + noff], 1, &result[ivv + noff], nvtot); dcopy(nn, &result[ivv0], 1, &result[ivv], nvtot); } /* iv2 loop */ return 0; } /* expec */ int getparv(nv, mv, iv, nvib2, parp, pxpecv) int nv, mv, iv, nvib2; SIPAR *parp; SXPEC **pxpecv; { static int n = 0; SXPEC *pxpecp, *pxpeci, *pxpec0; double val; long ityp; int i, iend, k, kd, nsym, md, knt, nknt, isunit, nlim; BOOL inham; ityp = parp->idval; if (ityp == 990099L) { mv = nv = 0; } else if (ityp == 800099L) { mv = nv = 0; parp->parval = 10000.; } pxpec0 = pxpecv[0]; nsym = pxpec0->nval; md = pxpec0->mval; nlim = pxpec0->isunit; kd = ideqv(&ityp, &val); if (mv >= 100) mv -= 100; nknt = 1; isunit = 0; if (nv == 0 && mv == 0 && pxpec0->ixvib >= 0) { isunit = kd + 1; } else if (nv <= -25 || nv >= 25) { isunit = -1; } if (nvib2 > 0) { nknt = 2; if (isunit != 0) { if (iv == 11) { parp->ptxpec = NULL; parp->ptxpecx = NULL; return n; } } } for(knt = 0; knt < nknt; ++knt) { inham = FALSE; k = nv / nsym; /* check symmetry for inclusion in diagonalization */ if (ityp == -99L && kd == 0 && nv >= 0 && nv < 25 && k <= (md + md)) { if ((iv % 11) == 0) { if (k * nsym == nv) { /* nv >= 0 and is a multiple of nsym */ if (mv == 2 && nv == 0) { inham = TRUE; } else if (mv == 0 && nv >= 0) { inham = TRUE; } } } else { if (mv == 0 && nv >= 0) { inham = TRUE; } } } val = 0.; if (inham && isunit == 0) { val = parp->parval; kd = -1; parp->flg |= MHAM; } ++n; iend = n; pxpecp = pxpecv[n]; pxpecp->kdel = kd; pxpecp->mval = mv; pxpecp->nval = nv; pxpecp->xval = val; pxpecp->xpec = NULL; pxpecp->ixvib = iv; pxpecp->isunit = isunit; for (i = 1; i < n; ++i) { pxpeci = pxpecv[i]; k = pxpeci->kdel - kd; if (k > 0) { /* insert in list */ for (k = n; k > i; --k) { pxpecv[k] = pxpecv[k - 1]; } pxpecv[i] = pxpecp; iend = i; break; } if (k == 0 && pxpeci->nval == nv && pxpeci->mval == mv && pxpeci->ixvib == iv) { /* full match */ pxpecp = pxpeci; --n; if (kd < 0) pxpecp->xval += val; break; } } if (n >= nlim) { printf("pexpecv too small :%d\n", nlim); exit(EXIT_FAILURE); } if (inham && pxpec0->kdel < iend) pxpec0->kdel = iend; if (knt > 0) { if (iv == 0) { parp->ptxpecx = parp->ptxpec; parp->ptxpec = pxpecp; parp->flg |= MREV; } else { parp->ptxpecx = pxpecp; } break; } parp->ptxpec = pxpecp; iv = 11 - iv; if (isunit >= 0) { if (kd < 0) kd = 0; if (isunit == 0) isunit = 1 + kd; mv = 0; nv = 0; } } return n; } /* getparv */ int ideqv(pidtmp, pfac) long *pidtmp; double *pfac; { #define IDIV 10000 static struct { double fac; int ityp, kd; } cmpv[] = { {-2.0, 4, 2}, { 0.5, 21, 2}, {-1.0, 40, 1}, { 1.0, 60, 1}, {-1.0, 61, 1}, { 1.0, 41, 1}, { 0.5, 22, 2}, {-2.0, 12, 2}, { 1.0, 0, 0}, }; long idtmp; int kdret, i, ii, key; kdret = 0; *pfac = 1.; idtmp = (*pidtmp); if (idtmp < 0) idtmp = -idtmp; if (idtmp < 99) { key = (int) idtmp % 10; if (key == 2) { ++idtmp; kdret = 1; *pfac = -1.; } else if (key == 3) { --idtmp; kdret = 1; } } else { key = (int) ((idtmp / IDIV) % 100); if (key != 0) { for (i = 0; (ii = cmpv[i].ityp) != 0; ++i) { if (ii == key) { kdret = cmpv[i].kd; *pfac = cmpv[i].fac; if (kdret != 0) { ii = i ^ 1; idtmp += IDIV * (long) (cmpv[ii].ityp - key); } break; } } } } *pidtmp = -idtmp; return kdret; } /* ideqv */ int ftanal(iflg, nft, txpec, xfc) int iflg, nft; double *txpec, *xfc; { int k, kk, nft2; dcopy(nft, txpec, 1, &txpec[nft], 1); iflg &= 1; nft2 = nft << 1; kk = 3; if (iflg != 0) { dneg(nft, &txpec[nft], 1); kk = 1; } ftran(nft2, txpec, 1, xfc, 0); for (k = 1; k < nft; k += 2) { xfc[k] = xfc[kk]; xfc[k + 1] = xfc[kk + 1]; kk += 4; } if (iflg != 0) nft = nft2; return nft; } int ksign(kdel, nft, txpec, xfc) int kdel, nft; double *txpec, *xfc; { double dif,val0; int k, kp, km, iret; iret = nft - kdel; if ((kdel & 1) != 0) { val0 = 0.; ++iret; kp = 0; } else { val0 = txpec[0]; kp = 1; } km = nft - 1; xfc[0] = val0; for (k = 1; k < iret; k += 2) { dif = 0.5 * (txpec[kp] - txpec[km]); xfc[k] = txpec[kp] - dif - val0; xfc[k + 1] = dif; --km; ++kp; } for (k = iret; k < nft; ++k) xfc[k] = 0.; return iret; } void ftfix(int nft2, int nft, double *xfc) { static double shalf, sbgn, chalf, cbgn; double c,s,vc,vs; int k; if (nft2 == 0) { vs = asin(1.) * (*xfc); sbgn = sin(vs); cbgn = cos(vs); vs *= 2.; shalf = sin(vs); chalf = cos(vs); return; } if (nft2 == nft) { s = shalf; c = chalf; } else { s = sbgn; c = cbgn; } for (k = 1; k < nft; k += 2){ vc = xfc[k]; vs = xfc[k + 1]; xfc[k + 1] = c * vs + s * vc; xfc[k] = c * vc - s * vs; vs = s; s = c * shalf + vs * chalf; c = c * chalf - vs * shalf; } } void dneg(int n, double *dx, int incx) { int k; if (n <= 0) return; *dx = -(*dx); for (k = 1; k < n; ++k) { dx += incx; *dx = -(*dx); } } void sxpec_alloc(PSXPEC *pxpecv, const int nvec) { SXPEC *pxpec; int i; pxpec = pxpecv[0]; pxpec->xpec = NULL; for (i = 1; i <= nvec; ++i) { pxpecv[i] = (++pxpec); pxpec->xpec = NULL; pxpec->nval = pxpec->mval = pxpec->kdel = 0; pxpec->xval = 0.; } } void spar_alloc(SIPAR *pswk, PSIPAR *par, const int nvec) { SIPAR *pspar; int i; par[0] = pswk; pspar = par[0]; pspar->ptxpec = NULL; pspar->ptxpecx = NULL; for (i = 1; i < nvec; ++i) { par[i] = (++pspar); pspar->ptxpec = NULL; pspar->ptxpecx = NULL; } } void seig_alloc(SEIG *eigv, const int nvec, const size_t nfill, int *pmorgwk, const int nvib) { SEIG *eig; int *pmorg; int k; k = 0; eig = eigv; pmorg = pmorgwk; do { eig->eigvec = (double *) mallocq(nfill); eig->morg = pmorg; eig->irhok = 0; ++eig; pmorg += nvib; } while (++k <= nvec); } int init2top(FILE *lu, int nvib2, int nsym, int nvib, int nvtot, int nsig, short *kmap, S2TOP *vmap, int *sigma2, int *ivtop) { S2TOP *pmap, *pmapp; int i, iv, iv1, iv2, k, kk, nline, isig1, isig2, isig, isold, nvt, nvtop; sigma2[0] = 0; if (nvib2 <= 0) nvtot = 1; ivtop[0] = 0; k= 0; do { pmap = &vmap[k]; sigma2[k] = 0; pmap->iqv = -16; pmap->iqsig = 0; pmap->ix1 = 0; pmap->ix2 = 0; pmap->inew = 0; ++k; } while (k < nvtot); if (nvib2 <= 0) return 0; pmap = NULL; nvt = nvib / nsym; nvtop = 0; nline = (int) kmap[0] * ND2TOP + 1; /* user input equivalent states */ for (k = 1; k < nline; k += ND2TOP) { iv = (int) kmap[k]; if (iv < 0 || iv >= nvtot) continue; pmap = &vmap[iv]; isig1 = (int) kmap[k + 2]; if (isig1 < 0) isig1 += nsym; if (isig1 >= nsym) continue; isig2 = (int) kmap[k + 3]; if (isig2 < 0) isig2 += nsym; if (isig2 >= nsym) continue; i = (int) kmap[k + 1]; if (isig1 == isig2) i = 0; if (i > 0) i = 2; else if (i < 0) i = 3; pmap->iqsig = i; if (isig1 > isig2) i ^= 1; if (i == 3) { kk = isig1; isig1 = isig2; isig2 = kk; } iv1 = (int) kmap[k + 5]; if (iv1 < 0 || iv1 >= nvt) continue; iv2 = (int) kmap[k + 6]; if (iv2 < 0 || iv2 >= nvt) continue; i = (int) kmap[k + 4]; if (kmap[k + 5] == kmap[k + 6]) i = 0; if (i > 0) i = 2; else if (i < 0) i = 3; pmap->iqv = i; if (iv1 > iv2) i ^= 1; if (i == 3) { kk = iv1; iv1 = iv2; iv2 = kk; } pmap->ix1 = iv1 * nsym + isig1; pmap->ix2 = iv2 * nsym + isig2; for (kk = 0; kk < nvtop; kk += 2) { if (ivtop[kk] == iv1 && ivtop[kk + 1] == iv2) break; } if (kk == nvtop) { if (iv1 > iv2) { kk = iv1; iv1 = iv2; iv2 = kk; } ivtop[nvtop++] = iv1; ivtop[nvtop++] = iv2; if (iv1 != iv2) { ivtop[nvtop++] = iv2; ivtop[nvtop++] = iv1; } } } pmap = NULL; /* find default sigmas */ for (k = 0; k < nvtot; ++k) { pmap = &vmap[k]; if (pmap->iqv >= 0) continue; iv = k / nsig; isig = k - iv * nsig; for (kk = isig; kk < nvtot; kk += nsig) { pmapp = &vmap[kk]; if (pmapp->iqv < 0) continue; pmap->iqv += 8; pmap->iqsig = pmapp->iqsig; pmap->ix1 += pmapp->ix1 % nsym; pmap->ix2 += pmapp->ix2 % nsym; break; } } pmap = NULL; pmapp = NULL; /* find default vibrations */ for (k = 0; k < nvtot; ++k) { pmap = &vmap[k]; if (pmap->iqv >= 0) continue; iv = k / nsig; i = iv * nsig; for (kk = 0; kk < nsig; ++kk) { pmapp = &vmap[i + kk]; if (pmapp->iqv < 0) continue; pmap->iqv += pmapp->iqv + 8; pmap->ix1 += (pmapp->ix1 / nsym) * nsym; pmap->ix2 += (pmapp->ix2 / nsym) * nsym; break; } } pmap = NULL; pmapp = NULL; /* find index for states */ for (k = 0; k < nvtot; ++k) { pmap = &vmap[k]; pmap->inew = 0; if (pmap->iqv < 0) continue; isig1 = pmap->ix1; iv1 = isig1 / nsym; isig1 -= iv1 * nsym; isig2 = pmap->ix2; iv2 = isig2 / nsym; isig2 -= iv2 * nsym; for (kk = 0; kk < nvtop; kk += 2) { if (ivtop[kk] == iv1 && ivtop[kk + 1] == iv2) { pmap->inew = isig2 + nsym * (isig1 + nsym * (kk >> 1)); break; } } } pmap = NULL; /* check symmetry */ for (k = 0; k < nvtot; ++k) { pmap = &vmap[k]; if (pmap->iqv < 0) continue; isig1 = pmap->ix1; iv1 = isig1 / nsym; isig1 -= iv1 * nsym; isig2 = pmap->ix2; iv2 = isig2 / nsym; isig2 -= iv2 * nsym; if (pmap->iqv == 3) { iv = pmap->inew - nsym * nsym; for (kk = 0; kk < nvtot; ++kk) { pmapp = &vmap[kk]; if (pmapp->inew == iv) { if (pmapp->iqv == 0) pmapp->iqv = 2; break; } } } if (pmap->iqsig == 3) { iv = pmap->inew + (nsym - 1) * (isig2 - isig1); for (kk = 0; kk < nvtot; ++kk) { pmapp = &vmap[kk]; if (pmapp->inew == iv) { if (pmapp->iqsig == 0) pmapp->iqsig = 2; } } } } pmap = NULL; pmapp = NULL; /* fill in sigma */ isold = 0; kk = 0; iv2 = 0; for (k = 0; k < nsig; ++k){ iv1 = iv2; pmap = &vmap[k]; isig1 = pmap->ix1 % nsym; isig2 = pmap->ix2 % nsym; iv2 = isig1 + isig2; if (isig1 == 0 && isig2 == 0) { sigma2[k] = 0; isold = 0; continue; } if (isold != 0) { isold = 0; if (iv2 == nsym) { sigma2[k] = kk; continue; } if (((iv1 + iv2) % nsym) == 0) { sigma2[k] = -kk; continue; } } if (isold == 0) { if (isig1 != 0 && isig2 != 0) ++kk; if (kk == 0) kk = 1; sigma2[k] = kk; isold = 1; } } for (k = 0; k < nsig; ++k) { kk = sigma2[k]; for (iv = nsig; iv < nvtot; iv += nsig) sigma2[k + iv] = kk; } if (lu == NULL) return nvtop; fputs("2 top mapping new v: iq old sig1 sig2, iqv vt, lz\n", lu); for (k = 0; k < nvtot; ++k){ pmap = &vmap[k]; i = pmap->iqv; if (i == 2) i = 1; if (i == 3) i = -1; isig = pmap->iqsig; if (isig == 2) isig = 1; if (isig == 3) isig = -1; isig1 = pmap->ix1; isig2 = pmap->ix2; iv2 = pmap->ix2 / nsym; iv1 = pmap->ix1 / nsym; fprintf(lu,"%3d: %2d %3d %3d, %2d %2d%2d, %3d %3d\n", k, isig, isig1, isig2, i, iv1, iv2, sigma2[k], pmap->inew); } return nvtop; } /* init2top */ int get2top(SIPAR *ppar,/*@out@*/ double *xpec2, int nvtot, int nft, int nsym, int *vmapsym, int *ivtop, int nvtop) { SXPEC *pxpec1, *pxpec2; double *dxpec1, *dxpec2, *dxpec; double va1, va2, vb1, vb2, fac; int nsymsq, iv, ivp, iv1, iv1p, iv2, iv2p, isig1, isig1p, isig2, isig2p, ivv; int ix, ix1, ix2, ndm2, noff, noff2, ioff, isig, isunit1, isunit2; int kdel, ndtot, ndtot2, ift, nft2, iret, nvib, nv1, nv2, isigp; kdel = -2; pxpec1 = ppar->ptxpec;\ if (pxpec1 != NULL) kdel = pxpec1->kdel; nsymsq = nsym * nsym; ndm2 = nsymsq * (nvtop >> 1); ndtot2 = ndm2 * ndm2; dxpec = xpec2; xpec2[0] = 0.; nft2 = nft; if (kdel > 0) nft2 = nft2 << 1; for (ift = 0; ift < nft2; ++ift) { if (ift > 0) dxpec += ndtot2; dcopy(ndtot2, &zero, 0, dxpec, 1); } if (pxpec1 == NULL) return 0; pxpec2 = ppar->ptxpecx; if (pxpec2 == NULL) return 0; dxpec1 = pxpec1->xpec; dxpec2 = pxpec2->xpec; if (dxpec1 == NULL || dxpec2 == NULL) return 0; noff2 = ndtot2 * nft; ndtot = nvtot * nvtot; nvib = nvtot >> 1; noff = ndtot * nft; iret = 0; isunit1 = pxpec1->isunit; isunit2 = pxpec2->isunit; nv1 = pxpec1->nval; nv2 = pxpec2->nval; /* load operators */ ioff = 0; for (iv = 0; iv < ndm2; ++iv) { ivv = iv / nsymsq; isig = iv - ivv * nsymsq; isig1 = isig / nsym; isig2 = isig - isig1 * nsym; ivv = ivv << 1; iv1 = isig1 + nsym * ivtop[ivv]; iv2 = isig2 + nsym * ivtop[ivv + 1] + nvib; for (ivp = 0; ivp < ndm2; ++ivp) { ivv = ivp / nsymsq; isigp = ivp - ivv * nsymsq; isig1p = isigp / nsym; isig2p = isigp - isig1p * nsym; if (nv1 == 0 && isig1p != isig1) continue; if (nv2 == 0 && isig2p != isig2) continue; ivv = ivv << 1; iv1p = isig1p + nsym * ivtop[ivv]; iv2p = isig2p + nsym * ivtop[ivv + 1] + nvib; if (isunit1 == 1 && iv1p != iv1) continue; if (isunit2 == 1 && iv2p != iv2) continue; ix1 = iv1 + nvtot * iv1p; ix2 = iv2 + nvtot * iv2p; va1 = dxpec1[ix1]; va2 = dxpec2[ix2]; ix = iv + ndm2 * ivp; if (kdel > 0) ioff = (isig - isigp) * (ndm2 - 1) + noff2; for (ift = 0; ift < nft; ++ift) { if (ift > 0) { ix1 += ndtot; ix2 += ndtot; ix += ndtot2; } va1 = dxpec1[ix1]; va2 = dxpec2[ix2]; if (kdel > 0) { vb1 = dxpec1[ix1 + noff]; vb2 = dxpec2[ix2 + noff]; if (nv1 < 0) vb1 = -vb1; if (nv2 < 0) vb2 = -vb2; xpec2[ix] = (va1 + vb1) * (va2 + vb2); xpec2[ix + ioff] = (va1 - vb1) * (va2 - vb2); } else { xpec2[ix] = va1 * va2; } } } } /* sigma symmetry */ for (iv = 0; iv < ndm2; ++iv) { if ((vmapsym[iv] & 3) == 0) continue; ivv = iv / nsymsq; isig = iv - ivv * nsymsq; isig1 = isig / nsym; isig2 = isig - isig1 * nsym; if (isig1 >= isig2) continue; ivv = iv + (nsym - 1) * (isig2 - isig1); ix1 = iv * ndm2; ix2 = ivv * ndm2; for (ift = 0; ift < nft2; ++ift) { if (ift > 0) { ix1 += ndtot2; ix2 += ndtot2; } drot(ndm2, &xpec2[ix1], 1, &xpec2[ix2], 1, rthalf, rthalf); } ix1 = iv; ix2 = ivv; for (ift = 0; ift < nft2; ++ift) { if (ift > 0) { ix1 += ndtot2; ix2 += ndtot2; } drot(ndm2, &xpec2[ix1], ndm2, &xpec2[ix2], ndm2, rthalf, rthalf); } } /* vibrational symmetry */ for (iv = 0; iv < ndm2; ++iv) { if ((vmapsym[iv] & 0x0c) == 0) continue; ivv = iv / nsymsq; ivv = ivv << 1; iv1 = ivtop[ivv]; iv2 = ivtop[ivv + 1]; if (iv1 >= iv2) continue; iv1p = ivtop[ivv + 2]; iv2p = ivtop[ivv + 3]; ivv = iv + nsymsq; ix1 = iv * ndm2; ix2 = ivv * ndm2; for (ift = 0; ift < nft2; ++ift) { if (ift > 0) { ix1 += ndtot2; ix2 += ndtot2; } drot(ndm2, &xpec2[ix1], 1, &xpec2[ix2], 1, rthalf, rthalf); } ix1 = iv; ix2 = ivv; for (ift = 0; ift < nft2; ++ift) { if (ift > 0) { ix1 += ndtot2; ix2 += ndtot2; } drot(ndm2, &xpec2[ix1], ndm2, &xpec2[ix2], ndm2, rthalf, rthalf); } } if (kdel > 0) { /* final operator fixup */ ivv = 0; if (ppar->offset != 0) ivv = 1; fac = 0.5; if (nv1 < 0 || nv2 < 0) fac = -fac; for (iv = 0; iv < ndm2; ++iv) { isig = iv % nsymsq; for (ivp = 0; ivp < ndm2; ++ivp) { isigp = ivp % nsymsq; ioff = (isig - isigp) * (ndm2 - 1) + noff2; ix = iv + ndm2 * ivp; for (ift = 0; ift < nft; ++ift) { if (ift > 0) { ix += ndtot2; } va1 = xpec2[ix]; vb1 = xpec2[ix + ioff]; if (ivv == 0) { xpec2[ix] = fac * (va1 + vb1); } else { xpec2[ix] = fac * (va1 - vb1); } } } } } ix = 5 * ndtot2; ioff = ix; if (kdel > 0) ioff += noff2; for (iv = 0; iv < ndm2; ++iv) { for (ivp = 0; ivp <= iv; ++ivp) { ix1 = iv + ndm2 * ivp; ix2 = ivp + ndm2 * iv; va1 = xpec2[ix1+ix]; va2 = xpec2[ix2+ix]; vb1 = xpec2[ix1+ioff]; vb2 = xpec2[ix2+ioff]; if (fabs(va1-va2) > 1.e-10) break; if (fabs(vb1-vb2) > 1.e-10) break; } if (ivp <= iv) break; } return iret; } /* get2top */ int wrpar(lu, id, nid, isdip, kflg, t, nt, labl, nfmt, drhok) FILE *lu; double *id; int kflg; double *t; int nt; int nid; int isdip; char *labl; int nfmt; double drhok; { /* id = parameter id */ /* isdip > 0 for dipole, else parameter */ /* kflg = flag indicating type of output */ /* t = vector of Fourier coefficients */ /* labl = parameter label */ /* nvfac2 = 100 or 10000 (size of vib field) */ /* nft = number of Fourier coefficients */ static double cmp; static char fmt0[] = " %14.0f %23.15E %s\n"; static char fmt1[] = "%14.0f%02d %23.15E %s\n"; static char fmt2[] = "%12.0f %10.6f %23.15E %s\n"; double fidc, finc, fidd, fida, fids, tmp, fid, tval, *tv, *tvp; int k, kk, nsym, n, i, ires, nret; long idtmp, idd; if (lu == NULL) return 0; fid = id[0]; tval = t[0]; nret = 0; if (kflg > 0) { /* print to output file format */ if (kflg <= 100) { if (fabs(tval) > cmp) { fprintf(lu, fmt0, fid, tval, labl); } } else { nsym = kflg - 100; if (dnrm2(nt, t, 1) > cmp) { for (k = 0; k < nt; ++k) { kk = k; if ((k + k) > nfmt) kk -= nfmt; tmp = kk * drhok; ++nret; fprintf(lu, fmt2, fid, tmp, t[k], labl); } } } if (isdip > 0) nret = 0; return nret; } else if (kflg == 0) { /* if kflg == 0 then print head type file and update comparison */ cmp = (fabs(tval) + tiny) * tiny; if (isdip == 0) { ++nret; if (nfmt > 0) fprintf(lu, fmt1, fid, nfmt, tval, labl); else fprintf(lu, fmt0, fid, tval, labl); } return nret; } /* if kflg < 0 then print par file format */ finc = (double) (nfmt / 100); n = nt - 1; if (isdip > 0) { /* dipole moments */ finc = 10. * finc; /* increment */ fidc = finc * 70.; /* base value */ fidd = finc * 10; /* sin - cos */ fida = finc * 90; /* carry */ if (n > 198) n = 198; } else { /* parameters */ finc *= 1.e7; fidc = 0.; fidd = finc * 10; fida = fidd; if (n > 98) n = 98; } tv = t; tmp = 0.; for (i = 0; i < nid; ++i) { fid = id[i]; tval = (*tv); if (fabs(tval) > cmp) { if (kflg == -2) { fid = fabs(fid); kflg = -1; } fprintf(lu, fmt0, fid, tval, labl); if (isdip == 0) ++nret; } else { *tv = 0.; } if (n > 0) tmp += dnrm2(n, &tv[1], 1); tv += nt; } if (tmp < tiny * nid) return nret; k = 0; if (isdip > 0) ++k; for (kk = 1; kk <= n; kk += 2) { if ((++k) > 10) { fidc += fida; k = 1; } fidc += finc; tv = &t[kk]; for (i = 0; i < nid; ++i) { idtmp = (long) id[i]; idd = idtmp / 100; ires = (int)(idtmp - 100 * idd); if (ires < 0) ires = - ires; fid = fidc + (double)idd; tval = (*tv); fids = fid + fidd; if (fabs(tval) > cmp) { if (kflg == -2) { fid = fabs(fid); kflg = -1; } fprintf(lu, fmt1, fid, ires, tval, labl); ++nret; } else { *tv = 0.; } tvp = tv + 1; tval = (*tvp); if (fabs(tval) > cmp) { if (kflg == -2) { fids = fabs(fids); kflg = -1; } fprintf(lu, fmt1, fids, ires, tval, labl); ++nret; } else { *tvp = 0.; } tv += nt; } } if (isdip > 0) nret = 0; return nret; } /* wrpar */