! BSPLINES ! Purpose: evaluate B-spline basis functions ! linear, quadratic or cubic ! equidistant (default) or at user-specified knots ! Input: via command line options (-h will list them) or interactively ! program will prompt for esential options not given on command line; ! ages and knot positions can be given in separate files ! Choose ! degree: command line option -d1, -d2 or -d3 for linear, quadratic or cubic; ! if not given, program will prompt for it ! "ages": command line option -a to read min. & max. age and step size ! interactively; if not given program will prompt for it, ! if given, program will expect to read ages from file "agesfile", ! default name "ages.dat" ! knots: command line option -eqx specificies a spline function with equal ! intervals, defined by x knots (x must be integer); if not given, ! program will prompt for the no. of knots. ! to select a spline with user-selected knots, a "knotsfile" (default ! name "knots" must exist in the working directory; program will ! count no. of knots in the file ! Format of "agesfile": ! one age per line ! each line comprised of two space-separated values: running no. ! (integer) and value for age (integer) ! Format for "knotsfile": ! one line per knot containing a single (real) value, ! knots should be in ascending order; ! it is the user's responsibility to ensure that knots are sensible & ! that the external knots & the range of ages specified are consistent! ! Output file "bspfile" with default name "bspline_Xn.dat" where X is the ! degree of the spline (L, Q or C) and n is the no. of knots given: ! lines in order of ages ! one line per age with n coefficients (real), followed by value for ! age; adjust format for output as necessary ! Compilation note: 'gfortran' may not accommadate the intrinsic functions ! 'iargc' and 'getarg' in subroutine cmdline; replace by ! 'k = command_argument_count()' and ! 'call get_command_argument( iarg, arg )' respectively ! ====================================================================== program Bsplines ! ===================================================@C-km-2004-======== implicit none ! -------------------- change as desired ---------------------------------- ! default name for file with user-chosen knots character(len=20) :: knotsfile ='knots ' ! default name for file with "ages" at which to evaluate B-spline function character(len=20) :: agesfile = 'ages.dat ' ! default name for output file character(len=16) :: bsplfile = 'bspline_X00.dat' ! format for output file character(len=12) :: fmt = '(00f12.8,i8)' ! ------------------- end of changes -------------------------------------- character(len=1), dimension(3) :: degree = (/ 'L', 'Q', 'C' /) real(8), dimension(:), allocatable :: kvec, tvec, w, p integer, dimension(:), allocatable :: iiage real(8), dimension(:,:,:), allocatable :: mm integer :: nknot, ndeg, nord, mknot, nage, nrr integer :: ii, i, j, iage, ia, iage1, iage2, & & istep real(8) :: xx, age, age1, age2, aa logical :: verbose, degset, kntset, equal, & & ages, lex ! read command line options call cmdline ! degree of basis functions if(.not.degset)then write(*,*)'degree ? (1=linear, 2=quad., 3=cubic)' read(*,*) ndeg; if(ndeg <1 .or. ndeg >3 ) stop 'wrong degree' end if nord = ndeg+1 ! order of fit ! ages for which to evaluate basis functions 100 continue if( ages ) then write(*,*)'Minimum age ?'; read(*,*)iage1 write(*,*)'Maximum age ?'; read(*,*)iage2 if(iage2.le.iage1)then write(*,*)'error : max. age must be greater than min. age' stop 'Bsplines' end if write(*,*)'Step size ?'; read(*,*) istep allocate( iiage(iage2-iage1+1) ); nage=0 do iage=iage1,iage2,istep nage=nage+1; iiage(nage) = iage end do if(iiage(nage) tvec(j) ) mm(j,ii,ia) = & & ( age - tvec(j) ) / ( tvec(j+ii)-tvec(j)) * mm(j,ii-1,ia) if(j+ii+1 > mknot) cycle if( tvec(j+ii+1) > tvec(j+1) ) mm(j,ii,ia) = mm(j,ii,ia) + & & ( tvec(j+ii+1) - age) / ( tvec(j+ii+1) - tvec(j+1)) * mm(j+1,ii-1,ia) end do end do end do ! write out file of covariables bsplfile(9:9)=degree(ndeg) if(nrr <10 )then write(bsplfile(11:11),'(i1)') nrr else write(bsplfile(10:11),'(i2)') nrr end if open(11,file=bsplfile,status='unknown',form='formatted') write( fmt(2:3),'(i2)' ) nrr do ia = 1, nage write(11,fmt) mm(:nrr,ndeg,ia), iiage(ia) end do close(11) ! write out a summary write(*,*)'number of ages = ',nage write(*,*)' ... range ',iiage(1),iiage(nage) write(*,*)'degree of polynomial = ',ndeg write(*,*)'number of knots = ',nknot write(*,*)'number of RR coefficients = ',nrr if( equal ) write(*,*)'Uniform spline with auxiliary knots outside range' write(*,'(1x,a,1h",a,1h")')'output file : ',bsplfile contains ! ================== subroutine cmdline ! ================== ! routine to evaluate command line options integer :: iargc, i, k, l character(len=30) :: arg external getarg ! default value for options verbose =.false.; degset=.false.; kntset=.false.; equal=.false.; ages =.false. k = iargc() ! no. of arguments do i = 1, k call getarg (i,arg); arg = adjustl(arg) if(arg(1:2) == '-v' .or. arg(1:2) == '-V') then verbose = .true. else if(arg(1:3) == '-eq' .or. arg(1:3) == '-EQ' ) then equal=.true.; read(arg(4:),*)nknot; kntset=.true. else if(arg(1:2) == '-a' .or. arg(1:2) == '-A')then ages = .true. else if( arg(1:2) == '-d' .or. arg(1:2) == '-D') then read(arg(3:),*) ndeg; if(ndeg <1 .or. ndeg >3 ) stop 'wrong degree' degset = .true. else if( arg(1:2) =='-h' .or. arg(1:2) == '-H') then write(*,*)'Valid command line options :' write(*,'(a,t10,a)')'-h','produces this message' write(*,'(a,t10,a)')'-u','how to use it' write(*,'(a,t10,a)')'-v','verbose screen output' write(*,'(a,t10,a)')'-a','specify range of ages & step size' write(*,'(a,t10,a)')'-dx','for x=1,2,3 : degree of spline' write(*,'(a,t10,a)')'-eqx','for x=1,2,... : uniform spline with x knots' else if( arg(1:2) == '-u' .or. arg(1:2) == '-U' ) then write(*,*)'Program BSPLINES : set up B-spline functions ' write(*,*)'------------------------------------------------' write(*,*)'Input: file "ages.out"' write(*,*)'Input: File "knots" with user-defined knots (one per line)' write(*,*)'Input: Options via command line or interactively' write(*,*)' - degree of spline (1=linear, 2=quadratic, 3=cubic)' write(*,*)' - absence of "knots" selects a uniform spline with' write(*,*)' auxiliary knots equi-distant outside range' write(*,*)' - for "ages.out" absent, user is prompted for age' write(*,*)' range and step size '; stop end if end do if( verbose ) then write(*,*)' **** Command line options ***' if(degset) write(*,'(1x,a,t30,1h=,i12)')'Degree of spline',ndeg if(equal) write(*,'(1x,a,t30,1h=,i12,1x,a)')'Uniform spline with', & & nknot,'knots' end if return end subroutine cmdline end program Bsplines