{"id":16660108,"url":"https://github.com/littleredcomputer/odex-js","last_synced_at":"2025-03-16T23:31:37.530Z","repository":{"id":41117522,"uuid":"55315482","full_name":"littleredcomputer/odex-js","owner":"littleredcomputer","description":"Bulirsch-Stoer integration of systems of ordinary differential equations in JavaScript","archived":false,"fork":false,"pushed_at":"2023-05-24T17:34:47.000Z","size":440,"stargazers_count":54,"open_issues_count":0,"forks_count":5,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-12T18:05:05.060Z","etag":null,"topics":["differential-equations","ode","ode-solver","odex","solver"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/littleredcomputer.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}},"created_at":"2016-04-02T20:48:23.000Z","updated_at":"2024-10-20T18:55:29.000Z","dependencies_parsed_at":"2024-06-18T22:35:26.049Z","dependency_job_id":"cf5d75fd-4ab3-4192-a28e-0f38eb4f25b1","html_url":"https://github.com/littleredcomputer/odex-js","commit_stats":{"total_commits":40,"total_committers":1,"mean_commits":40.0,"dds":0.0,"last_synced_commit":"f71980e9566ceaf384f0fa14d0c5c12cde80cd49"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/littleredcomputer%2Fodex-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/littleredcomputer%2Fodex-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/littleredcomputer%2Fodex-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/littleredcomputer%2Fodex-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/littleredcomputer","download_url":"https://codeload.github.com/littleredcomputer/odex-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243833007,"owners_count":20355188,"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":["differential-equations","ode","ode-solver","odex","solver"],"created_at":"2024-10-12T10:28:00.496Z","updated_at":"2025-03-16T23:31:37.017Z","avatar_url":"https://github.com/littleredcomputer.png","language":"TypeScript","readme":"## odex-js : ODEX in JavaScript\n[![Build Status](https://travis-ci.org/littleredcomputer/odex-js.svg?branch=master)](https://travis-ci.org/littleredcomputer/odex-js) [![GitHub license](https://img.shields.io/github/license/littleredcomputer/odex-js.svg)]() [![npm](https://img.shields.io/npm/v/odex.svg)]() [![Coverage Status](https://coveralls.io/repos/github/littleredcomputer/odex-js/badge.svg?branch=master)](https://coveralls.io/github/littleredcomputer/odex-js?branch=master)\n\n#### Numerically solves of non-stiff systems of ordinary differential equations in JavaScript.\n\nThis is a port to JavaScript (actually, TypeScript) of [E. Hairer and\nG. Wanner's implementation][odex] of the [Gragg-Bulirsch-Stoer][gbs] method of integrating\nsystems of differential equations. The original code is written in idiomatic\nFortran; this code tries to present an idiomatic JavaScript interface while\npreserving all the of the virtues of the original code, including its speed,\nconfigurability, and compact memory footprint.\n\n#### Examples\n(We'll write the usage examples in plain JavaScript. The usage from TypeScript\nis very similar.)\n##### One first-order equation\n\nThe simplest possible example would be y\u0026prime; = y, with y(0) = 1: we expect the\nsolution y(x) = exp(x). First we create a solver object, telling how many\nindependent variables there are in the system (in this case just one).\n\n```js\nvar odex = require('odex');\nvar s = new odex.Solver(1);\n```\n\nTo represent the differential equation, we write a\nroutine that computes y\u0026prime; given y at the point x. For this example it's very\nsimple:\n\n```js\nvar f = function(x, y) {\n  return y;\n}\n```\n\nSince we asked for one independent variable, `y` is an array of length 1.\nWe return an array of the same size.\n\n\nWe can solve the equation by supplying the initial data and the start\nand endpoints. Let's find y(1):\n\n```js\ns.solve(f,\n        0,    // initial x value\n        [1],  // initial y values (just one in this example)\n        1);   // final x value\n// { y: [ 2.7182817799042955 ],\n//   outcome: 0,\n//   nStep: 7,\n//   xEnd: 1,\n//   nAccept: 7,\n//   nReject: 0,\n//   nEval: 75 }\n```\n\nNot bad: the answer `y[1]` is close to *e*. It would be closer if we requested\nmore precision. When you create a new `Solver` object, it is\nequipped with a number of properties you can change to control the integration.\nYou can change a property and re-run the solution:\n\n```js\ns.absoluteTolerance = s.relativeTolerance = 1e-10;\ns.solve(f, 0, [1], 1).y\n// [ 2.7182818284562535 ]\nMath.exp(1) - 2.7182818284562535\n// 2.7915447731174936e-12\n```\n\n##### Integration callback\nYou can supply a callback function that runs during the integration to supply intermediate\npoints of the integration as it proceeds. The callback function is an optional\nparameter to `solve`, which receives the step number, x0, x1 and y(x1). (x0\nand x1 represent the interval covered in this integration step).\n\n```js\ns.solve(f, 0, [1], 1, function(n,x0,x1,y) {\n  console.log(n,x0,x1,y);\n}).y\n// 1 0 0 [ 1 ]\n// 2 0 0.0001 [ 1.0001000050001667 ]\n// 3 0.0001 0.0007841772783189289 [ 1.000784484825706 ]\n// 4 0.0007841772783189289 0.004832938716978181 [ 1.0048446362021166 ]\n// 5 0.004832938716978181 0.01913478583589434 [ 1.0193190291261103 ]\n// 6 0.01913478583589434 0.0937117110731088 [ 1.0982430889534374 ]\n// 7 0.0937117110731088 0.2862232977213724 [ 1.3313897183518322 ]\n// 8 0.2862232977213724 0.7103628434248046 [ 2.034729412908106 ]\n// 9 0.7103628434248046 1 [ 2.7182818284562535 ]\n// [ 2.7182818284562535 ]\n```\n\nYou will observe that `odex` has chosen its own grid points for evaluation.\nAdaptive step size is one of the nicest features of this library: you don't\nhave to worry about it too much.\n\n##### Dense Output\nHowever, you will often want to sample the data at points of your own choosing.\nWhen you request `denseOutput` in the `Solver` parameters, the function you\nsupply to solve receives a fifth argument which is a closure which you can call to obtain\nvery accurate y values in the interval [x0, x1].  You call this closure with\nthe index (within the y vector) of the component you want to evaluate, and the\nx value in [x0, x1] where you want to find that y value. One common use case\nfor this is to obtain otuput at evenly spaced points. To this end, we supply a\ncanned callback `grid` which you can use for this:\n\n```js\ns.denseOutput = true;  // request interpolation closure in solution callback\ns.solve(f, 0, [1], 1, s.grid(0.2, function(x,y) {\n  console.log(x,y);\n}));\n// 0 [ 1 ]\n// 0.2 [ 1.2214027470178732 ]\n// 0.4 [ 1.4918240050068732 ]\n// 0.6 [ 1.8221161568592519 ]\n// 0.8 [ 2.2255378426172316 ]\n// 1 [ 2.7182804587510203 ]\n// [ 2.7182804587510203 ]\n```\n\nTo see how you could use the dense output feature yourself, take a look at\nthe source to grid.\n##### A system of two first order equations\nNote that in all these examples, `y` is a vector: this software is designed to\nsolve systems. Let's work with the [Lotka-Volterra][lv] predator-prey system.\nThe system is:\n\n```\ndx/dt = a x - b x y\ndy/dt = c x y - d y\n```\n\nFor odex, we rename *t* to *x*, and then *x* and *y* become `y[0]` and `y[1]`.\nWe write a function LV which binds the constants of the population system\n`a`, `b`, `c`, `d` and returns a function suitable for the integrator.\nTo represent this system we can write:\n\n```js\nvar LotkaVolterra = function(a, b, c, d) {\n  return function(x, y) {\n    return [\n      a * y[0] - b * y[0] * y[1],\n      c * y[0] * y[1] - d * y[1]\n    ];\n  };\n};\n```\n\nThen we can solve it. It's the same as the previous examples, but this time\nwe need a solver created to handle two independent variables and must supply\ninitial data for both of them. To find the state of the rabbits and wolves\nat time 6, if the state at time zero is {y\u003csub\u003e0\u003c/sub\u003e = 1, y\u003csub\u003e1\u003c/sub\u003e\n= 1}:\n\n```js\ns = new odex.Solver(2);\ns.solve(LotkaVolterra(2/3, 4/3, 1, 1), 0, [1, 1], 6).y\n// [ 1.6542774481418214, 0.3252864486771545 ]\n````\nTo see more of this system of equations in action, you can visit a\n[demo page][lvdemo] which allows you to vary the initial conditions\nwith the mouse.\n\n##### A second-order equation\n\nYou can integrate second order ordinary differential equations by making a\nsimple transformation to a system of first order equations. Consider\n[Airy's equation][airy]: y\u0026Prime;\u0026nbsp;\u0026minus;\u0026nbsp;x\u0026thinsp;y = 0:\n\nIn ODEX, we could write y\u003csub\u003e0\u003c/sub\u003e for y and y\u003csub\u003e1\u003c/sub\u003e for y\u0026prime;,\nso that y\u0026Prime; = y\u0026prime;\u003csub\u003e1\u003c/sub\u003e and rewrite the system like this:\ny\u0026prime;\u003csub\u003e0\u003c/sub\u003e\u0026nbsp;=\u0026nbsp;y\u003csub\u003e1\u003c/sub\u003e;\u0026ensp;\ny\u0026prime;\u003csub\u003e1\u003c/sub\u003e\u0026nbsp;\u0026minus;\u0026nbsp;x\u0026nbsp;y\u003csub\u003e0\u003c/sub\u003e\u0026nbsp;=\u0026nbsp;0 to get:\n\n```js\nvar airy = function(x, y) {\n  return [y[1], x * y[0]];\n}\n```\nThere's also a [demo page][airydemo] for this equation too.\n\nYou might also enjoy a demo of the [Lorenz attractor][lorenz] or\n[Van der Pol equation][vanderpol]!\n\n#### Tests\nThis project comes with a mocha test suite. The suite contains other\nexamples of second-order equations which have been translated to\nsystems of first order equations you may examine.\n\n[odex]: http://www.unige.ch/~hairer/software.html\n[gbs]: https://en.wikipedia.org/wiki/Bulirsch%E2%80%93Stoer_algorithm\n[lv]: https://en.wikipedia.org/wiki/Lotka%E2%80%93Volterra_equations\n[lvdemo]: http://blog.littleredcomputer.net/math/odex/js/2016/04/03/lotka-volterra.html\n[airy]: https://en.wikipedia.org/wiki/Airy_function\n[airydemo]: http://blog.littleredcomputer.net/jekyll/update/2016/04/03/diffeq-javascript.html\n[lorenz]: http://blog.littleredcomputer.net/math/odex/js/2016/04/03/lorenz-attractor.html\n[vanderpol]: http://blog.littleredcomputer.net/math/odex/js/2016/04/20/van-der-pol.html\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flittleredcomputer%2Fodex-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flittleredcomputer%2Fodex-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flittleredcomputer%2Fodex-js/lists"}