SUBROUTINE T_UPDATE ( ! File [MAD.SRC]T_UPDATE.FOR c =================== + P_A, P_IH, C_IH, + LPA ,DM, DA, ISA, HELM, F1H, F1V, F2H, F2V, F, + EI, AKI, EF, AKF, QHKL, EN, + HX, HY, HZ, IF1, IF2, QM, IER) c cdec$ Ident 'V01C' c------------------------------------------------------------------ c Note: c IF1,If2 changed to Int*4. They were Real*4 in ILL version. c------------------------------------------------------------------ c Updates: c V01A 7-May-1996 DM. Put error output to IOLUN, use IMPLICIT NONE and c get the code indented so that it is readable! c V01C 12-Oct-1998 DM. Put in Mag Field calculation for SINQ Helmolz coils. C----------------------------------------------------------------------- c Entry points in this file: C T_UPDATE : USE THE MOTOR ANGLES TO CALCULATE VALUES OF c EI,KI,EF,KF,QH,QK,QL,EN AND TO DETERMINE c WHETHER FLIPPERS F1,F2 ARE 'ON' OR 'OFF'. c EX_UP : CALCULATE EX AND AKX FORM AX2 VALUES. c SAM_UP : CALCULATE THINGS IN RECIPROCICAL LATTICE. c HELM_UP : CALCULATE HELMHOLTZ FIELDS. c FLIP_UP : CHECK IF FLIPPERS ON OR OFF. C----------------------------------------------------------------------- c T_UPDATE: C ROUTINE TO USE THE MOTOR ANGLES TO C CALCULATE VALUES OF EI,KI,EF,KF,QH,QK,QL,EN C USE CURRENT-SUPPLY VALUES TO COMPUTE HELMHOLTZ FIELDS HX,HY,HZ C AND TO DETERMINE WHETHER FLIPPERS F1,F2 ARE 'ON' OR 'OFF'. C FLIPPERS ARE 'ON' ONLY IF CURRENTS ARE THOSE GIVEN BY C F1V,F1H,F2V,F2H C----------------------------------------------------------------------- IMPLICIT NONE ccc IMPLICIT DOUBLE PRECISION (A-H,O-Z) C include 'iolsddef.inc' C----------------------------------------------------------------------- c Define the dummy arguments c Input: real*4 p_a(6) ! Positions of angles A1-A6. real*4 p_ih(8) ! Position of currents for flippers and .. ! .. helmotz (8 currents). real*4 c_ih(4) ! Conversion factors for Helmotz (4 currents). ! Configuration of the machine ... logical*4 lpa ! True if machine in polarization mode. real*4 dm ! Monochr. d-spacing real*4 da ! Analyser d-spacing integer*4 isa ! Scattering sense at analyser (probably) .. ! .. +ve to the left. real*4 helm ! Angle between axis of Helmolz pair one and .. ! .. ki (probably). real*4 f1h, f1v ! Flipper 1 hor and vert currents (hor .. ! .. current is possibly ki*f1h ??) real*4 f2h, f2v ! Flipper 2 hor and vert currents (hor .. ! .. current is possibly kf*f2h ??) real*4 f ! Energy unit c Output: real*4 ei ! Incident neutron energy real*4 aki ! Incident neutron wave vector real*4 ef ! Final neutron energy real*4 akf ! Final neutron wave vector real*4 qhkl(3) ! Components of q in reciprocal space real*4 en ! Energy transfer real*4 hx, hy, hz ! Components of Helmolz field on sample integer*4 if1, if2 ! Status of Flippers 1 and 2 real*4 qm ! Length of q integer*4 ier ! Error status C----------------------------------------------------------------------- double precision dbqhkl(3), dhx, dhy, dhz double precision ddm, dda, df double precision da2, da3, da4, da6 double precision dei, daki, def, dakf double precision dqm, dqs, dphi real*4 qs c integer*4 ieri, ieru, imod, id C----------------------------------------------------------------------- C SET UP C DDM=DM DDA=DA DF=F DA2=P_A(2) DA3=P_A(3) DA4=P_A(4) DA6=P_A(6) C----------------------------------------------------------------------- C IERI=0 IERU=1 + 8 CALL EX_UP(DDM,DEI,DAKI,DA2,DF,IERI) IF (IERI.EQ.0) THEN EI=DEI AKI=DAKI IERU=0 ELSE IMOD=3 CALL ERRESO(IMOD,IERI) IERU = IERI + 8 ENDIF IERI=0 IERU=1 + 8 CALL EX_UP(DDA,DEF,DAKF,DA6,DF,IERI) IF (IERI.EQ.0) THEN EF=DEF AKF=DAKF IERU=0 ELSE IF (ISA.EQ.0) THEN EF=DEI AKF=DAKI DEF=DEI DAKF=DAKI IERU=0 ELSE IMOD=3 CALL ERRESO(IMOD,IERI) IERU = 8 + IERI ENDIF ENDIF IF (ISA.EQ.0) THEN EF=DEI AKF=DAKI DEF=DEI DAKF=DAKI IERU=0 ENDIF IF (IERU.EQ.0) EN=DEI-DEF IERI=0 IERU=1 + 4 CALL SAM_UP(DBQHKL,DQM,DQS,DPHI,DAKI,DAKF,DA3,DA4,IERI) IF (IERI.EQ.0) THEN DO ID=1,3 QHKL(ID)=DBQHKL(ID) ENDDO QM=DQM QS=DQS IERU=0 ELSE IMOD=2 CALL ERRESO(IMOD,IERI) IERU = IERI + 4 ENDIF C IERI=0 IF (LPA) THEN IERU=1 CALL HELM_UP(DPHI,HELM,P_IH,C_IH,DHX,DHY,DHZ,IERI) IF (IERI.NE.0) THEN C WRITE(6,*) 'ERROR IN HELM_UP CHECK COEFF' ELSE HX=DHX HY=DHY HZ=DHZ IERU=0 ENDIF CALL FLIP_UP(IF1,IF2,P_IH,F1V,F1H,F2V,F2H,AKI,AKF,IERI) ENDIF C----------------------------------------------------------------------- IER=IERU RETURN END c SUBROUTINE EX_UP(DX,EX,AKX,AX2,F,IER) ! Part of [MAD.SRC]T_UPDATE.FOR c ================ c C----------------------------------------------------------------------- C CALCULATE EX AND AKX FORM AX2 VALUES C----------------------------------------------------------------------- implicit none c DOUBLE PRECISION PI PARAMETER (PI=3.1415926535897932384626433832795E0) DOUBLE PRECISION RD PARAMETER (RD=57.29577951308232087679815481410517E0) DOUBLE PRECISION EPS4 PARAMETER (EPS4=1.D-4) C----------------------------------------------------------------------- c Define the dummy arguments c Input: DOUBLE PRECISION DX ! D-SPACING OF CRISTAL DOUBLE PRECISION AX2 ! TAKE OFF ANGLE DOUBLE PRECISION F ! ENERGY UNIT c Output: DOUBLE PRECISION EX ! ENERGY DOUBLE PRECISION AKX ! MOMENTUM INTEGER*4 IER ! Error - IER=1 if DX OR AX TOO SMALL C----------------------------------------------------------------------- DOUBLE PRECISION ARG C----------------------------------------------------------------------- C!!!!!!!!!! This has to be fixed manually after conversion by f2c. C!!!!!!!!!! The reason is a different definition of the abs function. C!!!!!!!!!! MK, May 2001 ARG=ABS(DX*SIN(AX2/(2.D0*RD))) IF(ARG.LE.EPS4) THEN IER=1 ELSE IER=0 AKX=PI/ARG EX=F*AKX**2 ENDIF C----------------------------------------------------------------------- RETURN END c SUBROUTINE SAM_UP ( ! Part of [MAD.SRC]T_UPDATE.FOR c ================= + QHKL, QM, QS, PHI, + AKI, AKF, A3, A4, IER) C----------------------------------------------------------------------- implicit none c double precision PI PARAMETER (PI=3.1415926535897932384626433832795D0) double precision RD PARAMETER (RD=57.29577951308232087679815481410517D0) double precision EPS3 PARAMETER (EPS3=1.D-3) C----------------------------------------------------------------------- c Define the dummy arguments c Input: double precision AKI ! Actual value of KI double precision AKF ! Actual value of KF double precision A3 ! Actual value of A3 double precision A4 ! Actual value of A4 c Output: double precision QHKL(3) ! CALCULATED POSITIONS IN RECIP. LATTICE double precision QM ! Q MODULUS double precision QS ! Q MODULUS SQUARED double precision PHI ! ANGLE BETWEEN KI AND Q integer*4 IER ! Error status. IER=1 if QM TOO SMALL (PHI ! NOT CALCULATED) C----------------------------------------------------------------------- C LOCAL PARAMETERS double precision QT(3) double precision QPAR, QPERP C----------------------------------------------------------------------- C QPAR AND QPERP ARE COMPONENTS OF Q PARALLEL AND PERP TO KI C TRANSFORM FROM SCATTERING PLANE INTO RECIPROCAL LATTICE C qpar = aki - akf * cos(a4/RD) qperp = -akf * sin(a4/RD) qt(1) = qpar * cos(a3/RD) + qperp * sin(a3/RD) qt(2) = -qpar * sin(a3/RD) + qperp * cos(a3/RD) qt(3) = 0.d0 call sp2rlv (qhkl, qt, qm, qs, ier) ier = 3 if (qm .gt. EPS3) ier = 0 phi = 0.d0 if (abs(qperp) .gt. EPS3 .and. abs(qpar) .gt. EPS3) then phi = atan2 (qperp, qpar) elseif (abs(qpar) .lt. EPS3) then if (a4 .gt. 0.0) then phi = -0.5 * PI else phi = 0.5 * PI endif endif c----------------------------------------------------------------------- return end c SUBROUTINE HELM_UP ( ! Part of [MAD.SRC]T_UPDATE.FOR c ================== + PHI, HELM, P_IH, C_IH, + DHX, DHY, DHZ, IER) c C---------------------------------------------------------------- C HELMHOLTZ COILS UPDATE (ONLY IF LPA IS TRUE) C---------------------------------------------------------------- implicit none c C include 'common_sinq.inc' c double precision PI PARAMETER (PI = 3.1415926535897932384626433832795D0) double precision RD PARAMETER (RD = 57.29577951308232087679815481410517D0) double precision EPS3 PARAMETER (EPS3 = 1.0D-3) C----------------------------------------------------------------------- c At ILL: c There are 3 coils for Hx/Hy at 120 degrees to each other. c c There is a 4th coil for Hz. c c At SINQ: c There is an Hx coil and an Hy coil (actually each is 4 coils powered c in series). They are mounted on a ring (SRO). The value of HELM is c the angle between the Hx coil and ki. c c There is a 3rd coil for Hz. C----------------------------------------------------------------------- c Define the dummy arguments c Input: double precision PHI ! Angle between KI and Q in scatt'g plane (rad) real*4 HELM ! Angle between first coil and KI (degrees) real*4 P_IH(8) ! Current values of 4 currents associated .. ! with Helmolz coils real*4 C_IH(4) ! Conversion factor between Amperes and Gauss c Output: double precision DHX ! \ double precision DHY ! > The calculated fields double precision DHZ ! / integer*4 IER ! Error status. IER=1 if C_I HAS A ZERO COEF C---------------------------------------------------------------- C LOCAL VARIABLES integer*4 ic double precision h(4), hpar, hperp, hmod, hdir, hdir2 LOGICAL AT_SINQ C---------------------------------------------------------------- C H !FIELD OF 4 COILS AROUND SAMPLE C HPAR !FIELD PAR COIL 1 C HPERP !FIELD PERP. TO COIL 1 C HDIR2 !ANGLE BETWEEN FIELD AND COIL 1 C HDIR !ANGLE BETWEEN FIELD AND Q C---------------------------------------------------------------- ier = 0 AT_SINQ = .TRUE. if (.not. at_sinq) then do ic = 1, 4 h(ic) = 0.d0 if (abs(c_ih(ic)) .gt. EPS3) then h(ic) = p_ih(ic+4) * c_ih(ic) else ier = 1 endif enddo hpar = h(1) - .5d0 * (h(2) + h(3)) hperp = .5d0 * sqrt(3.d0) * (h(2) - h(3)) dhz = h(4) else do ic = 1, 3 h(ic) = 0.d0 if (abs(c_ih(ic)) .gt. EPS3) then h(ic) = p_ih(ic+4) * c_ih(ic) else ier = 1 endif enddo hpar = h(1) hperp = h(2) dhz = h(3) endif c hmod = sqrt (hpar**2 + hperp**2) if (abs(hpar) .gt. EPS3 .and. abs(hperp) .gt. EPS3) then hdir2 = atan2 (abs(hperp), abs(hpar)) if (hpar .gt. 0 .and. hperp .lt. 0) then hdir2 = -hdir2 elseif (hpar .lt. 0 .and. hperp .gt. 0) then hdir2 = PI - hdir2 elseif (hpar .lt. 0 .and. hperp .lt. 0) then hdir2 = hdir2 - PI endif elseif (abs(hpar) .gt. EPS3) then if (hpar .ge. 0.0) hdir2 = 0.0 if (hpar .lt. 0.0) hdir2 = PI elseif (abs(hperp) .gt. EPS3) then if (hperp .ge. 0.0) hdir2 = 0.5 * PI if (hperp .lt. 0.0) hdir2 = -0.5 * PI else hdir2 = 0.0 endif hdir = hdir2 + (helm/RD) - phi dhx = hmod * cos(hdir) dhy = hmod * sin(hdir) c return end c SUBROUTINE FLIP_UP ( ! Part of [MAD.SRC]T_UPDATE.FOR c ================== + IF1, IF2, + P_IH, F1V, F1H, F2V, F2H, + AKI, AKF, IER) C---------------------------------------------------------------- C FLIPPERS; ONLY IF LPA C---------------------------------------------------------------- implicit none C----------------------------------------------------------------------- c Define the dummy arguments c Input: real*4 p_ih(8) ! Current values of 4 currents associated .. ! with flipper coils real*4 f1v, f1h ! Flipper 1 vert and hor currents (hor .. ! .. current is possibly aki*f1h ??) real*4 f2v, f2h ! Flipper 2 vert and hor currents (hor .. ! .. current is possibly akf*f2h ??) real*4 aki ! Incident neutron wave vector real*4 akf ! Final neutron wave vector c Output: integer*4 if1 ! Status of Flipper 1 (=1 if on and set OK) integer*4 if2 ! Status of Flipper 2 (=1 if on and set OK) integer*4 ier ! Error status. 0 if no error. C---------------------------------------------------------------- IER = 0 IF1 = 0 IF2 = 0 IF ((ABS(P_IH(1) - F1V) .LT. 0.05) .AND. + (ABS(P_IH(2) - AKI*F1H) .LT. 0.05)) IF1 = 1 IF ((ABS(P_IH(3) - F2V) .LT. 0.05) .AND. + (ABS(P_IH(4) - AKF*F2H) .LT. 0.05)) IF2 = 1 C----------------------------------------------------------------------- RETURN END