{"id":22669767,"url":"https://github.com/yurlungur/pyballd","last_synced_at":"2025-04-12T11:33:35.180Z","repository":{"id":146228879,"uuid":"90983147","full_name":"Yurlungur/pyballd","owner":"Yurlungur","description":"A Python-Based Elliptic Solver in Axisymmetry","archived":false,"fork":false,"pushed_at":"2017-06-29T00:41:48.000Z","size":7857,"stargazers_count":5,"open_issues_count":2,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-26T06:22:06.010Z","etag":null,"topics":["elliptic-pdes","numerical-analysis","numerical-methods","numerical-modelling","partial-differential-equations","pde","physics","physics-2d","spectral-methods"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Yurlungur.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":"2017-05-11T13:36:21.000Z","updated_at":"2025-03-20T15:15:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"af1e5a1e-e543-472c-ab1f-966b84fc1b82","html_url":"https://github.com/Yurlungur/pyballd","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yurlungur%2Fpyballd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yurlungur%2Fpyballd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yurlungur%2Fpyballd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yurlungur%2Fpyballd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Yurlungur","download_url":"https://codeload.github.com/Yurlungur/pyballd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248560389,"owners_count":21124644,"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":["elliptic-pdes","numerical-analysis","numerical-methods","numerical-modelling","partial-differential-equations","pde","physics","physics-2d","spectral-methods"],"created_at":"2024-12-09T15:40:01.992Z","updated_at":"2025-04-12T11:33:35.163Z","avatar_url":"https://github.com/Yurlungur.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/Yurlungur/pyballd.svg?branch=master)](https://travis-ci.org/Yurlungur/pyballd)\n\npyballd\n=======\n\nAuthor: Jonah Miller (jonah.maxwell.miller@gmail.com)\n\nA Pseudospectral Elliptic Solver for Axisymmetric Problems Implemented\nin Python\n\n# Installation\n\nSimply clone the repository and use\n\n```bash\npython setup.py install\n```\n\n# Pseudospectral Derivatives\n\nPyballd uses Chebyshev pseudospectral derivatives to attain very high\naccuracy with fairly low resolution. For example, if we numerically\ntake second-order derivatives of this function:\n\n![analytic function](figs/test_function.png)\n\nand vary the number of points (or alternatively the maximum order of\npolynomial used for differentiation), we find that our error decays\nexponentially with the number of points. This is called \"spectral\" or\n\"evanescent\" convergence:\n\n![evanescent convergence](figs/orthopoly_errors.png)\n\n# Domain\n\nThe appropriate domain for an axisymmetric problem is\n\n![axisymmetric domain base](eqns/domain_base.gif)\n\nwhere *r\u003csub\u003eh\u003c/sub\u003e* is some minimum radius. Infinite domains are\ndifficult to handle. Therefore, we define\n\n![definition of x for most boundaries](eqns/def_x_dirichlet.gif)\n\nfor most boundary situations or (following the work of [1])\n\n![definition of x](eqns/def_x_bh.gif)\n\nwhen *r\u003csub\u003eh\u003c/sub\u003e* is a black hole event horizon. Then, following\nBoyd [2], we then define\n\n![definition of X](eqns/def_X_new.gif)\n\nfor some characteristic length scale *L* so that *X* is defined on the\ndomain *[-1,1]*. We perform our differentiation on *X*, which has no\neffect on the original PDE system except the introduction of Jacobian\nterms of the form\n\n![jacobian terms](eqns/X_Jacobian.gif)\n\nin a few places. Since one may want to assume additional (or\ndifferent!) symmetry in the longitudinal direction, we do not impose\nany restriction there.\n\n## Jacobian for the Compactified Domain\n\nWhen *x* is defined as \n\n![definition of x for most boundaries](eqns/def_x_dirichlet.gif)\n\nthe Jacobian for the coordinate transformation looks like\n\n![Jacobian for the coordinate transformation](figs/domain_dXdr.png)\n\nAs we shall see, this spectral method can efficiently represent both\nexponential and algebraic decay with spectral accuracy.\n\n## Convergence on the Compactified Domain\n\nThe convergence of the scheme depends senitively on the characteristic\nlength scale *L*. Generically it will be *spectral* but\n*subgeometric*, meaning it's not quite as fast as in the non-compact\ncase.\n\n### Functions that Decay Rationally\n\nConsider this function\n\n![test function on compact domain](figs/domain_test_function_alg_2d.png)\n\nwhich has this derivative\n\n![derivative of test function on compact domain](figs/deriv_domain_test_function_alg_2d.png)\n\nOn the compact domain (on the equator), this function becomes\n\n![test function on equator](figs/domain_test_function_alg.png)\n\nwith derivative\n\n![derivative of test function on equator](figs/deriv_domain_test_function_alg.png)\n\nWe achieve best convergence for this function with *L=1*:\n\n![errors on compactified domain](figs/domain_l1_errors_alg.png)\n\n### Functions that decay exponentially\n\nOn the other hand, consider this function:\n\n![test function on compact domain](figs/domain_test_function_exp_2d.png)\n\nwhich has this derivative\n\n![derivative of test function on compact domain](figs/deriv_domain_test_function_exp_2d.png)\n\nOn the compact domain (on the equator), this function becomes\n\n![test function on equator](figs/domain_test_function_exp.png)\n\nwith derivative\n\n![derivative of test function on equator](figs/deriv_domain_test_function_exp.png)\n\nWe achieve best convergence for this function with\n\n![Lexp](eqns/Lexp.gif)\n\nas shown here:\n\n![errors on compactified domain](figs/domain_l1_errors_exp.png)\n\n# Solving an Elliptic PDE\n\nIn Pyballd, an elliptic system is defined via a *residual.* A residual\n\n![residual](eqns/residual.gif)\n\nacts on a state vector *u* and its first and second derivatives in (in\nour case, axisymmetry) *r* and \u0026#952;. If\n\n![residual vanishes](eqns/residual_vanishes.gif)\n\nthen *u(r,\u0026#952;)* is a solution to the PDE system.\n\nAn elliptic PDE is not well-posed without the addition of boundary\nconditions, which select for the particular solution. At infinity\n(*X=1*), we automatically demand that the solution must vanish. (In\nother words, we demand that all solutions are square-integrable.)\n\nDirichlet, Neumann, or Robin boundary conditions can be imposed on\nthe inner radius (*r_h*), the position of minimum \u0026#952; (often the\naxis of symmetry), and the position of maximum \u0026#952; (often the axis\nof symmetry or the equator).\n\nIn the case of black-hole like compactifications, where\n\n![definition of x](eqns/def_x_bh.gif)\n\nwe automatically impose Von-Neumann boundary conditions at the inner\nboundary such that\n\n![neumann regularity condition](eqns/von-neumann-regularity-condition.gif)\n\nwhich is a regularity condition we need to impose on solutions in\nthese coordinates.\n\n## Pyballd's API\n\nPyballd simply requires that the user pass in functions that vanish\nwhen the residual and boundary conditions are satisfied. Along with\ninformation about the domain, such as the value of *r\u003csub\u003eh\u003c/sub\u003e*,\nthis is sufficient information to construct a solution. \n\n## An Example: Poisson's Equation\n\nPoisson's equation is\n\n![poissons equation generic](eqns/poisson_generic.gif),\n\nor, in spherical coordinates it is\n\n![poisson in spherical coordinates](eqns/poisson_spherical_coordinates.gif).\n\nIf we assume axisymmetry so that the azimuthal derivatives vanish and\nmultiply both sides of the equation by the appropriate factors, we\nattain\n\n![poisson in axisymmetry](eqns/poisson_axisymmetry.gif).\n\nFor simplicity, we further restrict ourselves to the source-free case and attain\n\n![lapplace eqn in axisymmetry](eqns/lapplace_axisymmetry.gif).\n\nWe would like to solve this problem using pyballd.\n\nWe begin by importing `pyballd` and `numpy`.\n\n```python\nimport pyballd\nimport numpy as np\n```\n\n`pyballd` expects a residual, which defines the PDE system. The PDE is\nsatisfied when the residual vanishes. We define ours as\n\n```python\ndef residual(r,theta,u,d):\n    u = u[0]\n    out = (2*np.sin(theta)*r*d(u,1,0)\n           + r*r*np.sin(theta)*d(u,2,0)\n           + np.cos(theta)*d(u,0,1)\n           + np.sin(theta)*d(u,0,2))\n    out = out.reshape(tuple([1]) + out.shape)\n    return out\n```\n\nHere `d` is a derivative operator. So `d(u,2,0)` corresponds to two\nderivatives with respect to *r* of *u*, while `d(u,0,2)` corresponds\nto two derivatives with respect to \u0026#952;.\n\nThe weird array reshaping is an artifact of the fact that `pyballd` is\ndesigned for vector and tensor equations, not just scalar\nequations. Therefore, scalars must be treated as vectors of length 1.\n\n`pyballd` allso expects a boundary condition for the inner boundary. We\nchoose a Dirichlet boundary condition and define it as:\n\n```python\nk = 4\na = 2\ndef bdry_X_inner(theta,u,d):\n\tu = u[0]\n\tout = u - a*np.cos(k*theta)\n\tout = out.reshape(tuple([1]) + out.shape)\n\treturn out\n```\n\nThis works a lot like `residual` defined above. However, it will only\nbe evaluated at the inner boundary. The boundary condition is\nsatisfied when `bdry_X_inner` vanishes.\n\nNonlinear elliptic systems are not necessarily unique. (And even\nlinear ones may be difficult to uniquely solve numerically.)\nTherefore, we must feed the solver with an initial guess for the\nsolution. We define ours as\n\n```python\ndef initial_guess(r,theta):\n\tout = 1./r\n\tout = out.reshape(tuple([1]) + out.shape)\n\treturn out\n```\n\nwhich is a simple square integrable function. It's not a solution that\nmatches the boundary conditions. However, it should be sufficiently\nclose to the true solution to allow for convergence.\n\nFinally, we ask `pyballd` to generate a solution by calling\n`pyballd.pde_solve_once`. Because it's a spectral method, you don't\nneed many nodes! For example:\n\n```python\nSOLN,s = pyballd.pde_solve_once(residual,\n                                r_h = 1.0,\n                                order_X = 24,\n                                order_theta = 6\n                                theta_max = np.pi/2,\n                                bdry_X_inner = bdry_X_inner,\n                                initial_guess = initial_guess)\n```\n\n`pyballd.pde_solve_once` returns the solution on the product grid of\ncolocation points and a *discretization object* `s`, which can\ndifferentiate a function defined on the colocation points, or\ninterpolate it to a uniform grid. For example:\n\n```python\nSOLN = SOLN[0]\nr = np.linspace(r_h,4,200)\ntheta = np.linspace(0,np.pi/2,200)\nR,THETA = np.meshgrid(r,theta,indexing='ij')\ninterpolator = s.get_interpolator_of_r(SOLN)\nsoln_interp = interpolator(R,THETA)\nx,z = R*np.sin(THETA), R*np.cos(THETA)\nplt.pcolor(mx,mz,soln_interp)\nplt.xlim(0,2)\nplt.ylim(0,2)\n```\n\nwill produce a beautiful plot of the solution interpolated to a finer\ngrid, such as this one:\n\n![solution to the Poisson equation](figs/poisson_solution.png)\n\nBoth `pde_solve_once` and discretization objects, called\n`PyballdStencil`s in the code, have a large number of options and\ndefaults. For a full description of of these, see the help strings\nassociated with them.\n\n# References\n\n[1] Herderio, Radu, Runarrson. \"Kerr black holes with Proca\nhair.\" *Classical and Quantum Gravity* **33-15** (2016).\n\n[2] Boyd, John P. \"Orthogonal rational functions on a semi-infinite\ninterval.\" *Journal of Computational Physics* **70.1** (1987): 63-88.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyurlungur%2Fpyballd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyurlungur%2Fpyballd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyurlungur%2Fpyballd/lists"}