11 #include "sll_assert.h"
12 #include "sll_errors.h"
13 #include "sll_memory.h"
14 #include "sll_working_precision.h"
20 sll_s_uniform_bsplines_eval_basis
46 sll_real64,
intent(in) :: x(3)
47 sll_int32,
optional,
intent(in) :: component(:)
56 sll_int32,
intent( in ) :: n_cells(3)
57 sll_int32,
intent( in ) :: deg(3)
58 sll_int32,
intent( in ) :: component
61 sll_int32,
optional,
intent( in ) :: n_cells_min(3)
62 sll_int32,
optional,
intent( in ) :: n_cells_max(3)
64 sll_int32 :: i1, i2, i3, ind, k, begin(3), limit(3)
66 sll_real64 :: mass_line( 1:(2*deg(1)+1)*(2*deg(2)+1)*(2*deg(3)+1))
67 sll_real64,
allocatable :: xw_gauss_d1(:,:), xw_gauss_d2(:,:), xw_gauss_d3(:,:)
68 sll_real64,
allocatable :: bspl_d1(:,:), bspl_d2(:,:), bspl_d3(:,:)
72 allocate( xw_gauss_d1(1:2, 1:q(1)) )
73 allocate( xw_gauss_d2(1:2, 1:q(2)) )
74 allocate( xw_gauss_d3(1:2, 1:q(3)) )
75 allocate( bspl_d1(1:deg(1)+1, 1:q(1)) )
76 allocate( bspl_d2(1:deg(2)+1, 1:q(2)) )
77 allocate( bspl_d3(1:deg(3)+1, 1:q(3)) )
79 if(
present(n_cells_min) .and.
present(n_cells_max) )
then
80 ind = 1+((n_cells_min(2)-1)*n_cells(1)+(n_cells_min(3)-1)*n_cells(2)*n_cells(1))*&
81 (2*deg(1)+1)*(2*deg(2)+1)*(2*deg(3)+1)
97 call sll_s_uniform_bsplines_eval_basis( deg(1), xw_gauss_d1(1,k), bspl_d1(:, k) )
103 call sll_s_uniform_bsplines_eval_basis( deg(2), xw_gauss_d2(1,k), bspl_d2(:,k) )
109 call sll_s_uniform_bsplines_eval_basis( deg(3), xw_gauss_d3(1,k), bspl_d3(:,k) )
112 do i3 = begin(3), limit(3)
113 do i2 = begin(2), limit(2)
114 do i1 = 1, n_cells(1)
115 call sll_s_spline_fem_mass_line( q, deg, profile, [i1,i2,i3], n_cells, component, mass_line, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1, bspl_d2, bspl_d3 )
117 mass_line = mass_line/real(n_cells(1)*n_cells(2)*n_cells(3),f64)
118 call assemble_mass3d( deg(:), n_cells, mass_line(:), matrix, [i1,i2,i3], ind )
129 subroutine sll_s_spline_fem_mass_line ( q, deg, profile, row, n_cells, component, mass_line, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1, bspl_d2, bspl_d3 )
130 sll_int32,
intent( in ) :: q(3)
131 sll_int32,
intent( in ) :: deg(3)
133 sll_int32,
intent( in ) :: row(3)
134 sll_int32,
intent( in ) :: n_cells(3)
135 sll_int32,
intent( in ) :: component
136 sll_real64,
intent( out ) :: mass_line((2*deg(1)+1)*(2*deg(2)+1)*(2*deg(3)+1))
137 sll_real64,
intent ( in ) :: xw_gauss_d1(2, q(1)), xw_gauss_d2(2, q(2)), xw_gauss_d3(2, q(3))
138 sll_real64,
intent( in ) :: bspl_d1(deg(1)+1, q(1)), bspl_d2(deg(2)+1, q(2)), bspl_d3(deg(3)+1, q(3))
140 sll_int32 :: int1, int2, int3, j1, j2, j3, k1, k2, k3, l1, l2, l3
142 sll_int32 :: limit(3), ind1(3), ind2(3), ind3(3), ind4(3)
146 do j3 = 1, 2*deg(3)+1
149 ind1(3) = deg(3)+1-j3
151 limit(3) = 2*deg(3)+1
155 do int3 = j3, limit(3)
157 ind2(3) = deg(3)+1-int3+j3
158 ind3(3) = deg(3)+1-int3
162 ind3(3) = int3-deg(3)
163 ind4(3) = deg(3)+j3-int3
166 do j2 = 1, 2*deg(2)+1
169 ind1(2) = deg(2)+1-j2
171 limit(2) = 2*deg(2)+1
175 do int2 = j2, limit(2)
177 ind2(2) = deg(2)+1-int2+j2
178 ind3(2) = deg(2)+1-int2
182 ind3(2) = int2-deg(2)
183 ind4(2) = deg(2)+j2-int2
186 do j1 = 1, 2*deg(1)+1
189 ind1(1) = deg(1)+1-j1
191 limit(1) = 2*deg(1)+1
195 do int1 = j1, limit(1)
197 ind2(1) = deg(1)+1-int1+j1
198 ind3(1) = deg(1)+1-int1
202 ind3(1) = int1-deg(1)
203 ind4(1) = deg(1)+j1-int1
207 k3 = 1 - (-1)**l3 * l3/2 + q(3)*(l3+1-2*((l3+1)/2) )
208 c(3) = (xw_gauss_d3(1,k3)+ real( row(3)-1+ind4(3)-((row(3)-1+ind4(3))/n_cells(3))*n_cells(3),f64 ))/real(n_cells(3),f64)
210 k2 = 1 - (-1)**l2 * l2/2 + q(2)*(l2+1-2*((l2+1)/2) )
211 c(2) = (xw_gauss_d2(1,k2)+ real( row(2)-1+ind4(2)-((row(2)-1+ind4(2))/n_cells(2))*n_cells(2),f64 ))/real(n_cells(2),f64)
213 k1 = 1 - (-1)**l1 * l1/2 + q(1)*(l1+1-2*((l1+1)/2) )
214 c(1) = (xw_gauss_d1(1,k1)+ real( row(1)-1+ind4(1)-((row(1)-1+ind4(1))/n_cells(1))*n_cells(1),f64 ))/real(n_cells(1),f64)
215 mass_line(ind1(1)+(ind1(2)-1)*(2*deg(1)+1)+(ind1(3)-1)*(2*deg(1)+1)*(2*deg(2)+1)) = &
216 mass_line(ind1(1)+(ind1(2)-1)*(2*deg(1)+1)+(ind1(3)-1)*(2*deg(1)+1)*(2*deg(2)+1)) + &
217 xw_gauss_d1(2,k1)* xw_gauss_d2(2,k2)* xw_gauss_d3(2,k3) *&
218 bspl_d1(ind2(1), k1)*&
219 bspl_d2(ind2(2), k2)*&
220 bspl_d3(ind2(3), k3)*&
221 bspl_d1(ind3(1), k1)*&
222 bspl_d2(ind3(2), k2)*&
223 bspl_d3(ind3(3), k3)*&
224 profile( c, [component] )
240 sll_int32,
intent( in ) :: n_cells(3)
241 sll_int32,
intent( in ) :: deg1(3), deg2(3)
242 sll_int32,
intent( in ) :: component(2)
245 sll_int32,
optional,
intent( in ) :: n_cells_min(3)
246 sll_int32,
optional,
intent( in ) :: n_cells_max(3)
248 sll_int32 :: i1, i2, i3, ind, k, begin(3), limit(3), q(3)
249 sll_real64 :: mass_line(1:(deg1(1)+deg2(1)+1)*(deg1(2)+deg2(2)+1)*(deg1(3)+deg2(3)+1))
250 sll_real64,
allocatable :: xw_gauss_d1(:,:), xw_gauss_d2(:,:), xw_gauss_d3(:,:)
251 sll_real64,
allocatable :: bspl_d1a(:,:), bspl_d2a(:,:), bspl_d3a(:,:)
252 sll_real64,
allocatable :: bspl_d1b(:,:), bspl_d2b(:,:), bspl_d3b(:,:)
255 q = 2*max(deg1,deg2)+1
257 if(
present(n_cells_min) .and.
present(n_cells_max) )
then
258 ind = 1+((n_cells_min(2)-1)*n_cells(1)+(n_cells_min(3)-1)*n_cells(2)*n_cells(1))*&
259 (deg1(1)+deg2(1)+1)*(deg1(2)+deg2(2)+1)*(deg1(3)+deg2(3)+1)
269 allocate( xw_gauss_d1(1:2, 1:q(1)) )
270 allocate( xw_gauss_d2(1:2, 1:q(2)) )
271 allocate( xw_gauss_d3(1:2, 1:q(3)) )
272 allocate( bspl_d1a(1:deg1(1)+1, 1:q(1)) )
273 allocate( bspl_d2a(1:deg1(2)+1, 1:q(2)) )
274 allocate( bspl_d3a(1:deg1(3)+1, 1:q(3)) )
275 allocate( bspl_d1b(1:deg2(1)+1, 1:q(1)) )
276 allocate( bspl_d2b(1:deg2(2)+1, 1:q(2)) )
277 allocate( bspl_d3b(1:deg2(3)+1, 1:q(3)) )
286 call sll_s_uniform_bsplines_eval_basis( deg1(1),xw_gauss_d1(1,k), bspl_d1a(1:deg1(1)+1, k) )
287 call sll_s_uniform_bsplines_eval_basis( deg2(1),xw_gauss_d1(1,k), bspl_d1b(1:deg2(1)+1, k) )
294 call sll_s_uniform_bsplines_eval_basis( deg1(2),xw_gauss_d2(1,k), bspl_d2a(1:deg1(2)+1, k) )
295 call sll_s_uniform_bsplines_eval_basis( deg2(2),xw_gauss_d2(1,k), bspl_d2b(1:deg2(2)+1, k) )
302 call sll_s_uniform_bsplines_eval_basis( deg1(3),xw_gauss_d3(1,k), bspl_d3a(1:deg1(3)+1, k) )
303 call sll_s_uniform_bsplines_eval_basis( deg2(3),xw_gauss_d3(1,k), bspl_d3b(1:deg2(3)+1, k) )
306 do i3 = begin(3), limit(3)
307 do i2 = begin(2), limit(2)
308 do i1 = 1, n_cells(1)
309 call sll_s_spline_fem_mixedmass_line( q(:), deg1(:), deg2(:), profile, [i1,i2,i3], n_cells, component, mass_line(:), xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1a, bspl_d2a, bspl_d3a, bspl_d1b, bspl_d2b, bspl_d3b )
311 mass_line = mass_line/real(n_cells(1)*n_cells(2)*n_cells(3),f64)
319 deallocate( xw_gauss_d1 )
320 deallocate( xw_gauss_d2 )
321 deallocate( xw_gauss_d3 )
322 deallocate( bspl_d1a )
323 deallocate( bspl_d2a )
324 deallocate( bspl_d3a )
325 deallocate( bspl_d1b )
326 deallocate( bspl_d2b )
327 deallocate( bspl_d3b )
333 subroutine sll_s_spline_fem_mixedmass_line( q, deg1, deg2, profile, row, n_cells, component, mass_line, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1a, bspl_d2a, bspl_d3a, bspl_d1b, bspl_d2b, bspl_d3b )
334 sll_int32,
intent( in ) :: q(3)
335 sll_int32,
intent( in ) :: deg1(3), deg2(3)
337 sll_int32,
intent( in ) :: row(3)
338 sll_int32,
intent( in ) :: n_cells(3)
339 sll_int32,
intent( in ) :: component(2)
340 sll_real64,
intent( out ) :: mass_line((deg1(1)+deg2(1)+1)*(deg1(2)+deg2(2)+1)*(deg1(3)+deg2(3)+1))
342 sll_real64,
intent( in ) :: xw_gauss_d1(2, q(1)), xw_gauss_d2(2, q(2)), xw_gauss_d3(2, q(3))
343 sll_real64,
intent( in ) :: bspl_d1a(deg1(1)+1, q(1)), bspl_d2a(deg1(2)+1, q(2)), bspl_d3a(deg1(3)+1, q(3))
344 sll_real64,
intent( in ) :: bspl_d1b(deg2(1)+1, q(1)), bspl_d2b(deg2(2)+1, q(2)), bspl_d3b(deg2(3)+1, q(3))
346 sll_int32 :: int1, int2, int3, j1, j2, j3, k1, k2, k3, l1, l2, l3
348 sll_int32 :: limit(3), ind1(3), ind2(3), ind3(3), ind4(3)
353 do j3 = 1, deg1(3)+deg2(3)+1
354 if(j3 <= deg2(3))
then
356 ind1(3) = deg2(3)+1-j3
358 limit(3) = deg1(3)+deg2(3)+1
362 do int3 = j3, min(limit(3), j3+deg2(3))
363 if(j3 <= deg2(3))
then
364 ind2(3) = deg1(3)+1-int3+j3
365 ind3(3) = deg2(3)+1-int3
368 ind2(3) = limit(3)-int3+1
369 ind3(3) = deg2(3)+1-int3+j3
370 ind4(3) = int3-deg2(3)-1
373 do j2 = 1, deg1(2)+deg2(2)+1
374 if(j2 <= deg2(2))
then
376 ind1(2) = deg2(2)+1-j2
378 limit(2) = deg1(2)+deg2(2)+1
382 do int2 = j2, min(limit(2), j2+deg2(2))
383 if(j2 <= deg2(2))
then
384 ind2(2) = deg1(2)+1-int2+j2
385 ind3(2) = deg2(2)+1-int2
388 ind2(2) = limit(2)-int2+1
389 ind3(2) = deg2(2)+1-int2+j2
390 ind4(2) = int2-deg2(2)-1
393 do j1 = 1, deg1(1)+deg2(1)+1
394 if(j1 <= deg2(1))
then
396 ind1(1) = deg2(1)+1-j1
398 limit(1) = deg1(1)+deg2(1)+1
402 do int1 = j1, min(limit(1), j1+deg2(1))
403 if(j1 <= deg2(1))
then
404 ind2(1) = deg1(1)+1-int1+j1
405 ind3(1) = deg2(1)+1-int1
408 ind2(1) = limit(1)-int1+1
409 ind3(1) = deg2(1)+1-int1+j1
410 ind4(1) = int1-deg2(1)-1
414 k3 = 1 - (-1)**l3 * l3/2 + q(3)*(l3+1-2*((l3+1)/2) )
415 c(3) = (xw_gauss_d3(1,k3)+ real( row(3)-1+ind4(3)-((row(3)-1+ind4(3))/n_cells(3))*n_cells(3),f64 ))/real(n_cells(3),f64)
417 k2 = 1 - (-1)**l2 * l2/2 + q(2)*(l2+1-2*((l2+1)/2) )
418 c(2) = (xw_gauss_d2(1,k2)+ real( row(2)-1+ind4(2)-((row(2)-1+ind4(2))/n_cells(2))*n_cells(2),f64 ))/real(n_cells(2),f64)
420 k1 = 1 - (-1)**l1 * l1/2 + q(1)*(l1+1-2*((l1+1)/2) )
421 c(1) = (xw_gauss_d1(1,k1)+ real( row(1)-1+ind4(1)-((row(1)-1+ind4(1))/n_cells(1))*n_cells(1),f64 ))/real(n_cells(1),f64)
423 mass_line(ind1(1)+(ind1(2)-1)*(deg1(1)+deg2(1)+1)+(ind1(3)-1)*(deg1(1)+deg2(1)+1)*(deg1(2)+deg2(2)+1)) = &
424 mass_line(ind1(1)+(ind1(2)-1)*(deg1(1)+deg2(1)+1)+(ind1(3)-1)*(deg1(1)+deg2(1)+1)*(deg1(2)+deg2(2)+1)) + &
425 xw_gauss_d1(2,k1)* xw_gauss_d2(2,k2)* xw_gauss_d3(2,k3) *&
426 bspl_d1a(ind2(1), k1)*&
427 bspl_d2a(ind2(2), k2)*&
428 bspl_d3a(ind2(3), k3)*&
429 bspl_d1b(ind3(1), k1)*&
430 bspl_d2b(ind3(2), k2)*&
431 bspl_d3b(ind3(3), k3)*&
432 profile( c, component )
Gauss-Legendre integration.
real(kind=f64) function, dimension(2, 1:npoints), public sll_f_gauss_legendre_points_and_weights(npoints, a, b)
Returns a 2d array of size (2,npoints) containing gauss-legendre points and weights in the interval [...
Low level arbitrary degree splines.
Module interfaces for coordinate transformation.
module for Compressed Sparse Row Matrix (CSR)
Helper for spline finite elements utilites.
subroutine, public assemble_mixedmass3d(deg1, deg2, n_cells, mass_line, matrix, row, ind)
Assemble the given row of the mixed mass matrix.
subroutine, public assemble_mass3d(deg, n_cells, mass_line, matrix, row, ind)
Assemble the given row of the 3d mass matrix.
subroutine, public sll_s_spline_fem_sparsity_mass3d(deg, n_cells, spmat)
Helper function to create sparsity pattern of the 3d mass matrix.
subroutine, public sll_s_spline_fem_sparsity_mixedmass3d(deg1, deg2, n_cells, spmat)
Helper function to create sparsity pattern of the 3d mass matrix.
Utilites for 3D Maxwell solvers with spline finite elements.
subroutine, public sll_s_spline_fem_mass3d(n_cells, deg, component, matrix, profile, n_cells_min, n_cells_max)
Set up 3d mass matrix for specific spline degrees and profile function.
subroutine, public sll_s_spline_fem_mixedmass3d(n_cells, deg1, deg2, component, matrix, profile, n_cells_min, n_cells_max)
Set up 3d mixed mass matrix for specific spline degree and profile function.
subroutine, public sll_s_spline_fem_mixedmass_line(q, deg1, deg2, profile, row, n_cells, component, mass_line, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1a, bspl_d2a, bspl_d3a, bspl_d1b, bspl_d2b, bspl_d3b)
subroutine, public sll_s_spline_fem_mass_line(q, deg, profile, row, n_cells, component, mass_line, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1, bspl_d2, bspl_d3)
Computes the mass line for a mass matrix with degree splines.
Module to select the kind parameter.
type collecting functions for analytical coordinate mapping