from sympy import *
import sympy as sym
import numpy as np
""""
This module contains classes that support particluar domains transforms, that
are common in applications.
"""
[docs]class RectangleToEccentricAnnulus:
"""
This class permits to easily create and map a rectangle to a specific
eccentric annulus.
"""
def __init__(self, R1, R2, epsilon):
"""
Parameters
----------
R1 : Inner radius of target eccentric annulus
R2 : Outer radius of target eccentric annulus
epsilon : Relative eccentricity of target eccentric annulus
Returns
-------
None.
"""
self.R1 = R1
self.R2 = R2
self.epsilon = epsilon
self.bottom = self.bipolarConstants()[0]
self.top = self.bipolarConstants()[1]
self.shift = self.bipolarConstants()[2]
self.pole = self.bipolarConstants()[3]
self.left = -np.pi
self.right = np.pi
[docs] def bipolarConstants(self):
"""
Returns
-------
alpha : Value of bottom boundary of rectangle.
beta : Value of top boundary of rectangle.
yShift1 : shift of to center the outer radius at origin
cNum : pole of corresponding bipolar coordinate system
"""
innerRadius=self.R1
outerRadius=self.R2
shift=self.epsilon *(outerRadius-innerRadius)
shift=-shift
if shift != 0:
R1, R2,delta, b, A, B, C, epsilon, kappa, alpha, beta, c, M, F = sym.symbols('R1 R2 delta b A B C epsilon kappa alpha beta c M F', real=True)
k, m, n = sym.symbols('k m n', integer=True)
testF=(R2**2-R1**2+b**2)/(2*b)
testM=sqrt(F**2-R2**2)
testAlpha=0.5*log((F+M)/(F-M))
testBeta=0.5*log((F-b+M)/(F-b-M))
yShift1=float((testM*coth(testAlpha.subs(M,testM))).subs(F,testF).subs(R2,outerRadius).subs(R1,innerRadius).subs(b,abs(shift)))
yShift2=yShift1-abs(shift)
alphaNum=testAlpha.subs(M,testM).subs(F,testF).subs(R2,outerRadius).subs(R1,innerRadius).subs(b,abs(shift))
betaNum=testBeta.subs(M,testM).subs(F,testF).subs(R2,outerRadius).subs(R1,innerRadius).subs(b,abs(shift))
cNum=float(testM.subs(F,testF).subs(R2,outerRadius).subs(R1,innerRadius).subs(b,abs(shift)))
return float(alphaNum), float(betaNum), yShift1, cNum
[docs] def mapping(self, z):
"""
Parameters
----------
z : Symbolic complex variable
Returns
-------
value : Symbolic function, that mapps the specific rectangle to the target eccentric annulus
"""
value = self.pole*sym.tan((z)/2)-sym.I*self.shift
return value
[docs]class RectangleToEllipticAnnulus:
"""
This class permits to easily create and map a rectangle to a specific
concentric elliptical annulus.
"""
def __init__(self, b, a):
"""
Parameters
----------
b : Large half axis of inner ellipse
a : Large half axis of outer ellipse
Returns
-------
None.
"""
self.top = np.pi
self.bottom = -np.pi
self.a = a
self.b = b
self.c = np.sqrt(self.a**2-self.b**2)
self.k = round(a/np.sqrt(2),2)
if self.b > self.a/np.sqrt(2):
left = np.log(self.b/self.c+np.sqrt((self.b/self.c)**2-1))
right = np.log(self.a/self.c+np.sqrt((self.a/self.c)**2-1))
else:
print()
print('ERROR: smaller half axis must be larger than {0}:'.format(self.k))
print('The ratio of larger half axis and sqrt(2)')
print()
self.left = left
self.right = right
[docs] def mapping(self, z):
"""
Parameters
----------
z : Symbolic complex variable
Returns
-------
value : Returns a complex variable function that maps the rectangle
[left, right] x [-pi, pi] to an elliptic annulus where half axes are
b and a.
"""
value = self.c*sym.cosh(z)
return value
[docs]class ConcentricAnnulusToEccentricAnnulus:
"""
This class permits to easily create and map a concentric annulus
to a specific excentric elliptical annulus. Theory in Lauer-Bare and
Gaertig 2021 (scipy) and Brown and Churchil.
"""
def __init__(self, R1, R2, epsilon):
"""
Parameters
----------
R1 : Inner radius of target eccentric annulus
R2 : Outer radius of target eccentric annulus
epsilon : Relative eccentricity of target eccentric annulus
Returns
-------
None.
"""
self.R1 = R1
self.R2 = R2
self.epsilon = epsilon
self.rin = 1
self.rout = self.newRadii()[0]
self.moebiusConstant = self.newRadii()[1]
[docs] def newRadii(self):
R1, R2, b = sym.symbols('R1, R2, b', real=True)
R, a, x1, x2, l, delta = sym.symbols('R, a, x1,x2,l, delta', real=True)
# a and R from Churchill, Brown
a_ = (1+x1*x2+sym.sqrt((1-x1**2)*(1-x2**2)))/(x1+x2)
a_ = a_.subs(x2, (b-R1))
a_ = a_.subs(x1, (R1+b))
a_ = a_.subs(R1, R1/R2)
a_ = a_.subs(b, b/R2)
R_ = (1-x1*x2+sym.sqrt((1-x1**2)*(1-x2**2)))/(x1-x2)
R_ = R_.subs(x2, (b-R1))
R_ = R_.subs(x1, (R1+b))
R_ = R_.subs(R1, R1/R2)
R_ = R_.subs(b, b/R2)
# numerical values
R1_ = self.R1
R2_ = self.R2
shift = self.epsilon*(R2_-R1_)
RNum = R_.subs(R1, R1_).subs(R2, R2_)
RNum = float(RNum.subs(b, shift))
aNum = a_.subs(R1, R1_).subs(R2, R2_)
aNum = float(aNum.subs(b, shift))
return RNum, aNum
[docs] def mapping(self, z):
"""
Parameters
----------
z : Symbolic complex variable
Returns
-------
value : Returns a complex variable function that maps the concetric
annulus with inner radius 1 an outer radius 'outerRadius' to
a eccentric annulus with radii R1 (inner), R2 (outer) and
relative eccentricity
epsilon.
"""
a = self.moebiusConstant
value = self.R2*(-sym.I*a+sym.I*z)/(-a*z+1)
return value