Beispiel #1
0
/* Subroutine */ int deriv_(doublereal *geo, doublereal *grad)
{
    /* Initialized data */

    static integer icalcn = 0;

    /* System generated locals */
    integer i__1, i__2, i__3, i__4;
    doublereal d__1, d__2;
    char ch__1[80];
    olist o__1;
    alist al__1;

    /* Builtin functions */
    integer i_indx(char *, char *, ftnlen, ftnlen), f_open(olist *), f_rew(
	    alist *), s_rsfe(cilist *), do_fio(integer *, char *, ftnlen), 
	    e_rsfe(void), s_wsfe(cilist *), e_wsfe(void);
    /* Subroutine */ int s_stop(char *, ftnlen);
    integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), 
	    e_rsle(void);
    double pow_di(doublereal *, integer *), sqrt(doublereal);
    integer s_wsle(cilist *), e_wsle(void);

    /* Local variables */
    static integer i__, j;
    static logical ci;
    static integer ii, ij, il, jl, kl, ll, kk;
    static logical aic;
    extern doublereal dot_(doublereal *, doublereal *, integer *);
    static logical int__;
    extern /* Subroutine */ int mxm_(doublereal *, integer *, doublereal *, 
	    integer *, doublereal *, integer *);
    static doublereal sum;
    static logical scf1;
    static char line[80];
    static integer ncol;
    static doublereal xjuc[3], step;
    static logical slow;
    static integer icapa;
    static logical halfe, debug;
    extern /* Subroutine */ int dcart_(doublereal *, doublereal *);
    static integer iline;
    static logical geook;
    static doublereal grlim;
    static integer ilowa;
    static doublereal gnorm;
    extern /* Subroutine */ int geout_(integer *);
    static integer ilowz;
    static doublereal change[3], aidref[360];
    static integer idelta;
    extern /* Character */ VOID getnam_(char *, ftnlen, char *, ftnlen);
    static logical precis, noanci, aifrst;
    extern /* Subroutine */ int dernvo_(doublereal *, doublereal *), jcarin_(
	    doublereal *, doublereal *, doublereal *, logical *, doublereal *,
	     integer *), gmetry_(doublereal *, doublereal *), deritr_(
	    doublereal *, doublereal *), symtry_(void);

    /* Fortran I/O blocks */
    static cilist io___14 = { 0, 5, 0, "(A)", 0 };
    static cilist io___17 = { 1, 5, 1, "(A)", 0 };
    static cilist io___19 = { 0, 6, 0, "(//,A)", 0 };
    static cilist io___20 = { 0, 6, 0, "(A)", 0 };
    static cilist io___21 = { 0, 6, 0, "(//,A)", 0 };
    static cilist io___22 = { 0, 6, 0, "(A)", 0 };
    static cilist io___23 = { 0, 6, 0, "(6F12.6)", 0 };
    static cilist io___25 = { 1, 5, 1, 0, 0 };
    static cilist io___26 = { 0, 6, 0, "(/,A,/)", 0 };
    static cilist io___27 = { 0, 6, 0, "(5F12.6)", 0 };
    static cilist io___28 = { 0, 6, 0, "(/,A,/)", 0 };
    static cilist io___29 = { 0, 6, 0, "(5F12.6)", 0 };
    static cilist io___31 = { 0, 6, 0, "(/,A,/)", 0 };
    static cilist io___32 = { 0, 6, 0, "(5F12.6)", 0 };
    static cilist io___37 = { 0, 6, 0, "(' GEO AT START OF DERIV')", 0 };
    static cilist io___38 = { 0, 6, 0, "(F19.5,2F12.5)", 0 };
    static cilist io___42 = { 0, 6, 0, 0, 0 };
    static cilist io___43 = { 0, 6, 0, 0, 0 };
    static cilist io___54 = { 0, 6, 0, "(//,3(A,/),I3,A)", 0 };
    static cilist io___55 = { 0, 6, 0, "(//,A)", 0 };
    static cilist io___56 = { 0, 6, 0, 0, 0 };
    static cilist io___57 = { 0, 6, 0, "(' GRADIENTS')", 0 };
    static cilist io___58 = { 0, 6, 0, "(10F8.3)", 0 };
    static cilist io___59 = { 0, 6, 0, "(' ERROR FUNCTION')", 0 };
    static cilist io___60 = { 0, 6, 0, "(10F8.3)", 0 };
    static cilist io___61 = { 0, 6, 0, "(' COSINE OF SEARCH DIRECTION =',F30"
	    ".6)", 0 };


/* COMDECK SIZES */
/* *********************************************************************** */
/*   THIS FILE CONTAINS ALL THE ARRAY SIZES FOR USE IN MOPAC. */

/*     THERE ARE ONLY 5 PARAMETERS THAT THE PROGRAMMER NEED SET: */
/*     MAXHEV = MAXIMUM NUMBER OF HEAVY ATOMS (HEAVY: NON-HYDROGEN ATOMS) */
/*     MAXLIT = MAXIMUM NUMBER OF HYDROGEN ATOMS. */
/*     MAXTIM = DEFAULT TIME FOR A JOB. (SECONDS) */
/*     MAXDMP = DEFAULT TIME FOR AUTOMATIC RESTART FILE GENERATION (SECS) */
/*     ISYBYL = 1 IF MOPAC IS TO BE USED IN THE SYBYL PACKAGE, =0 OTHERWISE */
/*     SEE ALSO NMECI, NPULAY AND MESP AT THE END OF THIS FILE */


/* *********************************************************************** */

/*   THE FOLLOWING CODE DOES NOT NEED TO BE ALTERED BY THE PROGRAMMER */

/* *********************************************************************** */

/*    ALL OTHER PARAMETERS ARE DERIVED FUNCTIONS OF THESE TWO PARAMETERS */

/*      NAME                   DEFINITION */
/*     NUMATM         MAXIMUM NUMBER OF ATOMS ALLOWED. */
/*     MAXORB         MAXIMUM NUMBER OF ORBITALS ALLOWED. */
/*     MAXPAR         MAXIMUM NUMBER OF PARAMETERS FOR OPTIMISATION. */
/*     N2ELEC         MAXIMUM NUMBER OF TWO ELECTRON INTEGRALS ALLOWED. */
/*     MPACK          AREA OF LOWER HALF TRIANGLE OF DENSITY MATRIX. */
/*     MORB2          SQUARE OF THE MAXIMUM NUMBER OF ORBITALS ALLOWED. */
/*     MAXHES         AREA OF HESSIAN MATRIX */
/*     MAXALL         LARGER THAN MAXORB OR MAXPAR. */
/* *********************************************************************** */

/* *********************************************************************** */
/* DECK MOPAC */
/* *********************************************************************** */

/*    DERIV CALCULATES THE DERIVATIVES OF THE ENERGY WITH RESPECT TO THE */
/*          INTERNAL COORDINATES. THIS IS DONE BY FINITE DIFFERENCES. */

/*    THE MAIN ARRAYS IN DERIV ARE: */
/*        LOC    INTEGER ARRAY, LOC(1,I) CONTAINS THE ADDRESS OF THE ATOM */
/*               INTERNAL COORDINATE LOC(2,I) IS TO BE USED IN THE */
/*               DERIVATIVE CALCULATION. */
/*        GEO    ARRAY \GEO\ HOLDS THE INTERNAL COORDINATES. */
/*        GRAD   ON EXIT, CONTAINS THE DERIVATIVES */

/* *********************************************************************** */
    /* Parameter adjustments */
    --grad;
    geo -= 4;

    /* Function Body */
    if (icalcn != numcal_1.numcal) {
	aifrst = i_indx(keywrd_1.keywrd, "RESTART", (ftnlen)241, (ftnlen)7) ==
		 0;
	debug = i_indx(keywrd_1.keywrd, "DERIV", (ftnlen)241, (ftnlen)5) != 0;
	precis = i_indx(keywrd_1.keywrd, "PREC", (ftnlen)241, (ftnlen)4) != 0;
	int__ = i_indx(keywrd_1.keywrd, " XYZ", (ftnlen)241, (ftnlen)4) == 0;
	geook = i_indx(keywrd_1.keywrd, "GEO-OK", (ftnlen)241, (ftnlen)6) != 
		0;
	ci = i_indx(keywrd_1.keywrd, "C.I.", (ftnlen)241, (ftnlen)4) != 0;
	scf1 = i_indx(keywrd_1.keywrd, "1SCF", (ftnlen)241, (ftnlen)4) != 0;
	aic = i_indx(keywrd_1.keywrd, "AIDER", (ftnlen)241, (ftnlen)5) != 0;
	icapa = 'A';
	ilowa = 'a';
	ilowz = 'z';
	if (aic && aifrst) {
	    o__1.oerr = 0;
	    o__1.ounit = 5;
	    o__1.ofnmlen = 80;
	    getnam_(ch__1, (ftnlen)80, "FOR005", (ftnlen)6);
	    o__1.ofnm = ch__1;
	    o__1.orl = 0;
	    o__1.osta = "OLD";
	    o__1.oacc = 0;
	    o__1.ofm = 0;
	    o__1.oblnk = "ZERO";
	    f_open(&o__1);
	    al__1.aerr = 0;
	    al__1.aunit = 5;
	    f_rew(&al__1);

/*  ISOK IS SET FALSE: ONLY ONE SYSTEM ALLOWED */

	    okmany_1.isok = FALSE_;
	    for (i__ = 1; i__ <= 3; ++i__) {
/* L10: */
		s_rsfe(&io___14);
		do_fio(&c__1, line, (ftnlen)80);
		e_rsfe();
	    }
	    for (j = 1; j <= 1000; ++j) {
		i__1 = s_rsfe(&io___17);
		if (i__1 != 0) {
		    goto L40;
		}
		i__1 = do_fio(&c__1, line, (ftnlen)80);
		if (i__1 != 0) {
		    goto L40;
		}
		i__1 = e_rsfe();
		if (i__1 != 0) {
		    goto L40;
		}
/* *********************************************************************** */
		for (i__ = 1; i__ <= 80; ++i__) {
		    iline = *(unsigned char *)&line[i__ - 1];
		    if (iline >= ilowa && iline <= ilowz) {
			*(unsigned char *)&line[i__ - 1] = (char) (iline + 
				icapa - ilowa);
		    }
/* L20: */
		}
/* *********************************************************************** */
/* L30: */
		if (i_indx(line, "AIDER", (ftnlen)80, (ftnlen)5) != 0) {
		    goto L60;
		}
	    }
L40:
	    s_wsfe(&io___19);
	    do_fio(&c__1, " KEYWORD \"AIDER\" SPECIFIED, BUT NOT", (ftnlen)35)
		    ;
	    e_wsfe();
	    s_wsfe(&io___20);
	    do_fio(&c__1, " PRESENT AFTER Z-MATRIX.  JOB STOPPED", (ftnlen)37)
		    ;
	    e_wsfe();
	    s_stop("", (ftnlen)0);
L50:
	    s_wsfe(&io___21);
	    do_fio(&c__1, "  FAULT IN READ OF AB INITIO DERIVATIVES", (ftnlen)
		    40);
	    e_wsfe();
	    s_wsfe(&io___22);
	    do_fio(&c__1, "  DERIVATIVES READ IN ARE AS FOLLOWS", (ftnlen)36);
	    e_wsfe();
	    s_wsfe(&io___23);
	    i__1 = i__;
	    for (j = 1; j <= i__1; ++j) {
		do_fio(&c__1, (char *)&aidref[j - 1], (ftnlen)sizeof(
			doublereal));
	    }
	    e_wsfe();
	    s_stop("", (ftnlen)0);
L60:
	    if (geokst_1.natoms > 2) {
		j = geokst_1.natoms * 3 - 6;
	    } else {
		j = 1;
	    }
	    i__1 = s_rsle(&io___25);
	    if (i__1 != 0) {
		goto L50;
	    }
	    i__2 = j;
	    for (i__ = 1; i__ <= i__2; ++i__) {
		i__1 = do_lio(&c__5, &c__1, (char *)&aidref[i__ - 1], (ftnlen)
			sizeof(doublereal));
		if (i__1 != 0) {
		    goto L50;
		}
	    }
	    i__1 = e_rsle();
	    if (i__1 != 0) {
		goto L50;
	    }
	    s_wsfe(&io___26);
	    do_fio(&c__1, " AB-INITIO DERIVATIVES IN KCAL/MOL/(ANGSTROM OR R"
		    "ADIAN)", (ftnlen)55);
	    e_wsfe();
	    s_wsfe(&io___27);
	    i__1 = j;
	    for (i__ = 1; i__ <= i__1; ++i__) {
		do_fio(&c__1, (char *)&aidref[i__ - 1], (ftnlen)sizeof(
			doublereal));
	    }
	    e_wsfe();
	    i__1 = geovar_1.nvar;
	    for (i__ = 1; i__ <= i__1; ++i__) {
		if (geovar_1.loc[(i__ << 1) - 2] > 3) {
		    j = geovar_1.loc[(i__ << 1) - 2] * 3 + geovar_1.loc[(i__ 
			    << 1) - 1] - 9;
		} else if (geovar_1.loc[(i__ << 1) - 2] == 3) {
		    j = geovar_1.loc[(i__ << 1) - 1] + 1;
		} else {
		    j = 1;
		}
/* L70: */
		aidref[i__ - 1] = aidref[j - 1];
	    }
	    s_wsfe(&io___28);
	    do_fio(&c__1, " AB-INITIO DERIVATIVES FOR VARIABLES", (ftnlen)36);
	    e_wsfe();
	    s_wsfe(&io___29);
	    i__1 = geovar_1.nvar;
	    for (i__ = 1; i__ <= i__1; ++i__) {
		do_fio(&c__1, (char *)&aidref[i__ - 1], (ftnlen)sizeof(
			doublereal));
	    }
	    e_wsfe();
	    if (geosym_1.ndep != 0) {
		i__1 = geovar_1.nvar;
		for (i__ = 1; i__ <= i__1; ++i__) {
		    sum = aidref[i__ - 1];
		    i__2 = geosym_1.ndep;
		    for (j = 1; j <= i__2; ++j) {
			if (geovar_1.loc[(i__ << 1) - 2] == geosym_1.locpar[j 
				- 1] && (geovar_1.loc[(i__ << 1) - 1] == 
				geosym_1.idepfn[j - 1] || geovar_1.loc[(i__ <<
				 1) - 1] == 3 && geosym_1.idepfn[j - 1] == 14)
				) {
			    aidref[i__ - 1] += sum;
			}
/* L80: */
		    }
/* L90: */
		}
		s_wsfe(&io___31);
		do_fio(&c__1, " AB-INITIO DERIVATIVES AFTER SYMMETRY WEIGHTI"
			"NG", (ftnlen)47);
		e_wsfe();
		s_wsfe(&io___32);
		i__1 = geovar_1.nvar;
		for (j = 1; j <= i__1; ++j) {
		    do_fio(&c__1, (char *)&aidref[j - 1], (ftnlen)sizeof(
			    doublereal));
		}
		e_wsfe();
	    }
	}
	icalcn = numcal_1.numcal;
	if (i_indx(keywrd_1.keywrd, "RESTART", (ftnlen)241, (ftnlen)7) == 0) {
	    i__1 = geovar_1.nvar;
	    for (i__ = 1; i__ <= i__1; ++i__) {
/* L100: */
		errfn_1.errfn[i__ - 1] = 0.;
	    }
	}
	grlim = .01;
	if (precis) {
	    grlim = 1e-4;
	}
	halfe = molkst_1.nopen > molkst_1.nclose && molkst_1.fract != 2. && 
		molkst_1.fract != 0. || ci;
	idelta = -7;

/*   IDELTA IS A MACHINE-PRECISION DEPENDANT INTEGER */

	change[0] = pow_di(&c_b70, &idelta);
	change[1] = pow_di(&c_b70, &idelta);
	change[2] = pow_di(&c_b70, &idelta);

/*    CHANGE(I) IS THE STEP SIZE USED IN CALCULATING THE DERIVATIVES. */
/*    FOR "CARTESIAN" DERIVATIVES, CALCULATED USING DCART,AN */
/*    INFINITESIMAL STEP, HERE 0.000001, IS ACCEPTABLE. IN THE */
/*    HALF-ELECTRON METHOD A QUITE LARGE STEP IS NEEDED AS FULL SCF */
/*    CALCULATIONS ARE NEEDED, AND THE DIFFERENCE BETWEEN THE TOTAL */
/*    ENERGIES IS USED. THE STEP CANNOT BE VERY LARGE, AS THE SECOND */
/*    DERIVITIVE IN FLEPO IS CALCULATED FROM THE DIFFERENCES OF TWO */
/*    FIRST DERIVATIVES. CHANGE(1) IS FOR CHANGE IN BOND LENGTH, */
/*    (2) FOR ANGLE, AND (3) FOR DIHEDRAL. */

    }
    if (geovar_1.nvar == 0) {
	return 0;
    }
    if (debug) {
	s_wsfe(&io___37);
	e_wsfe();
	s_wsfe(&io___38);
	i__1 = geokst_1.natoms;
	for (i__ = 1; i__ <= i__1; ++i__) {
	    for (j = 1; j <= 3; ++j) {
		do_fio(&c__1, (char *)&geo[j + i__ * 3], (ftnlen)sizeof(
			doublereal));
	    }
	}
	e_wsfe();
    }
    gnorm = 0.;
    i__1 = geovar_1.nvar;
    for (i__ = 1; i__ <= i__1; ++i__) {
	genral_1.gold[i__ - 1] = grad[i__];
	genral_1.xparam[i__ - 1] = geo[geovar_1.loc[(i__ << 1) - 1] + 
		geovar_1.loc[(i__ << 1) - 2] * 3];
/* L110: */
/* Computing 2nd power */
	d__1 = grad[i__];
	gnorm += d__1 * d__1;
    }
    gnorm = sqrt(gnorm);
    slow = FALSE_;
    noanci = FALSE_;
    if (halfe) {
	noanci = i_indx(keywrd_1.keywrd, "NOANCI", (ftnlen)241, (ftnlen)6) != 
		0 || molkst_1.nopen == molkst_1.norbs;
	slow = noanci && (gnorm < grlim || scf1);
    }
    if (geosym_1.ndep != 0) {
	symtry_();
    }
    gmetry_(&geo[4], genral_1.coord);

/*  COORD NOW HOLDS THE CARTESIAN COORDINATES */

    if (halfe && ! noanci) {
	if (debug) {
	    s_wsle(&io___42);
	    do_lio(&c__9, &c__1, "DOING ANALYTICAL C.I. DERIVATIVES", (ftnlen)
		    33);
	    e_wsle();
	}
	dernvo_(genral_1.coord, xyzgra_1.dxyz);
    } else {
	if (debug) {
	    s_wsle(&io___43);
	    do_lio(&c__9, &c__1, "DOING VARIATIONALLY OPIMIZED DERIVATIVES", (
		    ftnlen)40);
	    e_wsle();
	}
	dcart_(genral_1.coord, xyzgra_1.dxyz);
    }
    ij = 0;
    i__1 = molkst_1.numat;
    for (ii = 1; ii <= i__1; ++ii) {
	i__2 = ucell_1.l1u;
	for (il = ucell_1.l1l; il <= i__2; ++il) {
	    i__3 = ucell_1.l2u;
	    for (jl = ucell_1.l2l; jl <= i__3; ++jl) {
		i__4 = ucell_1.l3u;
		for (kl = ucell_1.l3l; kl <= i__4; ++kl) {
/* $DOIT ASIS */
		    for (ll = 1; ll <= 3; ++ll) {
/* L120: */
			xjuc[ll - 1] = genral_1.coord[ll + ii * 3 - 4] + 
				euler_1.tvec[ll - 1] * il + euler_1.tvec[ll + 
				2] * jl + euler_1.tvec[ll + 5] * kl;
		    }
		    ++ij;
/* $DOIT ASIS */
		    for (kk = 1; kk <= 3; ++kk) {
			genral_1.cold[kk + ij * 3 - 4] = xjuc[kk - 1];
/* L130: */
		    }
/* L140: */
		}
	    }
	}
/* L150: */
    }
    step = change[0];
    jcarin_(genral_1.coord, genral_1.xparam, &step, &precis, work3_1.work2, &
	    ncol);
    mxm_(work3_1.work2, &geovar_1.nvar, xyzgra_1.dxyz, &ncol, &grad[1], &c__1)
	    ;
    if (precis) {
	step = .5 / step;
    } else {
	step = 1. / step;
    }
    i__1 = geovar_1.nvar;
    for (i__ = 1; i__ <= i__1; ++i__) {
/* L160: */
	grad[i__] *= step;
    }

/*  NOW TO ENSURE THAT INTERNAL DERIVATIVES ACCURATELY REFLECT CARTESIAN */
/*  DERIVATIVES */

    if (int__ && ! geook && geovar_1.nvar >= molkst_1.numat * 3 - 6 && 
	    euler_1.id == 0) {

/*  NUMBER OF VARIABLES LOOKS O.K. */

	sum = dot_(&grad[1], &grad[1], &geovar_1.nvar);
	i__1 = molkst_1.numat * 3;
/* Computing MAX */
	d__1 = 4., d__2 = sum * 4.;
	if (sum < 2. && dot_(xyzgra_1.dxyz, xyzgra_1.dxyz, &i__1) > max(d__1,
		d__2)) {

/* OOPS, LOOKS LIKE AN ERROR. */

	    i__1 = geovar_1.nvar;
	    for (i__ = 1; i__ <= i__1; ++i__) {
		j = (integer) (genral_1.xparam[i__ - 1] / 3.141);
		if (geovar_1.loc[(i__ << 1) - 1] == 2 && geovar_1.loc[(i__ << 
			1) - 2] > 3 && (d__1 = genral_1.xparam[i__ - 1] - j * 
			3.1415926, abs(d__1)) < .005) {

/*  ERROR LOCATED, BUT CANNOT CORRECT IN THIS RUN */

		    s_wsfe(&io___54);
		    do_fio(&c__1, " INTERNAL COORDINATE DERIVATIVES DO NOT R"
			    "EFLECT", (ftnlen)47);
		    do_fio(&c__1, " CARTESIAN COORDINATE DERIVATIVES", (
			    ftnlen)33);
		    do_fio(&c__1, " TO CORRECT ERROR, INCREASE DIHEDRAL OF A"
			    "TOM", (ftnlen)44);
		    do_fio(&c__1, (char *)&geovar_1.loc[(i__ << 1) - 2], (
			    ftnlen)sizeof(integer));
		    do_fio(&c__1, " BY 90 DEGREES", (ftnlen)14);
		    e_wsfe();
		    s_wsfe(&io___55);
		    do_fio(&c__1, "     CURRENT GEOMETRY", (ftnlen)21);
		    e_wsfe();
		    geout_(&c__6);
		    s_stop("", (ftnlen)0);
		}
/* L170: */
	    }
	}
    }

/*  THIS CODE IS ONLY USED IF THE KEYWORD NOANCI IS SPECIFIED */
    if (slow) {
	if (debug) {
	    s_wsle(&io___56);
	    do_lio(&c__9, &c__1, "DOING FULL SCF DERIVATIVES", (ftnlen)26);
	    e_wsle();
	}
	deritr_(errfn_1.errfn, &geo[4]);

/* THE ARRAY ERRFN HOLDS THE EXACT DERIVATIVES MINUS THE APPROXIMATE */
/* DERIVATIVES */
	i__1 = geovar_1.nvar;
	for (i__ = 1; i__ <= i__1; ++i__) {
/* L180: */
	    errfn_1.errfn[i__ - 1] -= grad[i__];
	}
    }
    gravec_1.cosine = dot_(&grad[1], genral_1.gold, &geovar_1.nvar) / sqrt(
	    dot_(&grad[1], &grad[1], &geovar_1.nvar) * dot_(genral_1.gold, 
	    genral_1.gold, &geovar_1.nvar) + 1e-20);
    i__1 = geovar_1.nvar;
    for (i__ = 1; i__ <= i__1; ++i__) {
/* L190: */
	grad[i__] += errfn_1.errfn[i__ - 1];
    }
    if (aic) {
	if (aifrst) {
	    aifrst = FALSE_;
	    i__1 = geovar_1.nvar;
	    for (i__ = 1; i__ <= i__1; ++i__) {
/* L200: */
		errfn_1.aicorr[i__ - 1] = -aidref[i__ - 1] - grad[i__];
	    }
	}
/* #         WRITE(6,'('' GRADIENTS BEFORE AI CORRECTION'')') */
/* #         WRITE(6,'(10F8.3)')(GRAD(I),I=1,NVAR) */
	i__1 = geovar_1.nvar;
	for (i__ = 1; i__ <= i__1; ++i__) {
/* L210: */
	    grad[i__] += errfn_1.aicorr[i__ - 1];
	}
    }
/* L220: */
    if (debug) {
	s_wsfe(&io___57);
	e_wsfe();
	s_wsfe(&io___58);
	i__1 = geovar_1.nvar;
	for (i__ = 1; i__ <= i__1; ++i__) {
	    do_fio(&c__1, (char *)&grad[i__], (ftnlen)sizeof(doublereal));
	}
	e_wsfe();
	if (slow) {
	    s_wsfe(&io___59);
	    e_wsfe();
	    s_wsfe(&io___60);
	    i__1 = geovar_1.nvar;
	    for (i__ = 1; i__ <= i__1; ++i__) {
		do_fio(&c__1, (char *)&errfn_1.errfn[i__ - 1], (ftnlen)sizeof(
			doublereal));
	    }
	    e_wsfe();
	}
    }
    if (debug) {
	s_wsfe(&io___61);
	do_fio(&c__1, (char *)&gravec_1.cosine, (ftnlen)sizeof(doublereal));
	e_wsfe();
    }
    return 0;
} /* deriv_ */
Beispiel #2
0
/* $Procedure      BODMAT ( Return transformation matrix for a body ) */
/* Subroutine */ int bodmat_(integer *body, doublereal *et, doublereal *tipm)
{
    /* Initialized data */

    static logical first = TRUE_;
    static logical found = FALSE_;

    /* System generated locals */
    integer i__1, i__2, i__3;
    doublereal d__1;

    /* Builtin functions */
    integer s_rnge(char *, integer, char *, integer);
    /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen);
    integer i_dnnt(doublereal *);
    double sin(doublereal), cos(doublereal), d_mod(doublereal *, doublereal *)
	    ;

    /* Local variables */
    integer cent;
    char item[32];
    doublereal j2ref[9]	/* was [3][3] */;
    extern integer zzbodbry_(integer *);
    extern /* Subroutine */ int eul2m_(doublereal *, doublereal *, doublereal 
	    *, integer *, integer *, integer *, doublereal *);
    doublereal d__;
    integer i__, j;
    doublereal dcoef[3], t, w;
    extern /* Subroutine */ int etcal_(doublereal *, char *, ftnlen);
    integer refid;
    doublereal delta;
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    doublereal epoch, rcoef[3], tcoef[200]	/* was [2][100] */, wcoef[3];
    extern /* Subroutine */ int errch_(char *, char *, ftnlen, ftnlen);
    doublereal theta;
    extern /* Subroutine */ int moved_(doublereal *, integer *, doublereal *),
	     repmi_(char *, char *, integer *, char *, ftnlen, ftnlen, ftnlen)
	    , errdp_(char *, doublereal *, ftnlen);
    doublereal costh[100];
    extern doublereal vdotg_(doublereal *, doublereal *, integer *);
    char dtype[1];
    doublereal sinth[100], tsipm[36]	/* was [6][6] */;
    extern doublereal twopi_(void);
    static integer j2code;
    doublereal ac[100], dc[100];
    integer na, nd;
    doublereal ra, wc[100];
    extern /* Subroutine */ int cleard_(integer *, doublereal *);
    extern logical bodfnd_(integer *, char *, ftnlen);
    extern /* Subroutine */ int bodvcd_(integer *, char *, integer *, integer 
	    *, doublereal *, ftnlen);
    integer frcode;
    extern doublereal halfpi_(void);
    extern /* Subroutine */ int ccifrm_(integer *, integer *, integer *, char 
	    *, integer *, logical *, ftnlen);
    integer nw;
    doublereal conepc, conref;
    extern /* Subroutine */ int pckmat_(integer *, doublereal *, integer *, 
	    doublereal *, logical *);
    integer ntheta;
    extern /* Subroutine */ int gdpool_(char *, integer *, integer *, integer 
	    *, doublereal *, logical *, ftnlen);
    char fixfrm[32], errmsg[1840];
    extern /* Subroutine */ int irfnum_(char *, integer *, ftnlen), dtpool_(
	    char *, logical *, integer *, char *, ftnlen, ftnlen);
    doublereal tmpmat[9]	/* was [3][3] */;
    extern /* Subroutine */ int setmsg_(char *, ftnlen), suffix_(char *, 
	    integer *, char *, ftnlen, ftnlen), errint_(char *, integer *, 
	    ftnlen), sigerr_(char *, ftnlen), chkout_(char *, ftnlen), 
	    irfrot_(integer *, integer *, doublereal *);
    extern logical return_(void);
    char timstr[35];
    extern doublereal j2000_(void);
    doublereal dec;
    integer dim, ref;
    doublereal phi;
    extern doublereal rpd_(void), spd_(void);
    extern /* Subroutine */ int mxm_(doublereal *, doublereal *, doublereal *)
	    ;

/* $ Abstract */

/*     Return the J2000 to body Equator and Prime Meridian coordinate */
/*     transformation matrix for a specified body. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     PCK */
/*     NAIF_IDS */
/*     TIME */

/* $ Keywords */

/*     CONSTANTS */

/* $ Declarations */
/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */


/*     Include File:  SPICELIB Error Handling Parameters */

/*        errhnd.inc  Version 2    18-JUN-1997 (WLT) */

/*           The size of the long error message was */
/*           reduced from 25*80 to 23*80 so that it */
/*           will be accepted by the Microsoft Power Station */
/*           FORTRAN compiler which has an upper bound */
/*           of 1900 for the length of a character string. */

/*        errhnd.inc  Version 1    29-JUL-1997 (NJB) */



/*     Maximum length of the long error message: */


/*     Maximum length of the short error message: */


/*     End Include File:  SPICELIB Error Handling Parameters */

/* $ Abstract */

/*     The parameters below form an enumerated list of the recognized */
/*     frame types.  They are: INERTL, PCK, CK, TK, DYN.  The meanings */
/*     are outlined below. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Parameters */

/*     INERTL      an inertial frame that is listed in the routine */
/*                 CHGIRF and that requires no external file to */
/*                 compute the transformation from or to any other */
/*                 inertial frame. */

/*     PCK         is a frame that is specified relative to some */
/*                 INERTL frame and that has an IAU model that */
/*                 may be retrieved from the PCK system via a call */
/*                 to the routine TISBOD. */

/*     CK          is a frame defined by a C-kernel. */

/*     TK          is a "text kernel" frame.  These frames are offset */
/*                 from their associated "relative" frames by a */
/*                 constant rotation. */

/*     DYN         is a "dynamic" frame.  These currently are */
/*                 parameterized, built-in frames where the full frame */
/*                 definition depends on parameters supplied via a */
/*                 frame kernel. */

/* $ Author_and_Institution */

/*     N.J. Bachman    (JPL) */
/*     W.L. Taber      (JPL) */

/* $ Literature_References */

/*     None. */

/* $ Version */

/* -    SPICELIB Version 3.0.0, 28-MAY-2004 (NJB) */

/*       The parameter DYN was added to support the dynamic frame class. */

/* -    SPICELIB Version 2.0.0, 12-DEC-1996 (WLT) */

/*        Various unused frames types were removed and the */
/*        frame time TK was added. */

/* -    SPICELIB Version 1.0.0, 10-DEC-1995 (WLT) */

/* -& */
/* $ Brief_I/O */

/*     VARIABLE  I/O  DESCRIPTION */
/*     --------  ---  -------------------------------------------------- */
/*     BODY       I   ID code of body. */
/*     ET         I   Epoch of transformation. */
/*     TIPM       O   Transformation from Inertial to PM for BODY at ET. */

/* $ Detailed_Input */

/*     BODY        is the integer ID code of the body for which the */
/*                 transformation is requested. Bodies are numbered */
/*                 according to the standard NAIF numbering scheme. */

/*     ET          is the epoch at which the transformation is */
/*                 requested. (This is typically the epoch of */
/*                 observation minus the one-way light time from */
/*                 the observer to the body at the epoch of */
/*                 observation.) */

/* $ Detailed_Output */

/*     TIPM        is the transformation matrix from Inertial to body */
/*                 Equator and Prime Meridian.  The X axis of the PM */
/*                 system is directed to the intersection of the */
/*                 equator and prime meridian. The Z axis points north. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1) If data required to define the body-fixed frame associated */
/*        with BODY are not found in the binary PCK system or the kernel */
/*        pool, the error SPICE(FRAMEDATANOTFOUND) is signaled. In */
/*        the case of IAU style body-fixed frames, the absence of */
/*        prime meridian polynomial data (which are required) is used */
/*        as an indicator of missing data. */

/*     2) If the test for exception (1) passes, but in fact requested */
/*        data are not available in the kernel pool, the error will be */
/*        signaled by routines in the call tree of this routine. */

/*     3) If the kernel pool does not contain all of the data required */
/*        to define the number of nutation precession angles */
/*        corresponding to the available nutation precession */
/*        coefficients, the error SPICE(INSUFFICIENTANGLES) is */
/*        signaled. */

/*     4) If the reference frame REF is not recognized, a routine */
/*        called by BODMAT will diagnose the condition and invoke the */
/*        SPICE error handling system. */

/*     5) If the specified body code BODY is not recognized, the */
/*        error is diagnosed by a routine called by BODMAT. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     This routine is related to the more general routine TIPBOD */
/*     which returns a matrix that transforms vectors from a */
/*     specified inertial reference frame to body equator and */
/*     prime meridian coordinates.  TIPBOD accepts an input argument */
/*     REF that allows the caller to specify an inertial reference */
/*     frame. */

/*     The transformation represented by BODMAT's output argument TIPM */
/*     is defined as follows: */

/*        TIPM = [W] [DELTA] [PHI] */
/*                 3        1     3 */

/*     If there exists high-precision binary PCK kernel information */
/*     for the body at the requested time, these angles, W, DELTA */
/*     and PHI are computed directly from that file.  The most */
/*     recently loaded binary PCK file has first priority followed */
/*     by previously loaded binary PCK files in backward time order. */
/*     If no binary PCK file has been loaded, the text P_constants */
/*     kernel file is used. */

/*     If there is only text PCK kernel information, it is */
/*     expressed in terms of RA, DEC and W (same W as above), where */

/*        RA    = PHI - HALFPI() */
/*        DEC   = HALFPI() - DELTA */

/*     RA, DEC, and W are defined as follows in the text PCK file: */

/*           RA  = RA0  + RA1*T  + RA2*T*T   + a  sin theta */
/*                                              i          i */

/*           DEC = DEC0 + DEC1*T + DEC2*T*T  + d  cos theta */
/*                                              i          i */

/*           W   = W0   + W1*d   + W2*d*d    + w  sin theta */
/*                                              i          i */

/*     where: */

/*           d = days past J2000. */

/*           T = Julian centuries past J2000. */

/*           a , d , and w  arrays apply to satellites only. */
/*            i   i       i */

/*           theta  = THETA0 * THETA1*T are specific to each planet. */
/*                i */

/*     These angles -- typically nodal rates -- vary in number and */
/*     definition from one planetary system to the next. */

/* $ Examples */

/*     In the following code fragment, BODMAT is used to rotate */
/*     the position vector (POS) from a target body (BODY) to a */
/*     spacecraft from inertial coordinates to body-fixed coordinates */
/*     at a specific epoch (ET), in order to compute the planetocentric */
/*     longitude (PCLONG) of the spacecraft. */

/*        CALL BODMAT ( BODY, ET, TIPM ) */
/*        CALL MXV    ( TIPM, POS, POS ) */
/*        CALL RECLAT ( POS, RADIUS, PCLONG, LAT ) */

/*     To compute the equivalent planetographic longitude (PGLONG), */
/*     it is necessary to know the direction of rotation of the target */
/*     body, as shown below. */

/*        CALL BODVCD ( BODY, 'PM', 3, DIM, VALUES ) */

/*        IF ( VALUES(2) .GT. 0.D0 ) THEN */
/*           PGLONG = PCLONG */
/*        ELSE */
/*           PGLONG = TWOPI() - PCLONG */
/*        END IF */

/*     Note that the items necessary to compute the transformation */
/*     TIPM must have been loaded into the kernel pool (by one or more */
/*     previous calls to FURNSH). */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     1)  Refer to the NAIF_IDS required reading file for a complete */
/*         list of the NAIF integer ID codes for bodies. */

/* $ Author_and_Institution */

/*     N.J. Bachman    (JPL) */
/*     W.L. Taber      (JPL) */
/*     I.M. Underwood  (JPL) */
/*     K.S. Zukor      (JPL) */

/* $ Version */

/* -    SPICELIB Version 4.1.1, 01-FEB-2008 (NJB) */

/*        The routine was updated to improve the error messages created */
/*        when required PCK data are not found. Now in most cases the */
/*        messages are created locally rather than by the kernel pool */
/*        access routines. In particular missing binary PCK data will */
/*        be indicated with a reasonable error message. */

/* -    SPICELIB Version 4.1.0, 25-AUG-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in MXM call. */

/*         Calls to ZZBODVCD have been replaced with calls to */
/*         BODVCD. */

/* -     SPICELIB Version 4.0.0, 12-FEB-2004 (NJB) */

/*         Code has been updated to support satellite ID codes in the */
/*         range 10000 to 99999 and to allow nutation precession angles */
/*         to be associated with any object. */

/*         Implementation changes were made to improve robustness */
/*         of the code. */

/* -     SPICELIB Version 3.2.0, 22-MAR-1995 (KSZ) */

/*        Gets TSIPM matrix from PCKMAT (instead of Euler angles */
/*        from PCKEUL.) */

/* -     SPICELIB Version 3.0.0, 10-MAR-1994 (KSZ) */

/*        Ability to get Euler angles from binary PCK file added. */
/*        This uses the new routine PCKEUL. */

/* -     SPICELIB Version 2.0.1, 10-MAR-1992 (WLT) */

/*         Comment section for permuted index source lines was added */
/*         following the header. */

/* -     SPICELIB Version 2.0.0, 04-SEP-1991 (NJB) */

/*         Updated to handle P_constants referenced to different epochs */
/*         and inertial reference frames. */

/*         The header was updated to specify that the inertial reference */
/*         frame used by BODMAT is restricted to be J2000. */

/* -    SPICELIB Version 1.0.0, 31-JAN-1990 (WLT) (IMU) */

/* -& */
/* $ Index_Entries */

/*     fetch transformation matrix for a body */
/*     transformation from j2000 position to bodyfixed */
/*     transformation from j2000 to bodyfixed coordinates */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 4.1.0, 25-AUG-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in MXM call. */

/*         Calls to ZZBODVCD have been replaced with calls to */
/*         BODVCD. */

/* -     SPICELIB Version 4.0.0, 12-FEB-2004 (NJB) */

/*         Code has been updated to support satellite ID codes in the */
/*         range 10000 to 99999 and to allow nutation precession angles */
/*         to be associated with any object. */

/*         Calls to deprecated kernel pool access routine RTPOOL */
/*         were replaced by calls to GDPOOL. */

/*         Calls to BODVAR have been replaced with calls to */
/*         ZZBODVCD. */

/* -     SPICELIB Version 3.2.0, 22-MAR-1995 (KSZ) */

/*        BODMAT now get the TSIPM matrix from PCKMAT, and */
/*        unpacks TIPM from it.  Also the calculated but unused */
/*        variable LAMBDA was removed. */

/* -     SPICELIB Version 3.0.0, 10-MAR-1994 (KSZ) */

/*        BODMAT now uses new software to check for the */
/*        existence of binary PCK files, search the for */
/*        data corresponding to the requested body and time, */
/*        and return the appropriate Euler angles, using the */
/*        new routine PCKEUL.  Otherwise the code calculates */
/*        the Euler angles from the P_constants kernel file. */

/* -     SPICELIB Version 2.0.0, 04-SEP-1991 (NJB) */

/*         Updated to handle P_constants referenced to different epochs */
/*         and inertial reference frames. */

/*         The header was updated to specify that the inertial reference */
/*         frame used by BODMAT is restricted to be J2000. */

/*         BODMAT now checks the kernel pool for presence of the */
/*         variables */

/*            BODY#_CONSTANTS_REF_FRAME */

/*         and */

/*            BODY#_CONSTANTS_JED_EPOCH */

/*         where # is the NAIF integer code of the barycenter of a */
/*         planetary system or of a body other than a planet or */
/*         satellite.  If either or both of these variables are */
/*         present, the P_constants for BODY are presumed to be */
/*         referenced to the specified inertial frame or epoch. */
/*         If the epoch of the constants is not J2000, the input */
/*         time ET is converted to seconds past the reference epoch. */
/*         If the frame of the constants is not J2000, the rotation from */
/*         the P_constants' frame to body-fixed coordinates is */
/*         transformed to the rotation from J2000 coordinates to */
/*         body-fixed coordinates. */

/*         For efficiency reasons, this routine now duplicates much */
/*         of the code of BODEUL so that it doesn't have to call BODEUL. */
/*         In some cases, BODEUL must covert Euler angles to a matrix, */
/*         rotate the matrix, and convert the result back to Euler */
/*         angles.  If this routine called BODEUL, then in such cases */
/*         this routine would convert the transformed angles back to */
/*         a matrix.  That would be a bit much.... */


/* -    Beta Version 1.1.0, 16-FEB-1989 (IMU) (NJB) */

/*        Examples section completed.  Declaration of unused variable */
/*        FOUND removed. */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     Local variables */


/*     Saved variables */


/*     Initial values */


/*     Standard SPICE Error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("BODMAT", (ftnlen)6);
    }

/*     Get the code for the J2000 frame, if we don't have it yet. */

    if (first) {
	irfnum_("J2000", &j2code, (ftnlen)5);
	first = FALSE_;
    }

/*     Get Euler angles from high precision data file. */

    pckmat_(body, et, &ref, tsipm, &found);
    if (found) {
	for (i__ = 1; i__ <= 3; ++i__) {
	    for (j = 1; j <= 3; ++j) {
		tipm[(i__1 = i__ + j * 3 - 4) < 9 && 0 <= i__1 ? i__1 : 
			s_rnge("tipm", i__1, "bodmat_", (ftnlen)485)] = tsipm[
			(i__2 = i__ + j * 6 - 7) < 36 && 0 <= i__2 ? i__2 : 
			s_rnge("tsipm", i__2, "bodmat_", (ftnlen)485)];
	    }
	}
    } else {

/*        The data for the frame of interest are not available in a */
/*        loaded binary PCK file. This is not an error: the data may be */
/*        present in the kernel pool. */

/*        Conduct a non-error-signaling check for the presence of a */
/*        kernel variable that is required to implement an IAU style */
/*        body-fixed reference frame. If the data aren't available, we */
/*        don't want BODVCD to signal a SPICE(KERNELVARNOTFOUND) error; */
/*        we want to issue the error signal locally, with a better error */
/*        message. */

	s_copy(item, "BODY#_PM", (ftnlen)32, (ftnlen)8);
	repmi_(item, "#", body, item, (ftnlen)32, (ftnlen)1, (ftnlen)32);
	dtpool_(item, &found, &nw, dtype, (ftnlen)32, (ftnlen)1);
	if (! found) {

/*           Now we do have an error. */

/*           We don't have the data we'll need to produced the requested */
/*           state transformation matrix. In order to create an error */
/*           message understandable to the user, find, if possible, the */
/*           name of the reference frame associated with the input body. */
/*           Note that the body is really identified by a PCK frame class */
/*           ID code, though most of the documentation just calls it a */
/*           body ID code. */

	    ccifrm_(&c__2, body, &frcode, fixfrm, &cent, &found, (ftnlen)32);
	    etcal_(et, timstr, (ftnlen)35);
	    s_copy(errmsg, "PCK data required to compute the orientation of "
		    "the # # for epoch # TDB were not found. If these data we"
		    "re to be provided by a binary PCK file, then it is possi"
		    "ble that the PCK file does not have coverage for the spe"
		    "cified body-fixed frame at the time of interest. If the "
		    "data were to be provided by a text PCK file, then possib"
		    "ly the file does not contain data for the specified body"
		    "-fixed frame. In either case it is possible that a requi"
		    "red PCK file was not loaded at all.", (ftnlen)1840, (
		    ftnlen)475);

/*           Fill in the variable data in the error message. */

	    if (found) {

/*              The frame system knows the name of the body-fixed frame. */

		setmsg_(errmsg, (ftnlen)1840);
		errch_("#", "body-fixed frame", (ftnlen)1, (ftnlen)16);
		errch_("#", fixfrm, (ftnlen)1, (ftnlen)32);
		errch_("#", timstr, (ftnlen)1, (ftnlen)35);
	    } else {

/*              The frame system doesn't know the name of the */
/*              body-fixed frame, most likely due to a missing */
/*              frame kernel. */

		suffix_("#", &c__1, errmsg, (ftnlen)1, (ftnlen)1840);
		setmsg_(errmsg, (ftnlen)1840);
		errch_("#", "body-fixed frame associated with the ID code", (
			ftnlen)1, (ftnlen)44);
		errint_("#", body, (ftnlen)1);
		errch_("#", timstr, (ftnlen)1, (ftnlen)35);
		errch_("#", "Also, a frame kernel defining the body-fixed fr"
			"ame associated with body # may need to be loaded.", (
			ftnlen)1, (ftnlen)96);
		errint_("#", body, (ftnlen)1);
	    }
	    sigerr_("SPICE(FRAMEDATANOTFOUND)", (ftnlen)24);
	    chkout_("BODMAT", (ftnlen)6);
	    return 0;
	}

/*        Find the body code used to label the reference frame and epoch */
/*        specifiers for the orientation constants for BODY. */

/*        For planetary systems, the reference frame and epoch for the */
/*        orientation constants is associated with the system */
/*        barycenter, not with individual bodies in the system.  For any */
/*        other bodies, (the Sun or asteroids, for example) the body's */
/*        own code is used as the label. */

	refid = zzbodbry_(body);

/*        Look up the epoch of the constants.  The epoch is specified */
/*        as a Julian ephemeris date.  The epoch defaults to J2000. */

	s_copy(item, "BODY#_CONSTANTS_JED_EPOCH", (ftnlen)32, (ftnlen)25);
	repmi_(item, "#", &refid, item, (ftnlen)32, (ftnlen)1, (ftnlen)32);
	gdpool_(item, &c__1, &c__1, &dim, &conepc, &found, (ftnlen)32);
	if (found) {

/*           The reference epoch is returned as a JED.  Convert to */
/*           ephemeris seconds past J2000.  Then convert the input ET to */
/*           seconds past the reference epoch. */

	    conepc = spd_() * (conepc - j2000_());
	    epoch = *et - conepc;
	} else {
	    epoch = *et;
	}

/*        Look up the reference frame of the constants.  The reference */
/*        frame is specified by a code recognized by CHGIRF.  The */
/*        default frame is J2000, symbolized by the code J2CODE. */

	s_copy(item, "BODY#_CONSTANTS_REF_FRAME", (ftnlen)32, (ftnlen)25);
	repmi_(item, "#", &refid, item, (ftnlen)32, (ftnlen)1, (ftnlen)32);
	gdpool_(item, &c__1, &c__1, &dim, &conref, &found, (ftnlen)32);
	if (found) {
	    ref = i_dnnt(&conref);
	} else {
	    ref = j2code;
	}

/*        Whatever the body, it has quadratic time polynomials for */
/*        the RA and Dec of the pole, and for the rotation of the */
/*        Prime Meridian. */

	s_copy(item, "POLE_RA", (ftnlen)32, (ftnlen)7);
	cleard_(&c__3, rcoef);
	bodvcd_(body, item, &c__3, &na, rcoef, (ftnlen)32);
	s_copy(item, "POLE_DEC", (ftnlen)32, (ftnlen)8);
	cleard_(&c__3, dcoef);
	bodvcd_(body, item, &c__3, &nd, dcoef, (ftnlen)32);
	s_copy(item, "PM", (ftnlen)32, (ftnlen)2);
	cleard_(&c__3, wcoef);
	bodvcd_(body, item, &c__3, &nw, wcoef, (ftnlen)32);

/*        There may be additional nutation and libration (THETA) terms. */

	ntheta = 0;
	na = 0;
	nd = 0;
	nw = 0;
	s_copy(item, "NUT_PREC_ANGLES", (ftnlen)32, (ftnlen)15);
	if (bodfnd_(&refid, item, (ftnlen)32)) {
	    bodvcd_(&refid, item, &c__100, &ntheta, tcoef, (ftnlen)32);
	    ntheta /= 2;
	}
	s_copy(item, "NUT_PREC_RA", (ftnlen)32, (ftnlen)11);
	if (bodfnd_(body, item, (ftnlen)32)) {
	    bodvcd_(body, item, &c__100, &na, ac, (ftnlen)32);
	}
	s_copy(item, "NUT_PREC_DEC", (ftnlen)32, (ftnlen)12);
	if (bodfnd_(body, item, (ftnlen)32)) {
	    bodvcd_(body, item, &c__100, &nd, dc, (ftnlen)32);
	}
	s_copy(item, "NUT_PREC_PM", (ftnlen)32, (ftnlen)11);
	if (bodfnd_(body, item, (ftnlen)32)) {
	    bodvcd_(body, item, &c__100, &nw, wc, (ftnlen)32);
	}
/* Computing MAX */
	i__1 = max(na,nd);
	if (max(i__1,nw) > ntheta) {
	    setmsg_("Insufficient number of nutation/precession angles for b"
		    "ody * at time #.", (ftnlen)71);
	    errint_("*", body, (ftnlen)1);
	    errdp_("#", et, (ftnlen)1);
	    sigerr_("SPICE(KERNELVARNOTFOUND)", (ftnlen)24);
	    chkout_("BODMAT", (ftnlen)6);
	    return 0;
	}

/*        Evaluate the time polynomials at EPOCH. */

	d__ = epoch / spd_();
	t = d__ / 36525.;
	ra = rcoef[0] + t * (rcoef[1] + t * rcoef[2]);
	dec = dcoef[0] + t * (dcoef[1] + t * dcoef[2]);
	w = wcoef[0] + d__ * (wcoef[1] + d__ * wcoef[2]);

/*        Add nutation and libration as appropriate. */

	i__1 = ntheta;
	for (i__ = 1; i__ <= i__1; ++i__) {
	    theta = (tcoef[(i__2 = (i__ << 1) - 2) < 200 && 0 <= i__2 ? i__2 :
		     s_rnge("tcoef", i__2, "bodmat_", (ftnlen)700)] + t * 
		    tcoef[(i__3 = (i__ << 1) - 1) < 200 && 0 <= i__3 ? i__3 : 
		    s_rnge("tcoef", i__3, "bodmat_", (ftnlen)700)]) * rpd_();
	    sinth[(i__2 = i__ - 1) < 100 && 0 <= i__2 ? i__2 : s_rnge("sinth",
		     i__2, "bodmat_", (ftnlen)702)] = sin(theta);
	    costh[(i__2 = i__ - 1) < 100 && 0 <= i__2 ? i__2 : s_rnge("costh",
		     i__2, "bodmat_", (ftnlen)703)] = cos(theta);
	}
	ra += vdotg_(ac, sinth, &na);
	dec += vdotg_(dc, costh, &nd);
	w += vdotg_(wc, sinth, &nw);

/*        Convert from degrees to radians and mod by two pi. */

	ra *= rpd_();
	dec *= rpd_();
	w *= rpd_();
	d__1 = twopi_();
	ra = d_mod(&ra, &d__1);
	d__1 = twopi_();
	dec = d_mod(&dec, &d__1);
	d__1 = twopi_();
	w = d_mod(&w, &d__1);

/*        Convert to Euler angles. */

	phi = ra + halfpi_();
	delta = halfpi_() - dec;

/*        Produce the rotation matrix defined by the Euler angles. */

	eul2m_(&w, &delta, &phi, &c__3, &c__1, &c__3, tipm);
    }

/*     Convert TIPM to the J2000-to-bodyfixed rotation, if is is not */
/*     already referenced to J2000. */

    if (ref != j2code) {

/*        Find the transformation from the J2000 frame to the frame */
/*        designated by REF.  Form the transformation from `REF' */
/*        coordinates to body-fixed coordinates.  Compose the */
/*        transformations to obtain the J2000-to-body-fixed */
/*        transformation. */

	irfrot_(&j2code, &ref, j2ref);
	mxm_(tipm, j2ref, tmpmat);
	moved_(tmpmat, &c__9, tipm);
    }

/*     TIPM now gives the transformation from J2000 to */
/*     body-fixed coordinates at epoch ET seconds past J2000, */
/*     regardless of the epoch and frame of the orientation constants */
/*     for the specified body. */

    chkout_("BODMAT", (ftnlen)6);
    return 0;
} /* bodmat_ */
Beispiel #3
0
/* $Procedure      M2EUL ( Matrix to Euler angles ) */
/* Subroutine */ int m2eul_(doublereal *r__, integer *axis3, integer *axis2, 
	integer *axis1, doublereal *angle3, doublereal *angle2, doublereal *
	angle1)
{
    /* Initialized data */

    static integer next[3] = { 2,3,1 };

    /* System generated locals */
    integer i__1, i__2;

    /* Builtin functions */
    integer s_rnge(char *, integer, char *, integer);
    double acos(doublereal), atan2(doublereal, doublereal), asin(doublereal);

    /* Local variables */
    doublereal sign;
    extern /* Subroutine */ int vhat_(doublereal *, doublereal *), mtxm_(
	    doublereal *, doublereal *, doublereal *);
    integer c__, i__;
    logical degen;
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    extern logical isrot_(doublereal *, doublereal *, doublereal *);
    doublereal change[9]	/* was [3][3] */;
    extern /* Subroutine */ int cleard_(integer *, doublereal *), sigerr_(
	    char *, ftnlen), chkout_(char *, ftnlen);
    doublereal tmpmat[9]	/* was [3][3] */;
    extern /* Subroutine */ int setmsg_(char *, ftnlen), errint_(char *, 
	    integer *, ftnlen);
    extern logical return_(void);
    doublereal tmprot[9]	/* was [3][3] */;
    extern /* Subroutine */ int mxm_(doublereal *, doublereal *, doublereal *)
	    ;

/* $ Abstract */

/*     Factor a rotation matrix as a product of three rotations about */
/*     specified coordinate axes. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     ROTATION */

/* $ Keywords */

/*     ANGLE */
/*     MATRIX */
/*     ROTATION */
/*     TRANSFORMATION */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     R          I   A rotation matrix to be factored. */
/*     AXIS3, */
/*     AXIS2, */
/*     AXIS1      I   Numbers of third, second, and first rotation axes. */
/*     ANGLE3, */
/*     ANGLE2, */
/*     ANGLE1     O   Third, second, and first Euler angles, in radians. */

/* $ Detailed_Input */

/*     R              is a 3x3 rotation matrix that is to be factored as */
/*                    a product of three rotations about a specified */
/*                    coordinate axes.  The angles of these rotations are */
/*                    called `Euler angles'. */

/*     AXIS3, */
/*     AXIS2, */
/*     AXIS1          are the indices of the rotation axes of the */
/*                    `factor' rotations, whose product is R.  R is */
/*                    factored as */

/*                       R = [ ANGLE3 ]     [ ANGLE2 ]     [ ANGLE1 ]   . */
/*                                    AXIS3          AXIS2         AXIS1 */

/*                    The axis numbers must belong to the set {1, 2, 3}. */
/*                    The second axis number MUST differ from the first */
/*                    and third axis numbers. */

/*                    See the $ Particulars section below for details */
/*                    concerning this notation. */

/* $ Detailed_Output */

/*     ANGLE3, */
/*     ANGLE2, */
/*     ANGLE1         are the Euler angles corresponding to the matrix */
/*                    R and the axes specified by AXIS3, AXIS2, and */
/*                    AXIS1.  These angles satisfy the equality */

/*                       R = [ ANGLE3 ]     [ ANGLE2 ]     [ ANGLE1 ] */
/*                                   AXIS3          AXIS2          AXIS1 */


/*                    See the $ Particulars section below for details */
/*                    concerning this notation. */

/*                    The range of ANGLE3 and ANGLE1 is (-pi, pi]. */

/*                    The range of ANGLE2 depends on the exact set of */
/*                    axes used for the factorization.  For */
/*                    factorizations in which the first and third axes */
/*                    are the same, */

/*                       R = [r]  [s]  [t] , */
/*                              a    b    a */

/*                    the range of ANGLE2 is [0, pi]. */


/*                    For factorizations in which the first and third */
/*                    axes are different, */

/*                       R = [r]  [s]  [t] , */
/*                              a    b    c */

/*                    the range of ANGLE2 is [-pi/2, pi/2]. */

/*                    For rotations such that ANGLE3 and ANGLE1 are not */
/*                    uniquely determined, ANGLE3 will always be set to */
/*                    zero; ANGLE1 is then uniquely determined. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)   If any of AXIS3, AXIS2, or AXIS1 do not have values in */

/*             { 1, 2, 3 }, */

/*          then the error SPICE(BADAXISNUMBERS) is signaled. */

/*     2)   An arbitrary rotation matrix cannot be expressed using */
/*          a sequence of Euler angles unless the second rotation axis */
/*          differs from the other two.  If AXIS2 is equal to AXIS3 or */
/*          AXIS1, then then error SPICE(BADAXISNUMBERS) is signaled. */

/*     3)   If the input matrix R is not a rotation matrix, the error */
/*          SPICE(NOTAROTATION) is signaled. */

/*     4)   If ANGLE3 and ANGLE1 are not uniquely determined, ANGLE3 */
/*          is set to zero, and ANGLE1 is determined. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     A word about notation:  the symbol */

/*        [ x ] */
/*             i */

/*     indicates a coordinate system rotation of x radians about the */
/*     ith coordinate axis.  To be specific, the symbol */

/*        [ x ] */
/*             1 */

/*     indicates a coordinate system rotation of x radians about the */
/*     first, or x-, axis; the corresponding matrix is */

/*        +-                    -+ */
/*        |  1      0       0    | */
/*        |                      | */
/*        |  0    cos(x)  sin(x) |. */
/*        |                      | */
/*        |  0   -sin(x)  cos(x) | */
/*        +-                    -+ */

/*     Remember, this is a COORDINATE SYSTEM rotation by x radians; this */
/*     matrix, when applied to a vector, rotates the vector by -x */
/*     radians, not x radians.  Applying the matrix to a vector yields */
/*     the vector's representation relative to the rotated coordinate */
/*     system. */

/*     The analogous rotation about the second, or y-, axis is */
/*     represented by */

/*        [ x ] */
/*             2 */

/*     which symbolizes the matrix */

/*        +-                    -+ */
/*        | cos(x)   0   -sin(x) | */
/*        |                      | */
/*        |  0       1      0    |, */
/*        |                      | */
/*        | sin(x)   0    cos(x) | */
/*        +-                    -+ */

/*     and the analogous rotation about the third, or z-, axis is */
/*     represented by */

/*        [ x ] */
/*             3 */

/*     which symbolizes the matrix */

/*        +-                    -+ */
/*        |  cos(x)  sin(x)   0  | */
/*        |                      | */
/*        | -sin(x)  cos(x)   0  |. */
/*        |                      | */
/*        |  0        0       1  | */
/*        +-                    -+ */


/*     The input matrix is assumed to be the product of three */
/*     rotation matrices, each one of the form */

/*        +-                    -+ */
/*        |  1      0       0    | */
/*        |                      | */
/*        |  0    cos(r)  sin(r) |     (rotation of r radians about the */
/*        |                      |      x-axis), */
/*        |  0   -sin(r)  cos(r) | */
/*        +-                    -+ */


/*        +-                    -+ */
/*        | cos(s)   0   -sin(s) | */
/*        |                      | */
/*        |  0       1      0    |     (rotation of s radians about the */
/*        |                      |      y-axis), */
/*        | sin(s)   0    cos(s) | */
/*        +-                    -+ */

/*     or */

/*        +-                    -+ */
/*        |  cos(t)  sin(t)   0  | */
/*        |                      | */
/*        | -sin(t)  cos(t)   0  |     (rotation of t radians about the */
/*        |                      |      z-axis), */
/*        |  0        0       1  | */
/*        +-                    -+ */

/*     where the second rotation axis is not equal to the first or */
/*     third.  Any rotation matrix can be factored as a sequence of */
/*     three such rotations, provided that this last criterion is met. */

/*     This routine is related to the SPICELIB routine EUL2M, which */
/*     produces a rotation matrix, given a sequence of Euler angles. */
/*     This routine is a `right inverse' of EUL2M:  the sequence of */
/*     calls */

/*        CALL M2EUL ( R,  AXIS3,   AXIS2,   AXIS1, */
/*       .                 ANGLE3,  ANGLE2,  ANGLE1     ) */

/*        CALL EUL2M (     ANGLE3,  ANGLE2,  ANGLE1, */
/*       .                 AXIS3,   AXIS2,   AXIS1,   R ) */

/*     preserves R, except for round-off error. */


/*     On the other hand, the sequence of calls */

/*        CALL EUL2M (     ANGLE3,  ANGLE2,  ANGLE1, */
/*       .                 AXIS3,   AXIS2,   AXIS1,   R ) */

/*        CALL M2EUL ( R,  AXIS3,   AXIS2,   AXIS1, */
/*       .                 ANGLE3,  ANGLE2,  ANGLE1     ) */


/*     preserve ANGLE3, ANGLE2, and ANGLE1 only if these angles start */
/*     out in the ranges that M2EUL's outputs are restricted to. */

/* $ Examples */

/*     1)  Conversion of instrument pointing from a matrix representation */
/*         to Euler angles: */

/*         Suppose we want to find camera pointing in alpha, delta, and */
/*         kappa, given the inertial-to-camera coordinate transformation */


/*    +-                                                               -+ */
/*    |  0.49127379678135830  0.50872620321864170  0.70699908539882417  | */
/*    |                                                                 | */
/*    | -0.50872620321864193 -0.49127379678135802  0.70699908539882428  | */
/*    |                                                                 | */
/*    |  0.70699908539882406 -0.70699908539882439  0.01745240643728360  | */
/*    +-                                                               -+ */


/*         We want to find angles alpha, delta, kappa such that */

/*            TICAM  =  [ kappa ]  [ pi/2 - delta ]  [ pi/2 + alpha ] . */
/*                               3                 1                 3 */

/*         We can use the following small program to do this computation: */


/*            PROGRAM EX1 */
/*            IMPLICIT NONE */

/*            DOUBLE PRECISION      DPR */
/*            DOUBLE PRECISION      HALFPI */
/*            DOUBLE PRECISION      TWOPI */

/*            DOUBLE PRECISION      ALPHA */
/*            DOUBLE PRECISION      ANG1 */
/*            DOUBLE PRECISION      ANG2 */
/*            DOUBLE PRECISION      DELTA */
/*            DOUBLE PRECISION      KAPPA */
/*            DOUBLE PRECISION      TICAM  ( 3, 3 ) */


/*            DATA TICAM /  0.49127379678135830D0, */
/*           .             -0.50872620321864193D0, */
/*           .              0.70699908539882406D0, */
/*           .              0.50872620321864170D0, */
/*           .             -0.49127379678135802D0, */
/*           .             -0.70699908539882439D0, */
/*           .              0.70699908539882417D0, */
/*           .              0.70699908539882428D0, */
/*           .              0.01745240643728360D0  / */


/*            CALL M2EUL ( TICAM, 3, 1, 3, KAPPA, ANG2, ANG1 ) */

/*            DELTA = HALFPI() - ANG2 */
/*            ALPHA = ANG1     - HALFPI() */

/*            IF ( KAPPA .LT. 0.D0 ) THEN */
/*               KAPPA = KAPPA + TWOPI() */
/*            END IF */

/*            IF ( ALPHA .LT. 0.D0 ) THEN */
/*               ALPHA = ALPHA + TWOPI() */
/*            END IF */

/*            WRITE (*,'(1X,A,F24.14)') 'Alpha (deg): ', DPR() * ALPHA */
/*            WRITE (*,'(1X,A,F24.14)') 'Delta (deg): ', DPR() * DELTA */
/*            WRITE (*,'(1X,A,F24.14)') 'Kappa (deg): ', DPR() * KAPPA */

/*            END */


/*         The program's output should be something like */

/*            Alpha (deg):       315.00000000000000 */
/*            Delta (deg):         1.00000000000000 */
/*            Kappa (deg):        45.00000000000000 */

/*         possibly formatted a little differently, or degraded slightly */
/*         by round-off. */


/*     2)  Conversion of instrument pointing angles from a non-J2000, */
/*         not necessarily inertial frame to J2000-relative RA, Dec, */
/*         and Twist. */

/*         Suppose that we have pointing for some instrument expressed as */

/*            [ gamma ]  [ beta ]  [ alpha ] */
/*                     3         2          3 */

/*         with respect to some coordinate system S.  For example, S */
/*         could be a spacecraft-fixed system. */

/*         We will suppose that the transformation from J2000 */
/*         coordinates to system S coordinates is given by the rotation */
/*         matrix J2S. */

/*         The rows of J2S are the unit basis vectors of system S, given */
/*         in J2000 coordinates. */

/*         We want to express the pointing with respect to the J2000 */
/*         system as the sequence of rotations */

/*            [ kappa ]  [ pi/2 - delta ]  [ pi/2 + alpha ] . */
/*                     3                 1                 3 */

/*         First, we use subroutine EUL2M to form the transformation */
/*         from system S to instrument coordinates S2INST. */

/*            CALL EUL2M ( GAMMA, BETA, ALPHA, 3, 2, 3, S2INST ) */

/*         Next, we form the transformation from J2000 to instrument */
/*         coordinates J2INST. */

/*            CALL MXM ( S2INST, J2S, J2INST ) */

/*         Finally, we express J2INST using the desired Euler angles, as */
/*         in the first example: */

/*            CALL M2EUL ( J2INST, 3, 1, 3, TWIST, ANG2, ANG3 ) */

/*            RA   =  ANG3 - HALFPI() */
/*            DEC  =  HALFPI() - ANG2 */

/*         If we wish to make sure that RA, DEC, and TWIST are in */
/*         the ranges [0, 2pi), [-pi/2, pi/2], and [0, 2pi) */
/*         respectively, we may add the code */

/*            IF ( RA .LT. 0.D0 ) THEN */
/*               RA = RA + TWOPI() */
/*            END IF */

/*            IF ( TWIST .LT. 0.D0 ) THEN */
/*               TWIST = TWIST + TWOPI() */
/*            END IF */

/*         Note that DEC is already in the correct range, since ANG2 */
/*         is in the range [0, pi] when the first and third input axes */
/*         are equal. */

/*         Now RA, DEC, and TWIST express the instrument pointing */
/*         as RA, Dec, and Twist, relative to the J2000 system. */

/*         A warning note:  more than one definition of RA, Dec, and */
/*         Twist is extant.  Before using this example in an application, */
/*         check that the definition given here is consistent with that */
/*         used in your application. */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     N.J. Bachman   (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.2.1, 21-DEC-2006 (NJB) */

/*        Error corrected in header example:  input matrix */
/*        previously did not match shown outputs.  Offending */
/*        example now includes complete program. */

/* -    SPICELIB Version 1.2.0, 15-OCT-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in MXM and MTXM calls.  A short error message cited in */
/*        the Exceptions section of the header failed to match */
/*        the actual short message used; this has been corrected. */

/* -    SPICELIB Version 1.1.2, 13-OCT-2004 (NJB) */

/*        Fixed header typo. */

/* -    SPICELIB Version 1.1.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -    SPICELIB Version 1.1.0, 02-NOV-1990 (NJB) */

/*        Header upgraded to describe notation in more detail.  Argument */
/*        names were changed to describe the use of the arguments more */
/*        accurately.  No change in functionality was made; the operation */
/*        of the routine is identical to that of the previous version. */

/* -    SPICELIB Version 1.0.0, 03-SEP-1990 (NJB) */

/* -& */
/* $ Index_Entries */

/*     matrix to euler angles */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 1.2.0, 26-AUG-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in MXM and MTXM calls.  A short error message cited in */
/*        the Exceptions section of the header  failed to match */
/*        the actual short message used; this has been corrected. */

/* -    SPICELIB Version 1.1.0, 02-NOV-1990 (NJB) */

/*        Argument names were changed to describe the use of the */
/*        arguments more accurately.  The axis and angle numbers */
/*        now decrease, rather than increase, from left to right. */
/*        The current names reflect the order of operator application */
/*        when the Euler angle rotations are applied to a vector:  the */
/*        rightmost matrix */

/*           [ ANGLE1 ] */
/*                     AXIS1 */

/*        is applied to the vector first, followed by */

/*           [ ANGLE2 ] */
/*                     AXIS2 */

/*        and then */

/*           [ ANGLE3 ] */
/*                     AXIS3 */

/*        Previously, the names reflected the order in which the Euler */
/*        angle matrices appear on the page, from left to right.  This */
/*        naming convention was found to be a bit obtuse by a various */
/*        users. */

/*        No change in functionality was made; the operation of the */
/*        routine is identical to that of the previous version. */

/*        Also, the header was upgraded to describe the notation in more */
/*        detail.  The symbol */

/*           [ x ] */
/*                i */

/*        is explained at mind-numbing length.  An example was added */
/*        that shows a specific set of inputs and the resulting output */
/*        matrix. */

/*        The angle sequence notation was changed to be consistent with */
/*        Rotations required reading. */

/*          1-2-3  and  a-b-c */

/*        have been changed to */

/*          3-2-1  and  c-b-a. */

/*       Also, one `)' was changed to a `}'. */

/*       The phrase `first and third' was changed to `first or third' */
/*       in the $ Particulars section, where the criterion for the */
/*       existence of an Euler angle factorization is stated. */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     NTOL and DETOL are used to determine whether R is a rotation */
/*     matrix. */

/*     NTOL is the tolerance for the norms of the columns of R. */

/*     DTOL is the tolerance for the determinant of a matrix whose */
/*     columns are the unitized columns of R. */



/*     Local variables */


/*     Saved variables */


/*     Initial values */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("M2EUL", (ftnlen)5);
    }

/*     The first order of business is to screen out the goofy cases. */

/*     Make sure the axis numbers are all right:  They must belong to */
/*     the set {1, 2, 3}... */

    if (*axis3 < 1 || *axis3 > 3 || (*axis2 < 1 || *axis2 > 3) || (*axis1 < 1 
	    || *axis1 > 3)) {
	setmsg_("Axis numbers are #,  #,  #. ", (ftnlen)28);
	errint_("#", axis3, (ftnlen)1);
	errint_("#", axis2, (ftnlen)1);
	errint_("#", axis1, (ftnlen)1);
	sigerr_("SPICE(BADAXISNUMBERS)", (ftnlen)21);
	chkout_("M2EUL", (ftnlen)5);
	return 0;

/*     ...and the second axis number must differ from its neighbors. */

    } else if (*axis3 == *axis2 || *axis1 == *axis2) {
	setmsg_("Middle axis matches neighbor: # # #.", (ftnlen)36);
	errint_("#", axis3, (ftnlen)1);
	errint_("#", axis2, (ftnlen)1);
	errint_("#", axis1, (ftnlen)1);
	sigerr_("SPICE(BADAXISNUMBERS)", (ftnlen)21);
	chkout_("M2EUL", (ftnlen)5);
	return 0;

/*     R must be a rotation matrix, or we may as well forget it. */

    } else if (! isrot_(r__, &c_b15, &c_b15)) {
	setmsg_("Input matrix is not a rotation.", (ftnlen)31);
	sigerr_("SPICE(NOTAROTATION)", (ftnlen)19);
	chkout_("M2EUL", (ftnlen)5);
	return 0;
    }

/*     AXIS3, AXIS2, AXIS1 and R have passed their tests at this */
/*     point.  We take the liberty of working with TMPROT, a version */
/*     of R that has unitized columns. */

    for (i__ = 1; i__ <= 3; ++i__) {
	vhat_(&r__[(i__1 = i__ * 3 - 3) < 9 && 0 <= i__1 ? i__1 : s_rnge(
		"r", i__1, "m2eul_", (ftnlen)667)], &tmprot[(i__2 = i__ * 3 - 
		3) < 9 && 0 <= i__2 ? i__2 : s_rnge("tmprot", i__2, "m2eul_", 
		(ftnlen)667)]);
    }

/*     We now proceed to recover the promised Euler angles from */
/*     TMPROT. */

/*        The ideas behind our method are explained in excruciating */
/*        detail in the ROTATION required reading, so we'll be terse. */
/*        Nonetheless, a word of explanation is in order. */

/*        The sequence of rotation axes used for the factorization */
/*        belongs to one of two categories:  a-b-a or c-b-a.  We */
/*        wish to handle each of these cases in one shot, rather than */
/*        using different formulas for each sequence to recover the */
/*        Euler angles. */

/*        What we're going to do is use the Euler angle formula for the */
/*        3-1-3 factorization for all of the a-b-a sequences, and the */
/*        formula for the 3-2-1 factorization for all of the c-b-a */
/*        sequences. */

/*        How can we get away with this?  The Euler angle formulas for */
/*        each factorization are different! */

/*        Our trick is to apply a change-of-basis transformation to the */
/*        input matrix R.  For the a-b-a factorizations, we choose a new */
/*        basis such that a rotation of ANGLE3 radians about the basis */
/*        vector indexed by AXIS3 becomes a rotation of ANGLE3 radians */
/*        about the third coordinate axis, and such that a rotation of */
/*        ANGLE2 radians about the basis vector indexed by AXIS2 becomes */
/*        a rotation of ANGLE2 radians about the first coordinate axis. */
/*        So R can be factored as a 3-1-3 rotation relative to the new */
/*        basis, and the Euler angles we obtain are the exact ones we */
/*        require. */

/*        The c-b-a factorizations can be handled in an analogous */
/*        fashion.  We transform R to a basis where the original axis */
/*        sequence becomes a 3-2-1 sequence.  In some cases, the angles */
/*        we obtain will be the negatives of the angles we require.  This */
/*        will happen if and only if the ordered basis (here the e's are */
/*        the standard basis vectors) */

/*            { e        e        e      } */
/*               AXIS3    AXIS2    AXIS1 */

/*        is not right-handed.  An easy test for this condition is that */
/*        AXIS2 is not the successor of AXIS3, where the ordering is */
/*        cyclic. */

    if (*axis3 == *axis1) {

/*        The axis order is a-b-a.  We're going to find a matrix CHANGE */
/*        such that */

/*                 T */
/*           CHANGE  R  CHANGE */

/*        gives us R in the a useful basis, that is, a basis in which */
/*        our original a-b-a rotation is a 3-1-3 rotation, but where the */
/*        rotation angles are unchanged. To achieve this pleasant */
/*        simplification, we set column 3 of CHANGE to to e(AXIS3), */
/*        column 1 of CHANGE to e(AXIS2), and column 2 of CHANGE to */

/*          (+/-) e(C), */

/*        (C is the remaining index) depending on whether */
/*        AXIS3-AXIS2-C is a right-handed sequence of axes:  if it */
/*        is, the sign is positive.  (Here e(1), e(2), e(3) are the */
/*        standard basis vectors.) */

/*        Determine the sign of our third basis vector, so that we can */
/*        ensure that our new basis is right-handed.  The variable NEXT */
/*        is just a little mapping that takes 1 to 2, 2 to 3, and 3 to */
/*        1. */

	if (*axis2 == next[(i__1 = *axis3 - 1) < 3 && 0 <= i__1 ? i__1 : 
		s_rnge("next", i__1, "m2eul_", (ftnlen)746)]) {
	    sign = 1.;
	} else {
	    sign = -1.;
	}

/*        Since the axis indices sum to 6, */

	c__ = 6 - *axis3 - *axis2;

/*        Set up the entries of CHANGE: */

	cleard_(&c__9, change);
	change[(i__1 = *axis3 + 5) < 9 && 0 <= i__1 ? i__1 : s_rnge("change", 
		i__1, "m2eul_", (ftnlen)762)] = 1.;
	change[(i__1 = *axis2 - 1) < 9 && 0 <= i__1 ? i__1 : s_rnge("change", 
		i__1, "m2eul_", (ftnlen)763)] = 1.;
	change[(i__1 = c__ + 2) < 9 && 0 <= i__1 ? i__1 : s_rnge("change", 
		i__1, "m2eul_", (ftnlen)764)] = sign * 1.;

/*        Transform TMPROT. */

	mxm_(tmprot, change, tmpmat);
	mtxm_(change, tmpmat, tmprot);

/*        Now we're ready to find the Euler angles, using a */
/*        3-1-3 factorization.  In general, the matrix product */

/*           [ a1 ]   [ a2 ]   [ a3 ] */
/*                 3        1        3 */

/*        has the form */

/*     +-                                                              -+ */
/*     |         cos(a1)cos(a3)          cos(a1)sin(a3)  sin(a1)sin(a2) | */
/*     | -sin(a1)cos(a2)sin(a3)  +sin(a1)cos(a2)cos(a3)                 | */
/*     |                                                                | */
/*     |        -sin(a1)cos(a3)         -sin(a1)sin(a3)  cos(a1)sin(a2) | */
/*     | -cos(a1)cos(a2)sin(a3)  +cos(a1)cos(a2)cos(a3)                 | */
/*     |                                                                | */
/*     |         sin(a2)sin(a3)         -sin(a2)cos(a3)         cos(a2) | */
/*     +-                                                              -+ */


/*        but if a2 is 0 or pi, the product matrix reduces to */


/*     +-                                                              -+ */
/*     |         cos(a1)cos(a3)          cos(a1)sin(a3)               0 | */
/*     | -sin(a1)cos(a2)sin(a3)  +sin(a1)cos(a2)cos(a3)                 | */
/*     |                                                                | */
/*     |        -sin(a1)cos(a3)         -sin(a1)sin(a3)               0 | */
/*     | -cos(a1)cos(a2)sin(a3)  +cos(a1)cos(a2)cos(a3)                 | */
/*     |                                                                | */
/*     |                      0                       0         cos(a2) | */
/*     +-                                                              -+ */


/*        In this case, a1 and a3 are not uniquely determined.  If we */
/*        arbitrarily set a1 to zero, we arrive at the matrix */

/*           +-                                         -+ */
/*           |         cos(a3)         sin(a3)      0    | */
/*           | -cos(a2)sin(a3)  cos(a2)cos(a3)      0    | */
/*           |               0            0      cos(a2) | */
/*           +-                                         -+ */

/*        We take care of this case first.  We test three conditions */
/*        that are mathematically equivalent, but may not be satisfied */
/*        simultaneously because of round-off: */


	degen = tmprot[6] == 0. && tmprot[7] == 0. || tmprot[2] == 0. && 
		tmprot[5] == 0. || abs(tmprot[8]) == 1.;

/*        In the following block of code, we make use of the fact that */

/*           SIN ( ANGLE2 )   >  0 */
/*                            - */
/*        in choosing the signs of the ATAN2 arguments correctly.  Note */
/*        that ATAN2(x,y) = -ATAN2(-x,-y). */


	if (degen) {
	    *angle3 = 0.;
	    *angle2 = acos(tmprot[8]);
	    *angle1 = atan2(tmprot[3], tmprot[0]);
	} else {

/*           The normal case. */

	    *angle3 = atan2(tmprot[6], tmprot[7]);
	    *angle2 = acos(tmprot[8]);
	    *angle1 = atan2(tmprot[2], -tmprot[5]);
	}
    } else {

/*        The axis order is c-b-a.  We're going to find a matrix CHANGE */
/*        such that */

/*                 T */
/*           CHANGE  R  CHANGE */

/*        gives us R in the a useful basis, that is, a basis in which */
/*        our original c-b-a rotation is a 3-2-1 rotation, but where the */
/*        rotation angles are unchanged, or at worst negated.  To */
/*        achieve this pleasant simplification, we set column 1 of */
/*        CHANGE to to e(AXIS3), column 2 of CHANGE to e(AXIS2), and */
/*        column 3 of CHANGE to */

/*          (+/-) e(AXIS1), */

/*        depending on whether AXIS3-AXIS2-AXIS1 is a right-handed */
/*        sequence of axes:  if it is, the sign is positive.  (Here */
/*        e(1), e(2), e(3) are the standard basis vectors.) */

/*        We must be cautious here, because if AXIS3-AXIS2-AXIS1 is a */
/*        right-handed sequence of axes, all of the rotation angles will */
/*        be the same in our new basis, but if it's a left-handed */
/*        sequence, the third angle will be negated.  Let's get this */
/*        straightened out right now.  The variable NEXT is just a */
/*        little mapping that takes 1 to 2, 2 to 3, and 3 to 1. */

	if (*axis2 == next[(i__1 = *axis3 - 1) < 3 && 0 <= i__1 ? i__1 : 
		s_rnge("next", i__1, "m2eul_", (ftnlen)883)]) {
	    sign = 1.;
	} else {
	    sign = -1.;
	}

/*        Set up the entries of CHANGE: */

	cleard_(&c__9, change);
	change[(i__1 = *axis3 - 1) < 9 && 0 <= i__1 ? i__1 : s_rnge("change", 
		i__1, "m2eul_", (ftnlen)894)] = 1.;
	change[(i__1 = *axis2 + 2) < 9 && 0 <= i__1 ? i__1 : s_rnge("change", 
		i__1, "m2eul_", (ftnlen)895)] = 1.;
	change[(i__1 = *axis1 + 5) < 9 && 0 <= i__1 ? i__1 : s_rnge("change", 
		i__1, "m2eul_", (ftnlen)896)] = sign * 1.;

/*        Transform TMPROT. */

	mxm_(tmprot, change, tmpmat);
	mtxm_(change, tmpmat, tmprot);

/*        Now we're ready to find the Euler angles, using a */
/*        3-2-1 factorization.  In general, the matrix product */

/*           [ a1 ]   [ a2 ]   [ a3 ] */
/*                 1        2        3 */

/*        has the form */


/*     +-                                                              -+ */
/*     |         cos(a2)cos(a3)          cos(a2)sin(a3)        -sin(a2) | */
/*     |                                                                | */
/*     |        -cos(a1)sin(a3)          cos(a1)cos(a3)  sin(a1)cos(a2) | */
/*     | +sin(a1)sin(a2)cos(a3)  +sin(a1)sin(a2)sin(a3)                 | */
/*     |                                                                | */
/*     |         sin(a1)sin(a3)         -sin(a1)cos(a3)  cos(a1)cos(a2) | */
/*     | +cos(a1)sin(a2)cos(a3)  +cos(a1)sin(a2)sin(a3)                 | */
/*     +-                                                              -+ */


/*        but if a2 is -pi/2 or pi/2, the product matrix reduces to */


/*     +-                                                              -+ */
/*     |                      0                       0        -sin(a2) | */
/*     |                                                                | */
/*     |        -cos(a1)sin(a3)          cos(a1)cos(a3)               0 | */
/*     | +sin(a1)sin(a2)cos(a3)  +sin(a1)sin(a2)sin(a3)                 | */
/*     |                                                                | */
/*     |         sin(a1)sin(a3)         -sin(a1)cos(a3)               0 | */
/*     | +cos(a1)sin(a2)cos(a3)  +cos(a1)sin(a2)sin(a3)                 | */
/*     +-                                                              -+ */


/*        In this case, a1 and a3 are not uniquely determined.  If we */
/*        arbitrarily set a1 to zero, we arrive at the matrix */

/*           +-                                              -+ */
/*           |               0                 0    -sin(a2)  | */
/*           |        -sin(a3)           cos(a3)          0   |, */
/*           |  sin(a2)cos(a3)    sin(a2)sin(a3)          0   | */
/*           +-                                              -+ */


/*        We take care of this case first.  We test three conditions */
/*        that are mathematically equivalent, but may not be satisfied */
/*        simultaneously because of round-off: */


	degen = tmprot[0] == 0. && tmprot[3] == 0. || tmprot[7] == 0. && 
		tmprot[8] == 0. || abs(tmprot[6]) == 1.;

/*        In the following block of code, we make use of the fact that */

/*           COS ( ANGLE2 )   >  0 */
/*                            - */
/*        in choosing the signs of the ATAN2 arguments correctly.  Note */
/*        that ATAN2(x,y) = -ATAN2(-x,-y). */


	if (degen) {
	    *angle3 = 0.;
	    *angle2 = asin(-tmprot[6]);
	    *angle1 = sign * atan2(-tmprot[1], tmprot[4]);
	} else {

/*           The normal case. */

	    *angle3 = atan2(tmprot[7], tmprot[8]);
	    *angle2 = asin(-tmprot[6]);
	    *angle1 = sign * atan2(tmprot[3], tmprot[0]);
	}
    }
    chkout_("M2EUL", (ftnlen)5);
    return 0;
} /* m2eul_ */
Beispiel #4
0
/* $Procedure      PXFRM2 ( Position Transform Matrix, Different Epochs ) */
/* Subroutine */ int pxfrm2_(char *from, char *to, doublereal *etfrom, 
	doublereal *etto, doublereal *rotate, ftnlen from_len, ftnlen to_len)
{
    /* Initialized data */

    static logical first = TRUE_;

    static char svto[32];
    extern /* Subroutine */ int zznamfrm_(integer *, char *, integer *, char *
	    , integer *, ftnlen, ftnlen), zzctruin_(integer *);
    integer fcode;
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    integer tcode;
    extern /* Subroutine */ int errch_(char *, char *, ftnlen, ftnlen);
    doublereal jf[9]	/* was [3][3] */;
    static integer svctr1[2], svctr2[2];
    doublereal tj[9]	/* was [3][3] */;
    extern /* Subroutine */ int refchg_(integer *, integer *, doublereal *, 
	    doublereal *);
    static integer svfcod, svtcde;
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, 
	    ftnlen), setmsg_(char *, ftnlen);
    static char svfrom[32];
    extern logical return_(void);
    extern /* Subroutine */ int mxm_(doublereal *, doublereal *, doublereal *)
	    ;

/* $ Abstract */

/*     Return the 3x3 matrix that transforms position vectors from one */
/*     specified frame at a specified epoch to another specified */
/*     frame at another specified epoch. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     FRAMES */

/* $ Keywords */

/*     FRAMES */
/*     TRANSFORM */

/* $ Declarations */
/* $ Abstract */

/*     This include file defines the dimension of the counter */
/*     array used by various SPICE subsystems to uniquely identify */
/*     changes in their states. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Parameters */

/*     CTRSIZ      is the dimension of the counter array used by */
/*                 various SPICE subsystems to uniquely identify */
/*                 changes in their states. */

/* $ Author_and_Institution */

/*     B.V. Semenov    (JPL) */

/* $ Literature_References */

/*     None. */

/* $ Version */

/* -    SPICELIB Version 1.0.0, 29-JUL-2013 (BVS) */

/* -& */

/*     End of include file. */

/* $ Brief_I/O */

/*     VARIABLE  I/O  DESCRIPTION */
/*     --------  ---  -------------------------------------------------- */
/*     FROM       I   Name of the frame to transform from. */
/*     TO         I   Name of the frame to transform to. */
/*     ETFROM     I   Evaluation time of 'FROM' frame. */
/*     ETTO       I   Evaluation time of 'TO' frame. */
/*     ROTATE     O   A position transformation matrix from */
/*                    frame FROM to frame TO. */

/* $ Detailed_Input */

/*     FROM       is the name of a reference frame recognized by */
/*                SPICELIB that corresponds to the input ETFROM. */


/*     TO         is the name of a reference frame recognized by */
/*                SPICELIB that corresponds to the desired output */
/*                at ETTO. */


/*     ETFROM     is the epoch in ephemeris seconds past the epoch */
/*                of J2000 (TDB) corresponding to the FROM reference */
/*                frame. */


/*     ETTO       is the epoch in ephemeris seconds past the epoch */
/*                of J2000 (TDB) that corresponds to the TO reference */
/*                frame. */


/* $ Detailed_Output */

/*     ROTATE     is the transformation matrix that relates the reference */
/*                frame FROM at epoch ETFROM to the frame TO at epoch */
/*                ETTO. */

/*                If (x, y, z) is a position relative to the reference */
/*                frame FROM at time ETFROM then the vector ( x', y', */
/*                z') is the same position relative to the frame TO at */
/*                epoch ETTO. Here the vector ( x', y', z' ) is defined */
/*                by the equation: */

/*                   -   -       -        -     -  - */
/*                  | x'  |     |          |   | x  | */
/*                  | y'  |  =  |  ROTATE  |   | y  | */
/*                  | z'  |     |          |   | z  | */
/*                   -   -       -        -     -  - */

/* $ Parameters */

/*     None. */


/* $ Exceptions */

/*     1)  If sufficient information has not been supplied via loaded */
/*         SPICE kernels to compute the transformation between the */
/*         two frames, the error will be diagnosed by a routine */
/*         in the call tree to this routine. */

/*     2)  If either frame FROM or TO is not recognized the error */
/*         'SPICE(UNKNOWNFRAME)' will be signaled. */

/* $ Files */

/*     Appropriate kernels must be loaded by the calling program before */
/*     this routine is called.  Kernels that may be required include */
/*     SPK files, PCK files, frame kernels, C-kernels, and SCLK kernels. */

/*     Such kernel data are normally loaded once per program */
/*     run, NOT every time this routine is called. */

/* $ Particulars */

/*     PXFRM2 is most commonly used to transform a position between */
/*     time-dependant reference frames. */

/*     For more examples of where to use PXFRM2, please see: */

/*           SINCPT */
/*           SURFPT */
/*           SUBSLR */
/*           ILUMIN */

/* $ Examples */

/*     The numerical results shown for these examples may differ across */
/*     platforms. The results depend on the SPICE kernels used as */
/*     input, the compiler and supporting libraries, and the machine */
/*     specific arithmetic implementation. */

/*     1) Suppose that MGS has taken a picture of Mars at time ETREC with */
/*        the MOC narrow angle camera. We want to know the latitude and */
/*        longitude associated with two pixels projected to Mars' */
/*        surface: the boresight and one along the boundary of the */
/*        field of view (FOV). Due to light time, the photons taken in */
/*        the picture left Mars at time ETEMIT, when Mars was at a */
/*        different state than at time ETREC. */

/*        In order to solve this problem, we could use the SINCPT */
/*        routine for both pixels, but this would be slow.  Instead, we */
/*        will assume that the light time for each pixel is the same. We */
/*        will call SINCPT once to get the light time and surface point */
/*        associated with the boresight. Then, we will rotate one of the */
/*        FOV boundary vectors from the camera frame at ETREC to the */
/*        body-fixed Mars frame at ETEMIT, and call the faster routine */
/*        SURFPT to retrieve the surface point for one of the FOV */
/*        boundary vectors. */

/*        This example problem could be extended to find the latitude */
/*        and longitude associated with every pixel in an instrument's */
/*        field of view, but this example is simplified to only solve */
/*        for two pixels:  the boresight and one along the boundary of */
/*        the field of view. */

/*        Assumptions: */

/*           1)  The light times from the surface points in the camera's */
/*               field of view to the camera are equal. */

/*           2)  The camera offset from the center of gravity of the */
/*               spacecraft is zero. If the data are more accurate */
/*               and precise, this assumption can be easily discarded. */

/*           3)  An ellipsoid shape model for the target body is */
/*               sufficient. */

/*           4)  The boundary field of view vector returned from GETFOV */
/*               is associated with a boundary field of view pixel. If */
/*               this example were extended to include a geometric camera */
/*               model, this assumption would not be needed since the */
/*               direction vectors associated with each pixel would be */
/*               calculated from the geometric camera model. */

/*        Use the meta-kernel shown below to load the required SPICE */
/*        kernels. */

/*           KPL/MK */

/*           File name: mgs_ex.tm */

/*           This is the meta-kernel file for the example problem for */
/*           the subroutine PXFRM2. These kernel files can be found in */
/*           the NAIF archives. */

/*           In order for an application to use this meta-kernel, the */
/*           kernels referenced here must be present in the user's */
/*           current working directory. */

/*           The names and contents of the kernels referenced */
/*           by this meta-kernel are as follows: */

/*              File name                     Contents */
/*              ---------                     -------- */
/*              de421.bsp                     Planetary ephemeris */
/*              pck00009.tpc                  Planet orientation and */
/*                                            radii */
/*              naif0009.tls                  Leapseconds */
/*              mgs_ext12_ipng_mgs95j.bsp     MGS ephemeris */
/*              mgs_moc_v20.ti                MGS MOC instrument */
/*                                            parameters */
/*              mgs_sclkscet_00061.tsc        MGS SCLK coefficients */
/*              mgs_sc_ext12.bc               MGS s/c bus attitude */

/*           \begindata */

/*           KERNELS_TO_LOAD = ( 'de421.bsp', */
/*                               'pck00009.tpc', */
/*                               'naif0009.tls', */
/*                               'mgs_ext12_ipng_mgs95j.bsp', */
/*                               'mgs_moc_v20.ti', */
/*                               'mgs_sclkscet_00061.tsc', */
/*                               'mgs_sc_ext12.bc' ) */

/*           \begintext */

/*           End of meta-kernel. */


/*       Example code begins here. */

/*           PROGRAM EX_PXFRM2 */
/*           IMPLICIT NONE */
/*     C */
/*     C     SPICELIB functions */
/*     C */
/*     C     Degrees per radian */
/*     C */
/*           DOUBLE PRECISION      DPR */
/*     C */
/*     C     Distance between two vectors */
/*     C */
/*           DOUBLE PRECISION      VDIST */
/*     C */
/*     C     Local parameters */
/*     C */
/*     C     ABCORR is the desired light time and stellar */
/*     C     aberration correction setting. */
/*     C */
/*           CHARACTER*(*)         ABCORR */
/*           PARAMETER           ( ABCORR = 'CN+S' ) */
/*     C */
/*     C     MGS_MOC_NA is the name of the camera that took */
/*     C     the picture being analyzed. */
/*     C */
/*           CHARACTER*(*)         CAMERA */
/*           PARAMETER           ( CAMERA = 'MGS_MOC_NA' ) */

/*           CHARACTER*(*)         METAKR */
/*           PARAMETER           ( METAKR = 'mgs_ex.tm' ) */

/*           INTEGER               FRNMLN */
/*           PARAMETER           ( FRNMLN = 32 ) */

/*           INTEGER               NCORNR */
/*           PARAMETER           ( NCORNR = 4 ) */

/*           INTEGER               SHPLEN */
/*           PARAMETER           ( SHPLEN = 80 ) */

/*     C */
/*     C     Local variables */
/*     C */
/*     C     OBSREF is the observer reference frame on MGS. */
/*     C */
/*           CHARACTER*(FRNMLN)    OBSREF */
/*           CHARACTER*(SHPLEN)    SHAPE */

/*           DOUBLE PRECISION      BOUNDS ( 3, NCORNR ) */
/*           DOUBLE PRECISION      BNDVEC ( 3 ) */
/*           DOUBLE PRECISION      BSIGHT ( 3 ) */
/*     C */
/*     C     ETEMIT is the time at which the photons were */
/*     C     emitted from Mars.  ETREC is the time at */
/*     C     which the picture was taken by MGS. */
/*     C */
/*           DOUBLE PRECISION      ETREC */
/*           DOUBLE PRECISION      ETEMIT */
/*           DOUBLE PRECISION      DIST */
/*     C */
/*     C     LAT and LON are the latitude and longitude */
/*     C     associated with one of the boundary FOV vectors. */
/*     C */
/*           DOUBLE PRECISION      LAT */
/*           DOUBLE PRECISION      LON */
/*     C */
/*     C     PMGSMR is the opposite of the apparent position of */
/*     C     Mars with respect to MGS. */
/*     C */
/*           DOUBLE PRECISION      PMGSMR ( 3 ) */
/*     C */
/*     C     RADII is a vector of the semi-axes of Mars. */
/*     C */
/*           DOUBLE PRECISION      RADII  ( 3 ) */
/*           DOUBLE PRECISION      RADIUS */
/*     C */
/*     C     ROTATE is a position transformation matrix from */
/*     C     the camera frame at ETREC to the IAU_MARS frame */
/*     C     at ETEMIT. */
/*     C */
/*           DOUBLE PRECISION      ROTATE ( 3, 3 ) */
/*           DOUBLE PRECISION      SPOINT ( 3 ) */
/*           DOUBLE PRECISION      SRFVEC ( 3 ) */
/*           DOUBLE PRECISION      TMP    ( 3 ) */

/*           INTEGER               CAMID */
/*           INTEGER               DIM */
/*           INTEGER               N */

/*           LOGICAL               FOUND */
/*     C */
/*     C     ------------------ Program Setup ------------------ */
/*     C */
/*     C     Load kernel files via the meta-kernel. */
/*     C */
/*           CALL FURNSH ( METAKR ) */
/*     C */
/*     C     Convert the time the picture was taken from a */
/*     C     UTC time string to seconds past J2000, TDB. */
/*     C */
/*           CALL STR2ET ( '2003 OCT 13 06:00:00 UTC', ETREC ) */
/*     C */
/*     C     Assume the one-way light times from different */
/*     C     surface points on Mars to MGS within the camera's */
/*     C     FOV are equal. This means the photons that make */
/*     C     up different pixels were all emitted from Mars at */
/*     C     ETEMIT and received by the MGS MOC camera at ETREC. It */
/*     C     would be slow to process images using SINCPT for every */
/*     C     pixel. Instead, we will use SINCPT on the */
/*     C     boresight pixel and use SURFPT for one of the FOV */
/*     C     boundary pixels. If this example program were extended */
/*     C     to include all of the camera's pixels, SURFPT would */
/*     C     be used for the remaining pixels. */
/*     C */
/*     C     Get the MGS MOC Narrow angle camera (MGS_MOC_NA) */
/*     C     ID code. Then look up the field of view (FOV) */
/*     C     parameters by calling GETFOV. */
/*     C */
/*           CALL BODN2C ( CAMERA, CAMID, FOUND ) */

/*           IF ( .NOT. FOUND ) THEN */

/*              CALL SETMSG ( 'Could not find ID code for ' // */
/*          .                 'instrument #.'               ) */
/*              CALL ERRCH  ( '#', CAMERA                   ) */
/*              CALL SIGERR ( 'SPICE(NOTRANSLATION)'        ) */

/*           END IF */
/*     C */
/*     C     GETFOV will return the name of the camera-fixed frame */
/*     C     in the string OBSREF, the camera boresight vector in */
/*     C     the array BSIGHT, and the FOV corner vectors in the */
/*     C     array BOUNDS. */
/*     C */
/*           CALL GETFOV ( CAMID,  NCORNR, SHAPE, OBSREF, */
/*          .              BSIGHT, N,      BOUNDS       ) */

/*           WRITE (*,*) 'Observation Reference frame:  ', OBSREF */

/*     C */
/*     C     ----------- Boresight Surface Intercept ----------- */
/*     C */
/*     C     Retrieve the time, surface intercept point, and vector */
/*     C     from MGS to the boresight surface intercept point */
/*     C     in IAU_MARS coordinates. */
/*     C */
/*           CALL SINCPT ( 'ELLIPSOID', 'MARS',  ETREC, 'IAU_MARS', */
/*          .               ABCORR,     'MGS',   OBSREF, BSIGHT, */
/*          .               SPOINT,      ETEMIT, SRFVEC, FOUND  ) */

/*           IF ( .NOT. FOUND ) THEN */

/*              CALL SETMSG ( 'Intercept not found for the ' // */
/*          .                 'boresight vector.'  ) */
/*              CALL SIGERR ( 'SPICE(NOINTERCEPT)' ) */

/*           END IF */
/*     C */
/*     C     Convert the intersection point of the boresight */
/*     C     vector and Mars from rectangular into latitudinal */
/*     C     coordinates. Convert radians to degrees. */
/*     C */
/*           CALL RECLAT ( SPOINT, RADIUS, LON, LAT ) */

/*           LON = LON * DPR () */
/*           LAT = LAT * DPR () */

/*           WRITE (*,*) 'Boresight surface intercept ' // */
/*          .            'coordinates:' */
/*           WRITE (*,*) '   Radius    (km) :  ', RADIUS */
/*           WRITE (*,*) '   Latitude  (deg):  ', LAT */
/*           WRITE (*,*) '   Longitude (deg):  ', LON */

/*     C */
/*     C     --------- A Boundary FOV Surface Intercept (SURFPT) ------ */
/*     C */
/*     C     Now we will transform one of the FOV corner vectors into the */
/*     C     IAU_MARS frame so the surface intercept point can be */
/*     C     calculated using SURFPT, which is faster than SUBPNT. */
/*     C */
/*     C     If this example program were extended to include all */
/*     C     of the pixels in the camera's FOV, a few steps, such as */
/*     C     finding the rotation matrix from the camera frame to the */
/*     C     IAU_MARS frame, looking up the radii values for Mars, */
/*     C     and finding the position of MGS with respect to Mars could */
/*     C     be done once and used for every pixel. */
/*     C */
/*     C     Find the rotation matrix from the ray's reference */
/*     C     frame at the time the photons were received (ETREC) */
/*     C     to IAU_MARS at the time the photons were emitted */
/*     C     (ETEMIT). */
/*     C */
/*           CALL PXFRM2 ( OBSREF, 'IAU_MARS', ETREC, ETEMIT, ROTATE ) */

/*     C */
/*     C     Look up the radii values for Mars. */
/*     C */
/*           CALL BODVRD ( 'MARS', 'RADII', 3, DIM, RADII ) */

/*     C */
/*     C     Find the position of the center of Mars with respect */
/*     C     to MGS.  The position of the observer with respect */
/*     C     to Mars is required for the call to SURFPT.  Note: */
/*     C     the apparent position of MGS with respect to Mars is */
/*     C     not the same as the negative of Mars with respect to MGS. */
/*     C */
/*           CALL VSUB   ( SPOINT, SRFVEC, PMGSMR ) */

/*     C */
/*     C     The selected boundary FOV pixel must be rotated into the */
/*     C     IAU_MARS reference frame. */
/*     C */
/*           CALL MXV    ( ROTATE, BOUNDS(1,1), BNDVEC ) */

/*     C */
/*     C     Calculate the surface point of the boundary FOV */
/*     C     vector. */
/*     C */
/*           CALL SURFPT ( PMGSMR,   BNDVEC, RADII(1), RADII(2), */
/*          .              RADII(3), SPOINT, FOUND ) */

/*           IF ( .NOT. FOUND ) THEN */

/*              CALL SETMSG ( 'Could not calculate surface point.') */
/*              CALL SIGERR ( 'SPICE(NOTFOUND)' ) */

/*           END IF */

/*           CALL VEQU   ( SPOINT, TMP ) */
/*     C */
/*     C     Convert the intersection point of the boundary */
/*     C     FOV vector and Mars from rectangular into */
/*     C     latitudinal coordinates. Convert radians */
/*     C     to degrees. */
/*     C */
/*           CALL RECLAT ( SPOINT, RADIUS, LON, LAT ) */

/*           LON = LON * DPR () */
/*           LAT = LAT * DPR () */

/*           WRITE (*,*) 'Boundary vector surface intercept ' // */
/*          .               'coordinates using SURFPT:' */
/*           WRITE (*,*) '   Radius    (km) :  ', RADIUS */
/*           WRITE (*,*) '   Latitude  (deg):  ', LAT */
/*           WRITE (*,*) '   Longitude (deg):  ', LON */
/*           WRITE (*,*) '   Emit time using' */
/*           WRITE (*,*) '   boresight LT(s):  ', ETEMIT */

/*     C */
/*     C     ------ A Boundary FOV Surface Intercept Verification ---- */
/*     C */
/*     C     For verification only, we will calculate the surface */
/*     C     intercept coordinates for the selected boundary vector */
/*     C     using SINCPT and compare to the faster SURFPT method. */
/*     C */
/*           CALL SINCPT ( 'ELLIPSOID', 'MARS',  ETREC, 'IAU_MARS', */
/*          .               ABCORR,     'MGS',   OBSREF, BOUNDS(1,1), */
/*          .               SPOINT,      ETEMIT, SRFVEC, FOUND ) */

/*           IF ( .NOT. FOUND ) THEN */

/*              CALL SETMSG ( 'Intercept not found for the ' // */
/*          .                 'boresight vector.'  ) */
/*              CALL SIGERR ( 'SPICE(NOINTERCEPT)' ) */

/*           END IF */
/*     C */
/*     C     Convert the intersection point of the selected boundary */
/*     C     vector and Mars from rectangular into latitudinal */
/*     C     coordinates. Convert radians to degrees. */
/*     C */
/*           CALL RECLAT ( SPOINT, RADIUS, LON, LAT ) */

/*           LON = LON * DPR () */
/*           LAT = LAT * DPR () */

/*           WRITE (*,*) 'Boundary vector surface intercept ' // */
/*          .               'coordinates using SINCPT:' */
/*           WRITE (*,*) '   Radius    (km) :  ', RADIUS */
/*           WRITE (*,*) '   Latitude  (deg):  ', LAT */
/*           WRITE (*,*) '   Longitude (deg):  ', LON */
/*           WRITE (*,*) '   Emit time using' */
/*           WRITE (*,*) '   boundary LT(s) :  ', ETEMIT */

/*     C */
/*     C     We expect this to be a very small distance. */
/*     C */
/*           DIST = VDIST ( TMP, SPOINT ) */

/*           WRITE (*,*) 'Distance between surface points' */
/*           WRITE (*,*) 'of the selected boundary vector using' */
/*           WRITE (*,*) 'SURFPT and SINCPT:' */
/*           WRITE (*,*) '   Distance (mm):     ', DIST*(10**6) */

/*           END */

/*     When this program was executed using gfortran on a PC Linux */
/*     64 bit environment, the output was: */

/*           Observation Reference frame:  MGS_MOC_NA */
/*           Boresight surface intercept coordinates: */
/*              Radius    (km) :     3384.9404101592791 */
/*              Latitude  (deg):    -48.479579821639035 */
/*              Longitude (deg):    -123.43645396290199 */
/*           Boundary vector surface intercept coordinates using SURFPT: */
/*              Radius    (km) :     3384.9411359300038 */
/*              Latitude  (deg):    -48.477481877892437 */
/*              Longitude (deg):    -123.47407986665237 */
/*              Emit time using */
/*              boresight LT(s):     119296864.18105948 */
/*           Boundary vector surface intercept coordinates using SINCPT: */
/*              Radius    (km) :     3384.9411359139663 */
/*              Latitude  (deg):    -48.477481924252693 */
/*              Longitude (deg):    -123.47407904898704 */
/*              Emit time using */
/*              boundary LT(s) :     119296864.18105946 */
/*           Distance between surface points */
/*           of the selected boundary vector using */
/*           SURFPT and SINCPT: */
/*              Distance (mm):       32.139879867352690 */


/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     S.C. Krening  (JPL) */
/*     B.V. Semenov  (JPL) */
/*     W.L. Taber    (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.0.0, 23-SEP-2013 (SCK) (WLT) (BVS) */

/* -& */
/* $ Index_Entries */

/*     Position transformation matrix for different epochs */

/* -& */
/* $ Revisions */

/*     None. */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */

/*     JCODE represents the NAIF ID of the J2000 reference frame. */
/*     The J2000 frame has a NAIF ID of 1. Any inertial reference */
/*     frame could have been used for this program instead of J2000. */


/*     Saved frame name length. */


/*     Local variables */


/*     Saved frame name/ID item declarations. */


/*     Saved frame name/ID items. */


/*     Initial values. */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    }
    chkin_("PXFRM2", (ftnlen)6);

/*     Initialization. */

    if (first) {

/*        Initialize counters. */

	zzctruin_(svctr1);
	zzctruin_(svctr2);
	first = FALSE_;
    }

/*     The frame names must be converted to their corresponding IDs. */

    zznamfrm_(svctr1, svfrom, &svfcod, from, &fcode, (ftnlen)32, from_len);
    zznamfrm_(svctr2, svto, &svtcde, to, &tcode, (ftnlen)32, to_len);

/*     Only non-zero ID codes are legitimate frame ID codes.  Zero */
/*     indicates that the frame was not recognized. */

    if (fcode != 0 && tcode != 0) {

/*        The following three lines of code calculate the following: */

/*        1)  [JF]      The rotation matrix is calculated from the frame */
/*                          FROM to the inertial J2000 frame at ETFROM. */
/*        2)  [TJ]      The rotation matrix is calculated from the J2000 */
/*                          frame to the TO frame at ETTO. */
/*        3)  [ROTATE]  The rotation matrix from frame FROM at ETFROM to */
/*                          frame TO at ETTO is given by the following: */

/*                              [ROTATE] = [TF] = [TJ][JF] */

	refchg_(&fcode, &c__1, etfrom, jf);
	refchg_(&c__1, &tcode, etto, tj);
	mxm_(tj, jf, rotate);
    } else if (fcode == 0 && tcode == 0) {
	setmsg_("Neither frame # nor # was recognized as a known reference f"
		"rame. ", (ftnlen)65);
	errch_("#", from, (ftnlen)1, from_len);
	errch_("#", to, (ftnlen)1, to_len);
	sigerr_("SPICE(UNKNOWNFRAME)", (ftnlen)19);
    } else if (fcode == 0) {
	setmsg_("The frame # was not recognized as a known reference frame. ",
		 (ftnlen)59);
	errch_("#", from, (ftnlen)1, from_len);
	sigerr_("SPICE(UNKNOWNFRAME)", (ftnlen)19);
    } else {

/*        TCODE is zero */

	setmsg_("The frame # was not recognized as a known reference frame. ",
		 (ftnlen)59);
	errch_("#", to, (ftnlen)1, to_len);
	sigerr_("SPICE(UNKNOWNFRAME)", (ftnlen)19);
    }
    chkout_("PXFRM2", (ftnlen)6);
    return 0;
} /* pxfrm2_ */
Beispiel #5
0
/* $Procedure      CKGP ( C-kernel, get pointing ) */
/* Subroutine */ int ckgp_(integer *inst, doublereal *sclkdp, doublereal *tol,
	 char *ref, doublereal *cmat, doublereal *clkout, logical *found, 
	ftnlen ref_len)
{
    logical pfnd, sfnd;
    integer sclk;
    extern /* Subroutine */ int sct2e_(integer *, doublereal *, doublereal *);
    integer type1, type2;
    char segid[40];
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    doublereal descr[5];
    extern /* Subroutine */ int dafus_(doublereal *, integer *, integer *, 
	    doublereal *, integer *), ckbss_(integer *, doublereal *, 
	    doublereal *, logical *), ckpfs_(integer *, doublereal *, 
	    doublereal *, doublereal *, logical *, doublereal *, doublereal *,
	     doublereal *, logical *), moved_(doublereal *, integer *, 
	    doublereal *), cksns_(integer *, doublereal *, char *, logical *, 
	    ftnlen);
    logical gotit;
    extern logical failed_(void);
    doublereal av[3], et;
    integer handle;
    extern /* Subroutine */ int refchg_(integer *, integer *, doublereal *, 
	    doublereal *);
    logical needav;
    extern /* Subroutine */ int ckmeta_(integer *, char *, integer *, ftnlen);
    integer refseg, center;
    extern /* Subroutine */ int namfrm_(char *, integer *, ftnlen), frinfo_(
	    integer *, integer *, integer *, integer *, logical *);
    integer refreq, typeid;
    extern /* Subroutine */ int chkout_(char *, ftnlen);
    doublereal tmpmat[9]	/* was [3][3] */;
    extern logical return_(void);
    doublereal dcd[2];
    integer icd[6];
    extern /* Subroutine */ int mxm_(doublereal *, doublereal *, doublereal *)
	    ;
    doublereal rot[9]	/* was [3][3] */;

/* $ Abstract */

/*     Get pointing (attitude) for a specified spacecraft clock time. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     CK */
/*     SCLK */

/* $ Keywords */

/*     POINTING */

/* $ Declarations */
/* $ Abstract */

/*     The parameters below form an enumerated list of the recognized */
/*     frame types.  They are: INERTL, PCK, CK, TK, DYN.  The meanings */
/*     are outlined below. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Parameters */

/*     INERTL      an inertial frame that is listed in the routine */
/*                 CHGIRF and that requires no external file to */
/*                 compute the transformation from or to any other */
/*                 inertial frame. */

/*     PCK         is a frame that is specified relative to some */
/*                 INERTL frame and that has an IAU model that */
/*                 may be retrieved from the PCK system via a call */
/*                 to the routine TISBOD. */

/*     CK          is a frame defined by a C-kernel. */

/*     TK          is a "text kernel" frame.  These frames are offset */
/*                 from their associated "relative" frames by a */
/*                 constant rotation. */

/*     DYN         is a "dynamic" frame.  These currently are */
/*                 parameterized, built-in frames where the full frame */
/*                 definition depends on parameters supplied via a */
/*                 frame kernel. */

/* $ Author_and_Institution */

/*     N.J. Bachman    (JPL) */
/*     W.L. Taber      (JPL) */

/* $ Literature_References */

/*     None. */

/* $ Version */

/* -    SPICELIB Version 3.0.0, 28-MAY-2004 (NJB) */

/*       The parameter DYN was added to support the dynamic frame class. */

/* -    SPICELIB Version 2.0.0, 12-DEC-1996 (WLT) */

/*        Various unused frames types were removed and the */
/*        frame time TK was added. */

/* -    SPICELIB Version 1.0.0, 10-DEC-1995 (WLT) */

/* -& */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     INST       I   NAIF ID of instrument, spacecraft, or structure. */
/*     SCLKDP     I   Encoded spacecraft clock time. */
/*     TOL        I   Time tolerance. */
/*     REF        I   Reference frame. */
/*     CMAT       O   C-matrix pointing data. */
/*     CLKOUT     O   Output encoded spacecraft clock time. */
/*     FOUND      O   True when requested pointing is available. */

/* $ Detailed_Input */

/*     INST       is the NAIF integer ID for the instrument, spacecraft, */
/*                or other structure for which pointing is requested. */
/*                For brevity we will refer to this object as the */
/*                "instrument," and the frame fixed to this object as */
/*                the "instrument frame" or "instrument-fixed" frame. */

/*     SCLKDP     is the encoded spacecraft clock time for which */
/*                pointing is requested. */

/*                The SPICELIB routines SCENCD and SCE2C respectively */
/*                convert spacecraft clock strings and ephemeris time to */
/*                encoded spacecraft clock.  The inverse conversions are */
/*                performed by SCDECD and SCT2E. */

/*     TOL        is a time tolerance in ticks, the units of encoded */
/*                spacecraft clock time. */

/*                The SPICELIB routine SCTIKS converts a spacecraft */
/*                clock tolerance duration from its character string */
/*                representation to ticks.  SCFMT performs the inverse */
/*                conversion. */

/*                The C-matrix returned by CKGP is the one whose time */
/*                tag is closest to SCLKDP and within TOL units of */
/*                SCLKDP.  (More in Particulars, below.) */

/*                In general, because using a non-zero tolerance */
/*                affects selection of the segment from which the */
/*                data is obtained, users are strongly discouraged */
/*                from using a non-zero tolerance when reading CKs */
/*                with continuous data. Using a non-zero tolerance */
/*                should be reserved exclusively to reading CKs with */
/*                discrete data because in practice obtaining data */
/*                from such CKs using a zero tolerance is often not */
/*                possible due to time round off. */

/*     REF        is the desired reference frame for the returned */
/*                pointing.  The returned C-matrix CMAT gives the */
/*                orientation of the instrument designated by INST */
/*                relative to the frame designated by REF.  When a */
/*                vector specified relative to frame REF is left- */
/*                multiplied by CMAT, the vector is rotated to the */
/*                frame associated with INST.  See the discussion of */
/*                CMAT below for details. */

/*                Consult the SPICE document "Frames" for a discussion */
/*                of supported reference frames. */

/* $ Detailed_Output */

/*     CMAT       is a rotation matrix that transforms the components of */
/*                a vector expressed in the reference frame specified by */
/*                REF to components expressed in the frame tied to the */
/*                instrument, spacecraft, or other structure at time */
/*                CLKOUT (see below). */

/*                Thus, if a vector v has components x,y,z in the REF */
/*                reference frame, then v has components x',y',z' in the */
/*                instrument fixed frame at time CLKOUT: */

/*                     [ x' ]     [          ] [ x ] */
/*                     | y' |  =  |   CMAT   | | y | */
/*                     [ z' ]     [          ] [ z ] */

/*                If you know x', y', z', use the transpose of the */
/*                C-matrix to determine x, y, z as follows: */

/*                     [ x ]      [          ]T    [ x' ] */
/*                     | y |  =   |   CMAT   |     | y' | */
/*                     [ z ]      [          ]     [ z' ] */
/*                              (Transpose of CMAT) */


/*     CLKOUT     is the encoded spacecraft clock time associated with */
/*                the returned C-matrix. This value may differ from the */
/*                requested time, but never by more than the input */
/*                tolerance TOL. */

/*                The particulars section below describes the search */
/*                algorithm used by CKGP to satisfy a pointing */
/*                request.  This algorithm determines the pointing */
/*                instance (and therefore the associated time value) */
/*                that is returned. */

/*     FOUND      is true if a record was found to satisfy the pointing */
/*                request.  FOUND will be false otherwise. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)  If a C-kernel file has not been loaded using FURNSH prior to */
/*         a call to this routine, an error is signaled by a routine in */
/*         the call tree of this routine. */

/*     2)  If TOL is negative, found is set to .FALSE. */

/*     3)  If REF is not a supported reference frame, an error is */
/*         signaled by a routine in the call tree of this routine and */
/*         FOUND is set to .FALSE. */

/* $ Files */

/*     CKGP searches through files loaded by FURNSH to locate a */
/*     segment that can satisfy the request for pointing for instrument */
/*     INST at time SCLKDP.  You must load a C-kernel file using FURNSH */
/*     prior to calling this routine. */

/* $ Particulars */

/*     How the tolerance argument is used */
/*     ================================== */


/*     Reading a type 1 CK segment (discrete pointing instances) */
/*     --------------------------------------------------------- */

/*     In the diagram below */

/*        - "0" is used to represent discrete pointing instances */
/*          (quaternions and associated time tags). */

/*        - "( )" are used to represent the end points of the time */
/*          interval covered by a segment in a CK file. */

/*        - SCLKDP is the time at which you requested pointing. */
/*          The location of SCLKDP relative to the time tags of the */
/*          pointing instances is indicated by the "+" sign. */

/*        - TOL is the time tolerance specified in the pointing */
/*          request.  The square brackets "[ ]" represent the */
/*          endpoints of the time interval */

/*             SCLKDP-TOL : SCLKDP+TOL */

/*        - The quaternions occurring in the segment need not be */
/*          evenly spaced in time. */


/*     Case 1:  pointing is available */
/*     ------------------------------ */

/*                              SCLKDP */
/*                                   \   TOL */
/*                                    | / */
/*                                    |/\ */
/*     Your request                [--+--] */
/*                                 .  .  . */
/*     Segment      (0-----0--0--0--0--0--0---0--0------------0--0--0--0) */
/*                                     ^ */
/*                                     | */
/*                         CKGP returns this instance. */


/*     Case 2:  pointing is not available */
/*     ---------------------------------- */

/*                                                   SCLKDP */
/*                                                      \   TOL */
/*                                                       | / */
/*                                                       |/\ */
/*     Your request                                   [--+--] */
/*                                                    .  .  . */
/*     Segment      (0-----0--0--0--0--0--0---0--0--0---------0--0--0--0) */


/*                         CKGP returns no pointing; the output */
/*                         FOUND flag is set to .FALSE. */



/*     Reading a type 2, 3, 4, or 5 CK segment (continuous pointing) */
/*     ------------------------------------------------------------- */

/*     In the diagrams below */

/*        - "==" is used to represent periods of continuous pointing. */

/*        - "--" is used to represent gaps in the pointing coverage. */

/*        - "( )" are used to represent the end points of the time */
/*          interval covered by a segment in a CK file. */

/*        - SCLKDP is the time at which you requested pointing. */
/*          The location of SCLKDP relative to the time tags of the */
/*          pointing instances is indicated by the "+" sign. */

/*        - TOL is the time tolerance specified in the pointing */
/*          request.  The square brackets "[ ]" represent the */
/*          endpoints of the time interval */

/*             SCLKDP-TOL : SCLKDP+TOL */

/*        - The quaternions occurring in the periods of continuous */
/*          pointing need not be evenly spaced in time. */


/*     Case 1:  pointing is available at the request time */
/*     -------------------------------------------------- */

/*                             SCLKDP */
/*                                   \   TOL */
/*                                    | / */
/*                                    |/\ */
/*     Your request                [--+--] */
/*                                 .  .  . */
/*                                 .  .  . */
/*                                 .  .  . */
/*     Segment            (==---===========---=======----------===--) */
/*                                    ^ */
/*                                    | */

/*                   The request time lies within an interval where */
/*                   continuous pointing is available. CKGP returns */
/*                   pointing at the requested epoch. */


/*     Case 2:  pointing is available "near" the request time */
/*     ------------------------------------------------------ */

/*                                    SCLKDP */
/*                                          \   TOL */
/*                                           | / */
/*                                           |/\ */
/*     Your request                       [--+--] */
/*                                        .  .  . */
/*     Segment            (==---===========----=======---------===--) */
/*                                             ^ */
/*                                             | */

/*                   The request time lies in a gap:  an interval where */
/*                   continuous pointing is *not* available.  CKGP */
/*                   returns pointing for the epoch closest to the */
/*                   request time SCLKDP. */


/*     Case 3:  pointing is not available */
/*     ---------------------------------- */

/*                                                 SCLKDP */
/*                                                       \   TOL */
/*                                                        | / */
/*                                                        |/\ */
/*     Your request                                    [--+--] */
/*                                                     .  .  . */
/*     Segment            (==---===========----=======---------===--) */

/*                         CKGP returns no pointing; the output */
/*                         FOUND flag is set to .FALSE. */



/*     Tolerance and segment priority */
/*     ============================== */

/*     CKGP searches through loaded C-kernels to satisfy a pointing */
/*     request. Last-loaded files are searched first. Individual files */
/*     are searched in backwards order, so that between competing */
/*     segments (segments containing data for the same object, for */
/*     overlapping time ranges), the one closest to the end of the file */
/*     has highest priority. */

/*     The search ends when a segment is found that can provide pointing */
/*     for the specified instrument at a time falling within the */
/*     specified tolerance on either side of the request time. Within */
/*     that segment, the instance closest to the input time is located */
/*     and returned. */

/*     The following four cases illustrate this search procedure. */
/*     Segments A and B are in the same file, with segment A located */
/*     further towards the end of the file than segment B. Both segments */
/*     A and B contain discrete pointing data, indicated by the number */
/*     0. */


/*     Case 1:  Pointing is available in the first segment searched. */
/*              Because segment A has the highest priority and can */
/*              satisfy the request, segment B is not searched. */


/*                                  SCLKDP */
/*                                        \  TOL */
/*                                         | / */
/*                                         |/\ */
/*     Your request                     [--+--] */
/*                                      .  .  . */
/*     Segment A          (0-----------------0--------0--0-----0) */
/*                                           ^ */
/*                                           | */
/*                                           | */
/*                               CKGP returns this instance */

/*     Segment B     (0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0) */



/*     Case 2:  Pointing is not available in the first segment searched. */
/*              Because segment A cannot satisfy the request, segment B */
/*              is searched. */


/*                             SCLKDP */
/*                                  \   TOL */
/*                                   | / */
/*                                   |/\ */
/*     Your request               [--+--] */
/*                                .  .  . */
/*     Segment A          (0-----------------0--------0--0-----0) */
/*                                .  .  . */
/*     Segment B     (0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0) */
/*                                   ^ */
/*                                   | */
/*                       CKGP returns this instance */


/*     Segments that contain continuous pointing data are searched in */
/*     the same manner as segments containing discrete pointing data. */
/*     For request times that fall within the bounds of continuous */
/*     intervals, CKGP will return pointing at the request time. When */
/*     the request time does not fall within an interval, then a time at */
/*     an endpoint of an interval may be returned if it is the closest */
/*     time in the segment to the user request time and is also within */
/*     the tolerance. */

/*     In the following examples, segment A is located further towards */
/*     the end of the file than segment C. Segment A contains discrete */
/*     pointing data and segment C contains continuous data, indicated */
/*     by the "=" character. */


/*     Case 3:  Pointing is not available in the first segment searched. */
/*              Because segment A cannot satisfy the request, segment C */
/*              is searched. */

/*                             SCLKDP */
/*                                   \  TOL */
/*                                    | / */
/*                                    |/\ */
/*     Your request                [--+--] */
/*                                 .  .  . */
/*                                 .  .  . */
/*     Segment A          (0-----------------0--------0--0-----0) */
/*                                 .  .  . */
/*                                 .  .  . */
/*     Segment C          (---=============-----====--------==--) */
/*                                    ^ */
/*                                    | */
/*                                    | */
/*                         CKGP returns this instance */


/*     In the next case, assume that the order of segments A and C in the */
/*     file is reversed:  A is now closer to the front, so data from */
/*     segment C are considered first. */


/*     Case 4:  Pointing is available in the first segment searched. */
/*              Because segment C has the highest priority and can */
/*              satisfy the request, segment A is not searched. */

/*                                             SCLKDP */
/*                                            / */
/*                                           |  TOL */
/*                                           | / */
/*                                           |/\ */
/*     Your request                       [--+--] */
/*                                        .  .  . */
/*                                        .  .  . */
/*     Segment C          (---=============-----====--------==--) */
/*                                             ^ */
/*                                             | */
/*                                CKGP returns this instance */

/*     Segment A          (0-----------------0--------0--0-----0) */
/*                                           ^ */
/*                                           | */
/*                                     "Best" answer */


/*     The next case illustrates an unfortunate side effect of using */
/*     a non-zero tolerance when reading multi-segment CKs with */
/*     continuous data. In all cases when the look-up interval */
/*     formed using tolerance overlaps a segment boundary and */
/*     the request time falls within the coverage of the lower */
/*     priority segment, the data at the end of the higher priority */
/*     segment will be picked instead of the data from the lower */
/*     priority segment. */


/*     Case 5:  Pointing is available in the first segment searched. */
/*              Because segment C has the highest priority and can */
/*              satisfy the request, segment A is not searched. */

/*                                             SCLKDP */
/*                                            / */
/*                                           |  TOL */
/*                                           | / */
/*                                           |/\ */
/*     Your request                       [--+--] */
/*                                        .  .  . */
/*                                        .  .  . */
/*     Segment C                                (===============) */
/*                                              ^ */
/*                                              | */
/*                                CKGP returns this instance */

/*     Segment A          (=====================) */
/*                                           ^ */
/*                                           | */
/*                                     "Best" answer */

/* $ Examples */

/*     Suppose you have two C-kernel files containing data for the */
/*     Voyager 2 narrow angle camera.  One file contains predict values, */
/*     and the other contains corrected pointing for a selected group */
/*     of images, that is, for a subset of images from the first file. */

/*     The following example program uses CKGP to get C-matrices for a */
/*     set of images whose SCLK counts (un-encoded character string */
/*     versions) are contained in the array SCLKCH. */

/*     If available, the program will get the corrected pointing values. */
/*     Otherwise, predict values will be used. */

/*     For each C-matrix, a unit  pointing vector is constructed */
/*     and printed. */


/*     C */
/*     C     Constants for this program. */
/*     C */
/*     C     -- The code for the Voyager 2 spacecraft clock is -32 */
/*     C */
/*     C     -- The code for the narrow angle camera on the Voyager 2 */
/*     C        spacecraft is -32001. */
/*     C */
/*     C    --  Spacecraft clock times for successive Voyager images */
/*     C        always differ by more than 0:0:400.  This is an */
/*     C        acceptable tolerance, and must be converted to "ticks" */
/*     C        (units of encoded SCLK) for input to CKGP. */
/*     C */
/*     C     -- The reference frame we want is FK4. */
/*     C */
/*     C     -- The narrow angle camera boresight defines the third */
/*     C        axis of the instrument-fixed coordinate system. */
/*     C        Therefore, the vector ( 0, 0, 1 ) represents */
/*     C        the boresight direction in the camera-fixed frame. */
/*     C */
/*           IMPLICIT NONE */

/*           INTEGER               FILEN */
/*           PARAMETER           ( FILEN  = 255 ) */

/*           INTEGER               NPICS */
/*           PARAMETER           ( NPICS  = 2 ) */

/*           INTEGER               TIMLEN */
/*           PARAMETER           ( TIMLEN = 30 ) */

/*           INTEGER               REFLEN */
/*           PARAMETER           ( REFLEN = 32 ) */

/*           CHARACTER*(TIMLEN)    CLKCH */
/*           CHARACTER*(FILEN)     CKPRED */
/*           CHARACTER*(FILEN)     CKCORR */
/*           CHARACTER*(REFLEN)    REF */
/*           CHARACTER*(FILEN)     SCLK */
/*           CHARACTER*(TIMLEN)    SCLKCH ( NPICS ) */
/*           CHARACTER*(TIMLEN)    TOLVGR */

/*           DOUBLE PRECISION      CLKOUT */
/*           DOUBLE PRECISION      CMAT   ( 3, 3 ) */
/*           DOUBLE PRECISION      SCLKDP */
/*           DOUBLE PRECISION      TOLTIK */
/*           DOUBLE PRECISION      VCFIX  ( 3 ) */
/*           DOUBLE PRECISION      VINERT ( 3 ) */

/*           INTEGER               SC */
/*           INTEGER               I */
/*           INTEGER               INST */

/*           LOGICAL               FOUND */

/*           CKPRED     = 'voyager2_predict.bc' */
/*           CKCORR     = 'voyager2_corrected.bc' */
/*           SCLK       = 'voyager2_sclk.tsc' */
/*           SC         = -32 */
/*           INST       = -32001 */
/*           SCLKCH(1)  = '4/08966:30:768' */
/*           SCLKCH(2)  = '4/08970:58:768' */
/*           TOLVGR     = '0:0:400' */
/*           REF        = 'FK4' */
/*           VCFIX( 1 ) =  0.D0 */
/*           VCFIX( 2 ) =  0.D0 */
/*           VCFIX( 3 ) =  1.D0 */

/*     C */
/*     C     Loading the files in this order ensures that the */
/*     C     corrected file will get searched first. */
/*     C */
/*           CALL FURNSH ( CKPRED ) */
/*           CALL FURNSH ( CKCORR ) */

/*     C */
/*     C     Need to load a Voyager 2 SCLK kernel to convert from */
/*     C     clock strings to ticks. */
/*     C */
/*           CALL FURNSH ( SCLK ) */

/*     C */
/*     C     Convert tolerance from VGR formatted character string */
/*     C     SCLK to ticks which are units of encoded SCLK. */
/*     C */
/*           CALL SCTIKS ( SC, TOLVGR, TOLTIK ) */


/*           DO I = 1, NPICS */
/*     C */
/*     C        CKGP requires encoded spacecraft clock. */
/*     C */
/*              CALL SCENCD ( SC, SCLKCH( I ), SCLKDP ) */

/*              CALL CKGP ( INST,   SCLKDP, TOLTIK, REF, CMAT, */
/*          .               CLKOUT, FOUND                      ) */

/*              IF ( FOUND ) THEN */

/*     C */
/*     C           Use the transpose of the C-matrix to transform the */
/*     C           boresight vector from camera-fixed to reference */
/*     C           coordinates. */
/*     C */
/*                 CALL MTXV   ( CMAT, VCFIX,  VINERT ) */
/*                 CALL SCDECD ( SC,   CLKOUT, CLKCH  ) */

/*                 WRITE (*,*) 'VGR 2 SCLK Time:         ', CLKCH */
/*                 WRITE (*,*) 'VGR 2 NA ISS boresight ' */
/*          .      //          'pointing vector: ',         VINERT */

/*              ELSE */

/*                 WRITE (*,*) 'Pointing not found for time ', SCLKCH(I) */

/*              END IF */

/*           END DO */

/*           END */


/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     C.H. Acton     (JPL) */
/*     N.J. Bachman   (JPL) */
/*     W.L. Taber     (JPL) */
/*     J.M. Lynch     (JPL) */
/*     B.V. Semenov   (JPL) */
/*     M.J. Spencer   (JPL) */
/*     R.E. Thurman   (JPL) */
/*     I.M. Underwood (JPL) */

/* $ Version */

/* -    SPICELIB Version 5.3.1, 09-JUN-2010 (BVS) */

/*        Header update: description of the tolerance and Particulars */
/*        section were expanded to address some problems arising from */
/*        using a non-zero tolerance. */

/* -    SPICELIB Version 5.3.0, 23-APR-2010 (NJB) */

/*        Bug fix: this routine now obtains the rotation */
/*        from the request frame to the applicable CK segment's */
/*        base frame via a call to REFCHG. Formerly the routine */
/*        used FRMCHG, which required that angular velocity data */
/*        be available for this transformation. */

/* -    SPICELIB Version 5.2.0, 25-AUG-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in MXM call. */

/* -    SPICELIB Version 5.1.2, 29-JAN-2004 (NJB) */

/*        Header update:  description of input argument REF was */
/*        expanded. */

/* -    SPICELIB Version 5.1.1, 27-JUL-2003 (CHA) (NJB) */

/*        Various header corrections were made. */

/* -    SPICELIB Version 3.2.0, 23-FEB-1999 (WLT) */

/*        The previous editions of this routine did not properly handle */
/*        the case when TOL was negative.  The routine now returns a */
/*        value of .FALSE. for FOUND as is advertised above. */

/* -    SPICELIB Version 3.1.0, 13-APR-1998 (WLT) */

/*        The call to CHKOUT in the case when FAILED returned the */
/*        value TRUE used to check out with the name 'CKGPAV'.  This */
/*        has been changed to a CKGP. */

/* -    SPICELIB Version 3.0.0, 19-SEP-1994 (WLT) */

/*        The routine was upgraded to support non-inertial frames. */

/* -    SPICELIB Version 2.0.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -    SPICELIB Version 2.0.0, 30-AUG-1991 (JML) */

/*        The Particulars section was updated to show how the */
/*        search algorithm processes segments with continuous */
/*        pointing data. */

/*        The example program now loads an SCLK kernel. */

/*        FAILED is checked after the call to IRFROT to handle the */
/*        case where the reference frame is invalid and the error */
/*        handling is not set to abort. */

/*        FAILED is checked in the DO WHILE loop to handle the case */
/*        where an error is detected by a SPICELIB routine inside the */
/*        loop and the error handling is not set to abort. */

/* -    SPICELIB Version 1.0.1, 02-NOV-1990 (JML) */

/*        The restriction that a C-kernel file must be loaded */
/*        was explicitly stated. */


/* -    SPICELIB Version 1.0.0, 07-SEP-1990 (RET) (IMU) */

/* -& */
/* $ Index_Entries */

/*     get ck pointing */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 5.2.0, 25-AUG-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in MXM call. */

/* -    SPICELIB Version 3.1.0, 20-DEC-1995 (WLT) */

/*        A call to FRINFO did not have enough arguments and */
/*        went undetected until Howard Taylor of ACT.  Many */
/*        thanks go out to Howard for tracking down this error. */

/* -    SPICELIB Version 3.0.0, 19-SEP-1994 (WLT) */

/*        The routine was upgraded to support non-inertial frames. */

/*        Calls to NAMIRF and IRFROT were replaced with calls to */
/*        NAMFRM and FRMCHG respectively. */


/* -    SPICELIB Version 1.0.2, 30-AUG-1991 (JML) */

/*        1) The Particulars section was updated to show how the */
/*           search algorithm processes segments with continuous */
/*           pointing data. */

/*        2) The example program now loads an SCLK kernel. */

/*        3) FAILED is checked after the call to IRFROT to handle the */
/*           case where the reference frame is invalid and the error */
/*           handling is not set to abort. */

/*        4) FAILED is checked in the DO WHILE loop to handle the case */
/*           where an error is detected by a SPICELIB routine inside the */
/*           loop and the error handling is not set to abort. */

/* -    SPICELIB Version 1.0.1, 02-NOV-1990 (JML) */

/*        1) The restriction that a C-kernel file must be loaded */
/*           was explicitly stated. */
/*        2) Minor changes were made to the wording of the header. */


/* -    Beta Version 1.1.0, 29-AUG-1990 (MJS) */

/*        The following changes were made as a result of the */
/*        NAIF CK Code and Documentation Review: */

/*        1) The variable SCLK was changed to SCLKDP. */
/*        2) The variable INSTR was changed to INST. */
/*        3) The variable IDENT was changed to SEGID. */
/*        4) The declarations for the parameters NDC, NIC, NC, and */
/*           IDLEN were moved from the "Declarations" section of the */
/*           header to the "Local parameters" section of the code below */
/*           the header. These parameters are not meant to modified by */
/*           users. */
/*        5) The header was updated to reflect the changes. */

/* -    Beta Version 1.0.0, 04-MAY-1990 (RET) (IMU) */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */

/*        NDC        is the number of double precision components in an */
/*                   unpacked C-kernel segment descriptor. */

/*        NIC        is the number of integer components in an unpacked */
/*                   C-kernel segment descriptor. */

/*        NC         is the number of components in a packed C-kernel */
/*                   descriptor.  All DAF summaries have this formulaic */
/*                   relationship between the number of its integer and */
/*                   double precision components and the number of packed */
/*                   components. */

/*        IDLEN      is the length of the C-kernel segment identifier. */
/*                   All DAF names have this formulaic relationship */
/*                   between the number of summary components and */
/*                   the length of the name (You will notice that */
/*                   a name and a summary have the same length in bytes.) */


/*     Local variables */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("CKGP", (ftnlen)4);
    }

/*     Don't need angular velocity data. */
/*     Assume the segment won't be found until it really is. */

    needav = FALSE_;
    *found = FALSE_;

/*     If the tolerance is less than zero, we go no further. */

    if (*tol < 0.) {
	chkout_("CKGP", (ftnlen)4);
	return 0;
    }

/*     Begin a search for this instrument and time, and get the first */
/*     applicable segment. */

    ckbss_(inst, sclkdp, tol, &needav);
    cksns_(&handle, descr, segid, &sfnd, (ftnlen)40);

/*     Keep trying candidate segments until a segment can produce a */
/*     pointing instance within the specified time tolerance of the */
/*     input time. */

/*     Check FAILED to prevent an infinite loop if an error is detected */
/*     by a SPICELIB routine and the error handling is not set to abort. */

    while(sfnd && ! failed_()) {
	ckpfs_(&handle, descr, sclkdp, tol, &needav, cmat, av, clkout, &pfnd);
	if (pfnd) {

/*           Found one. If the C-matrix doesn't already rotate from the */
/*           requested frame, convert it to one that does. */

	    dafus_(descr, &c__2, &c__6, dcd, icd);
	    refseg = icd[1];

/*           Look up the id code for the requested reference frame. */

	    namfrm_(ref, &refreq, ref_len);
	    if (refreq != refseg) {

/*              We may need to convert the output ticks CLKOUT to ET */
/*              so that we can get the needed state transformation */
/*              matrix.  This is the case if either of the frames */
/*              is non-inertial. */

		frinfo_(&refreq, &center, &type1, &typeid, &gotit);
		frinfo_(&refseg, &center, &type2, &typeid, &gotit);
		if (type1 == 1 && type2 == 1) {

/*                 Any old value of ET will do in this case.  We'll */
/*                 use zero. */

		    et = 0.;
		} else {

/*                 Look up the spacecraft clock id to use to convert */
/*                 the output CLKOUT to ET. */

		    ckmeta_(inst, "SCLK", &sclk, (ftnlen)4);
		    sct2e_(&sclk, clkout, &et);
		}

/*              Get the transformation from the requested frame to */
/*              the segment frame at ET. */

		refchg_(&refreq, &refseg, &et, rot);

/*              If REFCHG detects that the reference frame is invalid */
/*              then return from this routine with FOUND equal to false. */

		if (failed_()) {
		    chkout_("CKGP", (ftnlen)4);
		    return 0;
		}

/*              Transform the attitude information: convert CMAT so that */
/*              it maps from request frame to C-matrix frame. */

		mxm_(cmat, rot, tmpmat);
		moved_(tmpmat, &c__9, cmat);
	    }
	    *found = TRUE_;
	    chkout_("CKGP", (ftnlen)4);
	    return 0;
	}
	cksns_(&handle, descr, segid, &sfnd, (ftnlen)40);
    }
Beispiel #6
0
/* $Procedure  TIPBOD ( Transformation, inertial position to bodyfixed ) */
/* Subroutine */ int tipbod_(char *ref, integer *body, doublereal *et, 
	doublereal *tipm, ftnlen ref_len)
{
    doublereal ref2j[9]	/* was [3][3] */;
    extern /* Subroutine */ int chkin_(char *, ftnlen), moved_(doublereal *, 
	    integer *, doublereal *);
    extern logical failed_(void);
    extern /* Subroutine */ int bodmat_(integer *, doublereal *, doublereal *)
	    , chkout_(char *, ftnlen);
    doublereal tmpmat[9]	/* was [3][3] */;
    extern /* Subroutine */ int irftrn_(char *, char *, doublereal *, ftnlen, 
	    ftnlen);
    extern logical return_(void);
    extern /* Subroutine */ int mxm_(doublereal *, doublereal *, doublereal *)
	    ;

/* $ Abstract */

/*      Return a 3x3 matrix that transforms positions in inertial */
/*      coordinates to positions in body-equator-and-prime-meridian */
/*      coordinates. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*      PCK */
/*      NAIF_IDS */
/*     ROTATION */
/*      TIME */

/* $ Keywords */

/*      TRANSFORMATION */
/*      ROTATION */

/* $ Declarations */
/* $ Brief_I/O */

/*      VARIABLE  I/O  DESCRIPTION */
/*      --------  ---  -------------------------------------------------- */
/*      REF        I   ID of inertial reference frame to transform from. */
/*      BODY       I   ID code of body. */
/*      ET         I   Epoch of transformation. */
/*      TIPM       O   Transformation (position), inertial to prime */
/*                     meridian. */

/* $ Detailed_Input */

/*      REF         is the NAIF name for an inertial reference frame. */
/*                  Acceptable names include: */

/*                    Name       Description */
/*                    --------   -------------------------------- */
/*                    'J2000'    Earth mean equator, dynamical */
/*                               equinox of J2000 */

/*                    'B1950'    Earth mean equator, dynamical */
/*                               equinox of B1950 */

/*                    'FK4'      Fundamental Catalog (4) */

/*                    'DE-118'   JPL Developmental Ephemeris (118) */

/*                    'DE-96'    JPL Developmental Ephemeris ( 96) */

/*                    'DE-102'   JPL Developmental Ephemeris (102) */

/*                    'DE-108'   JPL Developmental Ephemeris (108) */

/*                    'DE-111'   JPL Developmental Ephemeris (111) */

/*                    'DE-114'   JPL Developmental Ephemeris (114) */

/*                    'DE-122'   JPL Developmental Ephemeris (122) */

/*                    'DE-125'   JPL Developmental Ephemeris (125) */

/*                    'DE-130'   JPL Developmental Ephemeris (130) */

/*                    'GALACTIC' Galactic System II */

/*                    'DE-200'   JPL Developmental Ephemeris (200) */

/*                    'DE-202'   JPL Developmental Ephemeris (202) */

/*                  (See the routine CHGIRF for a full list of names.) */

/*                  The output TIPM will give the transformation */
/*                  from this frame to the bodyfixed frame specified by */
/*                  BODY at the epoch specified by ET. */


/*      BODY        is the integer ID code of the body for which the */
/*                  position transformation matrix is requested. Bodies */
/*                  are numbered according to the standard NAIF */
/*                  numbering scheme.  The numbering scheme is */
/*                  explained in the NAIF_IDS required reading file. */

/*      ET          is the epoch at which the position transformation */
/*                  matrix is requested. (This is typically the */
/*                  epoch of observation minus the one-way light time */
/*                  from the observer to the body at the epoch of */
/*                  observation.) */

/* $ Detailed_Output */

/*      TIPM        is a 3x3 coordinate transformation matrix.  It is */
/*                  used to transform positions from inertial */
/*                  coordinates to body fixed (also called equator and */
/*                  prime meridian --- PM) coordinates. */

/*                  Given a position P in the inertial reference frame */
/*                  specified by REF, the corresponding bodyfixed */
/*                  position is given by the matrix vector product: */

/*                     TIPM * S */

/*                  The X axis of the PM system is directed to the */
/*                  intersection of the equator and prime meridian. */
/*                  The Z axis points along  the spin axis and points */
/*                  towards the same side of the invariable plane of */
/*                  the solar system as does earth's north pole. */

/* $ Parameters */

/*      None. */

/* $ Exceptions */

/*      1) If the kernel pool does not contain all of the data required */
/*         for computing the transformation matrix, TIPM, the error */
/*         SPICE(INSUFFICIENTANGLES) is signalled. */

/*      2) If the reference frame, REF,  is not recognized, a routine */
/*         called by TIPBOD will diagnose the condition and invoke the */
/*         SPICE error handling system. */

/*      3) If the specified body code, BODY, is not recognized, the */
/*         error is diagnosed by a routine called by TIPBOD. */

/* $ Files */

/*      None. */

/* $ Particulars */

/*     TIPBOD takes PCK information as input, either in the */
/*     form of a binary or text PCK file.  High precision */
/*     binary files are searched for first (the last loaded */
/*     file takes precedence); then it defaults to the text */
/*     PCK file.  If binary information is found for the */
/*     requested body and time, the Euler angles are */
/*     evaluated and the transformation matrix is calculated */
/*     from them.  Using the Euler angles PHI, DELTA and W */
/*     we compute */

/*            TIPM = [W] [DELTA] [PHI] */
/*                      3       1     3 */


/*      If no appropriate binary PCK files have been loaded, */
/*      the text PCK file is used.  Here information is found */
/*      as RA, DEC and W (with the possible addition of nutation */
/*      and libration terms for satellites).  Again, the Euler */
/*      angles are found, and the transformation matrix is */
/*      calculated from them.  The transformation from inertial to */
/*      bodyfixed coordinates is represented as: */

/*            TIPM = [W] [HALFPI-DEC] [RA+HALFPI] */
/*                      3            1           3 */

/*     These are basically the Euler angles, PHI, DELTA and W: */

/*       RA = PHI - HALFPI */
/*       DEC = HALFPI - DELTA */
/*       W = W */

/*      In the text file, RA, DEC, and W are defined as follows: */

/*                                         2      ____ */
/*                                    RA2*t       \ */
/*            RA  = RA0  + RA1*t/T  + ------   +  /     a  sin theta */
/*                                       2        ----   i          i */
/*                                      T           i */

/*                                          2     ____ */
/*                                    DEC2*t      \ */
/*            DEC = DEC0 + DEC1*t/T + -------  +  /    d  cos theta */
/*                                        2       ----  i          i */
/*                                       T          i */


/*                                        2      ____ */
/*                                    W2*t       \ */
/*            W   = W0   + W1*t/d   + -----   +  /     w  sin theta */
/*                                       2       ----   i          i */
/*                                      d          i */


/*      where: */

/*            d = seconds/day */

/*            T = seconds/Julian century */

/*            a , d , and w  arrays apply to satellites only. */
/*             i   i       i */

/*            theta  = THETA0(i) + THETA1(i)*t/T are specific to each */
/*                 i */

/*            planet. */


/*        These angles -- typically nodal rates -- vary in number and */
/*        definition from one planetary system to the next. */

/* $ Examples */

/*      Note that the items necessary to compute the Euler angles */
/*      must have been loaded into the kernel pool (by one or more */
/*      previous calls to FURNSH).  The Euler angles are typically */
/*      stored in the P_constants kernel file that comes with */
/*      SPICELIB. */

/*      1)  In the following code fragment, TIPBOD is used to transform */
/*          a position in J2000 inertial coordinates to a state in */
/*          bodyfixed coordinates. */

/*          The 3-vectors POSTN represents the inertial position */
/*          of an object with respect to the center of the */
/*          body at time ET. */

/*             C */
/*             C     First load the kernel pool. */
/*             C */
/*                   CALL FURNSH ( 'PLANETARY_CONSTANTS.KER' ) */

/*             C */
/*             C     Next get the transformation and its derivative. */
/*             C */
/*                   CALL TIPBOD ( 'J2000', BODY, ET, TIPM ) */

/*             C */
/*             C     Convert position, the first three elements of */
/*             C     STATE, to bodyfixed coordinates. */
/*             C */
/*                   CALL MXVG    ( TIPM, POSTN, BDPOS ) */

/* $ Restrictions */

/*      The kernel pool must be loaded with the appropriate */
/*      coefficients (from the P_constants kernel or binary PCK file) */
/*      prior to calling this routine. */

/* $ Literature_References */

/*      None. */

/* $ Author_and_Institution */

/*      N.J. Bachman   (JPL) */
/*      W.L. Taber     (JPL) */
/*      K.S. Zukor     (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.2.0, 23-OCT-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in MXM call.  Replaced header references to LDPOOL with */
/*        references to FURNSH. */

/* -    SPICELIB Version 1.1.0, 05-JAN-2005 (NJB) */

/*        Tests of routine FAILED() were added. */

/* -     SPICELIB Version 1.0.3, 10-MAR-1994 (KSZ) */

/*         Underlying BODMAT code changed to look for binary PCK */
/*         data files, and use them to get orientation information if */
/*         they are available.  Only the comments to TIPBOD changed. */

/* -     SPICELIB Version 1.0.2, 06-JUL-1993 (HAN) */

/*         Example in header was corrected. Previous version had */
/*         incorrect matrix dimension specifications passed to MXVG. */

/* -     SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */

/*         Comment section for permuted index source lines was added */
/*         following the header. */

/* -     SPICELIB Version 1.0.0, 05-AUG-1991 (NJB) (WLT) */

/* -& */
/* $ Index_Entries */

/*     transformation from inertial position to bodyfixed */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 1.2.0, 06-SEP-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in MXM call.  Replaced header references to LDPOOL with */
/*        references to FURNSH. */


/* -    SPICELIB Version 1.1.0, 05-JAN-2005 (NJB) */

/*        Tests of routine FAILED() were added.  The new checks */
/*        are intended to prevent arithmetic operations from */
/*        being performed with uninitialized or invalid data. */
/* -& */

/*     SPICELIB functions */


/*     Local variables */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("TIPBOD", (ftnlen)6);
    }

/*     Get the transformation from the inertial from REF to J2000 */
/*     coordinates. */

    irftrn_(ref, "J2000", ref2j, ref_len, (ftnlen)5);

/*     Get the transformation from J2000 to body-fixed coordinates */
/*     for the requested epoch. */

    bodmat_(body, et, tipm);
    if (failed_()) {
	chkout_("TIPBOD", (ftnlen)6);
	return 0;
    }

/*     Compose the transformations to arrive at the REF-to-J2000 */
/*     transformation. */

    mxm_(tipm, ref2j, tmpmat);
    moved_(tmpmat, &c__9, tipm);

/*     That's all folks.  Check out and get out. */

    chkout_("TIPBOD", (ftnlen)6);
    return 0;
} /* tipbod_ */
Beispiel #7
0
/* Subroutine */ int deri1_(doublereal *c__, integer *norbs, doublereal *
	coord, integer *number, doublereal *work, doublereal *grad, 
	doublereal *f, integer *minear, doublereal *fd, doublereal *wmat, 
	doublereal *hmat, doublereal *fmat)
{
    /* Initialized data */

    static integer icalcn = 0;

    /* System generated locals */
    integer c_dim1, c_offset, work_dim1, work_offset, i__1, i__2, i__3, i__4, 
	    i__5, i__6, i__7, i__8;

    /* Builtin functions */
    integer i_indx(char *, char *, ftnlen, ftnlen), s_wsle(cilist *), do_lio(
	    integer *, integer *, char *, ftnlen), e_wsle(void), s_wsfe(
	    cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void);

    /* Local variables */
    static integer i__, j, k, l, n1, n2, ll;
    static doublereal gse;
    extern doublereal dot_(doublereal *, doublereal *, integer *);
    extern /* Subroutine */ int mxm_(doublereal *, integer *, doublereal *, 
	    integer *, doublereal *, integer *);
    static integer nend, nati, lcut, loop, natx;
    static doublereal step;
    static integer iprt;
    extern /* Subroutine */ int mtxm_(doublereal *, integer *, doublereal *, 
	    integer *, doublereal *, integer *), mecid_(doublereal *, 
	    doublereal *, doublereal *, doublereal *), mecih_(doublereal *, 
	    doublereal *, integer *, integer *);
    static logical debug;
    extern /* Subroutine */ int timer_(char *, ftnlen);
    static integer ninit;
    extern /* Subroutine */ int scopy_(integer *, doublereal *, integer *, 
	    doublereal *, integer *), dfock2_(doublereal *, doublereal *, 
	    doublereal *, doublereal *, integer *, integer *, integer *, 
	    integer *, integer *), dijkl1_(doublereal *, integer *, integer *,
	     doublereal *, doublereal *, doublereal *, doublereal *);
    static doublereal enucl2;
    extern /* Subroutine */ int dhcore_(doublereal *, doublereal *, 
	    doublereal *, doublereal *, integer *, integer *, doublereal *);
    extern doublereal helect_(integer *, doublereal *, doublereal *, 
	    doublereal *);
    static integer linear;
    extern /* Subroutine */ int supdot_(doublereal *, doublereal *, 
	    doublereal *, integer *, integer *);

    /* Fortran I/O blocks */
    static cilist io___11 = { 0, 6, 0, 0, 0 };
    static cilist io___13 = { 0, 6, 0, "(5F12.6)", 0 };
    static cilist io___22 = { 0, 6, 0, 0, 0 };
    static cilist io___23 = { 0, 0, 0, "(' * * * GRADIENT COMPONENT NUMBER',"
	    "I4)", 0 };
    static cilist io___24 = { 0, 0, 0, "(' NON-RELAXED C.I-ACTIVE FOCK EIGEN"
	    "VALUES ',                    'DERIVATIVES (E.V.)')", 0 };
    static cilist io___25 = { 0, 0, 0, "(8F10.4)", 0 };
    static cilist io___26 = { 0, 0, 0, "(' NON-RELAXED 2-ELECTRONS DERIVATIV"
	    "ES (E.V.)'/  '    I    J    K    L       d<I(1)J(1)|K(2)L(2)>')", 
	    0 };
    static cilist io___28 = { 0, 0, 0, "(4I5,F20.10)", 0 };
    static cilist io___29 = { 0, 0, 0, "(' NON-RELAXED GRADIENT COMPONENT',F"
	    "10.4,        ' KCAL/MOLE')", 0 };


/* COMDECK SIZES */
/* *********************************************************************** */
/*   THIS FILE CONTAINS ALL THE ARRAY SIZES FOR USE IN MOPAC. */

/*     THERE ARE ONLY 5 PARAMETERS THAT THE PROGRAMMER NEED SET: */
/*     MAXHEV = MAXIMUM NUMBER OF HEAVY ATOMS (HEAVY: NON-HYDROGEN ATOMS) */
/*     MAXLIT = MAXIMUM NUMBER OF HYDROGEN ATOMS. */
/*     MAXTIM = DEFAULT TIME FOR A JOB. (SECONDS) */
/*     MAXDMP = DEFAULT TIME FOR AUTOMATIC RESTART FILE GENERATION (SECS) */
/*     ISYBYL = 1 IF MOPAC IS TO BE USED IN THE SYBYL PACKAGE, =0 OTHERWISE */
/*     SEE ALSO NMECI, NPULAY AND MESP AT THE END OF THIS FILE */


/* *********************************************************************** */

/*   THE FOLLOWING CODE DOES NOT NEED TO BE ALTERED BY THE PROGRAMMER */

/* *********************************************************************** */

/*    ALL OTHER PARAMETERS ARE DERIVED FUNCTIONS OF THESE TWO PARAMETERS */

/*      NAME                   DEFINITION */
/*     NUMATM         MAXIMUM NUMBER OF ATOMS ALLOWED. */
/*     MAXORB         MAXIMUM NUMBER OF ORBITALS ALLOWED. */
/*     MAXPAR         MAXIMUM NUMBER OF PARAMETERS FOR OPTIMISATION. */
/*     N2ELEC         MAXIMUM NUMBER OF TWO ELECTRON INTEGRALS ALLOWED. */
/*     MPACK          AREA OF LOWER HALF TRIANGLE OF DENSITY MATRIX. */
/*     MORB2          SQUARE OF THE MAXIMUM NUMBER OF ORBITALS ALLOWED. */
/*     MAXHES         AREA OF HESSIAN MATRIX */
/*     MAXALL         LARGER THAN MAXORB OR MAXPAR. */
/* *********************************************************************** */

/* *********************************************************************** */
/* DECK MOPAC */
/* ******************************************************************** */

/*     DERI1 COMPUTE THE NON-RELAXED DERIVATIVE OF THE NON-VARIATIONALLY */
/*     OPTIMIZED WAVEFUNCTION ENERGY WITH RESPECT TO ONE CARTESIAN */
/*     COORDINATE AT A TIME */
/*                             AND */
/*     COMPUTE THE NON-RELAXED FOCK MATRIX DERIVATIVE IN M.O BASIS AS */
/*     REQUIRED IN THE RELAXATION SECTION (ROUTINE 'DERI2'). */

/*   INPUT */
/*     C(NORBS,NORBS) : M.O. COEFFICIENTS. */
/*     COORD  : CARTESIAN COORDINATES ARRAY. */
/*     NUMBER : LOCATION OF THE REQUIRED VARIABLE IN COORD. */
/*     WORK   : WORK ARRAY OF SIZE N*N. */
/*     WMAT     : WORK ARRAYS FOR d<PQ|RS> (2-CENTERS  A.O) */
/*   OUTPUT */
/*     C,COORD,NUMBER : NOT MODIFIED. */
/*     GRAD   : DERIVATIVE OF THE HEAT OF FORMATION WITH RESPECT TO */
/*              COORD(NUMBER), WITHOUT RELAXATION CORRECTION. */
/*     F(MINEAR) : NON-RELAXED FOCK MATRIX DERIVATIVE WITH RESPECT TO */
/*              COORD(NUMBER), EXPRESSED IN M.O BASIS, SCALED AND */
/*              PACKED, OFF-DIAGONAL BLOCKS ONLY. */
/*     FD     : IDEM BUT UNSCALED, DIAGONAL BLOCKS, C.I-ACTIVE ONLY. */

/* *********************************************************************** */
    /* Parameter adjustments */
    work_dim1 = *norbs;
    work_offset = 1 + work_dim1 * 1;
    work -= work_offset;
    c_dim1 = *norbs;
    c_offset = 1 + c_dim1 * 1;
    c__ -= c_offset;
    --coord;
    --f;
    --fd;
    --wmat;
    --hmat;
    --fmat;

    /* Function Body */

    if (icalcn != numcal_1.numcal) {
	debug = i_indx(keywrd_1.keywrd, "DERI1", (ftnlen)241, (ftnlen)5) != 0;
	iprt = 6;
	linear = *norbs * (*norbs + 1) / 2;
	icalcn = numcal_1.numcal;
    }
    if (debug) {
	timer_("BEFORE DERI1", (ftnlen)12);
    }
    step = .001;

/*     2 POINTS FINITE DIFFERENCE TO GET THE INTEGRAL DERIVATIVES */
/*     ---------------------------------------------------------- */
/*     STORED IN HMAT AND WMAT, WITHOUT DIVIDING BY THE STEP SIZE. */

    nati = (*number - 1) / 3 + 1;
    natx = *number - (nati - 1) * 3;
    dhcore_(&coord[1], &hmat[1], &wmat[1], &enucl2, &nati, &natx, &step);

/* HMAT HOLDS THE ONE-ELECTRON DERIVATIVES OF ATOM NATI FOR DIRECTION */
/*      NATX W.R.T. ALL OTHER ATOMS */
/* WMAT HOLDS THE TWO-ELECTRON DERIVATIVES OF ATOM NATI FOR DIRECTION */
/*      NATX W.R.T. ALL OTHER ATOMS */
    step = .5 / step;

/*     NON-RELAXED FOCK MATRIX DERIVATIVE IN A.O BASIS. */
/*     ------------------------------------------------ */
/*     STORED IN FMAT, DIVIDED BY STEP. */

    scopy_(&linear, &hmat[1], &c__1, &fmat[1], &c__1);
    dfock2_(&fmat[1], densty_1.p, densty_1.pa, &wmat[1], &molkst_1.numat, 
	    molkst_1.nfirst, molkst_1.nmidle, molkst_1.nlast, &nati);

/*  FMAT HOLDS THE ONE PLUS TWO - ELECTRON DERIVATIVES OF ATOM NATI FOR */
/*       DIRECTION NATX W.R.T. ALL OTHER ATOMS */

/*       DERIVATIVE OF THE SCF-ONLY ENERGY (I.E BEFORE C.I CORRECTION) */

    *grad = (helect_(norbs, densty_1.p, &hmat[1], &fmat[1]) + enucl2) * step;
/*     TAKE STEP INTO ACCOUNT IN FMAT */
    i__1 = linear;
    for (i__ = 1; i__ <= i__1; ++i__) {
/* L10: */
	fmat[i__] *= step;
    }

/*     RIGHT-HAND SIDE SUPER-VECTOR F = C' FMAT C USED IN RELAXATION */
/*     ----------------------------------------------------------- */
/*     STORED IN NON-STANDARD PACKED FORM IN F(MINEAR) AND FD. */
/*     THE SUPERVECTOR IS THE NON-RELAXED FOCK MATRIX DERIVATIVE IN */
/*     M.O BASIS: F(IJ)= ( (C' * FOCK * C)(I,J) )   WITH I.GT.J . */
/*     F IS SCALED AND PACKED IN SUPERVECTOR FORM WITH */
/*                THE CONSECUTIVE FOLLOWING OFF-DIAGONAL BLOCKS: */
/*             1) OPEN-CLOSED  I.E. F(IJ)=F(I,J) WITH I OPEN & J CLOSED */
/*                                  AND I RUNNING FASTER THAN J, */
/*             2) VIRTUAL-CLOSED SAME RULE OF ORDERING, */
/*             3) VIRTUAL-OPEN   SAME RULE OF ORDERING. */
/*     FD IS PACKED OVER THE C.I-ACTIVE M.O WITH */
/*                THE CONSECUTIVE DIAGONAL BLOCKS: */
/*             1) CLOSED-CLOSED   IN CANONICAL ORDER, WITHOUT THE */
/*                                DIAGONAL ELEMENTS, */
/*             2) OPEN-OPEN       SAME RULE OF ORDERING, */
/*             3) VIRTUAL-VIRTUAL SAME RULE OF ORDERING. */

/*     PART 1 : WORK(N,N) = FMAT(N,N) * C(N,N) */
    i__1 = *norbs;
    for (i__ = 1; i__ <= i__1; ++i__) {
/* L20: */
	supdot_(&work[i__ * work_dim1 + 1], &fmat[1], &c__[i__ * c_dim1 + 1], 
		norbs, &c__1);
    }

/*     PART 2 : F(IJ) =  (C' * WORK)(I,J) ... OFF-DIAGONAL BLOCKS. */
    l = 1;
    if (cibits_1.nbo[1] != 0 && cibits_1.nbo[0] != 0) {
/*        OPEN-CLOSED */
	mtxm_(&c__[(cibits_1.nbo[0] + 1) * c_dim1 + 1], &cibits_1.nbo[1], &
		work[work_offset], norbs, &f[l], cibits_1.nbo);
	l += cibits_1.nbo[1] * cibits_1.nbo[0];
    }
    if (cibits_1.nbo[2] != 0 && cibits_1.nbo[0] != 0) {
/*        VIRTUAL-CLOSED */
	mtxm_(&c__[(molkst_1.nopen + 1) * c_dim1 + 1], &cibits_1.nbo[2], &
		work[work_offset], norbs, &f[l], cibits_1.nbo);
	l += cibits_1.nbo[2] * cibits_1.nbo[0];
    }
    if (cibits_1.nbo[2] != 0 && cibits_1.nbo[1] != 0) {
/*        VIRTUAL-OPEN */
	mtxm_(&c__[(molkst_1.nopen + 1) * c_dim1 + 1], &cibits_1.nbo[2], &
		work[(cibits_1.nbo[0] + 1) * work_dim1 + 1], norbs, &f[l], &
		cibits_1.nbo[1]);
    }
/*     SCALE F ACCORDING TO THE DIAGONAL METRIC TENSOR 'SCALAR '. */
    i__1 = *minear;
    for (i__ = 1; i__ <= i__1; ++i__) {
/* L30: */
	f[i__] *= fokmat_1.scalar[i__ - 1];
    }
    if (debug) {
	s_wsle(&io___11);
	do_lio(&c__9, &c__1, " F IN DERI1", (ftnlen)11);
	e_wsle();
	j = min(20,*minear);
	s_wsfe(&io___13);
	i__1 = j;
	for (i__ = 1; i__ <= i__1; ++i__) {
	    do_fio(&c__1, (char *)&f[i__], (ftnlen)sizeof(doublereal));
	}
	e_wsfe();
    }

/*     PART 3 : SUPER-VECTOR FD, C.I-ACTIVE DIAGONAL BLOCKS, UNSCALED. */
    l = 1;
    nend = 0;
    for (loop = 1; loop <= 3; ++loop) {
	ninit = nend + 1;
	nend += cibits_1.nbo[loop - 1];
/* Computing MAX */
	i__1 = ninit, i__2 = cibits_1.nelec + 1;
	n1 = max(i__1,i__2);
/* Computing MIN */
	i__1 = nend, i__2 = cibits_1.nelec + cibits_1.nmos;
	n2 = min(i__1,i__2);
	if (n2 < n1) {
	    goto L50;
	}
	i__1 = n2;
	for (i__ = n1; i__ <= i__1; ++i__) {
	    if (i__ > ninit) {
		i__2 = i__ - ninit;
		mxm_(&c__[i__ * c_dim1 + 1], &c__1, &work[ninit * work_dim1 + 
			1], norbs, &fd[l], &i__2);
		l = l + i__ - ninit;
	    }
/* L40: */
	}
L50:
	;
    }

/*     NON-RELAXED C.I CORRECTION TO THE ENERGY DERIVATIVE. */
/*     ---------------------------------------------------- */

/*     C.I-ACTIVE FOCK EIGENVALUES DERIVATIVES, STORED IN FD(CONTINUED). */
    lcut = l;
    i__1 = cibits_1.nelec + cibits_1.nmos;
    for (i__ = cibits_1.nelec + 1; i__ <= i__1; ++i__) {
	fd[l] = dot_(&c__[i__ * c_dim1 + 1], &work[i__ * work_dim1 + 1], 
		norbs);
/* L60: */
	++l;
    }

/*     C.I-ACTIVE 2-ELECTRONS INTEGRALS DERIVATIVES. STORED IN XY. */
/*   FMAT IS USED HERE AS SCRATCH SPACE */

    dijkl1_(&c__[(cibits_1.nelec + 1) * c_dim1 + 1], norbs, &nati, &wmat[1], &
	    fmat[1], &hmat[1], &fmat[1]);
    i__1 = cibits_1.nmos;
    for (i__ = 1; i__ <= i__1; ++i__) {
	i__2 = cibits_1.nmos;
	for (j = 1; j <= i__2; ++j) {
	    i__3 = cibits_1.nmos;
	    for (k = 1; k <= i__3; ++k) {
		i__4 = cibits_1.nmos;
		for (l = 1; l <= i__4; ++l) {
/* L70: */
		    xyijkl_1.xy[i__ + (j + (k + (l << 3) << 3) << 3) - 585] *=
			     step;
		}
	    }
	}
    }

/*     BUILD THE C.I MATRIX DERIVATIVE, STORED IN WMAT. */
    mecid_(&fd[lcut - cibits_1.nelec], &gse, vector_1.eigb, &work[work_offset]
	    );
    if (debug) {
	s_wsle(&io___22);
	do_lio(&c__9, &c__1, " GSE:", (ftnlen)5);
	do_lio(&c__5, &c__1, (char *)&gse, (ftnlen)sizeof(doublereal));
	e_wsle();
/* #      WRITE(6,*)' EIGB:',(EIGB(I),I=1,10) */
/* #      WRITE(6,*)' WORK:',(WORK(I,1),I=1,10) */
    }
    mecih_(&work[work_offset], &wmat[1], &cibits_1.nmos, &cibits_1.lab);

/*     NON-RELAXED C.I CONTRIBUTION TO THE ENERGY DERIVATIVE. */
    supdot_(&work[work_offset], &wmat[1], civect_1.conf, &cibits_1.lab, &c__1)
	    ;
    *grad = (*grad + dot_(civect_1.conf, &work[work_offset], &cibits_1.lab)) *
	     23.061;
    if (debug) {
	io___23.ciunit = iprt;
	s_wsfe(&io___23);
	do_fio(&c__1, (char *)&(*number), (ftnlen)sizeof(integer));
	e_wsfe();
	io___24.ciunit = iprt;
	s_wsfe(&io___24);
	e_wsfe();
	io___25.ciunit = iprt;
	s_wsfe(&io___25);
	i__4 = cibits_1.nmos;
	for (i__ = 1; i__ <= i__4; ++i__) {
	    do_fio(&c__1, (char *)&fd[lcut - 1 + i__], (ftnlen)sizeof(
		    doublereal));
	}
	e_wsfe();
	io___26.ciunit = iprt;
	s_wsfe(&io___26);
	e_wsfe();
	i__4 = cibits_1.nmos;
	for (i__ = 1; i__ <= i__4; ++i__) {
	    i__3 = i__;
	    for (j = 1; j <= i__3; ++j) {
		i__2 = i__;
		for (k = 1; k <= i__2; ++k) {
		    ll = k;
		    if (k == i__) {
			ll = j;
		    }
		    i__1 = ll;
		    for (l = 1; l <= i__1; ++l) {
/* L80: */
			io___28.ciunit = iprt;
			s_wsfe(&io___28);
			i__5 = cibits_1.nelec + i__;
			do_fio(&c__1, (char *)&i__5, (ftnlen)sizeof(integer));
			i__6 = cibits_1.nelec + j;
			do_fio(&c__1, (char *)&i__6, (ftnlen)sizeof(integer));
			i__7 = cibits_1.nelec + k;
			do_fio(&c__1, (char *)&i__7, (ftnlen)sizeof(integer));
			i__8 = cibits_1.nelec + l;
			do_fio(&c__1, (char *)&i__8, (ftnlen)sizeof(integer));
			do_fio(&c__1, (char *)&xyijkl_1.xy[i__ + (j + (k + (l 
				<< 3) << 3) << 3) - 585], (ftnlen)sizeof(
				doublereal));
			e_wsfe();
		    }
		}
	    }
	}
	io___29.ciunit = iprt;
	s_wsfe(&io___29);
	do_fio(&c__1, (char *)&(*grad), (ftnlen)sizeof(doublereal));
	e_wsfe();
	timer_("AFTER DERI1", (ftnlen)11);
    }
    return 0;
} /* deri1_ */