{"id":26600796,"url":"https://github.com/scinim/numericalnim","last_synced_at":"2025-04-09T16:23:54.614Z","repository":{"id":40426598,"uuid":"189655891","full_name":"SciNim/numericalnim","owner":"SciNim","description":"A collection of numerical methods written in Nim","archived":false,"fork":false,"pushed_at":"2024-09-16T08:27:49.000Z","size":747,"stargazers_count":87,"open_issues_count":4,"forks_count":9,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-23T18:47:47.547Z","etag":null,"topics":["curve-fitting","discrete-points","integral","integration","interpolation","lbfgs","nim","nim-lang","numerical-computation","numerical-integration","numerical-methods","ode","ode-integrators","ode-solver","optimization-methods","science","scientific","scientific-computing","simpson-rule","vectors"],"latest_commit_sha":null,"homepage":"https://scinim.github.io/numericalnim/","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SciNim.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE.md","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}},"created_at":"2019-05-31T20:41:21.000Z","updated_at":"2024-09-16T08:20:58.000Z","dependencies_parsed_at":"2024-09-16T09:53:29.030Z","dependency_job_id":"f24f6b4f-743b-430c-807c-fd75fd1d83ff","html_url":"https://github.com/SciNim/numericalnim","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SciNim%2Fnumericalnim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SciNim%2Fnumericalnim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SciNim%2Fnumericalnim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SciNim%2Fnumericalnim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SciNim","download_url":"https://codeload.github.com/SciNim/numericalnim/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065991,"owners_count":21042012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["curve-fitting","discrete-points","integral","integration","interpolation","lbfgs","nim","nim-lang","numerical-computation","numerical-integration","numerical-methods","ode","ode-integrators","ode-solver","optimization-methods","science","scientific","scientific-computing","simpson-rule","vectors"],"created_at":"2025-03-23T18:35:24.181Z","updated_at":"2025-04-09T16:23:54.592Z","avatar_url":"https://github.com/SciNim.png","language":"Nim","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NumericalNim\n\n![Monthly Test](https://github.com/SciNim/numericalnim/actions/workflows/ci.yml/badge.svg?event=schedule)\n\u003ca href=\"https://matrix.to/#/#nim-science:envs.net\"\u003e\n  \u003cimg src=\"https://img.shields.io/static/v1?message=join%20chat\u0026color=blue\u0026label=nim-science\u0026logo=matrix\u0026logoColor=gold\u0026style=flat-square\u0026.svg\"/\u003e\n\u003c/a\u003e\n\u003ca href=\"https://discord.gg/f5hA9UK3dY\"\u003e\n  \u003cimg src=\"https://img.shields.io/discord/371759389889003530?color=blue\u0026label=nim-science\u0026logo=discord\u0026logoColor=gold\u0026style=flat-square\u0026.svg\"/\u003e\n\u003c/a\u003e\n\nNumericalNim is a collection of numerical methods written in Nim. Currently it has support for integration, optimization, curve-fitting, interpolation and ODEs. It can operate on floats and custom structures, such as vectors and tensors (if they support a set of operators).\n\n\n# Table of contents\n\n\u003c!-- TOC --\u003e\n\n- [Documentation \u0026 Tutorials](#documentation--tutorials)\n- [Installation](#installation)\n- [ODE](#ode)\n  - [Tutorials](#tutorials)\n  - [The integrators](#the-integrators)\n- [Integration](#integration)\n  - [Tutorials](#tutorials)\n  - [The methods](#the-methods)\n- [Optimization](#optimization)\n  - [Tutorials:](#tutorials)\n  - [One Dimensional optimization methods](#one-dimensional-optimization-methods)\n  - [Multidimensional optimization methods](#multidimensional-optimization-methods)\n- [Curve fitting](#curve-fitting)\n  - [Tutorials](#tutorials)\n  - [Levenberg-Marquardt](#levenberg-marquardt)\n- [Interpolation](#interpolation)\n  - [Tutorials](#tutorials)\n  - [Natural Cubic Splines](#natural-cubic-splines)\n  - [Cubic Hermite Splines](#cubic-hermite-splines)\n  - [Radial basis function interpolation](#radial-basis-function-interpolation)\n- [Utils](#utils)\n  - [Documentation](#documentation)\n  - [linspace](#linspace)\n  - [arange](#arange)\n  - [meshgrid](#meshgrid)\n  - [chi2](#chi2)\n- [Tips and tricks](#tips-and-tricks)\n  - [Suggested compilation flags](#suggested-compilation-flags)\n  - [Using enums as keys for NumContext](#using-enums-as-keys-for-numcontext)\n- [Status](#status)\n\n\u003c!-- /TOC --\u003e\n\n# Documentation \u0026 Tutorials\n- NumericalNim's [documentation](https://scinim.github.io/numericalnim/)\n- SciNim's [getting-started](https://scinim.github.io/getting-started/) site has a bunch of tutorials. Specific tutorial are linked below in their respective sections.\n\n# Installation\nInstall NumericalNim using Nimble:\n\n`nimble install numericalnim`\n\n# ODE\n## Tutorials\n- ODE tutorial in SciNim getting-started: https://scinim.github.io/getting-started/numerical_methods/ode.html\n- [Documentation](https://scinim.github.io/numericalnim/numericalnim/ode.html)\n\n## The integrators\nThese are the implemented ODE integrators:\n\n- `rk21` - Heun's Adaptive 2nd order method.\n- `BS32` - Bogacki–Shampine 3rd order adaptive method.\n- `DOPRI54` - Dormand \u0026 Prince's adaptive 5th order method.\n- `Heun2` - Heun's 2nd order fixed timestep method.\n- `Ralston2` - Ralston's 2nd order fixed timestep method.\n- `Kutta3` - Kutta's 3rd order fixed timestep method.\n- `Heun3` - Heuns's 3rd order fixed timestep method.\n- `Ralston3` - Ralston's 3rd order fixed timestep method.\n- `SSPRK3` - Strong Stability Preserving Runge-Kutta 3rd order fixed timestep method.\n- `Ralston4` - Ralston's 4th order fixed timestep method.\n- `Kutta4` - Kutta's 4th order fixed timestep method.\n- `RK4` - The standard 4th order, fixed timestep method we all know and love.\n- `Tsit54` - Tsitouras adaptive 5th order method.\n- `Vern65` - Verner's \"most efficient\" 6th order adaptive timestep method. (https://www.sfu.ca/~jverner/)\n\n\n### Dense Output\nAll integrators support dense output using a 3rd order Hermite interpolant. Method specific interpolants may be added in the future.\n\n\n# Integration\n## Tutorials\n- Integration tutorial in SciNim getting-started: https://scinim.github.io/getting-started/numerical_methods/integration1d.html\n- [Documentation](https://scinim.github.io/numericalnim/numericalnim/integrate.html)\n\n## The methods\n- `adaptiveGauss` - Uses Gauss-Kronrod Quadrature to adaptivly integrate function. This is the recommended proc to use! Typically this is both the fastest and most accurate of the methods. This is the only one of the methods that supports using `Inf` and `-Inf` as integration limits.\n- `gaussQuad` - Uses Gauss-Legendre Quadrature to integrate functions. Choose between 20 different accuracies by setting how many function evaluations should be made on each subinterval with the `nPoints` parameter (1 - 20 is valid options).\n- `trapz` - Uses the trapezoidal rule to integrate both functions and discrete points. 2nd order method.\n- `simpson` - Uses Simpson's rule to integrate both functions and discrete points. 4th order method.\n- `adaptiveSimpson` - Uses a adaptive Simpson's rule to subdivide the integration interval in finer pieces where the integrand is changing a lot and wider pieces in intervals where it doesn't change much. This allows it to perform the integral efficiently and still have accuracy. The error is approximated using Richardson extrapolation. So technically the values it outputs are actually not Simpson's, but Booles' method.\n- `romberg` - Uses Romberg integration to integrate both functions and discrete points. __Note:__ If discrete points are provided they must be equally spaced and the number of points must be of the form 2^k + 1 ie 3, 5, 9, 17, 33, 65, 129 etc.\n- `cumtrapz` - Uses the trapezoidal rule to integrate both functions and discrete points but it outputs a seq of the integral values at provided x-values. \n- `cumsimpson` - Uses Simpson's rule to integrate both functions and discrete points but it outputs a seq of the integral values at provided x-values.\n\n\n\n# Optimization\n## Tutorials:\n- Optimization tutorial in SciNim getting-started: https://scinim.github.io/getting-started/numerical_methods/optimization.html\n- [Documentation](https://scinim.github.io/numericalnim/numericalnim/optimize.html)\n\n## One Dimensional optimization methods\n- `steepest_descent` - Basic method for local minimum finding.\n- `conjugate_gradient` - iterative implementation of solving Ax = b\n- `newtons` - Newton-Raphson implementation for 1D functions.\n- `secant` - The secant method for 1D functions.\n\n## Multidimensional optimization methods\n- `lbfgs`: Limited-memory BFGS, a lighter version of BFGS. This is the recommended method\nfor larger problems.\n- `bfgs`: Broyden–Fletcher–Goldfarb–Shanno algorithm for optimization. Quasi-Newton method.\n- `newton`: The classic Newton method. Fast for small problems but struggles with bigger ones.\n- `steepestDescent`: The basic gradient descent method. Only use this if you have specific reasons to, as it is slower than the others for almost all problems.\n\n\n# Curve fitting\n## Tutorials\n- Curve-fitting tutorial in SciNim getting-started: https://scinim.github.io/getting-started/numerical_methods/curve_fitting.html\n- [Documentation](https://scinim.github.io/numericalnim/numericalnim/optimize.html)\n\n## Levenberg-Marquardt\nLevenberg-Marquardt (`levmarq`) is an algorithm for solving non-linear least squares problems,\nlike curve fitting. You provide the data points (x- \u0026 y-values), and optionally the errors in your data, along with a function describing the curve you want to fit\nand a starting guess of the parameters.\n`levmarq` will then find a (locally) optimal solution that minimizes the squared error\n(or the χ² if you provided errors). The uncertainties of the parameters can be approximated using `paramUncertainties`. \n\n\n# Interpolation\n## Tutorials\n- Interpolation tutorial in SciNim getting-started: https://scinim.github.io/getting-started/numerical_methods/interpolation.html\n- [Interpolation Documentation](https://scinim.github.io/numericalnim/numericalnim/interpolate.html)\n- [RBF Documentation](https://scinim.github.io/numericalnim/numericalnim/rbf.html)\n\n## Natural Cubic Splines\nCubic splines are piecewise polynomials of degree 3 ie. it is defined differently on different intervals. It passes through all the supplied points and has a continuos derivative. To find which interval a certain x-value is in we use a binary search algorithm to find it instead of looping over all intervals one after another.  \n\n## Cubic Hermite Splines\nCubic Hermite Splines are piecewise polynomials of degree 3, the same as Natural Cubic Splines. The difference is that we can pass the the derivative at each point as well as the function value. If the derivatives are not passed, a three-point finite difference will be used instead but this will not give as accurate results compared to with derivatives. It may be better to use Natural Cubic Splines then instead. The advantage Hermite Splines have over Natural Cubic Splines in NumericalNim is that it can handle other types of y-values than floats. For example if you want to interpolate data (dependent on one variable) in Arraymancer `Tensor`s you can do it by passing those as a `seq[Tensor]`. Hermite Splines' main mission in NumericalNim is to interpolate data points you get from solving ODEs as both the function value and the derivative is known at every point in time. \n\n## Radial basis function interpolation\nRadial basis function interpolation conceptually works by placing a Gaussian at every data point in the dataset and\nscale them all such that the linear combination of them interpolates the values in each point. This means that this \nmethod don't have to construct a mesh. It also means the interpolant will be smooth as it simply is a sum of smooth Gaussians.\nInternally a *partition of unity* method is employed though to improve performance and numerical stability. Simply put,\nthe domain is divided into patches and only points in neighboring patches affect each other. \n\n# Utils\nI have included a few handy tools in `numericalnim/utils`.\n## Documentation\n- [Documentation](https://scinim.github.io/numericalnim/numericalnim/utils.html)\n\n## linspace\n`linspace` creates a seq of N evenly spaced points between two numbers x1 and x2. \n```nim\necho linspace(0.0, 10.0, 11)\n```\n```nim\n@[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]\n```\n\n## arange\n`arange` creates a seq of float between x1 and x2 separated by dx. You can choose to include or exclude the start- and endpoint (unless the steps goes exactly to x2).\n```nim\necho arange(0.0, 5.0, 0.5)\necho arange(0.0, 4.9, 0.5)\n```\n```nim\n@[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]\n@[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5]\n```\n\n## meshgrid\nMeshgrid allows you to create a Tensor containing the points in an N-dimensional grid.\n\n## chi2\nCalculates the fit of a curve to data points.\n\n# Tips and tricks\n\n## Suggested compilation flags\n\nThere are many optimizations the C/C++ compiler can do but doesn't do by default.\nThese can be activated by passing flags to the underlying compiler with `-t:\u003cflag\u003e`.\nThese can be both of the [SIMD](https://en.wikipedia.org/wiki/SIMD) variety where\nmultiple operations are done at the same time, or fast-math which breaks the standards of floating point arithmetics to exchange a small bit of accuracy for performance. \n\nTo enable these, nim has to pass some flags to the C compiler.\nBelow is a small table, listing the flags to add when compiling with `nim c` for some widely used compilers:\n\nCompiler     | Flags\n------------ | -----\nclang        | `-t:-march=native -t:-ffast-math`\ngcc          | `-t:-march=native -t:-ffast-math`\nicc          | `-t:-march=core-avx2 -t:-fast`\nmsvc         | `-t:arch:AVX2 -t:fp:fast`\n\n## Using enums as keys for `NumContext`\nIf you want to avoid KeyErrors regarding mistyped keys, you can use enums for the keys instead. The enum value will be converted to a string internally so there is no constraint that all keys must be from the same enum. Here is one example of how to use it:\n```nim\ntype\n  MyKeys = enum\n    key1\n    key2\n    key3\nvar ctx = newNumContext[float]()\nctx[key1] = 3.14\nctx[key2] = 6.28\n```\n\n\n# Status\nThis is a hobby project of mine, so please keep that in mind. I have tried to cover most of the use-cases in the tests but there's always the risk that I have missed something. If you spot a bug (or something worse) please open an Issue. If you want to help improve this project I would very much appreciate it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscinim%2Fnumericalnim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscinim%2Fnumericalnim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscinim%2Fnumericalnim/lists"}