CCL Home Page
Up Directory CCL fit.f
      program fit
c 
c          This program is a general purpose fitting utility.  It will prompt
c     the user for a valid FORTRAN equation, number of points, and input and
c     output files.  It will then use these data to write a program to fit
c     the data in the input file to the given equation using a SIMPLEX
c     algorithm. It will compile it, link it and run it.
c
c          The main advantages of this approach are :
c
c          - the user is not required to write, compile, link and run any
c            programs.
c          - the equations can be non-linear in either the parameters or
c            independent variables.
c          - no numerical or analytical differentiation is required
c
      character*999 inline,outline,tmpline
      character*132 infile,outfile
      character*80  eqn,answer
      character*24  today
      character*20  who
      character*4   revon,revoff
      character*1   ch1,bell
      integer       start,end
      logical       done,errora,errorx,fileOK
c
      parameter(maxlines=99)
c
      dimension eqn(maxlines)
c
      done      = .false.
      numlines  = 0
      revon     = char(27)//'[7m'
      revoff    = char(27)//'[0m'
      bell      = char(7)
      call fdate(today)
      call getlog(who)
      numargs = iargc()
c
c     header :
c
      write(*,1001) revon//'General Purpose Fitting Facility'//revoff,bell
      if (numargs .ge. 1) then
         call getarg (1,answer)
         if (answer(1:2).eq.'-h' .or. answer(1:2).eq.'-H') 
     &      call system('more /usr/local/src/splx/fitinstr.txt')
      endif
   10 write(*,1003)
      read(*,1004) inline
      call lowcase(inline)
      call limits(inline,start,end)
      if (end.eq.start)stop
      call check_sequence(inline,'a(',')',numpar,errora)
      call check_sequence(inline,'x(',')',numx,errorx)
      if (errora .or. errorx .or. (numpar.eq.0) .or. (numx.eq.0)) then
         write(*,*) ' error in equation'
         goto 10
      else
c
c        partition the line into the needed sub-lines
c
         outline='      '//inline(start:end)
   20    numlines=numlines+1
         call limits(outline,start,end)
         if (end.le.72) then
            eqn(numlines)=outline(1:72)
         else
            do 40 i=72,1,-1
               ch1=outline(i:i)
               if (ch1.eq.'(' .or. ch1.eq.')' .or. ch1.eq.'+'
     &                 .or. ch1.eq.'-' .or. ch1.eq.'*' .or.
     &                 ch1.eq.'/' .or. ch1.eq.' ') then
                   eqn(numlines)=outline(1:i)
                   tmpline='     &      '
                   do 30 j=1,(end-i+1)
                      tmpline(12+j:12+j)=outline(i+j:i+j)
   30              continue
                   outline=tmpline
                   goto 20
               endif
   40       continue
         endif
      endif
c
c     The equation seems to be OK, get the maximum number of points :
c
      write(*,1005)
      read(*,*) numpoints
c
c     now get the name of input and output files :
c
   50 write(*,1006)
      read(*,1007) infile
      call limits(infile,iib,iie)
      inquire(file=infile(iib:iie),exist=fileOK)
      if (.not.fileOK) then
           write(*,1008)
           goto 50
      endif
   60 write(*,1009)
      read(*,1007) outfile
      call limits(outfile,iob,ioe)
      inquire(file=outfile(iob:ioe),exist=fileOK)
      if (fileOK) then
           write(*,1010)
           goto 60
      endif
      open(4,file=outfile(iob:ioe),status='new')
      write(4,*) ' '
      write(4,*) ' '
      open(3,file='simplexfit.f',status='new')
      call limits(who,start,end)
      write(3,'(a)') '      program simplex_fit'
      write(3,'(a)') 'c'
      write(3,'(2a)') 'c     Generated by the FIT utility by '//who(
     &            start:end)//' at ',today
      write(3,'(a)') 'c'
      write(3,'(2a)') 'c     it will fit a set of data points to the ',
     &                              'equation :'
      write(4,*) '      fit of a set of data points to the ',
     &                              'equation :'
      write(3,'(a)') 'c'
      write(4,*) ' '
      do 70 i=1,numlines
         write(3,'(a)') 'c          '//eqn(i)(7:72)
         write(4,*) '           '//eqn(i)(7:72)
   70 continue
      write(3,'(a)') 'c'
      write(3,'(a,i,a)') '      parameter (maxpar    = ',numpar,')'
      write(3,'(a,i,a)') '      parameter (maxvar    = ',numx,')'
      write(3,'(a,i,a)') '      parameter (maxpoints = ',numpoints,')'
      write(3,'(a)') 'c'
      write(3,'(a)') "      include '/usr/local/src/splx/simplex1.f'"
      write(3,'(a)') 'c'
      write(3,'(a)') "      include '/usr/local/src/splx/simplex2.f'"
      write(3,'(a)') 'c'
      do 80 i=1,numlines
         write(3,'(a)') eqn(i)(1:72)
   80 continue
      write(3,'(a)') 'c'
      write(3,'(a)') "      include '/usr/local/src/splx/simplex3.f'"
      close(3)
      write(4,*) ' '
      write(4,*) '      Procedure executed by '//who(start:end)//' at ',
     &           today
      write(4,*) ' '
      write(4,*) '      input data comes from file: '//infile(iib:iie)
      write(4,*) ' '
      close(4)
      call system('f77 simplexfit.f -O -NC20099'//
     &            ' -o simplexfit 1> /usr/tmp/fitlog 2>&1')
c     &  'f77 simplexfit.f -NC200 -o simplexfit')
      inquire(file='simplexfit',exist=fileOK)
      if (.not.fileOK) then
           write(*,1011)
           call system('rm -f simplexfit.f '//outfile(iob:ioe))
           goto 10
      endif
      call system('rm /usr/tmp/fitlog')
      call system('simplexfit < '//infile(iib:iie)//' >> '//
     &                  outfile(iob:ioe))
      call system('more '//outfile(iob:ioe))
      call system('rm -f simplexfit simplexfit.f')
      stop
 1001 format(///,20x,a40,///,2x,a1)
 1002 format(a80)
 1003 format(/,2x,'Enter the equation : ',$)
 1004 format(a999)
 1005 format(2x,'Enter the maximum number of points: ',$)
 1006 format(2x,'Enter the name of the input file  : ',$)
 1007 format(a132)
 1008 format(/,2x,'file does not exist, wrong name?')
 1009 format(2x,'Enter the name of the output file : ',$)
 1010 format(/,2x,'file already exists, use other name?')
 1011 format(//,6x,'executable program could not be generated',/,
     &          6x,'check your equation and input again',/)
      end
c-----------------------------------------------------------------------
      subroutine check_sequence(line,left,right,number,error)
c-----------------------------------------------------------------------
c
c          Checks the "equation" for correctness of sequence of
c     parameters or variables as enclosed by the given substrings.
c     Its main purpose is to check the expressions used in the FIT
c     utility.  Typically, an input equation can be something like
c
c               ycalc = a(1) + a(2)*x(1) + a(3)*x(2)**2 ...
c
c     where both the "parameters" (a's) or "variables" (x's) have
c     to be in sequence.  The running indeces can be in perfect
c     increasing sequence or reference can be made to previously
c     defined values, i. e.
c
c               ycalc = a(1) + a(2)*x(1) + a(1)*a(3)*(x(2)/x(3)) ...
c
c     input  :
c
c              line   : character string containing the "equation"
c              left   : substring that marks the beginning of an
c                       index
c              right  : substring that marks the ending of an
c                       index
c              the preceeding strings are variable-dimensioned to
c              allow greater flexibility
c     output :
c
c              number : index of the highest variable or parameter in
c                       the sequence found
c              error  : logical variable, returned .TRUE. if an incorrect
c                       sequence was encountered.
c
      character*(*) line,left,right
      character*12  rtf,tmpstr
      integer       start,end,par_open,par_close,curr_par
      logical       error,finished
c
      error      = .false.
      next_par   = 1
      next_start = 1
      finished   = .false.
c
      call limits(line,start,end)
      do while (.not.finished .and. next_start.lt.end)
         par_open=index(line(next_start:end),left)+next_start-1
         if (par_open.gt.(next_start-1)) then
            par_close=index(line(par_open:end),right)+par_open-1
            if (par_close.gt.(par_open-1)) then
               tmpstr=line(par_open+2:par_close-1)
               lentmp=par_close-(par_open+2)
               call findformat(tmpstr,1,lentmp,'I',rtf)
               read(tmpstr,fmt=rtf,err=999) curr_par
               if (curr_par.eq.next_par) then
                  next_par=next_par+1
               else if (curr_par.gt.next_par .or. curr_par.lt.1) then
                  goto 999
               endif
               next_start=par_close
            else
               goto 999
            endif
         else
           finished=.true.
         endif
      enddo
      number=next_par-1
      return
  999 error=.true.
      return
      end
Modified: Fri Dec 11 17:00:00 1992 GMT
Page accessed 7629 times since Sat Apr 17 22:01:37 1999 GMT