C C This code is distributed under the terms and conditions of the C CCP4 licence agreement as `Part ii)' software. See the conditions C in the CCP4 manual for a copyright statement. C C************************************************************************ C C POLARRFN C C C Fast polar rotation function program, by W. KABSCH C C 15/9/93 PRE: output weighted mean & RMS to map file C C 1/1/90 PRE replaced s/r DCOSFD with more robust alternative C C 26/6/89 PRE test maximum & minimum amplitude after applying B-factor C Apply temperature factor correctly ie multiply F by C exp ( - B sintheta/lambda) C C 2/6/89 PRE allow peak threshold to be given as multiple of RMS C Interpolate peaks C C Fancy input and output by Phil Evans, Feb 1986 C C 25/5/89 PRE edited variable names ALFA, BETA, GAMA to PHI, OMEG, KAPA C Changed plotting to more portable interface (see routines PLT... C at end) C C 3/3/87 PRE Correction in s/r MAPRED, allowed title change in READ C Added JOIN option C C 30/7/86 PRE increased map array size, and check C C VAX compile /NOPT (Fortran v4.3 anyway) C link with F77LCFLIB, MAPLIB, PLOT84, CCPLIB C C************************************************************************ PROGRAM POLARRFN C ================ C COMMON /MATRIX/ ORTHOG(3,3,2),FRAC(3,3,2),SYM(4,4,192,2),NSYM(2), . MRSYM,JRSYM(3,3,12),LSYMFG,LHALF COMMON /ALMFRF/ NCRYST,IPHI1,IPHI2,NPHI,IOMEG1,IOMEG2,NOMEG, . IKAPA1,IKAPA2,NKAPA,ARAD,EPS,RESMIN,RESMAX,NCODES(2),LSPGPS(2), . TFACS(2),FRMINS(2),FRMAXS(2),LPRINT,LMAP,LPLOT,CONTRS(50), . NCONTR,LREAD,LSAVE,PEAK,MAXPEK,LPKRMS,KRKAP1,KRKAP2, . RMIN,RMEAN,RRMS,RWT,NPOINT CHARACTER*80 TITLE,FNAME COMMON /TEXTC/ TITLE,FNAME C PARAMETER (MAXNPK=100) COMMON /PEAKS/ NPEAK,PEAKS(MAXNPK),PKPOS(3,MAXNPK),LPEAK, . LPKORD(MAXNPK),LPKOUT C C-- Open main read and write files. C CALL MTZINI CALL CCPFYP IFAIL=0 C CALL CCPDPN(5,'DATA','READONLY','F',1,IFAIL) CALL CCPDPN(6,'PRINTER','PRINTER','F',1,IFAIL) CALL CCPRCS(6,'POLARRFN', '$Date: 2002/08/06 12:29:31 $') C C Read control data C CALL DATAIN C IF(LPEAK.GT.0) THEN C Option to print peaks only CALL PPEAKS CALL CCPERR(0,' Normal Termination from ppeaks') ENDIF C C Option to read map calculated on a previous run C IF(LREAD.GT.0) THEN CALL MAPRED CALL CCPERR(0,' Normal Termination from mapred') ENDIF C C Calculate ALMN coefficients C IF(LSAVE.GE.0) THEN CALL CALMN ENDIF C C Sum rotation function CALL FRFSUM CALL CCPERR(0,' Normal termination from frfsum') C END C C C SUBROUTINE DATAIN C ================= C C Read in all data INTEGER MCOLS PARAMETER (MCOLS=500) INTEGER NPARM PARAMETER (NPARM=200) INTEGER MAXNPK PARAMETER (MAXNPK=100) C COMMON /MATRIX/ ORTHOG(3,3,2),FRAC(3,3,2),SYM(4,4,192,2),NSYM(2), . MRSYM,JRSYM(3,3,12),LSYMFG,LHALF COMMON /ALMFRF/ NCRYST,IPHI1,IPHI2,NPHI,IOMEG1,IOMEG2,NOMEG, . IKAPA1,IKAPA2,NKAPA,ARAD,EPS,RESMIN,RESMAX,NCODES(2),LSPGPS(2), . TFACS(2),FRMINS(2),FRMAXS(2),LPRINT,LMAP,LPLOT,CONTRS(50), . NCONTR,LREAD,LSAVE,PEAK,MAXPEK,LPKRMS,KRKAP1,KRKAP2, . RMIN,RMEAN,RRMS,RWT,NPOINT CHARACTER*200 LABIN_SAVE(2) CHARACTER*200 ERRLIN CHARACTER*80 TITLE,FNAME CHARACTER*80 FILIN(2) COMMON /TEXTC/ TITLE,FNAME C COMMON /PEAKS/ NPEAK,PEAKS(MAXNPK),PKPOS(3,MAXNPK),LPEAK, . LPKORD(MAXNPK),LPKOUT C COMMON /PKFILE/ PKFNAM CHARACTER*80 PKFNAM C LOGICAL NOTCAL CHARACTER*10 NAMSGP,NAMSGS(2),PGNAME,VERSNX REAL COLRNG(2,MCOLS) C C Maximum section size PARAMETER (NSMAP=33759) C C JOIN stuff PARAMETER (MXJOIN=30) COMMON /VJOIN/ NJOIN,PEAKJ(3,2,MXJOIN),DASH(2,MXJOIN) C INTEGER LOOKUP(MCOLS) INTEGER LSPGRP,NSM,IPRINT REAL RR(3,3,6),RO(4,4),RF(4,4) CHARACTER CTPRGI(MCOLS)*1,LSPRGI(MCOLS,2)*30 C SAVE /PKFILE/, /VJOIN/ C C .. External Functions .. INTEGER LENSTR EXTERNAL LENSTR C .. C .. External Subroutines .. EXTERNAL CCPUPC,GTPINT,GTPREA, + PARSER,RBRINV,LKYIN, + LRASSN,LRINFO,LROPEN,LRSYMM DIMENSION CELL(6,2),CELCHK(6) C .. C C Things for PARSER ---- CHARACTER KEY*4,CVALUE(NPARM)*4,LINE*600,LTYPE*1 INTEGER IBEG(NPARM),IEND(NPARM),ITYP(NPARM),IDEC(NPARM),NTOK REAL FVALUE(NPARM) LOGICAL LEND C PARAMETER (NKEY=20) CHARACTER KEYS(NKEY)*4 CHARACTER*15 CODES(5) DATA KEYS/'TITL','SELF','CROS','RESO','CRYS','CELL','LABI', . 'LIMI','PRIN','NOPR','MAP ','PLOT','FIND','READ','SAVE', . 'SUM ','PEAK','JOIN','END',' '/ C DATA CODES/'a,c*xa,c*','b,a*xb,a*','c,b*xc,b*', . 'a+b,c*x(a+b),c*','a*,cxa*,c'/ C C---- NLPRGI = number of input labels C DATA NLPRGI,(LSPRGI(JJ,1),JJ=1,MCOLS) + /5,'H','K','L','F','SIGF',495*' '/ DATA (LSPRGI(JJ,2),JJ=1,MCOLS) + /'H','K','L','F','SIGF',495*' '/ C C C---- This code signs which input columns are essential (LOOKUP) C DATA CTPRGI/'H','H','H','F','Q',495*' '/ DATA LOOKUP/-1,-1,-1,-1,-1,495*0/ DATA FILIN/'HKLIN','HKLIN2'/ C C Set defaults C MAXFILES = 2 NFILES_IN = 0 NFILE = 0 TITLE=' ' FNAME='COEFFS' NCRYST=1 IPHI1=0 IPHI2=180 NPHI=5 IOMEG1=0 IOMEG2=180 NOMEG=5 IKAPA1=0 IKAPA2=180 NKAPA=5 KRKAP1=-1000 KRKAP2=-1000 ARAD=20. EPS=0.0 RESMIN=10000. RESMAX=2. CELL(1,1)=0.0 CELL(1,2)=0.0 DO 2,I=1,2 NCODES(I)=1 LSPGPS(I)=1 TFACS(I)=0. FRMINS(I)=0. FRMAXS(I)=1.0E20 C CEJD CALL ZEROI(SYM(1,1,1,I),16) DO 33,J=1,4 DO 3,K=1,4 3 SYM(K,J,1,I)=0.0 33 SYM(J,J,1,I)=1.0 NSYM(I)=0 2 CONTINUE LPRINT=-100 LMAP=0 LPLOT=0 NCONTR=0 NPEAK=0 NJOIN=0 PEAK=10. MAXPEK=10 LPKRMS=0 LREAD=0 LSAVE=0 LPEAK=0 NOTCAL = .TRUE. C NERR=0 IXTL=1 C C 1 NTOK=NPARM LINE=' ' CALL PARSER( . KEY,LINE,IBEG,IEND,ITYP,FVALUE,CVALUE,IDEC,NTOK,LEND,.TRUE.) C IF(LEND) GO TO 1000 C Ignore blank line IF(NTOK.EQ.0) GO TO 1 C C Make uppercase CALL CCPUPC(KEY) DO 6,K=1,NKEY IF(KEY.EQ.KEYS(K)) GO TO 9 6 CONTINUE C WRITE(6,7) 7 FORMAT(/' Unrecognized keyword'/) NERR=NERR+1 GO TO 1 C DATA KEYS/'TITL','SELF','CROS','RESO','CRYS','CELL','LABI', C . 'LIMI','PRIN','NOPR','MAP ','PLOT','FIND','READ','SAVE', C . 'SUM ','PEAK','JOIN','END',' '/ C 9 GO TO . ( 10, 20, 30, 40, 50, 55, 60, . 70, 80, 90, 100, 110, 120, 130, 140, . 150, 160, 170, 1000, 1000),K C C ******************************************************** C TITLe read title C 10 TITLE=LINE(IBEG(2):) GO TO 1 C C ******************************************************** C SELF, set flag for self rotation, read integration radius ARAD, smoothing C radius EPS C 20 NCRYST=1 C 21 CALL GTPREA(2,ARAD,NTOK,ITYP,FVALUE) CALL GTPREA(3,EPS,NTOK,ITYP,FVALUE) GO TO 1 C C ******************************************************** C CROSS, set flag for self rotation, read integration radius ARAD, smoothing C radius EPS 30 NCRYST=2 GO TO 21 C C ******************************************************** C RESOlution read resolution limits in A, if only one treat as high C resolution limit 40 CONTINUE C read resolution limits in A, if only one treat as high C resolution limit ITOK = 2 C ******************************************************** CALL RDRESO(ITOK,ITYP,FVALUE,NTOK,RESMIN,RESMAX,SMIN,SMAX) C ******************************************************** GO TO 1 C C C C C---- CRYSTAL - subsiduary keywords; FILE SYMM ORTH BFAC FLIMITS C C---- Check command line for C---- subsidiary keyword FILE or NUMBER - crystal number C---- subsidiary keyword ORTH - orthogonalisation code NCODE, C---- subsidiary keyword BFAC - temperature factor B C Fused = Finput * exp(-Bssq/lsq) C---- subsidiary keyword FLIMITS - minimum F and maximum F(order unimportant) C---- subsidiary keyword CELL - a b c ( alpha beta gamma - default = 90.0) C rarely needed - just for peak analysis C C 50 CONTINUE C NOTCAL = .FALSE. C Set defaults F1 = 0.0 F2 = 1.0E20 NCODE = 1 BB = 0.0 C ITOK = 1 51 ITOK = ITOK + 1 IF (ITOK.GT.NTOK) THEN NCODES(IXTL) = NCODE TFACS(IXTL) = BB FRMINS(IXTL) = F1 FRMAXS(IXTL) = F2 GO TO 1 END IF KEY = LINE(IBEG(ITOK) :IEND(ITOK)) CALL CCPUPC(KEY) IF (KEY.EQ.'FILE'.OR.KEY.EQ.'NUMB') THEN ITOK = ITOK + 1 C ******************************** CALL GTPINT(ITOK,IXTL,NTOK,ITYP,FVALUE) C ******************************** C C---- Check if allowed range of files ... 1 to 2 (is this enough ???) C IF (IXTL.LE.0 .OR. IXTL.GT.MAXFILES) THEN WRITE (6,FMT='(a,/,a,i4,a,i2,a,/,a)') + ' Key_Word Error, For CRYSTAL FILE_NUMBER line:-', + ' File_Number Given = ',IXTL, + ' Is invalid only files 1 to ',MAXFILES, + ' Allowed, Ignoring this line -',LINE(1:LENSTR(LINE)) NERR = NERR+1 END IF GO TO 51 END IF C C IF (KEY.EQ.'ORTH') THEN ITOK = ITOK + 1 CALL GTPINT(ITOK,NCODE,NTOK,ITYP,FVALUE) GO TO 51 END IF C IF (KEY.EQ.'BFAC') THEN ITOK = ITOK + 1 CALL GTPREA(ITOK,BB,NTOK,ITYP,FVALUE) GO TO 51 END IF C IF (KEY.EQ.'FLIM') THEN ITOK = ITOK + 1 CALL GTPREA(ITOK,F1,NTOK,ITYP,FVALUE) ITOK = ITOK + 1 CALL GTPREA(ITOK,F2,NTOK,ITYP,FVALUE) IF(F1.LT.F2) GO TO 51 F3 = F1 F1 = F2 F2 = F3 GO TO 51 END IF C IF (KEY.EQ.'SYMM') THEN C SYMMetry read crystal number or space group ITOK = ITOK + 1 C C ************************************************************ CALL RDSYMM(ITOK,LINE,IBEG,IEND,ITYP,FVALUE,ITOK,NAMSGP, + LSPGRP,PGNAME,NSYM(IXTL),NSYMP,SYM(1,1,1,IXTL)) C ************************************************************ C C Only need primitive symmetry operators NSYM(IXTL) = NSYMP LSPGPS(IXTL) = LSPGRP NAMSGS(IXTL) = NAMSGP GO TO 51 END IF C C CELL read cell dimensions - not usually needed. IF (KEY.EQ.'CELL') THEN DO 52 I=4,6 52 CELL(I,IXTL)=90. ITOK = ITOK + 1 CALL GTPREA(ITOK,CELL(1,IXTL),NTOK,ITYP,FVALUE) ITOK = ITOK + 1 CALL GTPREA(ITOK,CELL(2,IXTL),NTOK,ITYP,FVALUE) ITOK = ITOK + 1 CALL GTPREA(ITOK,CELL(3,IXTL),NTOK,ITYP,FVALUE) IF(ITOK.LT.NTOK)THEN ITOK = ITOK + 1 CALL GTPREA(ITOK,CELL(4,IXTL),NTOK,ITYP,FVALUE) ITOK = ITOK + 1 CALL GTPREA(ITOK,CELL(5,IXTL),NTOK,ITYP,FVALUE) ITOK = ITOK + 1 CALL GTPREA(ITOK,CELL(6,IXTL),NTOK,ITYP,FVALUE) END IF GO TO 51 END IF C Unrecognized subkeyword WRITE (6, FMT='(/A,A,A/)') $ ' Key_word Error, unrecognized sub-keyword', $ ' for CRYSTAL command: ',KEY NERR = NERR+1 GO TO 51 C C C---- LABIN (File_Number) "a=b c=d ...." C ========== C 60 CONTINUE ITOK = 2 KEY = LINE(IBEG(ITOK) :IEND(ITOK)) C C ************* CALL CCPUPC(KEY) C ************* C IF (KEY(1:1).EQ.'F') THEN C C---- second arguement = 'FILE_NUMBER' C test if third argument is integer C IF (ITYP(3).NE.2) THEN WRITE (6,FMT='(A,A,/,A,A,A,/,A)') + ' Key_Word Error, Wrong type of input for LABIN',' line:-', + ' If Sub_KeyWord = FILE_NUMBER then ', + 'third Arguement MUST be an Integer Ignoring this', + ' line -',LINE(1:LENSTR(LINE)) NERR = NERR+1 GO TO 10 END IF C C---- For an input file being given C Get File_Number and check if valid C C ******************************** CALL GTPINT(3,NFILE,NTOK,ITYP,FVALUE) C ******************************** C NFILES_IN = NFILES_IN + 1 Cc max(nfiles_in,nfile) C C---- Check if allowed range of files ... 1 to 5 (is this enough ???) C IF (NFILE.LE.0 .OR. NFILE.GT.MAXFILES) THEN WRITE (6,FMT='(a,/,a,i4,a,i2,a,/,a)') + ' Key_Word Error, For LABIN FILE_NUMBER line:-', + ' File_Number Given = ',NFILE, + ' Is invalid only files 1 to ',MAXFILES, + ' Allowed, Ignoring this line -',LINE(1:LENSTR(LINE)) GO TO 10 END IF END IF C C---- Now save labels for this input file C LABIN_SAVE(NFILE) = 'LABIN '//LINE(IBEG(4) :IEND(NTOK)) Cc GOT_LABIN(NFILE) = .TRUE. C C GO TO 1 C C CELL read cell dimensions C 55 CONTINUE GO TO 1 C C C C LIMIts read limits and steps on phi,omega,kappa C 70 CALL GTPINT(2,IPHI1,NTOK,ITYP,FVALUE) CALL GTPINT(3,IPHI2,NTOK,ITYP,FVALUE) CALL GTPINT(4,NPHI,NTOK,ITYP,FVALUE) CALL GTPINT(5,IOMEG1,NTOK,ITYP,FVALUE) CALL GTPINT(6,IOMEG2,NTOK,ITYP,FVALUE) CALL GTPINT(7,NOMEG,NTOK,ITYP,FVALUE) CALL GTPINT(8,IKAPA1,NTOK,ITYP,FVALUE) CALL GTPINT(9,IKAPA2,NTOK,ITYP,FVALUE) CALL GTPINT(10,NKAPA,NTOK,ITYP,FVALUE) GO TO 1 C C PRINt read print threshold C 80 LPRINT=1 CALL GTPINT(2,LPRINT,NTOK,ITYP,FVALUE) GO TO 1 C C NOPRint switch off map print C 90 LPRINT=0 GO TO 1 C C MAP switch to write map to map file C 100 LMAP=1 GO TO 1 C C PLOT read contour start, interval , NOTItle flag C 110 LPLOT=1 C1=10. C2=100. C=10. CALL GTPREA(2,C1,NTOK,ITYP,FVALUE) CALL GTPREA(3,C,NTOK,ITYP,FVALUE) IF(C1.GT.C2.OR.C.LE.0) THEN WRITE(6,9110) C1,C2,C 9110 FORMAT(/' Unreasonable contour limits:',3F10.2/) NERR=NERR+1 GO TO 1 ENDIF C read NOTItle flag to suppress title plotting IF(NTOK.GE.4) THEN CALL CCPUPC(CVALUE(4)) IF(CVALUE(4).EQ.'NOTI') LPLOT=-1 ENDIF NCONTR=1 CONTRS(1)=C1 111 CONTRS(NCONTR+1)=CONTRS(NCONTR)+C IF(CONTRS(NCONTR+1).GT.C2) GO TO 1 NCONTR=NCONTR+1 GO TO 111 C C FIND read peak threshold and maximum number of peaks C optional keyword "RMS" to indicate that threshold is in C multiples of RMS density rather than absolute C optional keyword OUTPUT filename to output unique peak list to file C NB RMS must precede OUTPUT if both are present C 120 CALL GTPREA(2,PEAK,NTOK,ITYP,FVALUE) CALL GTPINT(3,MAXPEK,NTOK,ITYP,FVALUE) MAXPEK=MIN(MAXPEK,MAXNPK) C Process rest of line LPKRMS=0 LPKOUT=0 IF (NTOK .LT. 4) GO TO 1 DO 121, J = 4, NTOK IF (CVALUE(J) .EQ. 'RMS') THEN LPKRMS=1 ELSEIF(CVALUE(J) .EQ. 'OUTP') THEN LPKOUT=1 C Store rest of line as filename if given IF(NTOK .GT. J) THEN PKFNAM=LINE(IBEG(J+1):) GO TO 1 ELSE PKFNAM='PEAKS' ENDIF ENDIF 121 CONTINUE GO TO 1 C C READ set flag to read map in, instead of calculating it C read 1st and last sections to process (kappa values) C 130 LREAD=1 CALL GTPINT(2,KRKAP1,NTOK,ITYP,FVALUE) CALL GTPINT(3,KRKAP2,NTOK,ITYP,FVALUE) IF (KRKAP2.LT.-999) THEN KRKAP2 = KRKAP1 ENDIF IF (KRKAP1 .LT. -999 .OR. KRKAP2 .LT. KRKAP1) THEN WRITE (6, '(A)') ' *** Illegal read limits ***' NERR = NERR+1 ENDIF GO TO 1 C C SAVE read file name for saving ALMN output 140 LSAVE=1 C 141 IF(NTOK.GT.1) THEN FNAME=LINE(IBEG(2):IEND(2)) C&&&VAX !!! C Strip off any existing extension I=INDEX(FNAME,']') J=INDEX(FNAME(I+1:),'.') IF(J.GT.0) FNAME=FNAME(1:J-1) ENDIF GO TO 1 C C SUM read file name for reading previous ALMN results C 150 LSAVE=-1 GO TO 141 C C PEAK read list of peaks omega, phi, kappa from following cards, terminated C by blank line or 'END' C 160 LPEAK=1 NPEAK=0 IF (NTOK .GT. 1) THEN C Test second token to see if it the keyword MATRices CALL CCPUPC(CVALUE(2)) IF (CVALUE(2) .EQ. 'MATR') THEN LPEAK=2 WRITE(6,*) ' Matrices will be output for each peak' ENDIF ENDIF 161 NTOK=NPARM LINE=' ' CALL PARSER( . KEY,LINE,IBEG,IEND,ITYP,FVALUE,CVALUE,IDEC,NTOK,LEND,.TRUE.) C IF(LEND) GO TO 1000 C Make uppercase CALL CCPUPC(KEY) IF(NTOK.LE.0.OR.KEY.EQ.'END') GO TO 1 IF(NPEAK.GE.MAXNPK) THEN WRITE(6,162) MAXNPK 162 FORMAT(/' Too many peaks given, maximum =',I4/) NERR=NERR+1 GO TO 1 ENDIF IF(NTOK.LT.3) THEN WRITE(6,163) 163 FORMAT(/' !!! Three angles must be given !!!') GO TO 161 ENDIF NPEAK=NPEAK+1 CALL GTPREA(1,PKPOS(1,NPEAK),NTOK,ITYP,FVALUE) CALL GTPREA(2,PKPOS(2,NPEAK),NTOK,ITYP,FVALUE) CALL GTPREA(3,PKPOS(3,NPEAK),NTOK,ITYP,FVALUE) LPKORD(NPEAK)=NPEAK GO TO 161 C C C JOIN read peak positions to join up C kappa, omega1, phi1, omega2, phi2, [DASHED repeat dash] C (in fractions of radius) C 170 IF(NJOIN.GE.MXJOIN) THEN WRITE(6,1170) MXJOIN 1170 FORMAT(/' !!!! No more than ',I4,' joins can be stored'//) GO TO 1 ENDIF IF(NTOK.LT.6) THEN WRITE(6,1171) 1171 FORMAT(' Too few numbers for JOIN !!!') NERR=NERR+1 GO TO 1 ENDIF C NJOIN=NJOIN+1 C read kappa CALL GTPREA(2,PEAKJ(3,1,NJOIN),NTOK,ITYP,FVALUE) C Read 2 two sets of omega, phi K=2 DO 171,J=1,2 DO 171,I=1,2 K=K+1 CALL GTPREA(K,PEAKJ(I,J,NJOIN),NTOK,ITYP,FVALUE) 171 CONTINUE C C Check field 7 for keyword DASHed IF(NTOK.GE.7.AND.ITYP(7).EQ.1) THEN CALL CCPUPC(CVALUE(7)) IF(CVALUE(7).EQ.'DASH') THEN C Set default repat and dash length DASH(1,NJOIN)=0.05 DASH(2,NJOIN)=0.025 CALL GTPREA(8,DASH(1,NJOIN),NTOK,ITYP,FVALUE) CALL GTPREA(9,DASH(2,NJOIN),NTOK,ITYP,FVALUE) ELSE C Solid DASH(1,NJOIN)=0.0 ENDIF ENDIF GO TO 1 C C--------------------------------------------------------------------- C C End of input C C Check for errors 1000 IF(NERR.GT.0) THEN WRITE(6,9901) NERR 9901 FORMAT(/1X,I6,' errors in input, see above !!!!'/) CALL CCPERR(1,' error in input') ENDIF C Open MTZ files C---- Open input file for Read; print header... C IF(NFILES_IN .GE.0) THEN WRITE(6,*) ' Using ',NFILES_IN,' files' DO 1005 IFIL=1,NFILES_IN IERR = -1 IPRINT = 2 LOOKUP(1) = -1 LOOKUP(2) = -1 LOOKUP(3) = -1 LOOKUP(4) = -1 LOOKUP(5) = -1 C C ================================== CALL LROPEN(IFIL,FILIN(IFIL),IPRINT,IERR) C ================================== C ERRLIN = 'ERROR:HEADER NOT THERE, ILLEGAL FILE' C C ========================================= IF (IERR.EQ.3) CALL LERROR(2,1,ERRLIN(1:LENSTR(ERRLIN))) C ========================================= C C C Cc line= labin_save(nfile) LINE= LABIN_SAVE(IFIL) C C ====================================================== CALL PARSER(KEY,LINE,IBEG,IEND,ITYP,FVALUE,CVALUE,IDEC,NTOK, + LEND,.TRUE.) CALL LKYIN(IFIL,LSPRGI(1,IFIL),NLPRGI,NTOK,LINE,IBEG,IEND) CALL LRASSN(IFIL,LSPRGI(1,IFIL),NLPRGI,LOOKUP,CTPRGI) C ====================================================== C C ====================== CALL LRCELL(IFIL,CELCHK) C ====================== C check cell IF(CELL(1,IFIL).NE.0.0) THEN ACHK = 0.0 DO 351 II = 1,6 ACHK = ACHK + + ABS(CELCHK(II) - CELL(II,IFIL)) / + (CELCHK(II) + CELL(II,IFIL)) IF (ACHK.GT.0.02)CALL CCPERR(1, + ' Large Difference in CELL DIMENSIONS') IF (ACHK.GT.0.01) WRITE(6,*) + ' Small Difference in CELL DIMENSION' 351 CONTINUE ELSE DO 352 II = 1,6 CELL(II,IFIL) = CELCHK(II) 352 CONTINUE END IF C C---- Find out how many columns in input file? C C ======================================== CALL LRINFO(IFIL,VERSNX,NCOL,NREFTOT,COLRNG) C ======================================== C C Read symmetry and check CALL LRSYMI(IFIL,NSYMP,LTYPE,LSPGRP,NAMSGP,PGNAME) CALL LRSYMM(IFIL,NSM,SYM(1,1,1,IFIL) ) C IF(NSYM(IFIL).EQ.0 )THEN C Only need primitive symmetry operators NSYM(IFIL) = NSYMP LSPGPS(IFIL) = LSPGRP NAMSGS(IFIL) = NAMSGP END IF C IF(NSYM(IFIL).GT.0 .AND. NSYM(IFIL).NE.NSYMP)THEN C Stop CALL CCPERR(1,' Inconsistent symmetry information') END IF C 1005 CONTINUE END IF C DO 1006 IFIL = 1,NCRYST C Call pgdefn to make sure you have a primitive set of symops. C C---- Check NCODE defined C IF (NCODES(IFIL) .LT. 1 .OR. NCODES(IFIL) .GT. 6) THEN WRITE (6, 6101) J 6101 FORMAT(' !!!! Illegal or undefined NCODE for crystal ',I4/) CALL CCPERR(1,' error in ncode') ENDIF C C C Set up fractional to orthogonal matrix RR with appropriate NCODE. CALL RBFRO1(CELL(1,IFIL),VOLL,RR) C DO 1007 I=1,3 DO 1007 J=1,3 RO(I,4)=0.0 RO(4,I)=0.0 RO(I,J)=RR(I,J,NCODES(IFIL)) ORTHOG(I,J,IFIL)=RR(I,J,NCODES(IFIL)) 1007 CONTINUE RO(4,4)=1.0 C C and its inverse CALL RBRINV(RO,RF) DO 1008 I=1,3 DO 1008 J=1,3 FRAC(I,J,IFIL)=RF(I,J) 1008 CONTINUE 1006 CONTINUE C C Check that crystal cards were given and LCF files opened C unless READ or SUM options used IF(NOTCAL.AND.LREAD.EQ.0.AND. . LSAVE.GE.0.AND.LPEAK.EQ.0) THEN WRITE(6,9902) 9902 FORMAT(/' No CRYSTAL card given !!!'/) CALL CCPERR(1,' error in crystal') ENDIF C C If 1 crystal, copy symmetry etc to crystal 2 IF(NCRYST.EQ.1) THEN DO 9903 IS =1,NSYM(1) DO 9903 I =1,4 DO 9903 J =1,4 9903 SYM(I,J,IS,2) = SYM(I,J,IS,1) NSYM(2)=NSYM(1) NCODES(2)=NCODES(1) LSPGPS(2)=LSPGPS(1) CEJD CALL MOVEI(ORTHOG(1,1,2),ORTHOG(1,1,1),9) CEJD CALL MOVEI(FRAC(1,1,2),FRAC(1,1,1),9) DO 9900 I =1,3 DO 9900 J =1,3 ORTHOG(J,I,2) = ORTHOG(J,I,1) 9900 FRAC(J,I,2) = FRAC(J,I,1) ENDIF C C Default title C IF(LENSTR(TITLE).EQ.0) THEN IF(NCRYST.EQ.1) THEN TITLE='Self-rotation function' ELSE TITLE='Cross-rotation function' ENDIF ENDIF C C Print control data C C PEAK option C IF(LPEAK.GT.0) THEN WRITE(6,9101) NPEAK 9101 FORMAT('1 Rotation function peak calculation'/// . ' All symmetry related peaks and matrices will be', . ' calculated for ',I4,' input peaks'//) DO 1050,I=1,NCRYST J = LENSTR(NAMSGS(I)) WRITE(6,9102) I,NCODES(I),CODES(NCODES(I)),LSPGPS(I), . NAMSGS(I)(1:J),NSYM(I) 9102 FORMAT(/' Crystal',I3,': orthogonalisation code (NCODE) =', . I2,' x y z axes along ',A//' Space group ',I4, . ' (',A,'),',I4,' symmetry operations'//) WRITE(6,9103) (CELL(J,I),J=1,6) 9103 FORMAT(' Cell dimensions: ',6F8.2/) 1050 CONTINUE RETURN ENDIF C IF(LREAD.EQ.0) THEN C Set print default if not set explicitly IF(LPRINT.LT.-99) LPRINT=1 IF(NCRYST.EQ.1) THEN WRITE(6,9001) 'Self',TITLE 9001 FORMAT('1',20X, . 'Polar angle rotation function: ',A,'-rotation function'/ . 21X,'======================================================='// . ' Title: ',A//) ELSE WRITE(6,9001) 'Cross',TITLE ENDIF C IF(ARAD.GT.RESMAX*5.83) THEN C Reset maximum resolution to integration radius/5.83 RESMAX=ARAD/5.83 WRITE(6,9002) RESMAX,ARAD 9002 FORMAT(/ . ' !!! Warning !!! maximum resolution reset to', . F10.3,' = integration radius ',F10.3,'/ 5.83'/) ENDIF C WRITE(6,9003) ARAD,RESMIN,RESMAX 9003 FORMAT(/' Integration radius = ',F9.2,'A',20X, . 'Resolution limits ',2F9.2) C IF(EPS.GT.0.) WRITE(6,9004) EPS 9004 FORMAT(/' Radius for averaging (smoothing) ',F10.3) C DO 1010,I=1,NCRYST J=LENSTR(NAMSGS(I)) WRITE(6,9010) I,NCODES(I),CODES(NCODES(I)),LSPGPS(I), . NAMSGS(I)(1:J),NSYM(I),TFACS(I),FRMINS(I),FRMAXS(I) 9010 FORMAT(/' Crystal',I3,': orthogonalisation code (NCODE) =', . I2,' x y z axes along ',A//' Space group ',I4, . ' (',A,'),',I4, . ' symmetry operations'//' Temperature factor = ',F10.3/ . 5X,'Minimum F =',F10.0,' Maximum F = ',G14.4/) WRITE(6,9015) (CELL(J,I),J=1,6) 9015 FORMAT(' Cell dimensions: ',6F8.2/) 1010 CONTINUE C IF(LSAVE.GT.0) THEN L=LENSTR(FNAME) WRITE(6,9011) FNAME(1:L) 9011 FORMAT(/ . ' Output from ALMN stage will be saved in file(s) : ',A) ELSEIF(LSAVE.LT.0) THEN L=LENSTR(FNAME) WRITE(6,9012) FNAME(1:L) 9012 FORMAT(/ . ' Output from ALMN stage will be read from file(s) : ',A) ENDIF C C Check for maximum section size NSECSZ=((IPHI2-IPHI1)/NPHI+1)*((IOMEG2-IOMEG1)/NOMEG+1) IF(NSECSZ.GT.NSMAP) THEN WRITE(6,9050) NSECSZ,NSMAP 9050 FORMAT(//' Section size too large, =',I8, . ' maximum=',I8///) CALL CCPERR(1,' error in section') ENDIF ELSE C READ option WRITE(6,9020) TITLE 9020 FORMAT(/ . ' Previously calculated map will be read from MAPIN'// . ' Title: ',A/) C no save, no map output LSAVE=0 LMAP=0 ENDIF C C END C************************************************************************ C******************* ND500-ALMN ********************** W.KABSCH 10-1982 C************************************************************************ C************************* FILES **************************************** C SUBROUTINE CALMN C =============== C C C OUTPUT FILE C ----------- C THE OUTPUT DATA FILE CONTAINS BINARY DATA AS FOLLOWS: C C L,M,N,ALMNR,ALMNI C C L,M,N ARE THE INDICES OF THE SPHERICAL HARMONIC COEFFICIENT. C THE LAST RECORD HAS L=10000 TO INDICATE THE END OF VALID C DATA ON FILE. C ALMNR, ARE REAL AND IMAGINARY PART OF SPHERICAL HARMONIC C ALMNI EXPANSION COEFFICIENT C C ---------- C C PARAMETERS C ARAD RADIUS (ANGSTROM) OF CUT-OFF SPHERE IN C PATTERSON FUNCTION. THIS PROGRAM ALLOWS A C LARGEST VALUE FOR L OF 30. THIS LEADS TO THE C CONDITION ARAD ',60A) C C IF(IFIRST.EQ.0) THEN C--Setting arrays PHIMK() and OMEGMK() for marker lines. NBMK=1+((IOMEG2-IOMEG1)/NOMEG) DO 2146 IMK=1,NBMK OMEGMK(IMK)=IOMEG1+NOMEG*(IMK-1) 2146 CONTINUE NAMK=1+((IPHI2-IPHI1)/NPHI) DO 2148 IMK=1,NAMK PHIMK(IMK)=IPHI1+NPHI*(IMK-1) 2148 CONTINUE IFIRST=1 ENDIF C C C Write out section C L=LALF*(LBET-1)+1 SMAX=-1000. C WRITE(6,1020)JKAPA WRITE(6,1028) WRITE(6,1030) (OMEGMK(IMK),IMK=1,NBMK) IT=' V' WRITE(6,1031) (IT,IMK=1,NBMK) DO 660 J1=1,LALF KPR=0 DO 2341 J2=1,L,LALF R=RROT(J1+J2-1) IF(R.GT.SMAX) THEN SMAX=R J1M=J1 J2M=(J2-1)/LALF ENDIF N9=NINT(R) IF(N9.LT.0) THEN IT=' -' ELSEIF(N9.LT.LPRINT) THEN IT=' .' ELSE WRITE(IT,2009) N9 2009 FORMAT(I3) ENDIF KPR=KPR+1 LPRNT(KPR)=IT 2341 CONTINUE 660 WRITE(6,1057) PHIMK(J1),(LPRNT(J2),J2=1,KPR) IT=' ^' WRITE(6,1031) (IT,IMK=1,NBMK) WRITE(6,1030) (OMEGMK(IMK),IMK=1,NBMK) C J1=(J1M-1)*NPHI+IPHI1 J2=J2M*NOMEG+IOMEG1 WRITE(6,1035) SMAX,J2,J1 1035 FORMAT(/' Maximum on this section = ',F8.1,' at omega =',I4, . ' phi =',I4) RETURN END C C SUBROUTINE MAPRED C ================= C C Read back file of rotation function for plotting etc C Use sections KRKAP1 to KRKAP2 C COMMON /ALMFRF/ NCRYST,IPHI1,IPHI2,NPHI,IOMEG1,IOMEG2,NOMEG, . IKAPA1,IKAPA2,NKAPA,ARAD,EPS,RESMIN,RESMAX,NCODES(2),LSPGPS(2), . TFACS(2),FRMINS(2),FRMAXS(2),LPRINT,LMAP,LPLOT,CONTRS(50), . NCONTR,LREAD,LSAVE,PEAK,MAXPEK,LPKRMS,KRKAP1,KRKAP2, . RMIN,RMEAN,RRMS,RWT,NPOINT CHARACTER*80 TITLE,FNAME,QTITLE COMMON /TEXTC/ TITLE,FNAME C C Maximum section size PARAMETER (NSMAP=33759) C DIMENSION IUVW(3),MXYZ(3),DCELL(6),RROT(NSMAP) C C Open map file CALL MRDHDR(3,'MAPIN',QTITLE,NSEC,IUVW,MXYZ,IKAPA1, . IPHI1,NU2,IOMEG1,NV2,DCELL,LS,LMODE,RMIN,RMAX,RMEAN,RRMS) C C Keep input title if specified IF(TITLE.EQ.' ') TITLE=QTITLE C Set parameters from file. See FRFSUM for comments on what is in map header NPHI=360/MXYZ(1) NOMEG=360/MXYZ(2) NKAPA=360/MXYZ(3) NU=NU2-IPHI1+1 NV=NV2-IOMEG1+1 IKAPA2=IKAPA1+(NSEC-1)*NKAPA IPHI2=IPHI1+(NU-1)*NPHI IOMEG2=IOMEG1+(NV-1)*NOMEG IF(KRKAP1.LT.-999) KRKAP1=IKAPA1 IF(KRKAP2.LT.-999) KRKAP2=IKAPA2 C Check for maximum section size NSECSZ=NU*NV IF(NSECSZ.GT.NSMAP) THEN WRITE(6,9050) NSECSZ,NSMAP 9050 FORMAT(//' Section size too large, =',I8, . ' maximum=',I8///) CALL CCPERR(1,' error on section 9050') ENDIF C C Read sections KRkap1 to KRkap2 C C Corrected next line 3/3/87 PRE JSEC=(KRKAP1-IKAPA1)/NKAPA+IKAPA1 CALL MPOSN(3,JSEC) DO 10,JKAPA=KRKAP1,KRKAP2,NKAPA CALL MGULP(3,RROT,IER) IF(IER.NE.0) GO TO 11 C Print section IF(LPRINT.GT.0) CALL PRNSEC(RROT,NU,NV,JKAPA) C Plot and find peaks as required CALL MAPSEC(RROT,NU,NV,JKAPA) 10 CONTINUE C 11 CALL MAPSEC(RROT,NU,NV,-1) CALL PPEAKS RETURN END C C SUBROUTINE MAPSEC(RROT,LA,LB,IG) C ================================ C C Deal with section kappa = IG in RROT. C C 1. write out map section to map file if LMAP .gt. 0 C C 2. plot if LPLOT .ne. 0 C C 3. search for peaks in PREVIOUS section: if IG=-1 search last section CEJD LA - number of points along Phi CEJD LB - number of points along Omega - iomeg1,ipmeg2,nomeg CEJD IG = Kappa C C DIMENSION RROT(LA,LB) C COMMON /ALMFRF/ NCRYST,IPHI1,IPHI2,NPHI,IOMEG1,IOMEG2,NOMEG, . IKAPA1,IKAPA2,NKAPA,ARAD,EPS,RESMIN,RESMAX,NCODES(2),LSPGPS(2), . TFACS(2),FRMINS(2),FRMAXS(2),LPRINT,LMAP,LPLOT,CONTRS(50), . NCONTR,LREAD,LSAVE,PEAK,MAXPEK,LPKRMS,KRKAP1,KRKAP2, . RMIN,RMEAN,RRMS,RWT,NPOINT C COMMON /RHMOUT/ WRMEAN, WRMS SAVE /RHMOUT/, RMAP REAL WRMEAN, WRMS C C Maximum section size PARAMETER (NSMAP=33759) C DIMENSION PLTMAP(NSMAP),RMAP(3*NSMAP) C C IF(IG.LT.0) THEN IF (LMAP .GT. 0) THEN C Close map file if required CALL MCLOSC(4,RMIN,100., WRMEAN, WRMS) ENDIF C Close plot file if required IF(LPLOT.NE.0) CALL PLTSTP GO TO 10 ENDIF C IF(LMAP.GT.0) THEN C Write map section to map file CALL MSPEW(4,RROT) ENDIF C IF(LPLOT.NE.0) THEN C Plot section NLA=360/NPHI+1 NLB=90/NOMEG+1 IF(NLA*NLB.GT.NSMAP) CALL CCPERR(1, 'stop NSMAP!!!') CALL PLOTMP(RROT,LA,LB,IG,PLTMAP,NLA,NLB) ENDIF C C Pick peaks on PREVIOUS section 10 IF(LA*LB.GT.NSMAP) CALL CCPERR(1, 'stop-10 NSMAP!!!') CALL PEAKPK(RROT,LA,LB,IG,RMAP) C RETURN END C C C SUBROUTINE PLOTMP(RROT,LA,LB,IG,PLTMAP,NLA,NLB) C ============================================ C C Plot section as stereogram C C First generate array PLTMAP, using symmetry as necessary, C then plot (this part of program taken from RFPLOT) C If LPLOT .lt. 0, don't plot any labels C C In the absence of symmetry, each kappa section is plotted as C two hemispheres omega = 0 to 90, and 90 to 180. Subroutine C CHKSYM works out the symmeytry of the rotation function, and sets C flag LSYMFG to indicate whether one or two hemispheres need to C be plotted. LSYMFG = 2 no symmetry, plot both hemispheres C = 1 symmetry sufficient to reduce asymmetric unit C to one hemisphere C =-2 asymmetric unit omega = 0 to 180, phi = 0 to 180 C plot two quarter spheres in same circle C C DIMENSION RROT(LA,LB),PLTMAP(NLB,NLA) C COMMON /MATRIX/ ORTHOG(3,3,2),FRAC(3,3,2),SYM(4,4,192,2),NSYM(2), . MRSYM,JRSYM(3,3,12),LSYMFG,LHALF C COMMON /ALMFRF/ NCRYST,IPHI1,IPHI2,NPHI,IOMEG1,IOMEG2,NOMEG, . IKAPA1,IKAPA2,NKAPA,ARAD,EPS,RESMIN,RESMAX,NCODES(2),LSPGPS(2), . TFACS(2),FRMINS(2),FRMAXS(2),LPRINT,LMAP,LPLOT,CONTRS(50), . NCONTR,LREAD,LSAVE,PEAK,MAXPEK,LPKRMS,KRKAP1,KRKAP2, . RMIN,RMEAN,RRMS,RWT,NPOINT CHARACTER*80 TITLE,FNAME COMMON /TEXTC/ TITLE,FNAME C PARAMETER (IPTMAX=200) DIMENSION XXX(IPTMAX),YYY(IPTMAX) C Maximum section size PARAMETER (NSMAP=33759) C LOGICAL BITS(2*NSMAP) C CHARACTER*80 LINE SAVE IFIRST C C Set up plotting viewport and window C C Relative character sizes for tick marks and titles REAL CSZ1, CSZ2 REAL VWPORT(2,2), WINDOW(2,2) C WINDOW are the corresponding coordinates in user units, which C set radius of stereogram = 1 C x1 y1 x2 y2 DATA WINDOW/ -1.3, -1.3, 1.3, 1.3/ C DATA CSZ1, CSZ2/0.8,1.1/ C C VWPORT are corners of plotting space in range 0-1 on x & y C x1 y1 x2 y2 DATA VWPORT/ 0.05, 0.05, 0.95, 0.95/ DATA IFIRST/0/ C CHSZ = 0 C IF(IOMEG1.LT.0.OR.IOMEG2.GT.180) THEN WRITE(6,1001) IOMEG1,IOMEG2 1001 FORMAT(/' Plotting routine cannot cope with omega outside', . ' range 0 to 180, omega limits =',2I5/) RETURN ENDIF C C On first entry, start plotting C IF(IFIRST.EQ.0) THEN CALL PLTINI C Set plotting transform CALL PLTWIN(VWPORT, WINDOW) C Find rotation function symmetry from crystal symmetries CALL CHKSYM ENDIF C C C If necessary, loop for two halves of kappa section C LSYMFG = 1,2 or -2 see above C Kappa = 180 has symmetry type 1 (180-omega, 180+phi) NHALF=IABS(LSYMFG) IF(IG.EQ.180) THEN NHALF=1 C Add symmetry type 1 if not already present IF(NCRYST.EQ.2) THEN MRSYM=MRSYM+1 CALL SETSYM(JRSYM(1,1,MRSYM),1) ENDIF ENDIF C DO 200,LHALF=1,NHALF C C Copy appropriate part of RROT to PLTMAP using symmetry as necessary C First define limits required on omega(omeg) and phi(phi) in PLTMAP IF(LHALF.EQ.1) THEN IB1=0 IB2=90 ELSE IB1=90 IB2=180 ENDIF IF(LSYMFG.LT.0.AND.IG.NE.180) THEN C LSYMFG = -2, plot 2 half hemispheres in same circle MLA=(NLA+1)/2 IA1=0 IA2=180 LSPLIT=1 ELSE MLA=NLA IA1=0 IA2=360 LSPLIT=0 ENDIF C Cejd CALL ZEROI(PLTMAP,MLA*NLB) DO 201 JPLT = 1,NLB DO 201 IPLT = 1,MLA 201 PLTMAP(JPLT,IPLT) = 0 C C Loop points in output array PLTMAP KB=1 DO 11,IB=IB1,IB2,NOMEG KA=1 DO 12,IA=IA1,IA2,NPHI C Put point IA,IB into calculated area if possible: if not JA=0 CALL SYMPUT(JA,JB,IA,IB) IF(JA.GT.0) PLTMAP(KB,KA)=RROT(JA,JB) KA=KA+1 12 CONTINUE KB=KB+1 11 CONTINUE C C Start new picture except for LSYMFG=-2 IF(LHALF.EQ.1.OR.LSYMFG.GT.1) THEN IF (IFIRST .NE. 0) CALL PLTPIC IFIRST=1 C C C Now draw the ring around the edge, using a do loop of drawto's C CONV=360./6.28318 CALL PLTMVU(1.,0.) DO 110 K=1,101 FI=(3.60*FLOAT(K-1))/CONV CALL PLTDWU(COS(FI),SIN(FI)) 110 CONTINUE C C Plot tick marks TICK=0.01 CALL PLTMVU(1.,0.) CALL PLTDBU(TICK,0.) IF(LPLOT.GT.0) THEN CALL PLTTNF(1.+2.*TICK,0.,X,Y) CALL PLTCTX('0.0',X,Y,CSZ1,1,0.0) ENDIF C CALL PLTMVU(0.,1.) CALL PLTDBU(0.,TICK) IF(LPLOT.GT.0) THEN CALL PLTTNF(0.,1.+4.*TICK,X,Y) IF(LSPLIT.GT.0) THEN CALL PLTCTX( . '90.0, omega 0 to 90',X,Y,CSZ1,1,0.0) ELSE CALL PLTCTX('90.0',X,Y,CSZ1,2,0.0) ENDIF ENDIF C CALL PLTMVU(-1.,0.) CALL PLTDBU(-TICK,0.) IF(LPLOT.GT.0) THEN CALL PLTTNF(-1.-2.*TICK,0.,X,Y) CALL PLTCTX('180.0',X,Y,CSZ1,3,0.0) ENDIF C CALL PLTMVU(0.,-1.) CALL PLTDBU(0.,-TICK) IF(LPLOT.GT.0) THEN CALL PLTTNF(0.,-1.-4.*TICK-CHSZ,X,Y) IF(LSPLIT.GT.0) THEN CALL PLTCTX( . '90.0, omega 90 to 180',X,Y,CSZ1,1,0.0) ELSE CALL PLTCTX('-90.0',X,Y,CSZ1,2,0.0) ENDIF ENDIF C C Draw line across section IF(LSPLIT.GT.0) THEN CALL PLTMVU(1.,0.) CALL PLTDWU(-1.,0.) ENDIF C Plot title centred on 0,-1.1 IF(LPLOT.GT.0) THEN CALL PLTTNF(0.,-1.14,X,Y) CALL PLTCTX(TITLE,X,Y,CSZ2,2,0.0) XX=0. IF(LSYMFG.EQ.2) XX=-0.8 CALL PLTTNF(XX,-1.24,X,Y) WRITE (LINE, 6001) IG 6001 FORMAT('Section kappa = ',I4) L = LENSTR(LINE) + 1 IF(LSYMFG.EQ.2) THEN LINE(L:) = . ', omega = 0 to 90, omega = 90 to 180' ENDIF L = LENSTR(LINE) CALL PLTCTX(LINE(1:L),X,Y,CSZ2,2,0.0) ENDIF ENDIF C C Plot join lines (if any) CALL PLJOIN(IG,NPHI,NOMEG) C C Set solid lines for contour CALL PLTDSH(0,0.,0.,0.) C CALL HPCNTR(PLTMAP,NLB,MLA,BITS,CONTRS,NCONTR,XXX,YYY,IPTMAX) C C 200 CONTINUE C C C- - - - -- - - - - - - - - - - - - - - - - - - - - - - - C Remove special symmetry for kappa=180 IF(NCRYST.EQ.2.AND.IG.EQ.180) MRSYM=MRSYM-1 C RETURN END C C SUBROUTINE PLJOIN(IG,NPHI,NOMEG) C ================================= C C Plot JOIN lines for section kappa=IG C NPHI sampling interval in degrees along phi C NOMEG sampling interval in degrees along omega C C Lines are drawn between specified points along the great circle C JOIN stuff PARAMETER (MXJOIN=30) COMMON /VJOIN/ NJOIN,PEAKJ(3,2,MXJOIN),DASH(2,MXJOIN) SAVE /VJOIN/ C PEAKJ(I,J,K) contains peaks C I=1,2,3 omega, phi, kappa C J=1,2 point 1, point 2 (kappa2=kappa1) C DIMENSION P(3),Q(3),R(3),T(3,3),TINV(3,3),V1(3),V2(3) C C Line buffer PARAMETER (MAXLIN=200) DIMENSION X(MAXLIN),Y(MAXLIN) C C CONV=ATAN(1.)/45. C DO 1,K=1,NJOIN C Check all joins, is this one in current kappa section? IF(NINT(PEAKJ(3,1,K)).NE.IG) GO TO 1 C C We have a peak pair K C Direction cosines of points 1 & 2 CALL DRCCOS(V1,PEAKJ(1,1,K)) CALL DRCCOS(V2,PEAKJ(1,2,K)) C Define coordinate frame pqr with great circle perpendicular to z C Put p axis along x CALL VSET(P,V1) C r axis orthogonal to V1 and V2 CALL CROSS(R,V1,V2) CALL UNIT(R) C q axis completes set CALL CROSS(Q,R,P) CALL UNIT(Q) C Transformation matrix T takes point in pqr frame to xyz CALL VSET(T(1,1),P) CALL VSET(T(1,2),Q) CALL VSET(T(1,3),R) C Invert (transpose) T CALL TRANSP(TINV,T) C C Theta is angle in great circle from p (V1) towards q (v2) C Point 1 (V1) is at theta=0 C Get theta for point 2 CALL MATVEC(V1,TINV,V2) THETA2=ATAN2(V1(2),V1(1)) C Stepsize in radians VSTEP=SIGN(0.02,THETA2) N=NINT(ABS(THETA2)/VSTEP) VSTEP=THETA2/FLOAT(N) NSTEP=N+1 IF(NSTEP.GT.MAXLIN) THEN WRITE(6,1001) MAXLIN 1001 FORMAT(' More than',I6,'lines in PLJOIN') NSTEP=MAXLIN ENDIF C C Loop to draw line between points DO 10,N=1,NSTEP THETA=(N-1)*VSTEP P(1)=COS(THETA) P(2)=SIN(THETA) P(3)=0.0 CALL MATVEC(V1,T,P) SOMEGA=SQRT(V1(1)**2+V1(2)**2) C Store lines, x = omega, y= phi, stored as grid units to match what comes C out of the contour routine X(N)=ATAN2(SOMEGA,V1(3))/(CONV*NOMEG) IF(ABS(V1(1)).LT.0.000001.AND.ABS(V1(1)).LT.0.000001) THEN Y(N)=0.0 ELSE Y(N)=ATAN2(V1(2),V1(1))/(CONV*NPHI) ENDIF 10 CONTINUE C C Set dash parameters IF(DASH(1,K).EQ.0.) THEN C Solid M=0 ELSE C Dashed M=1 ENDIF CALL PLTDSH(M,DASH(1,K),DASH(2,K),0.) C Plot CALL LINES(X,Y,NSTEP) C 1 CONTINUE RETURN END C C C SUBROUTINE DRCCOS(V,P) C ====================== C C Set dircetion cosines V of axis along omega = P(1), phi = P(2) C DIMENSION V(3),P(2) C CONV=ATAN(1.)/45. C OMEGA=P(1)*CONV PHI=P(2)*CONV C SOMEGA=SIN(OMEGA) V(1)=SOMEGA*COS(PHI) V(2)=SOMEGA*SIN(PHI) V(3)=COS(OMEGA) RETURN END C C C SUBROUTINE CHKSYM C ================= C C Check symmetry of the two crystals and set up symmetry of rotation function C C Sets MRSYM number of symmetry operations C JRSYM rotation function symmetry operators, matrices to multiply C (omega phi 1) in degrees. C C Possible operations arise as follows: C C 1. 180-omega, 180+phi self-rotation C C 2. 180-omega, -phi x dyads in both crystals C C 3. 180-omega, 180-phi y dyads in both crystals C C 4. omega, 180+phi z dyads in both crystals C C Other operations may arise as combinations of these C COMMON /MATRIX/ ORTHOG(3,3,2),FRAC(3,3,2),SYM(4,4,192,2),NSYM(2), . MRSYM,JRSYM(3,3,12),LSYMFG,LHALF C COMMON /ALMFRF/ NCRYST,IPHI1,IPHI2,NPHI,IOMEG1,IOMEG2,NOMEG, . IKAPA1,IKAPA2,NKAPA,ARAD,EPS,RESMIN,RESMAX,NCODES(2),LSPGPS(2), . TFACS(2),FRMINS(2),FRMAXS(2),LPRINT,LMAP,LPLOT,CONTRS(50), . NCONTR,LREAD,LSAVE,PEAK,MAXPEK,LPKRMS,KRKAP1,KRKAP2, . RMIN,RMEAN,RRMS,RWT,NPOINT C DIMENSION JRMAT(3,3),LDYAD(24,2),LPERM(4) DATA LPERM/2,3,1,2/ C C Starting flags for no symmetry LSYMFG=2 MRSYM=0 C C Is this a self rotation function? IF(NCRYST.EQ.1) THEN MRSYM=1 LSYMFG=1 CALL SETSYM(JRSYM(1,1,1),1) ENDIF C C Find out which crystal symmetry operations are dyads DO 10,K=1,NCRYST DO 11,L=1,NSYM(K) LDYAD(L,K)=0 C A dyad matrix is diagonal with Trace = -1 TRACE=0. DO 12,I=1,3 12 TRACE=TRACE+SYM(I,I,L,K) IF(ABS(TRACE+1.).GT.0.0001) GO TO 11 C Trace=-1, check off diagonals M=0 DO 13,I=1,3 IF(SYM(I,I,L,K).GT.0.) M=I DO 13,J=1,3 IF(I.NE.J) THEN IF(ABS(SYM(I,J,L,K)).GT.0.0001) GO TO 11 ENDIF 13 CONTINUE C Yes we have a dyad along axis M C Allow for axis permutation from NCODE = 2 or 3 IF(NCODES(K).EQ.2) THEN M=LPERM(M+1) ELSEIF(NCODES(K).EQ.3) THEN M=LPERM(M) ENDIF LDYAD(L,K)=M C If self-rotation, dyads must be paralle in the two crystals IF(NCRYST.EQ.1) THEN C so add symmetry to list MRSYM=MRSYM+1 CALL SETSYM(JRSYM(1,1,MRSYM),M+1) ENDIF 11 CONTINUE 10 CONTINUE C C Now check for parallel dyads in the 2 crystals for cross-rotation IF(NCRYST.EQ.2) THEN C Loop 1st crystal operations DO 21,L=1,NSYM(1) IF(LDYAD(L,1).GT.0) THEN C Check 2nd crystal DO 22,K=1,NSYM(2) IF(LDYAD(K,2).EQ.LDYAD(L,1)) THEN C We have parallel dyads, so add symmetry M=LDYAD(L,1)+1 MRSYM=MRSYM+1 CALL SETSYM(JRSYM(1,1,MRSYM),M) C Set asymmetric unit flag IF(M.LE.3) THEN LSYMFG=1 ELSEIF(LSYMFG.EQ.2) THEN LSYMFG=-2 ENDIF ENDIF 22 CONTINUE ENDIF 21 CONTINUE ENDIF C C C We now have MRSYM symmetry operations: see if combinations generate C any new ones IF(MRSYM.LE.1) RETURN C Loop pairs of operations: any new ones generated need not be tested MRS=MRSYM DO 100,K=1,MRS-1 DO 110,L=K+1,MRS CALL MATMLI(JRMAT,JRSYM(1,1,L),JRSYM(1,1,K)) C 'Translations' can have 360 added or subtracted to bring into range 0 to 180 DO 111,I=1,2 J=JRMAT(I,3) IF(J.GT.359) J=J-360 IF(J.LT.-179) J=J+360 JRMAT(I,3)=J 111 CONTINUE C Check if we already have the same matrix DO 121,M=1,MRSYM DO 120,I=1,3 DO 120,J=1,3 IF(JRMAT(I,J).NE.JRSYM(I,J,M)) GO TO 121 120 CONTINUE C Same as this matrix M so ignore GO TO 110 121 CONTINUE C C New one, so add to list MRSYM=MRSYM+1 DO 125,I=1,3 DO 125,J=1,3 125 JRSYM(I,J,MRSYM)=JRMAT(I,J) C 110 CONTINUE 100 CONTINUE RETURN END C C C SUBROUTINE SETSYM(JRSYM,M) C ========================== C C Set symmetry matrix JRSYM to symmetry type M C C 1. 180-omega, 180+phi self-rotation C C 2. 180-omega, -phi x dyads in both crystals C C 3. 180-omega, 180-phi y dyads in both crystals C C 4. omega, 180+phi z dyads in both crystals C DIMENSION JRSYM(3,3) C IF(M.LE.0) RETURN C DO 1,I=1,3 DO 1,J=1,3 1 JRSYM(I,J)=0 JRSYM(3,3)=1 C IF(M.EQ.1) THEN C 180-omega, 180+phi JRSYM(1,1)=-1 JRSYM(1,3)=180 JRSYM(2,2)=+1 JRSYM(2,3)=180 ELSEIF(M.EQ.2) THEN C 180-omega, -phi JRSYM(1,1)=-1 JRSYM(1,3)=180 JRSYM(2,2)=-1 JRSYM(2,3)=0 ELSEIF(M.EQ.3) THEN C 180-omega, 180-phi JRSYM(1,1)=-1 JRSYM(1,3)=180 JRSYM(2,2)=-1 JRSYM(2,3)=180 ELSEIF(M.EQ.4) THEN C omega, 180+phi JRSYM(1,1)=1 JRSYM(1,3)=0 JRSYM(2,2)=1 JRSYM(2,3)=180 ENDIF C RETURN END C C C SUBROUTINE SYMPUT(JA,JB,IA,IB) C ============================== C C Put point IA, IB (phi, omega values in degrees) into calculated C area, using symmetry if required, return array index JA, JB. C If no corresponding point, return JA=0 C COMMON /MATRIX/ ORTHOG(3,3,2),FRAC(3,3,2),SYM(4,4,192,2),NSYM(2), . MRSYM,JRSYM(3,3,12),LSYMFG,LHALF C COMMON /ALMFRF/ NCRYST,IPHI1,IPHI2,NPHI,IOMEG1,IOMEG2,NOMEG, . IKAPA1,IKAPA2,NKAPA,ARAD,EPS,RESMIN,RESMAX,NCODES(2),LSPGPS(2), . TFACS(2),FRMINS(2),FRMAXS(2),LPRINT,LMAP,LPLOT,CONTRS(50), . NCONTR,LREAD,LSAVE,PEAK,MAXPEK,LPKRMS,KRKAP1,KRKAP2, . RMIN,RMEAN,RRMS,RWT,NPOINT C C INSIDE is a statement function to decide if a point is inside the C area calculated LOGICAL INSIDE INSIDE(LA,LB)=(LA.GE.IPHI1.AND.LA.LE.IPHI2).AND. . (LB.GE.IOMEG1.AND.LB.LE.IOMEG2) C C DO 10,L=0,MRSYM C IF(L.EQ.0) THEN C Identity IAA=IA IBB=IB ELSE IAA=JRSYM(2,2,L)*IA+JRSYM(2,3,L) IBB=JRSYM(1,1,L)*IB+JRSYM(1,3,L) ENDIF C IF(INSIDE(IAA,IBB)) GO TO 100 C Check 'translations' on phi IF(IAA.GT.0) THEN IAA=IAA-360 ELSE IAA=IAA+360 ENDIF IF(INSIDE(IAA,IBB)) GO TO 100 10 CONTINUE C C Not found JA=0 RETURN C C Valid point found, calculate array indices 100 JA=(IAA-IPHI1)/NPHI+1 JB=(IBB-IOMEG1)/NOMEG+1 RETURN END C C C SUBROUTINE HPCNTR (A,M,N,BITS,CONT,NCONT,X,Y,IPTMAX) C C*************************************** C C CONTUR ROUTINE C C*************************************** C C A IS FUNCTION TO BE CONTOURED, DIMENSIONED A(M,N) OR A(M*N) C M = NUMBER OF ROWS OF A C N = NUMBER OF COLUMN C BITS IS LOGICAL ARRAY DIMENSIONED AT LEAST 2*M*N IN CALLING ROUTINE. C CONT ARRAY OF NCONT CONTOUR LEVELS C X,Y ARRAYS OF DIMENSION IPTMAX USED IN SUBROUTINE TO STORE CONTOUR LINES C C IDIV = NUMBER OF LINE SEGMENTS BETWEEN CONTOUR LEVEL CROSSINGS IN UNIT GRID C CELL. IF >= 1, THEN ROUTINE FINDS IDIV-1 COORDINATES BETWEEN CROSSINGS, C BY LINEAR INTERPOLATION ON THE UNIT CELL. C CONTUR OUTPUT VIA CALLS TO SUBROUTINE APLOT (X,Y,IPT) C X,Y ARE COORDINATES WITH 0<=XP(10), = a,b,c,d,e,f,g,h,i,j C C p = [ (AT A)**-1 AT ] r C where (AT A)**-1 AT = SMAT is calculated in PKSETM C r = PEAKMX, observation vector C Note that in PKSETM, the order of grid points corresponding to the rows C of matrix A must correspond to the order of values in PEAKMX, ie x fast, C y medium, z slow C CALL GMPRD (SMAT, PEAKMX, P, NP, NG, 1) C C Set up matrix B and vector g for solving position of maximum from the C paraboloid parameters C C ( 2a d f ) ( -g ) C B = ( d 2b e ) g = ( -h ) C ( f e 2c ) ( -i ) C C Then position of maximum OFFSET = x = B**-1 g C B(1,1) = 2. * P(1) B(1,2) = P(4) B(2,1) = P(4) B(1,3) = P(6) B(3,1) = P(6) B(2,2) = 2. * P(2) B(2,3) = P(5) B(3,2) = P(5) B(3,3) = 2. * P(3) C G(1) = -P(7) G(2) = -P(8) G(3) = -P(9) C C Invert B CALL MINVN(B, 3, DET, W1, W2) IF (DET .EQ. 0.0) THEN CALL CCPERR(1, 'PKFITP: singular matrix') ENDIF C CALL GMPRD(B, G, OFFSET, 3, 3, 1) C ISTAT = 0 DO 50, I = 1, 3 IF (ABS(OFFSET(I)) .GT. OFFMAX) THEN C Reset to maximum, set flag ISTAT = 1 OFFSET(I) = SIGN(OFFMAX, OFFSET(I)) ENDIF 50 CONTINUE C RETURN END C SUBROUTINE SORT1(N,A0,A1) C ========================= C C**** C**** N IS THE LENGTH OF THE ARRAY TO BE SORTED I.E. THE NUMBER OF C**** ITEMS TO BE SORTED C**** THE ELEMENTS OF ARRAY A0(N) ARE SORTED INTO INCREASING ORDER OF C**** MAGNITUDE. ARRAYS A1 MAY BE CARRIED WITH A0 AS REQUIRED C**** DIMENSION A0(N),A1(N) INTEGER A1 C NO2 = N/2 DO 100 I=1,NO2 C = A0(I) D = C IH = I K = I IP1 = I+1 NP1 = N+1-I DO 20 J=IP1,NP1 A = A0(J) IF ( A.GE.C ) GO TO 15 IH = J C = A GO TO 20 15 IF ( D.GE.A ) GO TO 20 D = A K = J 20 CONTINUE IF ( C.EQ.D ) GO TO 200 IF ( IH.EQ.I ) GO TO 30 C = A1(IH) A1(IH) = A1(I) A1(I) = C C = A0(IH) A0(IH) = A0(I) A0(I) = C 30 IF ( K.EQ.I ) K=IH IF ( K.EQ.NP1 ) GO TO 100 D = A1(K) A1(K) = A1(NP1) A1(NP1) = D D = A0(K) A0(K) = A0(NP1) A0(NP1) = D 100 CONTINUE 200 RETURN END C C C SUBROUTINE PPEAKS C ================= C C Print all peaks found C COMMON /MATRIX/ ORTHOG(3,3,2),FRAC(3,3,2),SYM(4,4,192,2),NSYM(2), . MRSYM,JRSYM(3,3,12),LSYMFG,LHALF COMMON /ALMFRF/ NCRYST,IPHI1,IPHI2,NPHI,IOMEG1,IOMEG2,NOMEG, . IKAPA1,IKAPA2,NKAPA,ARAD,EPS,RESMIN,RESMAX,NCODES(2),LSPGPS(2), . TFACS(2),FRMINS(2),FRMAXS(2),LPRINT,LMAP,LPLOT,CONTRS(50), . NCONTR,LREAD,LSAVE,PEAK,MAXPEK,LPKRMS,KRKAP1,KRKAP2, . RMIN,RMEAN,RRMS,RWT,NPOINT C COMMON /PKFILE/ PKFNAM CHARACTER*80 PKFNAM SAVE /PKFILE/ C CHARACTER*80 TITLE,FNAME COMMON /TEXTC/ TITLE,FNAME C PARAMETER (MAXNPK=100) COMMON /PEAKS/ NPEAK,PEAKS(MAXNPK),PKPOS(3,MAXNPK),LPEAK, . LPKORD(MAXNPK),LPKOUT C DIMENSION AMINV(4,4) DIMENSION ARSYM(3,3,24,2),AJUNK4(3,3),TRSYM(3,3) 1 ,TRMAT(3,3),DC(5),AJUNK2(3,3),AJUNK3(3,3),AJUNK1(3,3) REAL EPKPOS(3,MAXNPK),PKHGHT(MAXNPK) C CHARACTER*15 CODES(5) EXTERNAL MATMUL DATA CODES/'a,c*xa,c*','b,a*xb,a*','c,b*xc,b*', . 'a+b,c*x(a+b),c*','a*,cxa*,c'/ C IF (NPEAK .LE. 0) RETURN C IF (LPEAK .LE. 0) THEN C Sort reflection pointers into ascending order of magnitude C Initialize pointers and copy peak height. Note that the sort C does not reorder storage arrays PEAKS & PKPOS, but just creates C a list of pointers DO 200, I = 1, NPEAK PKHGHT(I) = PEAKS(I) 200 LPKORD(I) = I CALL SORT1(NPEAK, PKHGHT, LPKORD) C ELSE C PEAK option, set peak order LPKORD to reverse, so that peaks are C printed out in same order as input DO 210, I = 1, NPEAK LPKORD(I) = NPEAK - I + 1 210 CONTINUE ENDIF C LI=6 C C Print symmetry CALL PRTSYM(LI,1,NSYM(1),SYM(1,1,1,1)) IF (NCRYST.EQ.2) CALL PRTSYM(LI,2,NSYM(2),SYM(1,1,1,2)) C IF(LPEAK.GT.0) THEN WRITE(LI,9011) NPEAK 9011 FORMAT('1 Positions of ',I4,' peaks'//) ELSEIF(LPKRMS.EQ.0) THEN WRITE(LI,9012) NPEAK,PEAK 9012 FORMAT('1 Positions of ',I4,' peaks above',F8.0//) ELSE WRITE(LI,9013) NPEAK,PEAK,RRMS 9013 FORMAT('1 Positions of ',I4,' peaks above',F8.0, . ' * RMS = ',F9.3//) ENDIF WRITE(LI,9014) 9014 FORMAT( . 24X,' Eulerian angles Polar angles'// . 20X,' Alpha Beta Gamma Peak ', . ' Omega Phi Kappa Direction cosines'/ . ' Symmetry: 1 2'//) C JSYM1=NSYM(1) JSYM2=NSYM(2) C Set up matrices for crystal 1 DO 1 ISYM1=1,JSYM1 DO 3 I=1,3 DO 3 J=1,3 3 AJUNK3(I,J)=SYM(I,J,ISYM1,1) C CALL MATMUL(AJUNK4,AJUNK3,FRAC(1,1,1)) CALL MATMUL(AJUNK3,ORTHOG(1,1,1),AJUNK4) DO 4 I=1,3 DO 4 J=1,3 4 ARSYM(I,J,ISYM1,1)=AJUNK3(I,J) C ARSYM(,,1 to JSYM1) contains Orthog . Sym . Frac 1 CONTINUE C C Set up matrices for crystal 2 DO 5 ISYM2=1,JSYM2 C inverse symmetry matrix AMINV (4x4) CALL RBRINV(SYM(1,1,ISYM2,2),AMINV) C copy to 3x3 DO 66 I=1,3 DO 66 J=1,3 AJUNK3(J,I)=AMINV(J,I) 66 CONTINUE C CALL MATMUL(AJUNK4,AJUNK3,FRAC(1,1,2)) CALL MATMUL(AJUNK3,ORTHOG(1,1,2),AJUNK4) DO 7 I=1,3 DO 7 J=1,3 7 ARSYM(I,J,ISYM2,2)=AJUNK3(I,J) C ARSYM(,,ISYM2,2) contains Orthog . Sym**-1 . Frac 5 CONTINUE C C Loop all peaks in list C DO 100 JP=1,NPEAK C Get peak number in descending order of size J=LPKORD(NPEAK-JP+1) C WRITE(LI,15) JP 15 FORMAT(/1X,' Peak ',I4) C C Get rotation matrix corresponding to angles in list C CALL POLMAT(TRMAT,PKPOS(1,J)) C C Convert to Eulerian for output file of unique peaks CALL EULERA(TRMAT,ALPHA,BETA,GAMMA) CALL RNGANG(ALPHA) EPKPOS(1,JP)=ALPHA CALL RNGANG(BETA) EPKPOS(2,JP)=BETA CALL RNGANG(GAMMA) EPKPOS(3,JP)=GAMMA C C DO 99 ISYM1=1,JSYM1 DO 103 I=1,3 DO 103 JJ=1,3 103 AJUNK3(I,JJ)=ARSYM(I,JJ,ISYM1,1) C DO 98 ISYM2=1,JSYM2 DO 102 I=1,3 DO 102 JJ=1,3 102 AJUNK2(I,JJ)=ARSYM(I,JJ,ISYM2,2) CALL MATMUL(AJUNK1,TRMAT,AJUNK2) CALL MATMUL(TRSYM,AJUNK3,AJUNK1) TRACE=TRSYM(1,1)+TRSYM(2,2)+TRSYM(3,3) IF (TRACE.GE.2.9999) THEN WRITE(LI,116) PEAKS(J),(PKPOS(I,J),I=1,3) 116 FORMAT(' Origin peak ',28X,F8.1,5X,3F7.1) GO TO 100 ENDIF C Get Euler angles CALL EULERA(TRSYM,ALPHA,BETA,GAMMA) C Get Kappa & direction cosines CALL DCOSFD(TRSYM, DC, AKAPPA) C Get polar angles CALL POLANG(DC,OMEGA,PHI) C Put all angles in range 0-360 degrees CALL RNGANG(ALPHA) CALL RNGANG(BETA) CALL RNGANG(GAMMA) CALL RNGANG(OMEGA) CALL RNGANG(PHI) CALL RNGANG(AKAPPA) WRITE(LI,14) ISYM1,ISYM2,ALPHA,BETA,GAMMA,PEAKS(J),OMEGA, 1 PHI,AKAPPA,DC(1),DC(2),DC(3) 14 FORMAT(8X,2I4,4X,3F7.1,3X,F8.1,5X,3F7.1,6X,3F8.4) C C IF(LPEAK.GT.1) THEN C Output matrices if peaks input and MATRICES keyword given CALL MINV3(AJUNK2,TRSYM,D) WRITE(LI,114) 1 ((TRSYM(I,JI),JI=1,3),(AJUNK2(I,K),K=1,3),I=1,3) 114 FORMAT(/' Rotation matrix and its inverse', + /(3(3F10.5,10X,3F10.5/))/) ENDIF C 98 CONTINUE 99 CONTINUE 100 CONTINUE C WRITE(LI,9022) 9022 FORMAT(///' The rotation given by the angles of a peak rotates', . ' coordinates in the orthogonal frame'/ . ' of crystal 2 to the orthogonal frame of crystal 1.'/ . ' Beware of axis permutations introduced by NCODE = 2, 3 or 4'// . /' Rotation matrices are defined as follows:'/// . ' ( l**2+(m**2+n**2)cos k lm(1-cos k)-nsin k ', . 'nl(1-cos k)+msin k )'/ . ' ( lm(1-cos k)+nsin k m**2+(l**2+n**2)cos k ', . 'mn(1-cos k)-lsin k )',5X,'Polar angles'/ . ' ( nl(1-cos k)-msin k mn(1-cos k)+lsin k ', . 'n*2+(l**2+m**2)cos k )'// . ' where l m n are the direction cosines of the axis about', . ' which the rotation k = kappa takes place.'// . 31X,'( l ) ( sin omega cos phi )'/ . 31X,'( m ) = ( sin omega sin phi )'/ . 31X,'( n ) ( cos omega )'/) C WRITE(LI,9023) 9023 FORMAT(// . ' ( cosa cosb cosg - sina sing -cosa cosb sing - sina cosg', . ' cosa sinb )'/ . ' ( sina cosb cosg + cosa sing -sina cosb sing + cosa cosg', . ' sina sinb )',5X,'Eulerian angles Alpha, Beta, Gamma'/ . ' ( -sinb cosg sinb sing ', . ' cosb )'/) C C C------------------------------------------------------------------------ C Write unique peaks out to file C IF (LPKOUT .GT. 0) THEN L=LENSTR(PKFNAM) WRITE(LI, 61001) PKFNAM(1:L) 61001 FORMAT(//' Unique peaks written out to file ',A) LUN=1 CALL CCPDPN(LUN, PKFNAM(1:L),'NEW','F',0,0) C L=LENSTR(TITLE) WRITE (LUN, 61000) TITLE(1:L) 61000 FORMAT('! Peaks from POLARRFN'/'TITLE ',A) IF (NCRYST .EQ. 1) THEN WRITE (LUN, 61002) 'SELF' ELSEIF (NCRYST .EQ. 1) THEN WRITE (LUN, 61002) 'CROSS' 61002 FORMAT(A) ENDIF DO 1001, L=1,NCRYST WRITE (LUN, 61003) NCODES(L),CODES(NCODES(L)) 61003 FORMAT( . 'CRYSTAL',I5,' ! Ncode, orthogonalization ',A) WRITE (LUN, 61004) L, NSYM(L) 61004 FORMAT('SYMORTHOGONAL',2I5) C DO 1002, K=1,NSYM(L) WRITE (LUN, 61005) K,((ARSYM(I,J,K,L), J=1,3), I=1,3) 61005 FORMAT('! Symmetry operation ',I5/ . 2(3F12.5/),3F12.5) 1002 CONTINUE 1001 CONTINUE C C Now the peaks C WRITE (LUN, 61006) NPEAK 61006 FORMAT('PEAKS',I8/ . '! Alpha Beta Gamma Height') DO 1010, L = 1, NPEAK K = LPKORD(NPEAK-L+1) WRITE (LUN, 61007) L, (EPKPOS(I, L), I = 1, 3), PEAKS(K) 61007 FORMAT(I6,3F10.1,F10.2) 1010 CONTINUE CLOSE(UNIT=LUN,STATUS='KEEP') ENDIF C RETURN END C C SUBROUTINE PRTSYM(IOUT,ICRYST,NSYM,ROT) C ======================================= C C Print symmetry matrices C INTEGER IOUT,ICRYST,NSYM REAL ROT(4,4,NSYM) C INTEGER J,M,L C WRITE(IOUT,2) ICRYST 2 FORMAT(///' Unpermuted symmetry operations for crystal ',I3,': ') C DO 3 J=1,NSYM WRITE(IOUT,4) J,((ROT(L,M,J),M=1,4),L=1,3) 4 FORMAT(/21X,'Symmetry matrix',I5,5X,3F10.5,5X,F10.5/ . 2(46X,3F10.5,5X,F10.5/)) C 3 CONTINUE RETURN END C SUBROUTINE EULERA(TRSYM,ALPHA,BETA,GAMMA) C ========================================= C C Get Euler angles ALPHA,BETA,GAMMA from matrix TRSYM C REAL TRSYM(3,3),ALPHA,BETA,GAMMA C CONV=45./ATAN(1.) IF(ABS(TRSYM(3,3)).GE.0.99999) GO TO 13 C BETA=CONV*ACOS(TRSYM(3,3)) C R13=TRSYM(1,3) R23=TRSYM(2,3) R31=TRSYM(3,1) R32=TRSYM(3,2) GAMMA=CONV*ATAN2(R32,-R31) ALPHA=CONV*ATAN2(R23,R13) RETURN C C C BETA = 0 OR 180 CAN ONLY FIND ALPHA + OR - GAMMA. 13 BETA=0. IF(TRSYM(3,3).LT.0.) BETA=180. GAMMA=CONV*ATAN2(TRSYM(2,1),TRSYM(2,2)) ALPHA=0. RETURN END C C C SUBROUTINE DCOSFD(ROT,DIRCOS,KAPPA) C =================================== C****************************************************** C Given a rotation matrix ROTN, expressing a rotation C through an angle KAPPA right-handedly about an axis C with direction cosines DIRCOS(I), C DCOSFD determines DIRCOS() and KAPPA C KAPPA is returned in degrees in the range 0 to 180 C C Expression for rotation matrix is (see J & J, "Mathl. C Phys.", p. 122):- C C cw + n(1)n(1)(1-cw) n(1)n(2)(1-cw)-n(3)sw n(1)n(3)(1-cw)+n(3)sw C n(1)n(2)(1-cw)+n(3)sw cw + n(2)n(2)(1-cw) n(2)n(3)(1-cw)-n(1)sw C n(3)n(1)(1-cw)-n(2)sw n(3)n(2)(1-cw)+n(1)sw cw + n(3)n(3)(1-cw) C C where cw = cos(KAPPA), sw = sin(KAPPA), C & n(1), n(2), n(3) are the direction cosines. C C*******************************************************} C REAL ROT(3,3),DIRCOS(3),S(3),P(3),D(3) REAL KAPPA REAL DIFF,PI,TRACE,R2,R3,SINKAP,COSKAP,TERM INTEGER NS(3),NP(3),NCS(3),ND(3),KNTRL,J,JMX C C DIFF=1.0E-04 PI=4.0*ATAN(1.) KNTRL=0 C Trace = 1 + 2.cos w TRACE=ROT(1,1)+ROT(2,2)+ROT(3,3) C S(1)=2.n(1).sin w C S(2)=2.n(2).sin w C S(3)=2.n(3).sin w S(1)=ROT(3,2)-ROT(2,3) S(2)=ROT(1,3)-ROT(3,1) S(3)=ROT(2,1)-ROT(1,2) CALL ORDR3(KNTRL,S,NS) C--Is biggest S() zero (i.e. is sin w = 0)? IF (ABS(S(NS(1))).GT.DIFF) THEN R2=S(NS(2))/S(NS(1)) R3=S(NS(3))/S(NS(1)) DIRCOS(NS(1))=1.0/SQRT(1 + R2**2 + R3**2) DIRCOS(NS(2))=R2*DIRCOS(NS(1)) DIRCOS(NS(3))=R3*DIRCOS(NS(1)) GO TO 123 END IF C--Calculation when sin w = 0 (esp. when w = 180'). C P(1)=n(2).n(3).{0(W=0)or2(w=180)} C P(2)=n(3).n(1).{0(W=0)or2(w=180)} C P(3)=n(1).n(2).{0(W=0)or2(w=180)} P(1)=ROT(3,2) P(2)=ROT(1,3) P(3)=ROT(2,1) CALL ORDR3(KNTRL,P,NP) C--Is biggest P() zero (i.e. are all off-diag. terms zero)? IF (ABS(P(NP(1))).LT.DIFF) THEN IF (TRACE.GT.0.0) THEN C--Matrix is unit matrix. KAPPA=0.0 DIRCOS(1)=0.0 DIRCOS(2)=0.0 DIRCOS(3)=1.0 RETURN END IF C--Trace -ve, so dyad about x,y or z. KAPPA=PI DO 40 J=1,3 40 D(J)=ROT(J,J)+1.0 CALL ORDR3(KNTRL,D,ND) DIRCOS(ND(1))=1.0 DIRCOS(ND(2))=0.0 DIRCOS(ND(3))=0.0 RETURN END IF IF (ABS(P(NP(2))).LT.DIFF) THEN C--One d.c. is zero. DIRCOS(NP(1))=0.0 DIRCOS(NP(2))=SQRT(0.5*(1.0+ROT(NP(2),NP(2)))) DIRCOS(NP(3))=SQRT(0.5*(1.0+ROT(NP(3),NP(3)))) IF (P(NP(1)).LT.0.0) DIRCOS(NP(2))=-DIRCOS(NP(2)) GO TO 123 END IF C--All d.c's are nonzero. C R2=n(NP(1))/n(NP(2)) C R3=n(NP(1))/n(NP(3)) R2=P(NP(2))/P(NP(1)) R3=P(NP(3))/P(NP(1)) DIRCOS(NP(2))=1.0/SQRT(1 + R2**2 + (R2/R3)**2) DIRCOS(NP(3))=1.0/SQRT(1 + R3**2 + (R3/R2)**2) C--Check: don't take sqrt of negative values TERM=1.0-DIRCOS(NP(2))**2-DIRCOS(NP(3))**2 IF (TERM.LT.0.0) THEN IF (ABS(TERM).GT.DIFF) + CALL CCPERR (1,'Negative value in DCOSFD') TERM=ABS(TERM) END IF DIRCOS(NP(1))=SQRT(TERM) C--Adjust signs of DIRCOS(). JMX=0 DO 20 J=1,3 IF (P(J).GT.0.0) THEN IF (JMX.GT.0) JMX=-1 IF (JMX.EQ.0) JMX=J END IF 20 CONTINUE IF (JMX.GT.0) DIRCOS(JMX)=-DIRCOS(JMX) IF (JMX.EQ.0) WRITE(*,1358) 1358 FORMAT(' All P()s. are negative or zero') C--Given d.c's, calculate KAPPA. 123 KNTRL=1 CALL ORDR3(KNTRL,DIRCOS,NCS) C Find KAPPA. SINKAP=ROT(NCS(3),NCS(2))-ROT(NCS(2),NCS(3)) SINKAP=0.5*SINKAP/DIRCOS(NCS(1)) COSKAP=0.5*(TRACE-1.0) KAPPA=ATAN2(SINKAP,COSKAP) KAPPA=KAPPA*180.0/PI C If kappa negative, negate kappa and invert DIRCOS IF (KAPPA .LT. 0.0) THEN KAPPA = -KAPPA DIRCOS(1) = -DIRCOS(1) DIRCOS(2) = -DIRCOS(2) DIRCOS(3) = -DIRCOS(3) ENDIF RETURN END C C C C C SUBROUTINE ORDR3(KNTRL,Q,NQ) C ============================ C C************************************************************* C Find NQ(1) so that |Q(NQ(1)| is biggest Q. C If KNTRL=1, make NQ(1),NQ(2),NQ(3) a positive permutn. C If KNTRL= anything else, C find nos. NQ() so that|Q(NQ(1)|>|Q(NQ(2))|>|Q(NQ(3))| C C************************************************************* REAL Q(3) INTEGER NQ(3),KNTRL,J C C Find no. NQ(1) of Q() with largest |Q()|. NQ(1)=1 IF (ABS(Q(2)).GT.ABS(Q(1))) NQ(1)=2 IF (ABS(Q(3)).GT.ABS(Q(NQ(1)))) NQ(1)=3 C Find nos. for other two Q()'s & order so |Q(NQ(2))|>|Q(NQ(3))| NQ(2)=MOD(NQ(1),3)+1 NQ(3)=MOD(NQ(2),3)+1 IF (KNTRL.EQ.1) GO TO 100 IF (ABS(Q(NQ(3))).GT.ABS(Q(NQ(2)))) THEN J=NQ(3) NQ(3)=NQ(2) NQ(2)=J END IF 100 RETURN END C C C SUBROUTINE POLANG(DC,OMEGA,PHI) C =============================== C C Find polar angles OMEGA & PHI (degrees) from direction cosines DC C OMEGA in range 0 to 180, PHI in range 0 to 360 C REAL DC(3), OMEGA, PHI C REAL CONV, SOMEGA C CONV=45./ATAN(1.) C SOMEGA=SQRT(ABS(1.-DC(3)*DC(3))) OMEGA=CONV*ATAN2(SOMEGA,DC(3)) IF(DC(1).EQ.0..AND.DC(2).EQ.0.) THEN PHI=0.0 ELSE PHI=CONV*ATAN2(DC(2),DC(1)) ENDIF C RETURN END C C C SUBROUTINE RNGANG(A) C ==================== C C Put angle A into range 0-360 degrees C REAL A C 1 IF (A .LT. 0.0) THEN A = A + 360.0 GO TO 1 ENDIF 2 IF(A .GE. 360.0) THEN A = A - 360.0 GO TO 2 ENDIF RETURN END C C C SUBROUTINE POLMAT(ROTN,ANGLES) C ============================== C C************************************************************** C Sets rotation matrix ROTN expressing a rotation through an C angle AKAPPA right-handedly about an axis C with polar angles OMEGA, PHI (OMEGA with Z-axis, projection C giving angle PHI with X-axis). C These angles give direction cosines DIRCOS(I). C*************************************************************** C REAL ROTN(3,3),DIRCOS(3),ANGLES(3) REAL OMEGA,PHI,AKAPPA C C CONV=ATAN(1.)/45. OMEGA=ANGLES(1) PHI=ANGLES(2) AKAPPA=ANGLES(3) SNOM=SIN(OMEGA*CONV) CSOM=COS(OMEGA*CONV) SNPH=SIN(PHI*CONV) CSPH=COS(PHI*CONV) SNKA=SIN(AKAPPA*CONV) CSKA=COS(AKAPPA*CONV) DIRCOS(1)=SNOM*CSPH DIRCOS(2)=SNOM*SNPH DIRCOS(3)=CSOM DO 40 I=1,3 DO 30 J=1,3 K1=6-I-J K=K1 IF ((K1.LT.1).OR.(K1.GT.3)) K=3 EPSIJK=((I-J)*(J-K)*(K-I))/2 ROTN(I,J)=DIRCOS(I)*DIRCOS(J)* $ (1.0-CSKA)-EPSIJK*DIRCOS(K)*SNKA IF (I.EQ.J) ROTN(I,J)=ROTN(I,J)+CSKA 30 CONTINUE 40 CONTINUE RETURN END