summaryrefslogtreecommitdiff
path: root/Dragon/src/SALTLC.f90
diff options
context:
space:
mode:
Diffstat (limited to 'Dragon/src/SALTLC.f90')
-rw-r--r--Dragon/src/SALTLC.f90360
1 files changed, 360 insertions, 0 deletions
diff --git a/Dragon/src/SALTLC.f90 b/Dragon/src/SALTLC.f90
new file mode 100644
index 0000000..1e6023e
--- /dev/null
+++ b/Dragon/src/SALTLC.f90
@@ -0,0 +1,360 @@
+!
+!-----------------------------------------------------------------------
+!
+!Purpose:
+! To generate the cyclic tracking lines (specular tracking) for a
+! geometry using the SALT algorithm.
+!
+!Copyright:
+! Copyright (C) 2015 Ecole Polytechnique de Montreal.
+! This library is free software; you can redistribute it and/or
+! modify it under the terms of the GNU Lesser General Public
+! License as published by the Free Software Foundation; either
+! version 2.1 of the License, or (at your option) any later version
+!
+!Author(s):
+! A. Hebert
+!
+!Parameters: input
+! IFTEMP pointer to a temporary TRACKING file in update or creation
+! mode.
+! IPRINT print level.
+! IGTRK flag to generate the tracking file. In the case where
+! IGTRK=1, the tracking is performed and
+! used to evaluate the track normalisation factor and the
+! tracking file is generated. When IGTRK=0, the tracking is
+! still performed and used to evaluate the
+! track normalisation factor but the tracking file is not
+! generated.
+! NDIM problem dimensions.
+! NFREG number of regions.
+! NBANGL number of angles.
+! RENO track normalisation option. A value RENO=-1 implies
+! a direction dependent normalization of the tracks
+! for the volume while a value RENO=0, implies
+! a global normalisation.
+! NBDR number of directions for track normalization.
+! IFMT tracking file format:
+! IFMT=0 for short file;
+! IFMT=1 long file required by TLM: module.
+! DENUSR user defined track density.
+! DANGLT angle cosines.
+! DDENWT angular density for each angle.
+! NBSANG number of subtracks for each angles.
+! GG geometry basic information.
+!
+!Parameters: output
+! MAXSUB maximum number of subtracks in a line.
+! MAXSGL maximum number of segments in a line.
+! NTLINE total number of lines generated.
+! DVNOR ratio of analytic to tracked volume.
+!
+!-----------------------------------------------------------------------
+!
+SUBROUTINE SALTLC(IFTEMP,IPRINT,IGTRK,NDIM,NFREG,NBANGL,RENO,NBDR,IFMT,DENUSR,DANGLT, &
+ DDENWT,NBSANG,GG,MAXSUB,MAXSGL,NTLINE,DVNOR)
+ USE PRECISION_AND_KINDS, ONLY : PDB,INFINITY,SMALL
+ USE SAL_GEOMETRY_TYPES, ONLY : T_G_BASIC,ANGGEO,TYPGEO
+ USE SAL_TRACKING_TYPES, ONLY : NMAX2,MINLEN,NNN,ITRAC2,RTRAC2,DELR,CNT,CNT0,NBTRAC,IERR,DD0,EX0, &
+ EY0,DELX,DINIT,EX,ANGTAB,ELMTAB,TORIG,DNEW,N_AXIS,NB_TOT,NB_MAX, &
+ N_AXIS_KEEP,IMPX
+ USE SAL_AUX_MOD, ONLY : SAL231,SAL232,SAL237,SAL220_1
+ USE SAL_TRAJECTORY_MOD, ONLY : SALTRA
+ IMPLICIT NONE
+ !----
+ ! Subroutine arguments
+ !----
+ INTEGER :: IFTEMP,IPRINT,IGTRK,NDIM,NFREG,NBANGL,MAXSUB,MAXSGL,NTLINE,RENO,NBDR,IFMT, &
+ NBSANG(5,NBANGL)
+ REAL(PDB) :: DENUSR,DANGLT(NDIM,4*NBANGL),DDENWT(4*NBANGL),DVNOR(NFREG,NBDR)
+ TYPE(T_G_BASIC) :: GG
+ !----
+ INTEGER :: AXIS(2),PIECE,NPIECE,IANGL,II0,II,KEEP_NAXIS,NN,MM,IPHI,P1,P2,INODE,OK,ISURF, &
+ JCURR,IJK1,ITR,ITRS,JPHI,NA,NAOLD,NEST,NSEG,NTRACK,NTSEG,IAVERR,NMAX3, &
+ ICYCL,NCYCLE
+ REAL(PDB) :: WR,WT,PROJTAB(6),KEEP_DELX,MOV_DELX,XFACT,ANGLE,COSSURF,DCERR,DAVERR,DMVERR, &
+ DSVERR,EPS0
+ REAL :: X
+ REAL(PDB), ALLOCATABLE, DIMENSION(:) :: VOLN
+ REAL(PDB), ALLOCATABLE, DIMENSION(:,:) :: FACNRM ! aux for normalisation
+ INTEGER, PARAMETER :: FOUT =6
+ INTEGER, ALLOCATABLE, DIMENSION(:) :: ITRACK_TMP
+ REAL(PDB), ALLOCATABLE, DIMENSION(:) :: RTRACK_TMP
+ INTEGER, POINTER, DIMENSION(:) :: ITRAC3
+ REAL(PDB), POINTER, DIMENSION(:) :: RTRAC3
+ !
+ IMPX=IPRINT
+ CALL SAL220_1(ANGGEO)
+ !
+ DELR=1.0D0/DENUSR
+ NB_MAX=2*MAXVAL(NBSANG(1,:)+NBSANG(2,:))
+ IF((TYPGEO.EQ.7).OR.(TYPGEO.EQ.12)) NB_MAX=2*NB_MAX
+ ALLOCATE(ANGTAB(2*NB_MAX),ELMTAB(2*NB_MAX),TORIG(2,NB_MAX),N_AXIS_KEEP(NB_MAX),STAT=OK)
+ IF(OK.NE.0) CALL XABORT('SALTLC: Not enough memory ird')
+ MAXSUB=0
+ MAXSGL=0
+ NBTRAC=0
+ CNT0=0
+ CNT=CNT0+NNN
+ ALLOCATE(VOLN(GG%NB_NODE),FACNRM(GG%NB_NODE,2*NBANGL),STAT=OK)
+ IF(OK/=0) CALL XABORT('SALTLC: NOT ENOUGH MEMORY R')
+ FACNRM(:GG%NB_NODE,:2*NBANGL)=0._PDB
+ ! initialize entering distance
+ DD0=-INFINITY
+ EPS0=REAL(10.*SQRT(EPSILON(X)))
+ NCYCLE=1
+ IF((TYPGEO == 5).OR.((TYPGEO == 9))) NCYCLE=2
+ DO ICYCL=1,NCYCLE
+ DO IANGL=1,NBANGL
+ ! keep IANGL
+ NN=NBSANG(2,IANGL) ; MM=NBSANG(1,IANGL)
+ IF(ICYCL == 1) THEN
+ EX0=DANGLT(1,IANGL) ; EY0=DANGLT(2,IANGL)
+ ELSE IF(ICYCL == 2) THEN
+ EX0=-DANGLT(1,IANGL) ; EY0=DANGLT(2,IANGL)
+ ELSE IF(ICYCL == 3) THEN
+ EX0=-DANGLT(1,IANGL) ; EY0=-DANGLT(2,IANGL)
+ ELSE IF(ICYCL == 4) THEN
+ EX0=DANGLT(1,IANGL) ; EY0=-DANGLT(2,IANGL)
+ ENDIF
+ IF(EX0 < 0.0) MM=-MM
+ IF(EY0 < 0.0) NN=-NN
+ ! projections of geometry outline onto the two rotation or symmetry axis
+ P1=GG%PPERIM_MAC2(3); P2=GG%PPERIM_MAC2(4)-1
+ CALL SAL237(EX0,EY0,MM,NN,PROJTAB,AXIS)
+ ! track in direction IANGL and its relative directions
+ NPIECE=AXIS(1)
+ ! tracking vector
+ DO PIECE=1,NPIECE
+ ! axis nber, position on the axis
+ N_AXIS=AXIS(2)
+ DELX=PROJTAB(3)+PROJTAB(5)*(REAL(PIECE)-0.5)
+ KEEP_NAXIS=N_AXIS
+ KEEP_DELX=DELX
+ ! radial weight of the track
+ WR=PROJTAB(6)
+ IERR=0
+ MOV_DELX=0.
+ DO WHILE (IERR==0)
+ ! compute one trajectory:
+ ! (1) compute one trajectory
+ ! (2) keep entering points if we have more trajectories
+ CALL SALTRA(DANGLT(:,:2*NBANGL),GG%NPERIM_MAC2,GG%PERIM_MAC2,GG%ISURF2_ELEM,GG%IPAR, &
+ GG%RPAR,GG%PPERIM_NODE,GG%PERIM_NODE,GG%IBC2_ELEM,GG%IDATA_BC2,GG%BCDATA, &
+ GG%PPERIM_MAC2,GG%DIST_AXIS)
+ IF(IERR==1) DINIT=DNEW
+ IF(IERR==0) THEN
+ ! if ierr=0,trajectory has entered into the seam of element joint,
+ ! moves delx -> delx+epsilon_pdb*n
+ MOV_DELX=MOV_DELX+EPS0
+ DELX=KEEP_DELX+MOV_DELX
+ N_AXIS=KEEP_NAXIS
+ CNT=CNT0+NNN
+ ENDIF
+ ENDDO
+ ! if ierr=-1,tracking have not re-entering point=no trajectory
+ IF(IERR/=-1) THEN
+ ! a trajectory has been completed: store angle order nber, total weight and WR
+ ANGLE=DACOS(EX)
+ ITRAC2(CNT0+4)=IANGL
+ RTRAC2(CNT0+7)=0.5_PDB*WR/DDENWT(IANGL)
+ RTRAC2(CNT0+8)=WR
+ II0=CNT0+1
+ IF(IPRINT > 3) CALL SAL231(RTRAC2(II0:),ITRAC2(II0:),DELX,EX0,EY0,ANGLE)
+ DO II=1,ITRAC2(II0)
+ IF(RTRAC2(II0+II+NNN-1) <= 0.0) CALL XABORT('SALTLC: INVALID SEGMENT LENGTH')
+ ENDDO
+ ! compute volumes
+ CALL SAL232(ITRAC2(II0:),RTRAC2(II0:),FACNRM,GG)
+ ! next line
+ IF(CNT+NNN+MINLEN>=NMAX2) THEN
+ NMAX3=CNT+NNN+MINLEN+1000
+ ALLOCATE(ITRAC3(2*NMAX3),RTRAC3(NMAX3),STAT=OK)
+ IF(OK/=0) CALL XABORT('SALTLC: NMAX2 overflow.')
+ RTRAC3(:NMAX2)=RTRAC2(:NMAX2)
+ ITRAC3(:2*NMAX2)=ITRAC2(:2*NMAX2)
+ DEALLOCATE(RTRAC2,ITRAC2)
+ RTRAC2=>RTRAC3
+ ITRAC2=>ITRAC3
+ NMAX2=CNT+NNN+MINLEN+1000
+ ENDIF
+ NBTRAC=NBTRAC+1
+ !
+ ! total weight and space weight
+ COSSURF=RTRAC2(II0+1)
+ WT=RTRAC2(II0-1+7)
+ NTRACK=ITRAC2(II0)
+ NB_TOT=ITRAC2(II0+1)
+ IF(NB_TOT > NB_MAX) CALL XABORT('SALTLC: NB_MAX overflow.')
+ !
+ ! identify entering end leaving surfaces
+ JCURR=0
+ IJK1=NNN+NTRACK
+ NTSEG=NTRACK+2*NB_TOT
+ !
+ MAXSGL=MAX(MAXSGL,NTSEG)
+ MAXSUB=MAX(MAXSUB,NB_TOT)
+ ALLOCATE(ITRACK_TMP(NTSEG),RTRACK_TMP(NTSEG))
+ !
+ ! loop over sub-trajectories
+ NSEG=0
+ NAOLD=0
+ ITR=NNN
+ DO ITRS=1,NB_TOT
+ IJK1=IJK1+1
+ NEST=ITRAC2(II0-1+IJK1)
+ IJK1=IJK1+1
+ JPHI=ITRAC2(II0-1+IJK1)
+ IF(IPRINT > 5) WRITE(FOUT,'(I6,"*",6X,I6,5X,I6)') ITRS,NEST,JPHI
+ IF(TYPGEO <= 7) NA=(JPHI-1)/NBANGL+1 ! Cartesian
+ ISURF=N_AXIS_KEEP(ITRS)
+ IF(ITRS == 1) THEN
+ ITRACK_TMP(1)=-ISURF
+ RTRACK_TMP(1)=0.5
+ IF(IPRINT > 5) WRITE(FOUT,*) ' -> surface',ISURF
+ ENDIF
+ IF(ISURF == 0) THEN
+ WRITE(FOUT,*) ' JPHI=',JPHI,' -> surface',ISURF
+ CALL XABORT('SALTLC: symmetry not implemented.')
+ ENDIF
+ IF(IPRINT > 5) THEN
+ IF(TYPGEO <= 7) THEN
+ WRITE(FOUT,*) ' JPHI=',JPHI,' NAOLD=',NAOLD,' NA=',NA,' -> surface',ISURF
+ ELSE
+ WRITE(FOUT,*) ' JPHI=',JPHI,' -> surface',ISURF
+ ENDIF
+ ENDIF
+ NSEG=NSEG+1
+ ITRACK_TMP(NSEG)=-ISURF
+ RTRACK_TMP(NSEG)=0.5
+ IF(ITRS > 1) THEN
+ NSEG=NSEG+1
+ ITRACK_TMP(NSEG)=-ISURF
+ RTRACK_TMP(NSEG)=0.5
+ ENDIF
+ DO II=1,NEST
+ ITR=ITR+1
+ IF(IPRINT > 5) THEN
+ WRITE(FOUT,'(5X,I6,"*",3(1P,I6,1P,E10.2,I7))') II, &
+ ITRAC2(II0-1+ITR),RTRAC2(II0-1+ITR),ITRAC2(II0-1+ITR+NMAX2)
+ ENDIF
+ NSEG=NSEG+1
+ ITRACK_TMP(NSEG)=ITRAC2(II0-1+ITR)
+ RTRACK_TMP(NSEG)=RTRAC2(II0-1+ITR)
+ ENDDO
+ NAOLD=NA
+ ENDDO
+ ! case of a geometry with specular reflective condition which is not a
+ ! rectangular -> anisotropy treatment not supported
+ IF(JCURR == 0) JCURR=1
+ NSEG=NSEG+1
+ IF(NSEG /= NTSEG) CALL XABORT('SALTLC: NTSEG inconsistency')
+ ITRACK_TMP(NSEG)=-JCURR
+ RTRACK_TMP(NSEG)=0.5
+ IF(IPRINT > 5) THEN
+ WRITE(FOUT,*) 'SALTLC: EXCELT entry with',NSEG,'segments:'
+ WRITE(FOUT,*) (ITRACK_TMP(II),II=1,NSEG)
+ WRITE(FOUT,*) (RTRACK_TMP(II),II=1,NSEG)
+ ENDIF
+ IF(IGTRK == 1) THEN
+ IF(IFMT == 1) THEN
+ WRITE(IFTEMP) NB_TOT,NTSEG,WT,(ANGTAB(II),II=2,2*NB_TOT,2),(ITRACK_TMP(II),II=1,NTSEG), &
+ (RTRACK_TMP(II),II=1,NTSEG),NBTRAC,1,1,1,((TORIG(II0,II),II0=1,NDIM),II=1,NB_TOT)
+ ELSE
+ WRITE(IFTEMP) NB_TOT,NTSEG,WT,(ANGTAB(II),II=2,2*NB_TOT,2),(ITRACK_TMP(II),II=1,NTSEG), &
+ (RTRACK_TMP(II),II=1,NTSEG)
+ ENDIF
+ ENDIF
+ !
+ DEALLOCATE(RTRACK_TMP,ITRACK_TMP)
+ CNT0=CNT
+ IF(CNT0+NNN+MINLEN >= NMAX2) THEN
+ CALL XABORT('SALTLC: NMAX2 overflow(2)')
+ ELSE
+ CNT=CNT0+NNN
+ ENDIF
+ ENDIF
+ ENDDO
+ ! end of trajectories for this angle
+ IF(IPRINT > 5) THEN
+ WRITE(FOUT,'('' SALTLC: ANGLE EX EY = '',1P,3E12.4/)') ANGLE,EX0,EY0
+ ENDIF
+ ENDDO
+ ENDDO
+ NTLINE=NBTRAC
+ !----
+ ! Compute merged normalization factors
+ !----
+ IF(RENO/=1) THEN
+ DO INODE=1,GG%NB_NODE
+ VOLN(INODE)=0._PDB
+ DO IANGL=1,NBANGL
+ VOLN(INODE)=VOLN(INODE)+(FACNRM(INODE,IANGL)+FACNRM(INODE,NBANGL+IANGL)) &
+ /DDENWT(IANGL)
+ ENDDO
+ ENDDO
+ DMVERR=0.0D0
+ DSVERR=0.0D0
+ DAVERR=0.0D0
+ IAVERR=0
+ DO INODE=1,GG%NB_NODE
+ DO IPHI=1,2*NBANGL
+ IF(RENO==0) THEN
+ IF(ABS(VOLN(INODE))>SMALL) THEN
+ FACNRM(INODE,IPHI)=GG%VOL_NODE(INODE)/VOLN(INODE)
+ ENDIF
+ ELSE IF(RENO==-1) THEN
+ IF(ABS(FACNRM(INODE,IPHI))>SMALL) THEN
+ FACNRM(INODE,IPHI)=GG%VOL_NODE(INODE)/FACNRM(INODE,IPHI)
+ ENDIF
+ ENDIF
+ ENDDO
+ IF(ABS(VOLN(INODE))>SMALL) THEN
+ IAVERR=IAVERR+1
+ DCERR=100.0D0*(1.0D0-GG%VOL_NODE(INODE)/VOLN(INODE))
+ DMVERR=MAX(DMVERR,ABS(DCERR))
+ DSVERR=DSVERR+DCERR*DCERR
+ DAVERR=DAVERR+DCERR
+ ENDIF
+ ENDDO
+ DSVERR=SQRT(DSVERR/DBLE(IAVERR))
+ DAVERR=DAVERR/DBLE(IAVERR)
+ IF(IPRINT > 0) WRITE(FOUT,6005) DSVERR,DMVERR,DAVERR
+ IF(IPRINT > 5) THEN
+ DO IPHI=1,2*NBANGL
+ WRITE(*,*) 'iphi=',IPHI
+ WRITE(*,*) 'facnrm : ',(FACNRM(INODE,IPHI),INODE=1,MIN(10,GG%NB_NODE))
+ ENDDO
+ ENDIF
+ IF(GG%NB_NODE > NFREG) CALL XABORT('SALTLC: bug.')
+ DVNOR(:,:)=0._PDB
+ DO INODE=1,GG%NB_NODE
+ IF(RENO==0) THEN
+ DVNOR(INODE,1)=DVNOR(INODE,1)+FACNRM(INODE,1)*GG%VOL_NODE(INODE)
+ ELSE IF(RENO==-1) THEN
+ DO IPHI=1,2*NBANGL
+ XFACT=FACNRM(INODE,IPHI)
+ DVNOR(INODE,IPHI+1)=DVNOR(INODE,IPHI+1)+XFACT*GG%VOL_NODE(INODE)
+ DVNOR(INODE,2*NBANGL+IPHI+1)=DVNOR(INODE,IPHI+1)
+ ENDDO
+ ENDIF
+ ENDDO
+ DO IPHI=1,NBDR
+ DVNOR(:,IPHI)=DVNOR(:,IPHI)/GG%VOL_NODE(:)
+ ENDDO
+ IF(IPRINT > 4) THEN
+ DO IPHI=1,NBDR
+ WRITE(*,*) 'iphi=',IPHI
+ WRITE(*,*) 'dvnor : ',(DVNOR(INODE,IPHI),INODE=1,MIN(10,NFREG))
+ ENDDO
+ ENDIF
+ ENDIF
+ !----
+ ! Scratch storage deallocation
+ !----
+ DEALLOCATE(FACNRM,VOLN)
+ DEALLOCATE(N_AXIS_KEEP,TORIG,ELMTAB,ANGTAB)
+ RETURN
+ 6005 FORMAT(' SALTLC: Global RMS, maximum and average errors (%) ', &
+ 'on region volumes :',3(2X,F10.5))
+END SUBROUTINE SALTLC