Search code examples
segmentation-faultfortranfortran90nonlinear-functionsnonlinear-optimization

Using nonlinear solver in Fortran: SNSQE - SLATEC


I am trying to figure out how to call a solver in Fortran to solve some n-dimensional nonlinear equation. I've come across the SLATEC library which has some nonlinear solver routines, and the one I'm trying to use is SNSQE. (aside: maybe you know of some better/easier solvers to use. please tell!)

My example code tries to solve a simple 2-dimensional problem. You could solve it by hand but the point is to figure out how the solver works. Code here:

program test
  implicit none

  ! declarations
  real :: theta0, x0, d(2), theta_ss(2)
  integer, parameter :: nprint=0, n=2, iopt=2, lwa = 180
  integer :: info
  real :: tol, fvec(2), jac(2), wa(lwa)

  ! set parameters
  theta_ss = 3.
  tol = .0000001

  ! make sure my function works
  d = FNC(theta_ss)
  write(*,*) theta_ss
  write(*,*) d

  ! call the solver and write output
  call SNSQE( FNC, jac, iopt, n, theta_ss, fvec, tol, nprint, info, wa, lwa )
  write(*,*) theta_ss, fvec, tol, info

contains 

  function FNC(x)
    real, intent(in) :: x(2)
    real :: FNC(2)

    FNC(1) =  x(1)**2 - 1
    FNC(2) =  x(2)**3 - 10

  end function FNC    
end program test

which I compile with the following:

ifort -fast test_solver.f90 -o test -lslatec

I run the resulting executable ./test and get:

3.000000       3.000000    
8.000000       17.00000 
forrtl: severe (174): SIGSEGV, segmentation fault occurred

So my function FNC works on its own, but not within SNSQE. All my inputs are of the correct type and in the correct order. I've tried writing the FNC function in different ways. I'm not sure why it isn't working.

Running OSX - Yosemite, Intel Fortran compiler, SLATEC is compiled from source with the same compiler.


Solution

  • The user-supplied function is not what SNSQE expects. From the comments in the linked file you can see that FCN must be a subroutine of the following form:

    SUBROUTINE FCN(N,X,FVEC,IFLAG)
      INTEGER N,IFLAG
      REAL X(N),FVEC(N)
      ! ----------
      ! Calculate the functions at X and
      ! return this vector in FVEC.
      ! ----------
    END SUBROUTINE