{"id":24560416,"url":"https://github.com/fgasdia/romberg.jl","last_synced_at":"2025-04-19T14:44:11.851Z","repository":{"id":55473407,"uuid":"262955167","full_name":"fgasdia/Romberg.jl","owner":"fgasdia","description":"Romberg integration routine in Julia","archived":false,"fork":false,"pushed_at":"2020-12-28T18:00:46.000Z","size":188,"stargazers_count":8,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-27T01:13:39.519Z","etag":null,"topics":["julia","numerical-integration","romberg"],"latest_commit_sha":null,"homepage":null,"language":"Julia","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/fgasdia.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}},"created_at":"2020-05-11T06:15:52.000Z","updated_at":"2022-03-30T12:12:43.000Z","dependencies_parsed_at":"2022-08-15T01:10:29.437Z","dependency_job_id":null,"html_url":"https://github.com/fgasdia/Romberg.jl","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fgasdia%2FRomberg.jl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fgasdia%2FRomberg.jl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fgasdia%2FRomberg.jl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fgasdia%2FRomberg.jl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fgasdia","download_url":"https://codeload.github.com/fgasdia/Romberg.jl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249716784,"owners_count":21315068,"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":["julia","numerical-integration","romberg"],"created_at":"2025-01-23T07:16:40.203Z","updated_at":"2025-04-19T14:44:11.829Z","avatar_url":"https://github.com/fgasdia.png","language":"Julia","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Romberg.jl\n\n[![Build Status](https://travis-ci.com/fgasdia/Romberg.jl.svg?branch=master)](https://travis-ci.com/fgasdia/Romberg.jl)\n\nA simple Julia package to perform Romberg integration over discrete 1-dimensional\ndata.\n\n[Romberg integration](https://en.wikipedia.org/wiki/Romberg's_method) combines trapezoidal integration with [Richardson extrapolation](https://github.com/JuliaMath/Richardson.jl) for improved accuracy. This package is\nmeant to be used for integrating discrete data sampled with equal spacing. If\nyour integrand can be evaluated at arbitrary points, then other methods are probably a better\nchoice, e.g. [QuadGK.jl](https://github.com/JuliaMath/QuadGK.jl). Similarly,\nif you have discrete data sampled at generic _unequally_ spaced points, you probably\nneed to use a low-order method like [Trapz.jl](https://github.com/francescoalemanno/Trapz.jl).\n\n## Usage\n\nFirst, install with the [Julia package manager](https://docs.julialang.org/en/v1/stdlib/Pkg/):\n\n```jl\n] add Romberg\n```\n\nThe Romberg module exports a single function, `romberg(x,y)`, or alternatively `romberg(Δx,y)`,\nthat returns a tuple `(I,E)` of the estimated integral `I` and a rough upper bound `E` on\nthe error.\n```jl\nusing Romberg\n\nx = range(0, stop=π, length=2^8+1)\ny = sin.(x)\n\nromberg(x, y)\n```\n\n## Limitations\n\n### Equally spaced `x`\n\nUnlike [Trapz.jl](https://github.com/francescoalemanno/Trapz.jl), Romberg\nintegration is a [Newton-Cotes](https://en.wikipedia.org/wiki/Newton%E2%80%93Cotes_formulas)\nformula which requires each element of `x` be equally spaced. This is indirectly\nenforced in `Romberg` by requiring `x::AbstractRange`, or directly by passing the\nspacing `Δx` between points.\n\n### Most effective if `length(x) - 1` a power of 2\n\nRomberg integration works by recursively breaking the integral down into\ntrapezoidal-rule evaluations using larger and larger spacings `Δx` and then\nextrapolating back towards `Δx → 0`.   This works by [factorizing](https://github.com/JuliaMath/Primes.jl) `length(x) - 1`,\nand therefore works best when `length(x) - 1` has **many small factors**, ideally\nbeing a power of two.\n\n(In the event that `length(x) - 1` is prime, the `romberg` function is nearly\nequivalent to the trapezoidal rule, since it extrapolates only from 2 points to\n`length(x)` points.)\n\n### 1-dimensional\n\nCurrently `Romberg` only allows integration over a single dimension, so\n`y::AbstractVector`.\n\n## Comparison to `trapz`\n\nGiven the limitations of `Romberg`, why use it over `Trapz`? For discrete\nsamples of an underlying smooth function, Romberg integration can obtain\n_significantly more accurate_ estimates at relatively _low additional\ncomputational cost_ over trapezoidal integration for a given number of samples.\nMoreover, unlike the trapezoidal rule, the `romberg` function also *returns an error estimate*.\n\nHere are some examples:\n\n### 1)\n\n![\\displaystyle \\int_0^\\pi \\sin(x) \\,\\mathrm{d}x = 2](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle%20%5Cint_0%5E%5Cpi%20%5Csin(x)%20%5C%2C%5Cmathrm%7Bd%7Dx%20%3D%202)\n\n```jl\nusing BenchmarkTools\nusing Trapz, Romberg\n\nx = range(0, stop=π, length=2^6+1)\ny = sin.(x)\nexact_answer = 2\n\ntans = trapz(x, y)\nrans, _ = romberg(x, y)\n```\n\n```jl\njulia\u003e exact_answer - tans\n0.0004016113599627502\n\njulia\u003e exact_answer - rans\n4.440892098500626e-16\n```\n\n```jl\njulia\u003e @btime trapz($x, $y);\n  340.834 ns (1 allocation: 96 bytes)\n\njulia\u003e @btime romberg($x, $y);\n  515.078 ns (1 allocation: 192 bytes)\n```\n\nSo `romberg` is ~30% slower than `trapz`, but achieves nearly machine-precision accuracy,\n~12 digits more accurate than `trapz`. Even if 500 times as many samples of the\nfunction were to be used in `trapz`, it would still be ~7 digits less accurate than `romberg`.\n\n### 2)\n\n![\\displaystyle \\int_0^1 x^3 \\,\\mathrm{d}x = 0.25](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle%20%5Cint_0%5E1%20x%5E3%20%5C%2C%5Cmathrm%7Bd%7Dx%20%3D%200.25)\n\n```jl\nx = range(0, stop=1, length=2^4+1)\ny = x.^3\nexact_answer = 0.25\n\ntans = trapz(x, y)\nrans, _ = romberg(x, y)\n```\n\n```jl\njulia\u003e exact_answer - tans\n-0.0009765625\n\njulia\u003e exact_answer - rans\n0.0\n```\n\n`romberg` is able to obtain the exact answer (and in general is exact for polynomials\nof sufficiently low degree), compared to ~3 digits of accuracy\nfor `trapz`, at the cost of ~2× the run time.\n\n### 3)\n\n![\\displaystyle \\int_0^\\pi \\sin(mx)\\cos(nx) \\,\\mathrm{d}x = \\frac{2m}{m^2 - n^2}, \\quad mn \\; \\text{odd}](https://render.githubusercontent.com/render/math?math=%5Cdisplaystyle%20%5Cint_0%5E%5Cpi%20%5Csin(mx)%5Ccos(nx)%20%5C%2C%5Cmathrm%7Bd%7Dx%20%3D%20%5Cfrac%7B2m%7D%7Bm%5E2%20-%20n%5E2%7D%2C%20%5Cquad%20mn%20%5C%3B%20%5Ctext%7Bodd%7D)\n\n```jl\nm = 3\nn = 4\nx = range(0, stop=π, length=2^6+1)\ny = sin.(m*x).*cos.(n*x)\nexact_answer = 2*m/(m^2 - n^2)\n\ntans = trapz(x, y)\nrans, _ = romberg(x, y)\n```\n\n```jl\njulia\u003e exact_answer - tans\n0.0012075513578178043\n\njulia\u003e exact_answer - rans\n-1.2385595582475872e-7\n```\n\n`romberg` is ~4 digits better accuracy than `trapz` and ~50% greater run time.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffgasdia%2Fromberg.jl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffgasdia%2Fromberg.jl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffgasdia%2Fromberg.jl/lists"}