10 #include "sll_memory.h"
11 #include "sll_working_precision.h"
12 #include "sll_poisson_solvers_macros.h"
31 sll_real64,
dimension(:, :),
pointer :: a
32 sll_real64,
dimension(:, :),
pointer :: m
33 sll_real64,
dimension(:, :),
pointer :: mat
34 sll_real64,
dimension(:),
pointer :: hx
35 sll_real64,
dimension(:),
pointer :: hy
39 sll_int32,
dimension(:),
pointer :: id
40 sll_real64,
dimension(:),
pointer :: xd
41 sll_real64,
dimension(:),
pointer :: yd
60 sll_int32,
intent(in) :: nn_x
61 sll_int32,
intent(in) :: nn_y
62 sll_real64,
dimension(nn_x) :: x
63 sll_real64,
dimension(nn_y) :: y
67 sll_real64,
dimension(4, 4) :: axelem
68 sll_real64,
dimension(4, 4) :: ayelem
69 sll_real64,
dimension(4, 4) :: mmelem
70 sll_real64,
dimension(2, 2) :: mfelem
71 sll_int32,
dimension(4) :: isom
89 sll_allocate(self%hx(1:nx), error)
90 sll_allocate(self%hy(1:ny), error)
91 sll_allocate(self%A((nx + 1)*(ny + 1), (nx + 1)*(ny + 1)), error)
92 sll_allocate(self%M((nx + 1)*(ny + 1), (nx + 1)*(ny + 1)), error)
95 self%hx(i) = x(i + 1) - x(i)
99 self%hy(j) = y(j + 1) - y(j)
103 axelem(1, :) = [2.0_f64, -2.0_f64, -1.0_f64, 1.0_f64]
104 axelem(2, :) = [-2.0_f64, 2.0_f64, 1.0_f64, -1.0_f64]
105 axelem(3, :) = [-1.0_f64, 1.0_f64, 2.0_f64, -2.0_f64]
106 axelem(4, :) = [1.0_f64, -1.0_f64, -2.0_f64, 2.0_f64]
108 axelem = axelem/6.0_f64
110 ayelem(1, :) = [2.0_f64, 1.0_f64, -1.0_f64, -2.0_f64]
111 ayelem(2, :) = [1.0_f64, 2.0_f64, -2.0_f64, -1.0_f64]
112 ayelem(3, :) = [-1.0_f64, -2.0_f64, 2.0_f64, 1.0_f64]
113 ayelem(4, :) = [-2.0_f64, -1.0_f64, 1.0_f64, 2.0_f64]
115 ayelem = ayelem/6.0_f64
117 mmelem(1, :) = [4.0_f64, 2.0_f64, 1.0_f64, 2.0_f64]
118 mmelem(2, :) = [2.0_f64, 4.0_f64, 2.0_f64, 1.0_f64]
119 mmelem(3, :) = [1.0_f64, 2.0_f64, 4.0_f64, 2.0_f64]
120 mmelem(4, :) = [2.0_f64, 1.0_f64, 2.0_f64, 4.0_f64]
122 mmelem = mmelem/36.0_f64
124 mfelem(1, :) = [2.0_f64, 1.0_f64]
125 mfelem(2, :) = [1.0_f64, 2.0_f64]
127 mfelem = mfelem/6.0_f64
135 isom(1) =
som(self%nx, i, j, 1)
136 isom(2) =
som(self%nx, i, j, 2)
137 isom(3) =
som(self%nx, i, j, 3)
138 isom(4) =
som(self%nx, i, j, 4)
141 self%A(isom(ii), isom(jj)) = self%A(isom(ii), isom(jj)) &
142 & + axelem(ii, jj)*self%hy(j)/self%hx(i) &
143 & + ayelem(ii, jj)*self%hx(i)/self%hy(j)
144 self%M(isom(ii), isom(jj)) = self%M(isom(ii), isom(jj)) &
145 & + mmelem(ii, jj)*self%hy(j)*self%hx(i)
152 self%nd = 2*(nx + ny)
153 allocate (self%id(self%nd))
159 k = (nx + 1)*(ny + 1) - i + 1
163 do i = nx + 1, nx*(ny + 1), nx + 1
178 sll_allocate(self%mat(kd + 1, (nx + 1)*(ny + 1)), error)
180 n = (nx + 1)*(ny + 1)
182 do j = i, min(n, i + kd)
183 self%mat(kd + 1 + i - j, j) = self%a(i, j)
187 call dpbtrf(
'U', (nx + 1)*(ny + 1), kd, self%mat, kd + 1, error)
189 allocate (self%xd((nx + 1)*(ny + 1)))
190 allocate (self%yd((nx + 1)*(ny + 1)))
204 integer function som(nx, i, j, k)
206 integer :: i, j, k, nx
209 som = i + (j - 1)*(nx + 1)
210 else if (k == 2)
then
211 som = i + (j - 1)*(nx + 1) + 1
212 else if (k == 3)
then
213 som = i + (j - 1)*(nx + 1) + nx + 2
214 else if (k == 4)
then
215 som = i + (j - 1)*(nx + 1) + nx + 1
223 sll_real64,
dimension(:, :) :: ex
224 sll_real64,
dimension(:, :) :: ey
225 sll_real64,
dimension(:, :) :: rho
226 sll_real64,
dimension((self%nx + 1)*(self%ny + 1)) :: b
244 b = matmul(self%M, b)
248 b(k) = 1.0d20*(self%xd(k)*self%xd(k) + self%yd(k)*self%yd(k))
251 call dpbtrs(
'U', (nx + 1)*(ny + 1), nx + 2, 1, self%mat, nx + 3, b, (nx + 1)*(ny + 1), error)
264 ex(i, j) = -(rho(i + 1, j) - rho(i, j))/self%hx(i)
270 ey(i, j) = -(rho(i, j + 1) - rho(i, j))/self%hy(j)
Compute the electric potential.
Poisson solver using finite element.
integer function som(nx, i, j, k)
Get the node index.
subroutine initialize_poisson_2d_fem(self, x, y, nn_x, nn_y)
Initialize Poisson solver object using finite elements method.
subroutine solve_poisson_2d_fem(self, ex, ey, rho)
Solve the poisson equation.
Structure to solve Poisson equation on 2d domain. Mesh is cartesian and could be irregular.