{"id":25854783,"url":"https://github.com/jchristopherson/nonlin","last_synced_at":"2026-03-06T06:04:29.429Z","repository":{"id":94681056,"uuid":"94330898","full_name":"jchristopherson/nonlin","owner":"jchristopherson","description":"A library that provides routines to compute the solutions to systems of nonlinear equations.","archived":false,"fork":false,"pushed_at":"2025-08-10T21:45:52.000Z","size":4522,"stargazers_count":27,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-10T23:36:02.214Z","etag":null,"topics":["bfgs","fortran","least-squares","levenberg-marquardt","nelder-mead","newton-raphson-multivariable","newtons-method","nonlinear-equations","optimization","polynomials","quasi-newton"],"latest_commit_sha":null,"homepage":null,"language":"Fortran","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jchristopherson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-06-14T12:55:36.000Z","updated_at":"2025-06-18T20:11:59.000Z","dependencies_parsed_at":"2024-09-06T18:19:54.620Z","dependency_job_id":"9c108383-d46b-4357-8cd0-37dc763f71a3","html_url":"https://github.com/jchristopherson/nonlin","commit_stats":{"total_commits":399,"total_committers":2,"mean_commits":199.5,"dds":"0.040100250626566414","last_synced_commit":"72a027d2cd9b681380e90a81832912b2fed5710c"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/jchristopherson/nonlin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristopherson%2Fnonlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristopherson%2Fnonlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristopherson%2Fnonlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristopherson%2Fnonlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jchristopherson","download_url":"https://codeload.github.com/jchristopherson/nonlin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristopherson%2Fnonlin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30164532,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T04:43:31.446Z","status":"ssl_error","status_checked_at":"2026-03-06T04:40:30.133Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bfgs","fortran","least-squares","levenberg-marquardt","nelder-mead","newton-raphson-multivariable","newtons-method","nonlinear-equations","optimization","polynomials","quasi-newton"],"created_at":"2025-03-01T16:18:09.123Z","updated_at":"2026-03-06T06:04:29.409Z","avatar_url":"https://github.com/jchristopherson.png","language":"Fortran","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nonlin\nA library that provides routines to compute the solutions to systems of nonlinear equations.\n\n## Status\n[![CMake](https://github.com/jchristopherson/nonlin/actions/workflows/cmake.yml/badge.svg)](https://github.com/jchristopherson/nonlin/actions/workflows/cmake.yml)\n[![Actions Status](https://github.com/jchristopherson/nonlin/workflows/fpm/badge.svg)](https://github.com/jchristopherson/nonlin/actions)\n\n## Documentation\nDocumentation can be found [here](https://jchristopherson.github.io/nonlin/)\n\n## Building NONLIN\n[CMake](https://cmake.org/)This library can be built using CMake.  For instructions see [Running CMake](https://cmake.org/runningcmake/).\n\n[FPM](https://github.com/fortran-lang/fpm) can also be used to build this library using the provided fpm.toml.\n```txt\nfpm build\n```\nThe NONLIN library can be used within your FPM project by adding the following to your fpm.toml file.\n```toml\n[dependencies]\nnonlin = { git = \"https://github.com/jchristopherson/nonlin\" }\n```\n## External Libraries\nHere is a list of external code libraries utilized by this library.\n- [BLAS](http://www.netlib.org/blas/)\n- [LAPACK](http://www.netlib.org/lapack/)\n- [FERROR](https://github.com/jchristopherson/ferror)\n- [LINALG](https://github.com/jchristopherson/linalg)\n\n## Example 1\nThis example solves a set of two equations of two unknowns using a Quasi-Newton type solver.  In this example, the solver is left to compute the derivatives numerically.\n\n```fortran\nprogram  example\n    use iso_fortran_env\n    use nonlin\n    implicit none\n\n    ! Local Variables\n    type(vecfcn_helper) :: obj\n    procedure(vecfcn), pointer :: fcn\n    type(iteration_behavior) :: ib\n    type(quasi_newton_solver) :: solver\n    real(real64) :: x(2), f(2)\n\n    ! Locate the routine containing the equations to solve\n    fcn =\u003e fcns\n    call obj%set_fcn(fcn, 2, 2)\n\n    ! Define an initial guess\n    x = 1.0d0 ! Equivalent to x = [1.0d0, 1.0d0]\n\n    ! Defining solver parameters.  This step is optional as the defaults are\n    ! typically sufficient; however, this is being done for illustration \n    ! purposes.\n    !\n    ! Establish how many iterations are allowed to pass before the solver\n    ! forces a re-evaluation of the Jacobian matrix.  Notice, the solver may\n    ! choose to re-evaluate the Jacobian sooner than this, but that is \n    ! dependent upon the behavior of the problem.\n    call solver%set_jacobian_interval(20)\n\n    ! Establish convergence criteria.  Again, this step is optional as the\n    ! defaults are typically sufficient; however, this is being done for\n    ! illustration purposes.\n    call solver%set_fcn_tolerance(1.0d-8)\n    call solver%set_var_tolerance(1.0d-12)\n    call solver%set_gradient_tolerance(1.0d-12)\n\n    ! Solve\n    call solver%solve(obj, x, f, ib)\n\n    ! Display the output\n    print '(AF7.5AF7.5A)', \"Solution: (\", x(1), \", \", x(2), \")\"\n    print '(AE9.3AE9.3A)', \"Residual: (\", f(1), \", \", f(2), \")\"\n    print '(AI0)', \"Iterations: \", ib%iter_count\n    print '(AI0)', \"Function Evaluations: \", ib%fcn_count\n    print '(AI0)', \"Jacobian Evaluations: \", ib%jacobian_count\n\ncontains\n    ! Define the routine containing the equations to solve.  The equations are:\n    ! x**2 + y**2 = 34\n    ! x**2 - 2 * y**2 = 7\n    subroutine fcns(x, f, args)\n        real(real64), intent(in), dimension(:) :: x\n        real(real64), intent(out), dimension(:) :: f\n        class(*), intent(inout), optional :: args\n        f(1) = x(1)**2 + x(2)**2 - 34.0d0\n        f(2) = x(1)**2 - 2.0d0 * x(2)**2 - 7.0d0\n    end subroutine\nend program\n```\nThe above program produces the following output.\n```text\nSolution: (5.00000, 3.00000)\nResidual: (0.323E-11, 0.705E-11)\nIterations: 11\nFunction Evaluations: 15\nJacobian Evaluations: 1\n```\n\n## Example 2\nThis example uses a least-squares approach to determine the coefficients of a polynomial that best fits a set of data.\n\n```fortran\nprogram example\n    use iso_fortran_env\n    use nonlin\n    implicit none\n\n    ! Local Variables\n    type(vecfcn_helper) :: obj\n    procedure(vecfcn), pointer :: fcn\n    type(least_squares_solver) :: solver\n    real(real64) :: x(4), f(21) ! There are 4 coefficients and 21 data points\n\n    ! Locate the routine containing the equations to solve\n    fcn =\u003e fcns\n    call obj%set_fcn(fcn, 21, 4)\n\n    ! Define an initial guess\n    x = 1.0d0 ! Equivalent to x = [1.0d0, 1.0d0, 1.0d0, 1.0d0]\n\n    ! Solve\n    call solver%solve(obj, x, f)\n\n    ! Display the output\n    print '(AF12.10)', \"c0: \", x(4)\n    print '(AF12.10)', \"c1: \", x(3)\n    print '(AF12.10)', \"c2: \", x(2)\n    print '(AF12.10)', \"c3: \", x(1)\n    print '(AF7.5)', \"Max Residual: \", maxval(abs(f))\n\ncontains\n    ! The function containing the data to fit\n    subroutine fcns(x, f, args)\n        ! Arguments\n        real(real64), intent(in), dimension(:) :: x  ! Contains the coefficients\n        real(real64), intent(out), dimension(:) :: f\n        class(*), intent(inout), optional :: args\n\n        ! Local Variables\n        real(real64), dimension(21) :: xp, yp\n\n        ! Data to fit (21 data points)\n        xp = [0.0d0, 0.1d0, 0.2d0, 0.3d0, 0.4d0, 0.5d0, 0.6d0, 0.7d0, 0.8d0, \u0026\n            0.9d0, 1.0d0, 1.1d0, 1.2d0, 1.3d0, 1.4d0, 1.5d0, 1.6d0, 1.7d0, \u0026\n            1.8d0, 1.9d0, 2.0d0]\n        yp = [1.216737514d0, 1.250032542d0, 1.305579195d0, 1.040182335d0, \u0026\n            1.751867738d0, 1.109716707d0, 2.018141531d0, 1.992418729d0, \u0026\n            1.807916923d0, 2.078806005d0, 2.698801324d0, 2.644662712d0, \u0026\n            3.412756702d0, 4.406137221d0, 4.567156645d0, 4.999550779d0, \u0026\n            5.652854194d0, 6.784320119d0, 8.307936836d0, 8.395126494d0, \u0026\n            10.30252404d0]\n\n        ! We'll apply a cubic polynomial model to this data:\n        ! y = c3 * x**3 + c2 * x**2 + c1 * x + c0\n        f = x(1) * xp**3 + x(2) * xp**2 + x(3) * xp + x(4) - yp\n\n        ! For reference, the data was generated by adding random errors to\n        ! the following polynomial: y = x**3 - 0.3 * x**2 + 1.2 * x + 0.3\n    end subroutine\nend program\n```\nThe above program produces the following output.\n```text\nc0: 1.1866142244\nc1: 0.4466134462\nc2: -.1223202909\nc3: 1.0647627571\nMax Residual: 0.50636\n```\n\nThe following graph illustrates the fit.\n![](images/Curve_Fit_Example_1.png?raw=true)\n\n## Example 3\nThis example utilizes the polynomial type to fit a polynomial to the data set utilized in Example 2.\n```fortran\nprogram example\n    use iso_fortran_env\n    use nonlin\n    implicit none\n\n    ! Local Variables\n    integer(int32) :: i\n    real(real64), dimension(21) :: xp, yp, yf, yc, err\n    real(real64) :: res\n    type(polynomial) :: p\n\n    ! Data to fit\n    xp = [0.0d0, 0.1d0, 0.2d0, 0.3d0, 0.4d0, 0.5d0, 0.6d0, 0.7d0, 0.8d0, \u0026\n        0.9d0, 1.0d0, 1.1d0, 1.2d0, 1.3d0, 1.4d0, 1.5d0, 1.6d0, 1.7d0, \u0026\n        1.8d0, 1.9d0, 2.0d0]\n    yp = [1.216737514d0, 1.250032542d0, 1.305579195d0, 1.040182335d0, \u0026\n        1.751867738d0, 1.109716707d0, 2.018141531d0, 1.992418729d0, \u0026\n        1.807916923d0, 2.078806005d0, 2.698801324d0, 2.644662712d0, \u0026\n        3.412756702d0, 4.406137221d0, 4.567156645d0, 4.999550779d0, \u0026\n        5.652854194d0, 6.784320119d0, 8.307936836d0, 8.395126494d0, \u0026\n        10.30252404d0]\n\n    ! Create a copy of yp as it will be overwritten in the fit command\n    yc = yp\n\n    ! Fit the polynomial\n    call p%fit(xp, yp, 3)\n\n    ! Evaluate the polynomial at xp, and then determine the residual\n    yf = p%evaluate(xp)\n    err = abs(yf - yc)\n    res = maxval(err)\n\n    ! Print out the coefficients\n    print '(AI0AF12.10)', (\"c\", i - 1, \" = \", p%get(i), i = 1, 4)\n    print '(AF7.5)', \"Max Residual: \", res\nend program\n```\nThe above program yields the following coefficients.\n```text\nc0 = 1.1866141861\nc1 = 0.4466136311\nc2 = -.1223204989\nc3 = 1.0647628218\nMax Residual: 0.50636\n```\nNotice, as expected, the results are very similar to the output of Example 2.\n\n## Example 4\nThis example uses the Nelder-Mead simplex method to find the minimum of the Rosenbrock function.\n```fortran\nprogram example\n    use iso_fortran_env\n    use nonlin\n    implicit none\n\n    ! Local Variables\n    type(nelder_mead) :: solver\n    type(fcnnvar_helper) :: obj\n    procedure(fcnnvar), pointer :: fcn\n    real(real64) :: x(2), fout\n    type(iteration_behavior) :: ib\n\n    ! Initialization\n    fcn =\u003e rosenbrock\n    call obj%set_fcn(fcn, 2)\n\n    ! Define an initial guess - the solution is (1, 1)\n    call random_number(x)\n\n    ! Call the solver\n    call solver%solve(obj, x, fout, ib)\n\n     ! Display the output\n     print '(AF7.5AF7.5A)', \"Minimum: (\", x(1), \", \", x(2), \")\"\n     print '(AE9.3)', \"Function Value: \", fout\n     print '(AI0)', \"Iterations: \", ib%iter_count\n     print '(AI0)', \"Function Evaluations: \", ib%fcn_count\ncontains\n    ! Rosenbrock's Function\n    function rosenbrock(x, args) result(f)\n        real(real64), intent(in), dimension(:) :: x\n        class(*), intent(inout), optional :: args\n        real(real64) :: f\n        f = 1.0d2 * (x(2) - x(1)**2)**2 + (x(1) - 1.0d0)**2\n    end function\nend program\n```\nThe above program produces the following output:\n```text\nMinimum: (1.00000, 1.00000)\nFunction Value: 0.121E-12\nIterations: 52\nFunction Evaluations: 101\n```\nNotice, the convergence tolerance was set to its default value (1e-12).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjchristopherson%2Fnonlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjchristopherson%2Fnonlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjchristopherson%2Fnonlin/lists"}