      subroutine cpfixedpoint(funcnleq1,x0min,x0ori,xp,
     &  x0max,fequ,nunknowns,TOLF,stpmax,iwhichsolver)
      implicit none
      include 'cpnslasystem.h'
!-------- Inputs ---------------------------------------
! nunknowns:          The number of unknowns to be solved
! x0ori(1:nunknowns): initial guess for the unknowns
! x0min(1:nunknowns): lower bound of the solution
! x0max(1:nunknowns): upper bound of the solution
! stpmax: the maximum length of the steps allowed to prevent search into
! undefined region.
! TOLF: Error tolerance
! funcnleq1: the subroutine name for the nonlinear system
      integer nunknowns
      double precision x0min(1:nunknowns),x0ori(1:nunknowns),
     &  x0max(1:nunknowns),TOLF,stpmax
! --------- Outputs -------------------------------------
! fequ(1:nunknowns): function values at the last step of iteration
! xp(1:nunknowns): final solutions or solutions not worse than x0ori   
! iwhichsolver:    =1,2,3,4 successful
!                  =-9999 failed, best solution returned
      integer iwhichsolver     
      double precision fequ(1:nunknowns),xp(1:nunknowns)
! ---------Local variables --------------------------------
      integer i,j,k,maxiter,notfound,ncount,ierr,
     &        ismallest,iGuCall
      double precision swap,x1,x2,f1,f2,fsqsumold,
     &  fsqsumnew,xpold(nunknowns),fequold(nunknowns),
     &  gfuncsum(nunknowns),deltax(nunknowns),
     &  xpder(nunknowns),fjacob(nunknowns,nunknowns),
     &  fjacobcopy(nunknowns,nunknowns),fsqsum
      logical check
      parameter(maxiter=200,notfound=-9999,iGuCall=49)
      integer iselect(300*maxiter)
      logical resetran2
      common /cpran2reset/resetran2
      save /cpran2reset/
      external funcnleq1
!-----------------------------------------------------------
      resetran2=.true.
      do i=1,nunknowns
        xp(i)=x0ori(i)
      enddo
      iwhichsolver=notfound
      numeval=0
!--------------------------------------------------------------
!Plain fixed-point method. Fixed-point method 1
      do i=1,maxiter
        call funcnleq1(nunknowns,xp,fequ,fsqsum)
        call cpbookkeeping(nunknowns,xp,fequ,iGuCall,k)
        if(dabs(fequ(k)).lt.TOLF)then
          iwhichsolver=1
          return
        endif
        do j=1,nunknowns
          xp(j)=xp(j)-fequ(j)
          if(xp(j).lt.x0min(j).or.xp(j).gt.x0max(j))then
            call reinitialization(x0min(j),x0ori(j),
     &        x0max(j),xp(j),50000)
          endif
        enddo
      enddo
!_____________________________________________________________________
!try fixed-point method 2
      do j=1,nunknowns
        call reinitialization(x0min(j),x0ori(j),
     &        x0max(j),xp(j),10000)
      enddo
      call funcnleq1(nunknowns,xp,fequ,fsqsum)
      call cpbookkeeping(nunknowns,xp,fequ,iGuCall,k)
      do i=1,nunknowns
        xp(i)=xp(i)-fequ(i)
        if(xp(i).lt.x0min(i).or.xp(i).gt.x0max(i))then
          call reinitialization(x0min(i),x0ori(i),
     &      x0max(i),xp(i),2000)
        endif
      enddo
      do i=1,maxiter
        call funcnleq1(nunknowns,xp,fequ,fsqsum)
        call cpbookkeeping(nunknowns,xp,fequ,iGuCall,k)
        if(dabs(fequ(k)).lt.TOLF)then
          iwhichsolver=2
          return
        endif
        do j=1,nunknowns
          ierr=0
          x1=xevaluated(numeval-1,j)
          f1=x1-fevaluated(numeval-1,j)
          x2=xevaluated(numeval,j)
          f2=x2-fevaluated(numeval,j)
          if(dabs(f2-f1-x2+x1).gt.1.0d-20)then
            ierr=1
            xp(j)=(x1*(f2-f1)-f1*(x2-x1))/
     &        (f2-f1-x2+x1)
            if(xp(j).le.x0min(j).or.xp(j)
     &                .ge.x0max(j))then
              ierr=0
            endif
          endif
          if(ierr.le.0.and.numeval.ge.3)then
! haven't found a usable new point yet, first try the opposite sign point
            ncount=0
            do k=1,numeval-2
              if((fevaluated(k,j)*fevaluated(numeval,j))
     &             .lt.0.0d0)then
                ncount=ncount+1
                iselect(ncount)=k
              endif
            enddo
            if(ncount.gt.0)then
! there are points at different sides of the zero.
              ismallest=1
              do k=2,ncount
                if(dabs(xevaluated(iselect(k),j)-x2).lt.
     &      dabs(xevaluated(iselect(ismallest),j)-x2))then
                  ismallest=k
                endif
              enddo
              ierr=1
              x1=xevaluated(iselect(ismallest),j)
              f1=x1-fevaluated(iselect(ismallest),j)
              xp(j)=(x1*(f2-f1)-f1*(x2-x1))/
     &            (f2-f1-x2+x1)
            else
! all at the same sides of the zero.
              do k=1,numeval-2
                x1=xevaluated(k,j)
                f1=x1-fevaluated(k,j)
                if(dabs(f2-f1-x2+x1).gt.1.0d-10)then
                  xp(j)=(x1*(f2-f1)-f1*(x2-x1))/
     &            (f2-f1-x2+x1)
                  if(xp(j).gt.x0min(j).and.xp(j).lt.x0max(j))then
                    ierr=1
                  endif
                endif
                if(ierr.eq.1)goto 10
              enddo
10            continue
            endif
          endif
          if(ierr.eq.0)then
            call reinitialization(x0min(j),
     &        xevaluated(numeval,j),x0max(j),xp(j),1000)
          endif
        enddo
        ierr=0
        do k=1,nunknowns
          if(xp(k).ne.xevaluated(numeval,k))ierr=1
        enddo
        if(ierr.eq.0)then
          do k=1,nunknowns
            call reinitialization(x0min(k),
     &        xevaluated(numeval,k),x0max(k),xp(k),25000)   
          enddo
        endif
      enddo
!__________________________________________________________________
!Try fixed-point method 3
      do i=1,nunknowns
        xp(i)=x0ori(i)+1.0d-6
        if(xp(i).lt.x0min(i).or.xp(i).gt.x0max(i))then
          call reinitialization(x0min(i),x0ori(i),
     &        x0max(i),xp(i),250910)
        endif
      enddo
      do j=1,maxiter
        call funcnleq1(nunknowns,xp,fequ,fsqsum)
        call cpbookkeeping(nunknowns,xp,fequ,iGuCall,k)
        if(dabs(fequ(k)).lt.TOLF)then
          iwhichsolver=3
          return
        endif
        do i=1,nunknowns
          xp(i)=xp(i)-fequ(i) 
          if(xp(i).lt.x0min(i).or.xp(i).gt.x0max(i))then
            call reinitialization(x0min(i),x0ori(i),
     &        x0max(i),xp(i),25500)
          endif
        enddo
        call funcnleq1(nunknowns,xp,fequ,fsqsum)
        call cpbookkeeping(nunknowns,xp,fequ,iGuCall,k)
        if(dabs(fequ(k)).lt.TOLF)then
          iwhichsolver=3
          return
        endif
        do i=1,nunknowns
          if(fevaluated(numeval,i).eq.
     &       fevaluated(numeval-1,i))then
            x1=(xevaluated(numeval,i)+
     &        xevaluated(numeval-1,i))/2.0d0
            call reinitialization(x0min(i),x1,
     &        x0max(i),xp(i),35678)
          else
            xp(i)=(xevaluated(numeval,i)*fevaluated(numeval-1,i)
     &         -xevaluated(numeval-1,i)*fevaluated(numeval,i))/
     &         (fevaluated(numeval-1,i)-fevaluated(numeval,i))
            if(xp(i).lt.x0min(i).or.xp(i).gt.x0max(i))then
              call reinitialization(x0min(i),x0ori(i),
     &         x0max(i),xp(i),45678)
            endif
          endif
        enddo
      enddo
!------------------------------------------------------------
!Try fixed-point method 4

!11    call funcnleq1(nunknowns,xp,fequ,fsqsumold)
!      call cpbookkeeping(nunknowns,xp,fequ,iGuCall,i)

      fsqsumold=0.0d0
      do i=1,nunknowns
        xpold(i)=xevaluated(1,i)
        fequold(i)=fevaluated(1,i)
        fsqsumold=fsqsumold+fequold(i)*fequold(i)
      enddo
      fsqsumold=0.5d0*fsqsumold
      do k=1,maxiter
        do j=1,nunknowns
          do i=1,nunknowns
            xpder(i)=xpold(i)
          enddo
          if(dabs(fequold(j)).lt.1.0d-10)then
            xpder(j)=xpold(j)+1.0d-5
          else
            xpder(j)=xpold(j)-fequold(j)           
          endif
          if(xpder(j).lt.x0min(j).or.xpder(j).
     &       gt.x0max(j))then
            call reinitialization(x0min(j),xpold(j),
     &         x0max(j),xpder(j),89000)
          endif
          call funcnleq1(nunknowns,xpder,fequ,fsqsumnew)
          call cpbookkeeping(nunknowns,xpder,fequ,iGuCall,i)
          if(dabs(fequ(i)).lt.TOLF)then
            iwhichsolver=4
            return
          endif
          do i=1,nunknowns
            fjacob(i,j)=(fequ(i)-fequold(i))/
     &        (xpder(j)-xpold(j))
            fjacobcopy(i,j)=fjacob(i,j)
          enddo
          gfuncsum(j)=(fsqsumnew-fsqsumold)/
     &      (xpder(j)-xpold(j))
        enddo
        call cpxmprove(nunknowns,nunknowns,
     &     fjacob,fequold,deltax,ierr)
!if ierr = 0, matrix is singular. ierr = 1, everything is ok.
        if(ierr.eq.0)then
          call adsor(fjacobcopy,nunknowns,nunknowns,
     &       fequold,deltax,ierr)
          if(ierr.ne.1)ierr=0
        endif
        if(ierr.ne.0)then
          do i=1,nunknowns
            deltax(i)=-deltax(i)
          enddo
          call cplnsrch(nunknowns,xpold,fsqsumold,
     &      gfuncsum,deltax,xp,fsqsumnew,stpmax,
     &      check,funcnleq1,fequ)
          if(check.eqv..true..or.check.eqv..TRUE.)then
            do i=1,nunknowns
              call reinitialization(x0min(i),xpold(i),
     &         x0max(i),xp(i),6678)
            enddo
          endif
          do i=1,nunknowns
            if(xp(i).lt.x0min(i).or.xp(i).gt.x0max(i))then
              call reinitialization(x0min(i),x0ori(i),
     &         x0max(i),xp(i),678)
            endif
          enddo
        else
          do i=1,nunknowns
            call reinitialization(x0min(i),x0ori(i),
     &        x0max(i),xp(i),75678)
          enddo
        endif
        call funcnleq1(nunknowns,xp,fequ,fsqsumold)
        call cpbookkeeping(nunknowns,xp,fequ,iGuCall,i)
        if(dabs(fequ(i)).lt.TOLF)then
          iwhichsolver=4
          return
        endif
        do i=1,nunknowns
          xpold(i)=xp(i)
          fequold(i)=fequ(i)
        enddo
      enddo
!_____________________________________________________________
!If all four methods failed, choose the best xp
      do i=1,numeval
        do k=i+1,numeval
          if(flargest(k).lt.flargest(i))then
            swap=flargest(k)
            flargest(k)=flargest(i)
            flargest(i)=swap
            do ncount=1,nunknowns
              swap=xevaluated(k,ncount)   
              xevaluated(k,ncount)=xevaluated(i,ncount)
              xevaluated(i,ncount)=swap
              swap=fevaluated(k,ncount)
              fevaluated(k,ncount)=fevaluated(i,ncount)
              fevaluated(i,ncount)=swap
            enddo
          endif
        enddo
      enddo
! Best solution found so far        
      do i=1,nunknowns
        xp(i)=xevaluated(1,i)
        fequ(i)=fevaluated(1,i)
      enddo
      return
      end subroutine cpfixedpoint
