/* tacov.f -- translated by f2c (version 20000817).
   You must link the resulting object file with the libraries:
	-lf2c -lm   (in that order)
*/

#include "f2c.h"

/* Common Block Declarations */

struct {
    integer inx;
    real c1rx, c2rx, rmin, rmax, cl1r;
} curve_;

#define curve_1 curve_

/* Table of constant values */

static doublereal c_b7 = 1.;
static doublereal c_b9 = 360.;

/* ----------------------------------------------------------------------- */
/*       FILE T_CONV */
/*       SUBROUTINE T_CONV(EI,AKI,EF,AKF,QHKL,EN,HX,HY,HZ,IF1,IF2,LDK,LDH,LDF */
/*       1       LPA,DM,DA,HELM,F1H,F1V,F2H,F2V,F,IFX,ISS,ISM,ISA, */
/*       2       T_A,T_RM,T_ALM,LDRA,LDR_RM,LDR_ALM,P_IH,C_IH,IER) */
/*       SUBROUTINE EX_CASE(DX,ISX,AKX,AX1,AX2,RX,ALX,IER) */
/*       SUBROUTINE SAM_CASE(QT,QM,QS,AKI,AKF,AX3,AX4,ISS,IER) */
/*       SUBROUTINE HELM_CASE(HX,HY,HZ,P_IH,AKI,AKF,A4,QM,HELM,IER) */
/*       SUBROUTINE FLIP_CASE(IF1,IF2,P_IH,F1V,F1H,F2V,F2H,AKI,AKF,IER) */
/* ----------------------------------------------------------------------- */
/* Subroutine */ int t_conv__(real *ei, real *aki, real *ef, real *akf, real *
	qhkl, real *en, real *hx, real *hy, real *hz, integer *if1, integer *
	if2, logical *ldk, logical *ldh, logical *ldf, logical *lpa, real *dm,
	 real *da, real *helm, real *f1h, real *f1v, real *f2h, real *f2v, 
	real *f, integer *ifx, integer *iss, integer *ism, integer *isa, real 
	*t_a__, real *t_rm__, real *t_alm__, real *qm, logical *ldra, logical 
	*ldr_rm__, logical *ldr_alm__, real *p_ih__, real *c_ih__, integer *
	ier)
{
    /* System generated locals */
    doublereal d__1;

    /* Builtin functions */
    double sqrt(doublereal);

    /* Local variables */
    static doublereal edef[2], dakf, daki;
    static integer imod;
    extern /* Subroutine */ int sam_case__(doublereal *, doublereal *, 
	    doublereal *, doublereal *, doublereal *, doublereal *, 
	    doublereal *, integer *, integer *);
    static integer i__;
    static doublereal akdef[2];
    extern /* Subroutine */ int helm_case__(real *, real *, real *, real *, 
	    real *, real *, real *, doublereal *, real *, real *, integer *);
    static doublereal dqhkl[3];
    extern /* Subroutine */ int flip_case__(integer *, integer *, real *, 
	    real *, real *, real *, real *, real *, real *, integer *);
    static logical lmoan[2];
    static doublereal a1, a2, a3, a4, a5, a6;
    static integer id;
    static doublereal ra;
    extern /* Subroutine */ int rl2spv_(doublereal *, doublereal *, 
	    doublereal *, doublereal *, integer *);
    static integer iq;
    static doublereal rm;
    static logical lqhkle;
    extern /* Subroutine */ int erreso_(integer *, integer *);
    static doublereal dda, ala, def, dei, ddm, alm, dqm;
    extern /* Subroutine */ int ex_case__(doublereal *, integer *, doublereal 
	    *, doublereal *, doublereal *, doublereal *, doublereal *, 
	    integer *);
    static doublereal dqt[3], dqs;

/* ----------------------------------------------------------------------- */

/*       INPUT */
/*       EI,AKI,EF,AKF,QHKL,EN,HX,HY,HZ : POTENTIAL TARGETS */
/* 	IF1,IF2 Status of flippers On (1) Off (0) */
/*       LDK(8)          LOGICAL INDICATING IF (ENERGY,K OR Q) ARE DRIVEN */
/*       LDH,LDF         LOGICAL INDICATING IF (HX,HY,HZ) OR (F1,F2) ARE DRIVEN */

/*       configuration of the machine */
/*       LPA             LOGICAL  TRUE IF MACHINE IN POLARIZATION MODE */
/*       DM,DA,HELM,F1H,F1V,F2H,F2V,F,IFX,ISS,ISM,ISA,QM (F ENERGY UNIT) */

/*       OUTPUT */
/*       T_A             TARGETS OF ANGLES A1-A6 */
/*       T_RM,T_ALM      TARGETS OF RM ,LM */
/*       QM                      TARGETS OF QM */
/*       LDRA                    LOGICAL INDICATING WHICH ANGLES ARE TO BE DRIVEN */
/*       LDR_RM,LDR_ALM  LOGICAL INDICATING IF RM OR ALM ARE TO BE DRIVEN */
/*       P_IH    TARGETS OF CURRENTS FOR FLIPPERS AND HELMOTZ (8 CURRENTS) */
/*       C_IH    CONVERSION FACTORS FOR HELMOTZ (4 CURRENTS) */

/*       SPECIAL OUTPUTS */
/*       TARGET OF EI(EF) IS UPDATED IS KI(KF) IS DRIVEN */
/*       TARGET OF VARIABLE ENERGY IS UPDATED IF EN IS DRIVEN */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/*       PASSED PARAMETERS */
/* ----------------------------------------------------------------------- */
/*        LOCAL VARIABLES */

/* ----------------------------------------------------------------------- */
/*       SET UP */
/*       IMOD  INDEX FOR ERROR TREATMENAT BY ERRESO */
/*       LDQHKLE : LOGICAL INDICATING THAT WE ARE DEALING WITH A MOVE */
/*       IN RECIPROCICAL SPACE */
/*       WE REMAP THE ENERGY PB AS FIXED ENERGY IN EDEF(1) */
/*       AND VARIABLE ENERGY IN EDEF(2) */
/*       IF ISA IS NUL  SET IFX TO 1 AND PUT EF,KF, EQUAL TO EI,KI */

    /* Parameter adjustments */
    --c_ih__;
    --p_ih__;
    --ldra;
    --t_a__;
    --ldk;
    --qhkl;

    /* Function Body */
    imod = 3;
    ddm = *dm;
    dda = *da;
    for (i__ = 1; i__ <= 2; ++i__) {
	lmoan[i__ - 1] = FALSE_;
    }
    lqhkle = FALSE_;
    for (iq = 5; iq <= 8; ++iq) {
	lqhkle = lqhkle || ldk[iq];
    }
    daki = *aki;
    dakf = *akf;
    if (*isa == 0) {
	*ifx = 1;
    }
    edef[*ifx - 1] = *ei;
    akdef[*ifx - 1] = *aki;
    edef[3 - *ifx - 1] = *ef;
    akdef[3 - *ifx - 1] = *akf;
    if (*isa == 0) {
	edef[1] = edef[0];
	akdef[1] = akdef[0];
	ldk[3] = TRUE_;
	ldk[4] = TRUE_;
	t_a__[5] = 0.f;
	t_a__[6] = 0.f;
	ldra[5] = TRUE_;
	ldra[6] = TRUE_;
    }
/* ----------------------------------------------------------------------- */
/*       FIRST TAKE IN ACCOUNT THE FIXED ENERGY PB */

    if (ldk[(*ifx << 1) - 1] || ldk[*ifx * 2]) {
	lmoan[*ifx - 1] = TRUE_;
	if (ldk[(*ifx << 1) - 1]) {
	    *ier = 1;
	    if (edef[0] < .1) {
		goto L999;
	    }
	    *ier = 0;
	    akdef[0] = sqrt(edef[0] / *f);
	} else {
	    *ier = 1;
	    if (akdef[0] < .1) {
		goto L999;
	    }
	    *ier = 0;
/* Computing 2nd power */
	    d__1 = akdef[0];
	    edef[0] = *f * (d__1 * d__1);
	}
    }
/* ----------------------------------------------------------------------- */
/*       NOW TAKE IN ACCOUNT THE VARIABLE ENERGY PB */
/*       VARIABLE ENERGUY IS DRIVEN EITHER EXPLICITLY */
/*       E.G. BY DRIVING EI OR KI WITH IFX=2 */
/*        ( AND WE MUST CALCULATE EN FROM EVAR) */
/*       THE RULE IS : EI=EF+EN : EN IS THE ENERGY LOSS OF NEUTRONS */
/*       OR ENERGY GAIN OF SAMPLE */
/*       OR IMPLICITLY  BY DRIVING THE TRANSFERED ENERGY EN */
/*        ( AND WE MUST CALCULATE EVAR FROM EN) */
/*       IF KI IS CONSTANT USE THE CURRENT VALUE CONTAINED IN POSN ARRAY */
/*       TO CALCULATE THE NON-"CONSTANT" K. */
/*       IF KF IS CONSTANT USE ALWAYS THE VALUE IN TARGET AND */
/*        DO A DRIVE OF KF TO KEEP A5/A6 IN RIGHT POSITION */

    if (ldk[5 - (*ifx << 1)] || ldk[6 - (*ifx << 1)]) {
	lmoan[3 - *ifx - 1] = TRUE_;
	if (ldk[5 - (*ifx << 1)]) {
	    *ier = 1;
	    if (edef[1] < 1e-4) {
		goto L999;
	    }
	    *ier = 0;
	    akdef[1] = sqrt(edef[1] / *f);
	} else {
	    *ier = 1;
	    if (akdef[1] < 1e-4) {
		goto L999;
	    }
	    *ier = 0;
/* Computing 2nd power */
	    d__1 = akdef[1];
	    edef[1] = *f * (d__1 * d__1);
	}
	*en = (3 - (*ifx << 1)) * (edef[0] - edef[1]);
    } else if (lqhkle) {
	lmoan[3 - *ifx - 1] = TRUE_;
	edef[1] = edef[0] + ((*ifx << 1) - 3) * *en;
	*ier = 1;
	if (edef[1] < 1e-4) {
	    goto L999;
	}
	*ier = 0;
	akdef[1] = sqrt(edef[1] / *f);
    }
/* ----------------------------------------------------------------------- */
/*       CALCULATE MONOCHROMATOR AND ANALYSER ANGLES */

    if (lmoan[0]) {
	dei = edef[*ifx - 1];
	daki = akdef[*ifx - 1];
	ex_case__(&ddm, ism, &daki, &a1, &a2, &rm, &alm, ier);
	if (*ier == 0) {
	    *aki = daki;
	    *ei = dei;
	    t_a__[1] = a1;
	    t_a__[2] = a2;
	    *t_rm__ = rm;
	    *t_alm__ = alm;
	    ldra[1] = TRUE_;
	    ldra[2] = TRUE_;
	    *ldr_rm__ = TRUE_;
	    *ldr_alm__ = TRUE_;
	} else {
	    goto L999;
	}
    }
    if (lmoan[1]) {
	def = edef[3 - *ifx - 1];
	dakf = akdef[3 - *ifx - 1];
	ex_case__(&dda, isa, &dakf, &a5, &a6, &ra, &ala, ier);
	if (*ier == 0) {
	    *akf = dakf;
	    *ef = def;
	    t_a__[5] = a5;
	    t_a__[6] = a6;
	    ldra[5] = TRUE_;
	    ldra[6] = TRUE_;
	} else {
	    goto L999;
	}
    }
/* ----------------------------------------------------------------------- */
/*       USE (QH,QK,QL) TO CALCULATE A3 AND A4 */
/*       CALCULATE Q1 AND Q2 IN SCATTERING PLANE */

    imod = 2;
    if (lqhkle) {
	for (id = 1; id <= 3; ++id) {
	    dqhkl[id - 1] = qhkl[id];
	}
	rl2spv_(dqhkl, dqt, &dqm, &dqs, ier);
	if (*ier != 0) {
	    goto L999;
	}
	sam_case__(dqt, &dqm, &dqs, &daki, &dakf, &a3, &a4, iss, ier);
	if (*ier == 0) {
	    t_a__[3] = a3;
	    t_a__[4] = a4;
	    ldra[3] = TRUE_;
	    ldra[4] = TRUE_;
	    *qm = dqm;
	} else {
	    goto L999;
	}
    }
/* ----------------------------------------------------------------------- */
/*        DEAL WITH FLIPPERS AND HELMOTZ COILS IF LPA */

    if (*lpa && (lmoan[0] || lmoan[1])) {
	if (*ldf) {
	    flip_case__(if1, if2, &p_ih__[1], f1v, f1h, f2v, f2h, aki, akf, 
		    ier);
	}
	if (*ldh) {
	    helm_case__(hx, hy, hz, &p_ih__[1], &c_ih__[1], aki, akf, &a4, qm,
		     helm, ier);
	}
    }
/* ----------------------------------------------------------------------- */
L999:
    if (*ier != 0) {
	erreso_(&imod, ier);
    }
    return 0;
} /* t_conv__ */

/* Subroutine */ int ex_case__(doublereal *dx, integer *isx, doublereal *akx, 
	doublereal *ax1, doublereal *ax2, doublereal *rx, doublereal *alx, 
	integer *ier)
{
    /* System generated locals */
    doublereal d__1, d__2;

    /* Builtin functions */
    double asin(doublereal), sin(doublereal), cos(doublereal), sqrt(
	    doublereal);

    /* Local variables */
    static doublereal dcl1r, dc1rx, dc2rx, drmin, drmax, arg;

/* ----------------------------------------------------------------------- */
/*        CALCULATE  ANGLES ON MONO/ANALYSER */
/*       CALCULATE AX1  AX2 */
/*       CALCULATE RX LX MONO CURVATURE AND LM FOR IN8 */

/*       INPUT */
/*       DX      D-SPACINGS */
/*       ISX     SENS OF SCATTERING ON CRYSTAL */
/*       AKX     TARGET OF MOMENTUM */
/*       OUTPUT */
/*       AX1 AX2  THETA 2*THETA ANGLES */
/*       RX      MONO OR ANALYSER CURVATURE */
/*       ALX     SPECIAL TRANSLATION FOR IN8 */
/*       IER */
/*        1       ' KI OR KF CANNOT BE OBTAINED CHECK D-SPACINGS', */
/*        2       ' KI OR KF TOO SMALL', */
/*        3       ' KI OR KF TOO BIG', */

/* ----------------------------------------------------------------------- */
/* 	Values of parameters */

/* 	INX=1 IN8 , INX=0 others instruments */
/* 	C1RX C2RX constants values to calculate RM on all instruments */
/* 	RMIN, RMAX min max on RNM */
/* 	CL1R constant value to calculate LM for IN8 */

/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/*       PASSED PARAMETERS */
/* ----------------------------------------------------------------------- */
/*       LOCAL VAR */
/* ----------------------------------------------------------------------- */
/*       INIT AND TEST */

    *ier = 0;
    dc1rx = curve_1.c1rx;
    dc2rx = curve_1.c2rx;
    drmin = curve_1.rmin;
    drmax = curve_1.rmax;
    dcl1r = curve_1.cl1r;
    if (*dx < .1f) {
	*ier = 1;
    }
    if (*akx < .1f) {
	*ier = 2;
    }
    arg = 3.1415926535897932384626433832795f / (*dx * *akx);
    if (abs(arg) > 1.f) {
	*ier = 3;
    }
    if (*ier != 0) {
	goto L999;
    }
/* ----------------------------------------------------------------------- */
/*       CALCULATION OF THE TWO ANGLES */

    *ax1 = asin(arg) * *isx * 57.29577951308232087679815481410517f;
    *ax2 = *ax1 * 2.;
/* ----------------------------------------------------------------------- */
/*        CALCULATION OF MONO CURVATURE RM OR ANALYSER CURVATURE RA */
/*       STANDARD LAW IS  C1RX+C2RX/SIN(A1/RD) */
/*       C1RX AND C2RX ARE CONSTANTS DEPENDING ON MONO AND MACHINES */

/*        C1RX=.47 */
/*        C2RX=.244 */
/*        RMIN=0. */
/*       RMAX=20. */
/* 	IN1/IN3/IN12/IN14/IN20 CASE */
    if (curve_1.inx == 0) {
/* Computing MIN */
/* Computing MAX */
	d__2 = dc1rx + dc2rx / sin(abs(*ax1) / 
		57.29577951308232087679815481410517f);
	d__1 = max(d__2,drmin);
	*rx = min(d__1,drmax);
    } else {
/* 	IN8 CASE */
	*alx = dcl1r / sin(*ax2 / 57.29577951308232087679815481410517f) * cos(
		*ax2 / 57.29577951308232087679815481410517f);
	*rx = dc2rx * sqrt(sin(*ax2 / 57.29577951308232087679815481410517f)) 
		- dc1rx;
    }
/* ----------------------------------------------------------------------- */
L999:
    return 0;
} /* ex_case__ */

/* ========================================================================= */
/* Subroutine */ int sam_case__(doublereal *qt, doublereal *qm, doublereal *
	qs, doublereal *aki, doublereal *akf, doublereal *ax3, doublereal *
	ax4, integer *iss, integer *ier)
{
    /* System generated locals */
    doublereal d__1, d__2;

    /* Builtin functions */
    double acos(doublereal), atan2(doublereal, doublereal), d_sign(doublereal 
	    *, doublereal *), d_mod(doublereal *, doublereal *);

    /* Local variables */
    static doublereal arg, sax3;

/* ----------------------------------------------------------------------- */
/*               DEAL WITH SAMPLE ANGLES CALCULATION FROM Q VERTOR IN C-N PLANE */
/*       CALCULATE A3 AND A4 */
/*       INPUT */
/*       QT      Q-VECTOR IN SCATTERING PLANE */
/*       QM,QS   Q MODULUS AND QMODULUS SQUARED */
/*       AKI,AKF MOMEMTA ON MONO AND ANYLSER */
/*       ISS             SENS OF SCATTERING ON SAMPLE */

/*       OUTPUT */
/*       AX3 AX4         ANGLES ON SAMPLES */
/*       IER SAME ERROR AS RL2SPV */
/*       IER */
/*        1       ' MATRIX S NOT OK', */
/*        2       ' Q NOT IN SCATTERING PLANE', */
/*        3       ' Q MODULUS TOO SMALL', */
/*        4       ' Q MODULUS TOO BIG', */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/*       PASSED PARAMETERS */
/* ----------------------------------------------------------------------- */
/*       INIT AND TEST */

    /* Parameter adjustments */
    --qt;

    /* Function Body */
    *ier = 0;
    if (abs(*qs) < 1e-6 || abs(*qm) < .001) {
	*ier = 3;
	goto L999;
    }
/* ----------------------------------------------------------------------- */
/*       CALCULATE A3 AND MOVE IT INTHE -180 ,+180 INTERVAL */

/* Computing 2nd power */
    d__1 = *aki;
/* Computing 2nd power */
    d__2 = *akf;
    arg = (d__1 * d__1 + d__2 * d__2 - *qs) / (*aki * 2. * *akf);
    if (abs(arg) > 1.) {
	*ier = 4;
	goto L999;
    } else {
	*ax4 = acos(arg) * *iss * 57.29577951308232087679815481410517;
    }
/* Computing 2nd power */
    d__1 = *akf;
/* Computing 2nd power */
    d__2 = *aki;
    *ax3 = (-atan2(qt[2], qt[1]) - acos((d__1 * d__1 - *qs - d__2 * d__2) / (*
	    qm * -2. * *aki)) * d_sign(&c_b7, ax4)) * 
	    57.29577951308232087679815481410517;
    sax3 = d_sign(&c_b7, ax3);
    d__1 = *ax3 + sax3 * 180.;
    *ax3 = d_mod(&d__1, &c_b9) - sax3 * 180.;

/*       IF(LPLATE) AX3=-ATAN(SIN(AX4/RD)/(LSA*TAN(AX5/RD)/(ALMS*C */
/*       1       TAN(AX1/RD))*(AKI/KF)**2-COS(AX4/RD)))*RD       !PLATE FOCALIZATION OPTION */
/*       IF(AXX3.GT.180.D0) AX3=AX3-360.D0 */
/*       IF( A3.LT.-180.D0) AX3=AX3+360.D0 */
/*       IF(LPLATE.AND.A3.GT.0.0) AX3=AX3-180 */
/* C----------------------------------------------------------------------- */
L999:
    return 0;
} /* sam_case__ */

/* ============================================================================ */
/* Subroutine */ int helm_case__(real *hx, real *hy, real *hz, real *t_ih__, 
	real *c_ih__, real *aki, real *akf, doublereal *a4, real *qm, real *
	helm, integer *ier)
{
    /* System generated locals */
    real r__1, r__2;

    /* Builtin functions */
    double cos(doublereal), sin(doublereal), atan2(doublereal, doublereal), 
	    sqrt(doublereal);

    /* Local variables */
    static real hrad, hdir, qpar, hdir2, qperp;
    static integer ic;
    static real phi;

/* ----------------------------------------------------------------------- */
/*               DEAL WITH HELMOTZ COIL FIELD CALCULATIONS */
/*       CALCULATE HX HY HZ */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/*       PASSED PARAMETERS */
/* ----------------------------------------------------------------------- */
/*       INIT AND TEST */

    /* Parameter adjustments */
    --c_ih__;
    --t_ih__;

    /* Function Body */
    *ier = 1;
    if (dabs(*qm) < 1e-4f) {
	goto L999;
    }
    *ier = 0;
    for (ic = 1; ic <= 4; ++ic) {
	if (c_ih__[ic] < 1e-4f) {
	    *ier = 2;
	}
    }
    if (*ier != 0) {
	goto L999;
    }
/* ----------------------------------------------------------------------- */
/*       CALCULATE MODULE AND ANGLES OF IN PLANE FIELD H */
/*       PHI                     !ANGLE BETWEEN Q AND KI */
/*       HRAD            !RADIAL COMP. OF H */
/*       HDIR            !DIRECTION OF H (IN RADIANS) */
/*       HDIR2           !ANGLE BETWEEN FIELD AND AXE OF COIL 1 */

    qpar = *aki - *akf * cos(*a4 / 57.29577951308232087679815481410517f);
    qperp = *akf * sin(*a4 / 57.29577951308232087679815481410517f);
    phi = atan2(qpar, qperp);
/* Computing 2nd power */
    r__1 = *hx;
/* Computing 2nd power */
    r__2 = *hy;
    hrad = sqrt(r__1 * r__1 + r__2 * r__2);
    if (hrad > 1e-4f) {
	hdir = atan2(*hy, *hx);
    }
    hdir2 = phi + hdir + *helm / 57.29577951308232087679815481410517f + 
	    1.5707963267948966f;
/* ----------------------------------------------------------------------- */
/*               !CALC CURRENTS */
/*               !POSITION OF PSP FOR COIL I */

    for (ic = 1; ic <= 3; ++ic) {
	t_ih__[ic + 4] = cos(hdir2 + (ic - 1) * 2.f * 
		3.1415926535897932384626433832795f / 3.f) * hrad / c_ih__[ic] 
		/ 1.5f;
    }
    t_ih__[8] = *hz / c_ih__[4];
/* ----------------------------------------------------------------------- */
L999:
    return 0;
} /* helm_case__ */

/* Subroutine */ int flip_case__(integer *if1, integer *if2, real *t_ih__, 
	real *f1v, real *f1h, real *f2v, real *f2h, real *aki, real *akf, 
	integer *ier)
{
/* ----------------------------------------------------------------------- */
/*               DEAL WITH FLIPPER COIL  CALCULATIONS */
/*       CALCULATE P_IF CURRENTS FOR THE TWO FLIPPERS */
/* ----------------------------------------------------------------------- */
/*       PASSED PARAMETERS */
/* ----------------------------------------------------------------------- */
/*       INIT AND TEST */

    /* Parameter adjustments */
    --t_ih__;

    /* Function Body */
    *ier = 0;
/* ----------------------------------------------------------------------- */

    if (*if1 == 1) {
	t_ih__[1] = *f1v;
	t_ih__[2] = *aki * *f1h;
    } else {
	t_ih__[1] = 0.f;
	t_ih__[2] = 0.f;
    }
    if (*if2 == 1) {
	t_ih__[3] = *f2v;
	t_ih__[4] = *akf * *f2h;
    } else {
	t_ih__[3] = 0.f;
	t_ih__[4] = 0.f;
    }
/* ----------------------------------------------------------------------- */
/* L999: */
    return 0;
} /* flip_case__ */

