Poisson Solver in Tranformed 2D Space using Finite Difference
Project description
Poisson 2D Transform
This is a finite difference solver for poisson equations in curved 2d space.
Many different poisson solvers exist but few solve for curved-spaces.
This package provides that in a very simple to use interface.
How to use
Install
pip install poisson_transform
Use
First you specify the following inputs:
- f: The RHS of poisson's equation (as a function that takes input coordinates and outputs a value). If empty will set
f(x, y)=1
. - g: the Boundary conditions of poisson's equation. If empty will set BCs to Dirichlet.
g
should be a function that takes in coordinates and returns (a, b, g) for the boundary condition such thata*u + b*∂u/∂n = g
on ∂Ω (boundary of domain)- For example, returning
(1, 0, 0)
setsu=0
which is a dirichlet conditions on that point. - For example, returning
(0, 1, 0)
sets∂u/∂n=0
which is a neumann conditions on that point. - For example, returning
(1, 2, 3)
setsu + 2*∂u/∂n = 3
on that point.
- For example, returning
- Specify the transformation to be used
T_x, T_y
wherex = T_x(ksi)
andy = T_y(eta)
.ksi
andeta
are the identity coordinates: $\xi \in [0, 1]$ and $\eta \in [0, 1]$. If empty then the identity transformation will be used.- To do this, simply obtain the variables
ksi, eta
with the following lineksi, eta = Transformation.get_ksi_eta()
- Then, define an arbitrary transformation on the unit square
Tx = ksi**2 + 0.75*ksi ; Ty = (1-eta)*(1.25*ksi) + eta*(2.75-ksi)
. This step can be arbitrarily complex and usesSympy
under the hood to perform the calculations. See below examples for more complex transformations such as rotated ellipses. - Then, get the
transformation
object to be given to the solver usingtransformation = Transformation(ksi, eta, Tx, Ty)
- To do this, simply obtain the variables
- Finally, call
solve_and_plot
with the number of point to use for the mesh.- Since the above inputs can be left blank, the simplest use case is
solve_and_plot(Nx=30, Ny=30)
which will solve poisson's equation on the unit square with Dirichlet BCs using a mesh grid of ($30 \times 30$). - To provide all the above inputs, simply write
solve_and_plot(Nx=29, Ny=29, transformation=transformation, f=f, g=g)
- Since the above inputs can be left blank, the simplest use case is
See below for example uses.
Note: This package has not been tested extensively. If you find an issue please report it (or make a pull-request if fixed)
Examples
from poisson_transform import solve_and_plot
solve_and_plot(Nx=30, Ny=30)
22:54:15 Warning: both f and g are None. Are you sure this is what you want?
22:54:15 f is None. Setting f=1
22:54:15 g is None. Setting Dirichlet BCs
22:54:17 Integral: 0.03500889856987609
from poisson_transform import solve_and_plot
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
if (x - 0.3)**2 + (y - 0.4)**2 < 0.2**2 :
return 10
return 0
solve_and_plot(Nx=31, Ny=31, f=f)
22:54:19 g is None. Setting Dirichlet BCs
22:54:21 Integral: 0.06935111999589494
from poisson_transform import solve_and_plot
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
if 0.45 < x < 0.55:
return 10
return 0
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if ksi == 0: # left, neumann = 0
return (0, 1, 0)
if eta == 1: # top, dirichlet = 0
return (1, 0, 0)
if ksi == 1: # right, neumann = 0
return (0, 1, 0)
if eta == 0: # bottom, dirichlet = 0
return (1, 0, 0)
solve_and_plot(Nx=31, Ny=31, f=f, g=g)
22:54:24 Integral: 0.0832355038593408
from poisson_transform import Transformation, solve_and_plot, plotGeometry
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
if 0.45 < ksi < 0.55:
return 100
return 0
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if ksi == 0: # left, neumann = 0
return (0, 1, 0)
if eta == 1: # top, dirichlet = 0
return (1, 0, 0)
if ksi == 1: # right, neumann = 0
return (0, 1, 0)
if eta == 0: # bottom, dirichlet = 0
return (1, 0, 0)
ksi, eta = Transformation.get_ksi_eta()
Tx = ksi**2 + 0.75*ksi
Ty = (1-eta)*(1.25*ksi) + eta*(2.75-ksi)
transformation = Transformation(ksi, eta, Tx, Ty)
# plotGeometry(29, 29, transformation)
solve_and_plot(Nx=29, Ny=29, transformation=transformation, f=f, g=g)
22:54:28 Integral: 5.2916463228833726
from poisson_transform import Transformation, plotGeometry, solve_and_plot
ksi, eta = Transformation.get_ksi_eta()
Tx = ksi**2 + 0.1*ksi
Ty = 1/2*ksi*(1-eta) + eta
transformation = Transformation(ksi, eta, Tx, Ty)
plotGeometry(Nx=29, Ny=29, transformation=transformation)
solve_and_plot(Nx=29, Ny=29, transformation=transformation)
22:54:30 Warning: both f and g are None. Are you sure this is what you want?
22:54:30 f is None. Setting f=1
22:54:30 g is None. Setting Dirichlet BCs
22:54:32 Integral: 0.016063603756651158
import numpy as np
from poisson_transform import Transformation, solve_and_plot
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
if (0.7 < ksi < 0.8 and 0.6 < eta < 0.7) or (0.3 < ksi < 0.4 and 0.3 < eta < 0.4) or (0.1 < ksi < 0.2 and 0.4 < eta < 0.55):
return 100
return 0
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if ksi == 0: # left, neumann = 0
return (0, 1, 0)
if ksi == 1: # right, neumann = 0
return (0, 1, 0)
if eta == 1: # top, dirichlet = 0
return (1, 0, 0)
if eta == 0: # bottom, dirichlet = 0
return (1, 0, 0)
ksi, eta = Transformation.get_ksi_eta()
Tx = ksi
ellipse_bottom = (ksi-0.5)**2 + 0.2
ellipse_top = 1 - ellipse_bottom
Ty = ellipse_bottom*(1-eta) + ellipse_top*eta
rotate_phi = -1.2*np.pi/4
Tx_rot, Ty_rot = np.cos(rotate_phi)*Tx - np.sin(rotate_phi)*Ty, np.sin(rotate_phi)*Tx + np.cos(rotate_phi)*Ty
solve_and_plot(Nx=15, Ny=15, transformation=Transformation(ksi, eta, Tx_rot, Ty_rot), f=f, g=g, contour_levels=20)
22:54:35 Integral: 0.021996048708012562
import importlib
import poisson_transform
importlib.reload(poisson_transform)
import numpy as np
from poisson_transform import Transformation, solve_and_plot
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
# centers = ((0.7, 0.6, 0.1), (0.3, 0.3, 0.1), (0.1, 0.4, 0.1))
centers = ((0.7, 0.0, 0.1), (0.9, -0.4, 0.1), (0.5, 0.0, 0.1))
if any((x - xc)**2 + (y - yc)**2 < r**2 for xc, yc, r in centers):
return 100
return 0
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if ksi == 0: # left, neumann = 0
return (0, 1, 0)
if ksi == 1: # right, neumann = 0
return (0, 1, 0)
if eta == 1: # top, dirichlet = 0
return (1, 0, 0)
if eta == 0: # bottom, dirichlet = 0
return (1, 0, 0)
ksi, eta = Transformation.get_ksi_eta()
Tx = ksi
ellipse_bottom = (ksi-0.5)**2 + 0.2
ellipse_top = 1 - ellipse_bottom
Ty = ellipse_bottom*(1-eta) + ellipse_top*eta
rotate_phi = -1.2*np.pi/4
Tx_rot, Ty_rot = np.cos(rotate_phi)*Tx - np.sin(rotate_phi)*Ty, np.sin(rotate_phi)*Tx + np.cos(rotate_phi)*Ty
solve_and_plot(Nx=15, Ny=15, transformation=Transformation(ksi, eta, Tx_rot, Ty_rot), f=f, g=g, contour_levels=20)
22:54:37 Integral: 0.20123610428427863
import sympy
from poisson_transform import Transformation, solve_and_plot, plotGeometry
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
return 1
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if eta == 1: # top, neumann = 0
return (0, 1, 0)
if ksi == 0: # left, dirichlet = 0
return (1, 0, 0)
if ksi == 1: # right, dirichlet = 0
return (1, 0, 0)
if eta == 0: # bottom, dirichlet = 0
return (1, 0, 0)
ksi, eta = Transformation.get_ksi_eta()
Tx = (2*ksi+0.25-eta)
bottom_curve = 0.5*sympy.Abs(Tx+1e-6) # add 1e-6 to avoid derivative at kink
Ty = bottom_curve + (1.8 - bottom_curve)*eta
plotGeometry(38, 38, Transformation(ksi, eta, Tx, Ty))
solve_and_plot(Nx=38, Ny=38, transformation=Transformation(ksi, eta, Tx, Ty), f=f, g=g)
22:54:52 Integral: 0.46734117404100667
import importlib
import poisson_transform
importlib.reload(poisson_transform)
import sympy
from poisson_transform import Transformation, solve_and_plot, plotGeometry
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
return 1
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if eta == 1: # top, neumann = 0
return (0, 1, 0)
if ksi == 0: # left, neumann = 0
return (0, 1, 0)
if ksi == 1: # right, dirichlet = 0
return (1, 0, 0)
if eta == 0: # bottom, dirichlet = 0
return (1, 0, 0)
ll, cc, hh = 3, 0.5, 1
bb = np.sqrt((1/2*ll - hh + cc)**2 - cc**2)
ksi, eta = Transformation.get_ksi_eta()
Tx = ksi*bb
Ty = cc*ksi*(1-eta)+hh*eta
# plotGeometry(21, 21, Transformation(ksi, eta, Tx, Ty))
solve_and_plot(Nx=38, Ny=38, transformation=Transformation(ksi, eta, Tx, Ty), f=f, g=g)
22:54:57 Integral: 0.06464775169432217
from poisson_transform import Transformation, solve_and_plot
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
return 0
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if ksi == 0: # left, dirichlet = 0.5
return (1, 0, 0.5)
if ksi == 1: # right, dirichlet = 1.2
return (1, 0, 1.2)
if eta == 0: # bottom, dirichlet = -0.75
return (1, 0, -0.75)
if eta == 1: # top, dirichlet = -1
return (1, 0, -1)
ksi, eta = Transformation.get_ksi_eta()
Tx = 12*ksi - 6
Ty = 6*eta - 3
solve_and_plot(Nx=30, Ny=30, transformation=Transformation(ksi, eta, Tx, Ty), f=f, g=g)
22:55:01 Integral: -29.042871607935275
from poisson_transform import Transformation, solve_and_plot
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
return 0
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if ksi == 0: # left, dirichlet = 0.5
return (1, 0, 0.5)
if ksi == 1: # right, dirichlet = 1.2
return (1, 0, 1.2)
if eta == 0: # bottom, dirichlet = -0.75
return (1, 0, -0.75)
if eta == 1: # top, dirichlet = -1
return (1, 0, -1)
# dirichlet conditions inside the domain
if 1 < x < 1.4 and -0.5 < y < 0.2:
return (1, 0, 1.5)
ksi, eta = Transformation.get_ksi_eta()
Tx = 12*ksi - 6
Ty = 6*eta - 3
solve_and_plot(Nx=30, Ny=30, transformation=Transformation(ksi, eta, Tx, Ty), f=f, g=g)
22:55:04 Integral: -11.898317261702779
from poisson_transform import Transformation, solve_and_plot
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
return 0
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if ksi == 0: # left, neumann = 0
return (0, 1, 0)
if ksi == 1: # right, neumann = 0
return (0, 1, 0)
if eta == 0: # bottom, dirichlet = 0
return (1, 0, 0)
if eta == 1: # top, neumann = 0
return (0, 1, 0)
# dirichlet conditions inside the domain
if 1 < x < 1.4 and -0.5 < y < 0.2:
return (1, 0, 1.5)
ksi, eta = Transformation.get_ksi_eta()
Tx = 12*ksi - 6
Ty = 6*eta - 3
solve_and_plot(Nx=50, Ny=50, transformation=Transformation(ksi, eta, Tx, Ty), f=f, g=g)
22:55:10 Integral: 35.2240775563179
from poisson_transform import Transformation, solve_and_plot
def f(x, y, ksi, eta):
"""Returns f for the equation -∇2 u = f in Ω"""
return 0
def g(x, y, ksi, eta):
"""Returns (a, b, g) for the boundary condition a*u + b*∂u/∂n = g on ∂Ω and (1, 0, g) for dirichlet conditions inside the domain)"""
if ksi == 0: # left, neumann = 0
return (0, 1, 0)
if ksi == 1: # right, neumann = 0
return (0, 1, 0)
if eta == 0: # bottom, neumann = 0
return (0, 1, 0)
if eta == 1: # top, neumann = 0
return (0, 1, 0)
# dirichlet conditions inside the domain
if (x)**2 + (y)**2 < 0.4**2:
return (1, 0, 1)
elif (x+1.4)**2 + (y)**2 < 0.2**2:
return (1, 0, -2)
elif (x-1.4)**2 + (y)**2 < 0.2**2:
return (1, 0, -2)
elif -3.5 < x < -2 and -0.25 < y < 0.25:
return (1, 0, 2)
elif 2 < x < 3.5 and -0.25 < y < 0.25:
return (1, 0, 2)
ksi, eta = Transformation.get_ksi_eta()
Tx = 8*ksi - 4
Ty = 8*eta - 4
solve_and_plot(Nx=60, Ny=60, transformation=Transformation(ksi, eta, Tx, Ty), f=f, g=g)
22:55:18 Integral: 64.89227055928428
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
poisson_transform-0.2.2.tar.gz
(10.6 kB
view details)
File details
Details for the file poisson_transform-0.2.2.tar.gz
.
File metadata
- Download URL: poisson_transform-0.2.2.tar.gz
- Upload date:
- Size: 10.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.9.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6a5ede96e1f426456cedcd627b047f00fdcf984065f93d43958237fc2a613d0a |
|
MD5 | 2cf6328d4d47d892cce2c2d81517247d |
|
BLAKE2b-256 | 13b101fc29d54f1cc138455196df3f24d047b6e309b00db6983f4e309e68808a |