{"id":17352371,"url":"https://github.com/maroba/multipoles","last_synced_at":"2025-04-06T21:14:55.754Z","repository":{"id":40680434,"uuid":"164120058","full_name":"maroba/multipoles","owner":"maroba","description":"A Python package for multipole expansions of electrostatic or gravitational potentials","archived":false,"fork":false,"pushed_at":"2024-12-21T18:03:01.000Z","size":2941,"stargazers_count":43,"open_issues_count":2,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-30T20:11:13.122Z","etag":null,"topics":["electrostatic-potential","mathematics","physics","scientific-computing"],"latest_commit_sha":null,"homepage":"","language":"Python","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/maroba.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":["maroba"]}},"created_at":"2019-01-04T14:54:32.000Z","updated_at":"2025-03-22T17:58:58.000Z","dependencies_parsed_at":"2023-12-07T17:44:44.812Z","dependency_job_id":"4c176b9a-bd20-4b28-b620-cc0bd5f13a86","html_url":"https://github.com/maroba/multipoles","commit_stats":{"total_commits":56,"total_committers":6,"mean_commits":9.333333333333334,"dds":0.25,"last_synced_commit":"cfe61d1e99f4df6b05357dcef4117a8bf01a6cd4"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maroba%2Fmultipoles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maroba%2Fmultipoles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maroba%2Fmultipoles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maroba%2Fmultipoles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maroba","download_url":"https://codeload.github.com/maroba/multipoles/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247550690,"owners_count":20956987,"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":["electrostatic-potential","mathematics","physics","scientific-computing"],"created_at":"2024-10-15T17:13:37.552Z","updated_at":"2025-04-06T21:14:55.730Z","avatar_url":"https://github.com/maroba.png","language":"Python","funding_links":["https://github.com/sponsors/maroba"],"categories":[],"sub_categories":[],"readme":"# multipoles\n\n\u003cp\u003e\u003ca href=\"https://badge.fury.io/py/multipoles\"\u003e \u003cimg src=\"https://badge.fury.io/py/multipoles.svg?branch=kill_cache=1\" alt=\"PyPI version\"\u003e\u003c/a\u003e \n\u003ca href=\"\"\u003e \u003cimg src=\"https://github.com/maroba/multipoles/actions/workflows/python-app.yml/badge.svg\" alt=\"build\"\u003e\u003c/a\u003e\n\u003ca href=\"https://codecov.io/gh/maroba/multipoles\"\u003e \u003cimg src=\"https://codecov.io/gh/maroba/multipoles/branch/master/graph/badge.svg?token=JNH9SP7BRG\" alt=\"\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n*multipoles* is a Python package for multipole expansions of the solutions of the Poisson equation (e.g. electrostatic\nor gravitational potentials). It can handle discrete and continuous charge or mass distributions.\n\n## Installation\n\nSimply use `pip`:\n\n```\npip install --upgrade multipoles\n```\n\n## Documentation\n\nThe documentation is available [here](https://maroba.github.io/multipoles/).\n\n## Theory\n\nFor a given function $\\rho(x,y,z)$, the solution $\\Phi(x,y,z)$ of the Poisson equation $\\nabla^2\\Phi=-4\\pi \\rho$ with\nvanishing Dirichlet boundary conditions at infinity is\n\n$$\\Phi(x,y,z)=\\int d^3r'\\frac{\\rho(r')}{|r-r'|}$$\n\nExamples of this are the electrostatic and Newtonian gravitational potential.\nIf you need to evaluate $\\Phi(x,y,z)$ at many points, calculating the integral for each point is computationally\nexpensive. As a faster alternative, we can express $\\Phi(x,y,z)$ in terms of the multipole moments $q_{lm}$ or $I_\n{lm}$ (note some literature uses the subscripts $(\\cdot)_{nm}$):\n\n$$\\Phi(x,y,z)=\\sum_{l=0}^\\infty\\underbrace{\\sqrt{\\frac{4\\pi}{2l+1}}\\sum_{m=-l}^lY_{lm}(\\theta, \\varphi)\\frac{q_\n{lm}}{r^{l+1}}}_{\\Phi^{(l)}}$$\n\nfor a exterior expansion, or\n\n$$\\Phi(x,y,z)=\\sum_{l=0}^\\infty\\underbrace{\\sqrt{\\frac{4\\pi}{2l+1}}\\sum_{m=-l}^lY_{lm}(\\theta, \\varphi)I_{lm}r^{l}}_\n{\\Phi^{(l)}}$$\n\nfor an interior expansion; where $r, \\theta, \\varphi$ are the usual spherical coordinates corresponding to the cartesian\ncoordinates $x, y, z$ and $Y_{lm}(\\theta, \\varphi)$ are the spherical harmonics.\n\nThe multipole moments for the exterior expansion are:\n\n$$q_{lm} = \\sqrt{\\frac{4\\pi}{2l+1}}\\int d^3 r' \\rho(r')r'^l Y^*_{lm}(\\theta', \\varphi')$$\n\nand the multipole moments for the interior expansion are:\n\n$$I_{lm} = \\sqrt{\\frac{4\\pi}{2l+1}}\\int d^3 r' \\frac{\\rho(r')}{r'^{l+1}} Y^*_{lm}(\\theta', \\varphi')$$\n\nThis approach is usually much faster because the contributions $\\Phi^{(l)}$ are getting smaller with increasing \u003ci\u003e\nl\u003c/i\u003e. So we just have to calculate a few integrals for obtaining some $q_{lm}$ or $I_{lm}$.\n\nSome literature considers the $\\sqrt{\\frac{4\\pi}{2l+1}}$ as part of the definition of $Y_{lm}(\\theta, \\varphi)$.\n\n## Examples\n\n### Discrete Charge Distribution\n\nAs example for a discrete charge distribution we model two point charges with positive and negative unit charge located\non the z-axis:\n\n```python\nfrom multipoles import MultipoleExpansion\n\n# Prepare the charge distribution dict for the MultipoleExpansion object:\n\ncharge_dist = {\n    'discrete': True,  # point charges are discrete charge distributions\n    'charges': [\n        {'q': 1, 'xyz': (0, 0, 1)},\n        {'q': -1, 'xyz': (0, 0, -1)},\n    ]\n}\n\nl_max = 2  # where to stop the infinite multipole sum; here we expand up to the quadrupole (l=2)\n\nPhi = MultipoleExpansion(charge_dist, l_max)\n\n# We can evaluate the multipole expanded potential at a given point like this:\n\nx, y, z = 30.5, 30.6, 30.7\nvalue = Phi(x, y, z)\n\n# The multipole moments are stored in a dict, where the keys are (l, m) and the values q_lm:\nPhi.multipole_moments\n```\n\n### Continuous Charge Distribution\n\nAs an example for a continuous charge distribution, we smear out the point charges from the previous\nexample:\n\n```python\nfrom multipoles import MultipoleExpansion\nimport numpy as np\n\n# First we set up our grid, a cube of length 10 centered at the origin:\n\nnpoints = 101\nedge = 10\nx, y, z = [np.linspace(-edge / 2., edge / 2., npoints)] * 3\nXYZ = np.meshgrid(x, y, z, indexing='ij')\n\n\n# We model our smeared out charges as gaussian functions:\n\ndef gaussian(XYZ, xyz0, sigma):\n    g = np.ones_like(XYZ[0])\n    for k in range(3):\n        g *= np.exp(-(XYZ[k] - xyz0[k]) ** 2 / sigma ** 2)\n    g *= (sigma ** 2 * np.pi) ** -1.5\n    return g\n\n\nsigma = 1.5  # the width of our gaussians\n\n# Initialize the charge density rho, which is a 3D numpy array:\nrho = gaussian(XYZ, (0, 0, 1), sigma) - gaussian(XYZ, (0, 0, -1), sigma)\n\n# Prepare the charge distribution dict for the MultipoleExpansion object:\n\ncharge_dist = {\n    'discrete': False,  # we have a continuous charge distribution here\n    'rho': rho,\n    'xyz': XYZ\n}\n\n# The rest is the same as for the discrete case:\n\nl_max = 2  # where to stop the infinite multipole sum; here we expand up to the quadrupole (l=2)\n\nPhi = MultipoleExpansion(charge_dist, l_max)\n\nx, y, z = 30.5, 30.6, 30.7\nvalue = Phi(x, y, z)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaroba%2Fmultipoles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaroba%2Fmultipoles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaroba%2Fmultipoles/lists"}