- Thank you received: 0
Point source of electric current in radially symmetric cylindrical coordinates
4 years 2 months ago - 4 years 2 months ago #3130
by eMWu
Hello, Netgen/NGSolve community,
I am trying to model the distribution of electric potential around a point source of DC electric current in radially symmetric cylindrical coordinates.
The problem I am trying to solve is given by the following equation:
[tex]\nabla \cdot (\sigma \nabla u) = - \nabla \cdot j[/tex]
with the source term
[tex]\nabla \cdot j = I \delta (x-x_s) \delta (y-y_s) \delta (z-z_s)[/tex]
where sigma is the distribution of conductivity in the domain, u is the electrostatic potential, j is the electric current density, I is a current injected at the point source located at (xs, ys, zs) and delta is the Dirac’s delta.
In radially symmetric cylindrical coordinates (r, z), with the source located at (0, 0) this equation can be rewritten as:
[tex]\frac{1}{ r} \frac{ \partial}{ \partial r} [ \sigma \frac{\partial u}{\partial r}] + \frac{ \partial}{ \partial z} [ \sigma \frac{\partial u}{\partial z}] = \frac {I \delta (r) \delta (z)}{2 \Pi r}[/tex]
Originally I was using GMSH and FEniCS, but over time I realised that switching to Netgen/NGSolve might be beneficial since model geometry I am dealing with is easier to describe in Netgen than in GMSH. In addition, this will allow me to skip mesh conversion from GMSH format to FEniCS format which is surprisingly time-consuming.
Bellow, I supplied the code I managed to create. In the final implementation the domain around the current source will be much more complex but for the sake of simplicity of an example and to allow comparison with the analytical solution let’s assume that the current source is located in a homogenous medium. At the end of the code I’ve added a comparison with an analytical solution:
[tex]U (r_I) = \frac {I} {4 \Pi r_I \sigma } [/tex]
where rI is a distance between the source point and the point at which the potential value is measured.
The numerical and analytical results should match (taking aside drop of potential caused by the finite size of the domain), but unfortunately, they are pretty far apart in case of my Netgen/NGSolve implementation while in FEniCS similar code gives me correct results. Since I have no experience with Netgen/NGSolve I probably messed something up. I guess that the problem is associated with the source term. In FEniCS I used build-in function PointSource() to add point source in one point of the domain. To my knowledge similar function is not present in Netgen/NGSolve, therefore I added point source using a coefficient function with Dirac’s delta approximation.
I would be very grateful if someone will help track the source of error. In addition, I wonder if it is possible to assign maxh value to the point or project it as a coefficient function on the entire mesh. In all examples I was looking at the maxh value was assigned to lines. In my implementation, I quite crudely added two short lines on both sides of the source location and assing maxh value to them.
EDIT: Attachments are in zip format because I was unable to add attachments as individual images.
I am trying to model the distribution of electric potential around a point source of DC electric current in radially symmetric cylindrical coordinates.
The problem I am trying to solve is given by the following equation:
[tex]\nabla \cdot (\sigma \nabla u) = - \nabla \cdot j[/tex]
with the source term
[tex]\nabla \cdot j = I \delta (x-x_s) \delta (y-y_s) \delta (z-z_s)[/tex]
where sigma is the distribution of conductivity in the domain, u is the electrostatic potential, j is the electric current density, I is a current injected at the point source located at (xs, ys, zs) and delta is the Dirac’s delta.
In radially symmetric cylindrical coordinates (r, z), with the source located at (0, 0) this equation can be rewritten as:
[tex]\frac{1}{ r} \frac{ \partial}{ \partial r} [ \sigma \frac{\partial u}{\partial r}] + \frac{ \partial}{ \partial z} [ \sigma \frac{\partial u}{\partial z}] = \frac {I \delta (r) \delta (z)}{2 \Pi r}[/tex]
Originally I was using GMSH and FEniCS, but over time I realised that switching to Netgen/NGSolve might be beneficial since model geometry I am dealing with is easier to describe in Netgen than in GMSH. In addition, this will allow me to skip mesh conversion from GMSH format to FEniCS format which is surprisingly time-consuming.
Bellow, I supplied the code I managed to create. In the final implementation the domain around the current source will be much more complex but for the sake of simplicity of an example and to allow comparison with the analytical solution let’s assume that the current source is located in a homogenous medium. At the end of the code I’ve added a comparison with an analytical solution:
[tex]U (r_I) = \frac {I} {4 \Pi r_I \sigma } [/tex]
where rI is a distance between the source point and the point at which the potential value is measured.
The numerical and analytical results should match (taking aside drop of potential caused by the finite size of the domain), but unfortunately, they are pretty far apart in case of my Netgen/NGSolve implementation while in FEniCS similar code gives me correct results. Since I have no experience with Netgen/NGSolve I probably messed something up. I guess that the problem is associated with the source term. In FEniCS I used build-in function PointSource() to add point source in one point of the domain. To my knowledge similar function is not present in Netgen/NGSolve, therefore I added point source using a coefficient function with Dirac’s delta approximation.
I would be very grateful if someone will help track the source of error. In addition, I wonder if it is possible to assign maxh value to the point or project it as a coefficient function on the entire mesh. In all examples I was looking at the maxh value was assigned to lines. In my implementation, I quite crudely added two short lines on both sides of the source location and assing maxh value to them.
Code:
from ngsolve import *
from netgen.geom2d import SplineGeometry
import numpy as np
import math
def MakeGeometry(d_r, d_z, maxh):
geometry = SplineGeometry()
# point coordinates
points = [ (0, 0), (0, 0.1), (0, d_z), (d_r, d_z), (d_r, -d_z), (0, -d_z), (0, -0.1)]
pnums = [geometry.AppendPoint(*p) for p in points]
# start-point, end-point, boundary-condition, domain on left side, domain on right side, maxh:
lines = [ (0,1,1,0,1,0.01), (1,2,1,0,1,maxh), (2,3,2,0,1,maxh), (3,4,2,0,1,maxh), (4,5,2,0,1,maxh), (5,6,1,0,1,maxh), (6,0,1,0,1,0.01)]
for p1,p2,bc,left,right, mesh_size in lines:
geometry.Append( ["line", pnums[p1], pnums[p2]], bc=bc, leftdomain=left, rightdomain=right, maxh=mesh_size)
return geometry
# Parameters
I = 1 #electric current
rho = 100 #resistivity
d_r = 100 #radius of domain
d_z = 100 # 1/2 of hight of domain
maxh = 10 # mesh size
alpha = 1/10 # parameter in Dirac's delta aproximation
sigma = CoefficientFunction([1/rho]) #conductivity
dd = CoefficientFunction(1/(abs(alpha)*math.sqrt(np.pi))*exp(-((x**2 + y**2)**(1/2)/alpha)**2)) # Dirac's delta
model_geometry = MakeGeometry(d_r, d_z, maxh)
mesh = Mesh(model_geometry.GenerateMesh(maxh=maxh))
fes = H1(mesh, order=2, dirichlet=[2])
u = fes.TrialFunction()
v = fes.TestFunction()
a = BilinearForm(fes, symmetric=False)
a += 2*np.pi*grad(u)*grad(v)*x*sigma*dx
f = LinearForm(fes)
f += dd*I*v*dx
a.Assemble()
f.Assemble()
gfu = GridFunction(fes)
gfu.vec.data = a.mat.Inverse(fes.FreeDofs(), inverse="sparsecholesky") * f.vec
Draw (gfu)
#Comparison of numerical and analytical solution
import matplotlib.pyplot as plt
x_long = [0.01*i for i in range(d_r*100)]
x_short = [0.01*i for i in range(d_r*10)]
u_numerical_long = [gfu(mesh(p, 0.0)) for p in x_long]
u_numerical_short = [gfu(mesh(p, 0.0)) for p in x_short]
fig, axs = plt.subplots(2, figsize=(20, 10))
fig.suptitle('Netgen/NGSolve')
axs[0].plot(x_long, u_numerical_long, linewidth=3, label='Numerical')
axs[0].plot(x_long, I/(1/rho*4*np.pi*np.array(x_long)), linewidth=3, linestyle='--', label='Analytical')
axs[0].set_yscale('log')
axs[0].set_ylim(0.0001, 1000)
axs[0].grid()
axs[0].legend(loc=0)
axs[0].set_xlabel("r")
axs[0].set_ylabel("U(r)")
axs[1].plot(x_short, u_numerical_short, linewidth=3, label='Numerical')
axs[1].plot(x_short, I/(1/rho*4*np.pi*np.array(x_short)), linewidth=3, linestyle='--', label='Analytical')
axs[1].set_yscale('log')
axs[0].set_ylim(0.0001, 1000)
axs[1].grid()
axs[1].legend(loc=0)
axs[1].set_xlabel("r")
axs[1].set_ylabel("U(r)")
plt.show()
EDIT: Attachments are in zip format because I was unable to add attachments as individual images.
Attachments:
Last edit: 4 years 2 months ago by eMWu. Reason: Adding attachments
4 years 2 months ago #3134
by joachim
Replied by joachim on topic Point source of electric current in radially symmetric cylindrical coordinates
Hello,
welcome to NGSolve !
I put two versions for the point-sources into the attached file:
1.
fixing the approximation by the Gaussian peak: you need the radius-factor also for the right hand side.
In the file we are checking that the integral approximates 1.
2.
An AddPointSource Python-function.
It searches the element, evaluates shape functions, and adds the contributions to the linear-form.
It must be called after f.Assemble()
As you give the maxh to the geometry edges, you can also assign a maxh to the geometry points
Best,
Joachim
welcome to NGSolve !
I put two versions for the point-sources into the attached file:
1.
fixing the approximation by the Gaussian peak: you need the radius-factor also for the right hand side.
In the file we are checking that the integral approximates 1.
2.
An AddPointSource Python-function.
It searches the element, evaluates shape functions, and adds the contributions to the linear-form.
It must be called after f.Assemble()
As you give the maxh to the geometry edges, you can also assign a maxh to the geometry points
Best,
Joachim
Attachments:
The following user(s) said Thank You: eMWu
4 years 2 months ago #3139
by eMWu
Replied by eMWu on topic Point source of electric current in radially symmetric cylindrical coordinates
Thanks a lot, both versions work perfectly.
4 years 2 months ago #3151
by joachim
Replied by joachim on topic Point source of electric current in radially symmetric cylindrical coordinates
we have now a built in version of point sources (available in the current nightly):
best, Joachim
Code:
f = LinearForm(fes)
v = fes.TrialFunction()
f += v(0.7, 0.5)
f.Assemble()
best, Joachim
3 years 11 months ago - 3 years 11 months ago #3417
by Amad
Replied by Amad on topic Point source of electric current in radially symmetric cylindrical coordinates
Dear Joachim,
If I am solving a vector problem using HDG. How can I include pointwise sources using the function
?
The V space is defined as:
And the source is characterized as a vector field with intensity I, given by:
[tex]
\begin{equation}
\mathbf{I} = \left(
a + b \mathbf{i},
c + d \mathbf{i}
\right)^T
\end{equation}
[/tex]
[tex]
\begin{equation}
\mathbf{f} = \mathbf{I}\delta(x-x_0)
\end{equation}
[/tex]
Ultimately, I'd like to introduce several pointwise sources
[tex]
\begin{equation}
\mathbf{f}(\mathbf{x}) = \sum_{j = 1}^{n} \mathbf{I}_j \delta(\mathbf{x} - \mathbf{x}_j).
\end{equation}
[/tex]
But, CompoundFiniteElement has no attribute 'CalcShape'.
Is there a way to use the function
to generate the pointwise sources?
Best regards,
Alan.
If I am solving a vector problem using HDG. How can I include pointwise sources using the function
Code:
AddPointSource (f, x, y, z, fac)
The V space is defined as:
Code:
V = VectorL2(mesh, order=order, complex=True)
F = FacetFESpace(mesh, order=order, complex=True)
fes = FESpace([V,F,F,F],highest_order_dc=True)
And the source is characterized as a vector field with intensity I, given by:
[tex]
\begin{equation}
\mathbf{I} = \left(
a + b \mathbf{i},
c + d \mathbf{i}
\right)^T
\end{equation}
[/tex]
[tex]
\begin{equation}
\mathbf{f} = \mathbf{I}\delta(x-x_0)
\end{equation}
[/tex]
Ultimately, I'd like to introduce several pointwise sources
[tex]
\begin{equation}
\mathbf{f}(\mathbf{x}) = \sum_{j = 1}^{n} \mathbf{I}_j \delta(\mathbf{x} - \mathbf{x}_j).
\end{equation}
[/tex]
But, CompoundFiniteElement has no attribute 'CalcShape'.
Is there a way to use the function
Code:
AddPointSource (f, x, y, z, fac)
Best regards,
Alan.
Last edit: 3 years 11 months ago by Amad.
Time to create page: 0.101 seconds