Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_spline_fem_utilities_3d_clamped.F90
Go to the documentation of this file.
1 
8 
10  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 #include "sll_assert.h"
12 #include "sll_errors.h"
13 #include "sll_memory.h"
14 #include "sll_working_precision.h"
15 
16  use sll_m_matrix_csr, only: &
18 
19  use sll_m_low_level_bsplines, only: &
20  sll_s_uniform_bsplines_eval_basis
21 
24 
25  use sll_m_mapping_3d, only: &
27 
29 
31 
33 
34  implicit none
35 
36  public :: &
45 
46 
47  private
48  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
49 
50 contains
51 
53  subroutine sll_s_spline_fem_mass3d_clamped( n_cells, deg, component, matrix, profile, spline, n_cells_min, n_cells_max)
54  sll_int32, intent( in ) :: n_cells(3)
55  sll_int32, intent( in ) :: deg(3)
56  sll_int32, intent( in ) :: component
57  type(sll_t_matrix_csr), intent( out ) :: matrix
58  procedure(sll_i_profile_function) :: profile
59  type(sll_t_spline_pp_1d), intent( in ) :: spline
60  sll_int32, optional, intent( in ) :: n_cells_min(3)
61  sll_int32, optional, intent( in ) :: n_cells_max(3)
62  !local variables
63  sll_int32 :: i1, i2, i3, ind, k, begin(3), limit(3)
64  sll_int32 :: q(3), start
65  sll_real64 :: mass_line_b( 1:(7*deg(1)**2-deg(1)-2)/2*(2*deg(2)+1)*(2*deg(3)+1))
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(:,:)
69 
70  q = deg+1 !number of quadrature points
71  allocate( xw_gauss_d1(1:2, 1:q(1)) )
72  allocate( xw_gauss_d2(1:2, 1:q(2)) )
73  allocate( xw_gauss_d3(1:2, 1:q(3)) )
74  allocate( bspl_d1(1:deg(1)+1, 1:q(1)) )
75  allocate( bspl_d2(1:deg(2)+1, 1:q(2)) )
76  allocate( bspl_d3(1:deg(3)+1, 1:q(3)) )
77 
78  if( present(n_cells_min) .and. present(n_cells_max) )then
79  ind=1+((n_cells_min(2)-1)+(n_cells_min(3)-1)*n_cells(2))*&
80  ( ((n_cells(1)-deg(1))*(2*deg(1)+1)+(3*deg(1)**2+deg(1)))*&
81  (2*deg(2)+1)*(2*deg(3)+1) )
82  begin=n_cells_min
83  limit=n_cells_max
84  else
85  ind=1
86  begin=1
87  limit=n_cells
88  end if
89 
90  call sll_s_spline_fem_sparsity_mass3d_clamped( deg(:), n_cells, matrix )
91 
92  bspl_d1=0._f64
93  ! take enough Gauss points so that projection is exact for splines of deg deg
94  ! rescale on [0,1] for compatibility with B-splines
95  xw_gauss_d1 = sll_f_gauss_legendre_points_and_weights( q(1), 0._f64, 1._f64 )
96  ! Compute bsplines at gauss_points
97  do k=1, q(1)
98  call sll_s_uniform_bsplines_eval_basis( deg(1), xw_gauss_d1(1,k), bspl_d1(:, k) )
99  end do
100  bspl_d2=0._f64
101  xw_gauss_d2 = sll_f_gauss_legendre_points_and_weights( q(2), 0._f64, 1._f64 )
102  ! Compute bsplines at gauss_points
103  do k=1, q(2)
104  call sll_s_uniform_bsplines_eval_basis( deg(2), xw_gauss_d2(1,k), bspl_d2(:,k) )
105  end do
106  bspl_d3=0._f64
107  xw_gauss_d3 = sll_f_gauss_legendre_points_and_weights( q(3), 0._f64, 1._f64 )
108  ! Compute bsplines at gauss_points
109  do k=1, q(3)
110  call sll_s_uniform_bsplines_eval_basis( deg(3), xw_gauss_d3(1,k), bspl_d3(:,k) )
111  end do
112 
113  !loop over rows of the mass matrix to compute and assemble the massline
114  do i3=begin(3), limit(3)
115  do i2=begin(2), limit(2)
116  call sll_s_spline_fem_mass_line_boundary( q, deg, profile, [1,i2,i3], n_cells, component, mass_line_b, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1, bspl_d2, bspl_d3, spline )
117 
118  !scale with delta_x=1/n_cells
119  mass_line_b=mass_line_b/real(n_cells(1)*n_cells(2)*n_cells(3),f64)
120 
121  start=ind
122  do i1=1, 2*deg(1)-1
123  call assemble_mass3d_clamped_boundary( deg, n_cells, mass_line_b, matrix, [i1,i2,i3], ind )
124  end do
125  sll_assert( ind == start+(7*deg(1)**2-deg(1)-2)/2*(2*deg(2)+1)*(2*deg(3)+1))
126  do i1 = 2*deg(1), n_cells(1)-deg(1)+1
127  call sll_s_spline_fem_mass_line( q, deg, profile, [i1-deg(1),i2,i3], n_cells, component, mass_line, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1, bspl_d2, bspl_d3 )
128  !scale with delta_x=1/n_cells
129  mass_line=mass_line/real(n_cells(1)*n_cells(2)*n_cells(3),f64)
130  call assemble_mass3d_clamped( deg, n_cells, mass_line, matrix, [i1,i2,i3], ind )
131  end do
132  call sll_s_spline_fem_mass_line_boundary( q, deg, profile, [n_cells(1)+1,i2,i3], n_cells, component, mass_line_b, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1, bspl_d2, bspl_d3, spline )
133 
134  !scale with delta_x=1/n_cells
135  mass_line_b=mass_line_b/real(n_cells(1)*n_cells(2)*n_cells(3),f64)
136 
137  start=ind
138  do i1= n_cells(1)-deg(1)+2, n_cells(1)+deg(1)
139  call assemble_mass3d_clamped_boundary( deg, n_cells, mass_line_b, matrix, [i1,i2,i3], ind )
140  end do
141  sll_assert( ind == start+(7*deg(1)**2-deg(1)-2)/2*(2*deg(2)+1)*(2*deg(3)+1))
142  end do
143  end do
144 
145  end subroutine sll_s_spline_fem_mass3d_clamped
146 
147  ! Computes the mass line for a mass matrix with \a degree splines
148  subroutine sll_s_spline_fem_mass_line_boundary ( q, deg, profile, row, n_cells, component, mass_line, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1, bspl_d2, bspl_d3, spline )
149  sll_int32, intent( in ) :: q(3)
150  sll_int32, intent( in ) :: deg(3)
151  procedure(sll_i_profile_function) :: profile
152  sll_int32, intent( in ) :: row(3)
153  sll_int32, intent( in ) :: n_cells(3)
154  sll_int32, intent( in ) :: component
155  sll_real64, intent( out ) :: mass_line((7*deg(1)**2-deg(1)-2)/2*(2*deg(2)+1)*(2*deg(3)+1))
156 
157  sll_real64, intent ( in ) :: xw_gauss_d1(2, q(1)), xw_gauss_d2(2, q(2)), xw_gauss_d3(2, q(3))
158  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))
159  type(sll_t_spline_pp_1d), intent( in ) :: spline
160  ! local variables
161  sll_int32 :: int1, int2, int3, j1, j2, j3, k1, k2, k3, interval
162  sll_real64 :: c(3)
163  sll_int32 :: limit(3), ind1(3), ind2(3), ind3(3), ind4(3)
164  sll_real64 :: bspl_b(1:deg(1)+1, 1:q(1),1:2*deg(1)-1)
165 
166  mass_line=0._f64
167 
168  do interval = 1, deg(1)-1
169  do k1 = 1, q(1)
170  do j1 = 1, deg(1)+1
171  bspl_b(j1,k1,interval) = sll_f_spline_pp_horner_1d( deg(1), spline%poly_coeffs_boundary_left(:,:,interval), xw_gauss_d1(1,k1), j1)
172  end do
173  end do
174  end do
175  do interval = deg(1), 2*deg(1)-1
176  bspl_b(:,:,interval)=bspl_d1
177  end do
178  if( row(1) < 2*deg(1) )then
179  ind4(1)= 1
180  else if ( row(1) > n_cells(1) - deg(1)+1 .and. row(1) <= n_cells(1)+deg(1) )then
181  ind4(1)= -1
182  end if
183 
184  !loop over massline entries in third dimension
185  do j3 = 1, 2*deg(3)+1
186  if(j3<=deg(3))then
187  limit(3)=deg(3)
188  ind1(3)=deg(3)+1-j3 !position in massline
189  else
190  limit(3)=2*deg(3)+1
191  ind1(3)=j3 !position in massline
192  end if
193  !loop over spline cells
194  do int3=j3, limit(3)
195  if(j3<=deg(3))then
196  ind2(3)=deg(3)+1-int3+j3 !spline1
197  ind3(3)=deg(3)+1-int3 !spline2
198  ind4(3)=int3-j3 !left cellborder
199  else
200  ind2(3)=int3-j3+1 !spline1
201  ind3(3)=int3-deg(3) !spline2
202  ind4(3)=deg(3)+j3-int3 !left cellborder
203  end if
204  !loop over massline entries in second dimension
205  do j2 = 1, 2*deg(2)+1
206  if(j2<=deg(2))then
207  limit(2)=deg(2)
208  ind1(2)=deg(2)+1-j2
209  else
210  limit(2)=2*deg(2)+1
211  ind1(2)=j2
212  end if
213  !loop over spline cells
214  do int2= j2, limit(2)
215  if(j2<=deg(2))then
216  ind2(2)=deg(2)+1-int2+j2 !spline1
217  ind3(2)=deg(2)+1-int2 !spline2
218  ind4(2)=int2-j2 !left cellborder
219  else
220  ind2(2)=int2-j2+1 !spline1
221  ind3(2)=int2-deg(2) !spline2
222  ind4(2)=deg(2)+j2-int2 !left cellborder
223  end if
224  !loop over massline entries in first dimension
225  !interval
226  do interval = 1, 2*deg(1)-1
227  !row
228  do j1 = interval, min(interval+deg(1),2*deg(1)-1)
229  !column
230  do int1 = interval, deg(1)+interval
231  if(j1 <= deg(1)+1)then
232  ind1(1) = int1+((j1-1)*(2*deg(1)+j1))/2 !position in first dimension in massline
233  else if(j1 > deg(1)+1 .and. j1 < 2*deg(1))then
234  ind1(1) = int1 + (j1-deg(1)-1)*2*deg(1)+(3*deg(1)**2+deg(1))/2 !position in first dimension in massline
235  end if
236  ind2(1) = j1-interval+1 !spline1
237  ind3(1) = int1-interval+1 !spline2
238 
239  ! loop over Gauss points
240  do k3=1, q(3)
241  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)
242  do k2=1, q(2)
243  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)
244  do k1=1, q(1)
245  c(1)=(real(ind4(1),f64)*xw_gauss_d1(1,k1)+real(row(1)-1+ind4(1)*(interval-1),f64))/real(n_cells(1),f64)
246 
247  mass_line(ind1(1)+(ind1(2)-1)*(7*deg(1)**2-deg(1)-2)/2+(ind1(3)-1)*(7*deg(1)**2-deg(1)-2)/2*(2*deg(2)+1)) = &
248  mass_line(ind1(1)+(ind1(2)-1)*(7*deg(1)**2-deg(1)-2)/2+(ind1(3)-1)*(7*deg(1)**2-deg(1)-2)/2*(2*deg(2)+1)) + &
249  xw_gauss_d1(2,k1)* xw_gauss_d2(2,k2)* xw_gauss_d3(2,k3) *&
250  bspl_b(ind2(1), k1,interval)*&
251  bspl_d2(ind2(2), k2)*&
252  bspl_d3(ind2(3), k3)*&
253  bspl_b(ind3(1), k1,interval)*&
254  bspl_d2(ind3(2), k2)*&
255  bspl_d3(ind3(3), k3)*&
256  profile( c, [component] )
257  enddo
258  enddo
259  enddo
260  end do
261  end do
262  end do
263  end do
264  enddo
265  end do
266  end do
267 
269 
271  Subroutine sll_s_spline_fem_mixedmass3d_clamped( n_cells, deg1, deg2, component, matrix, profile, spline1, spline2, n_cells_min, n_cells_max )
272  sll_int32, intent( in ) :: n_cells(3)
273  sll_int32, intent( in ) :: deg1(3), deg2(3)
274  sll_int32, intent( in ) :: component(2)
275  type(sll_t_matrix_csr), intent( out ) :: matrix
276  procedure(sll_i_profile_function) :: profile
277  type(sll_t_spline_pp_1d), intent( in ) :: spline1
278  type(sll_t_spline_pp_1d), intent( in ) :: spline2
279  sll_int32, optional, intent( in ) :: n_cells_min(3)
280  sll_int32, optional, intent( in ) :: n_cells_max(3)
281  !local variables
282  sll_int32 :: q(3), begin(3), limit(3)
283  sll_int32 :: i1, i2, i3, ind, k, start
284  sll_real64 :: mass_line_b( 1:((deg1(1)+deg2(1))**2+(2*deg2(1)+deg1(1)-deg1(1)**2)/2)*(deg1(2)+deg2(2)+1)*(deg1(3)+deg2(3)+1) )
285  sll_real64 :: mass_line( 1:(deg1(1)+deg2(1)+1)*(deg1(2)+deg2(2)+1)*(deg1(3)+deg2(3)+1) )
286  sll_real64, allocatable :: xw_gauss_d1(:,:), xw_gauss_d2(:,:), xw_gauss_d3(:,:)
287  sll_real64, allocatable :: bspl_d1a(:,:), bspl_d2a(:,:), bspl_d3a(:,:)
288  sll_real64, allocatable :: bspl_d1b(:,:), bspl_d2b(:,:), bspl_d3b(:,:)
289 
290  !quadrature points
291  q = max(deg1,deg2)+1
292 
293  allocate( xw_gauss_d1(1:2, 1:q(1)) )
294  allocate( xw_gauss_d2(1:2, 1:q(2)) )
295  allocate( xw_gauss_d3(1:2, 1:q(3)) )
296  allocate( bspl_d1a(1:deg1(1)+1, 1:q(1)) )
297  allocate( bspl_d2a(1:deg1(2)+1, 1:q(2)) )
298  allocate( bspl_d3a(1:deg1(3)+1, 1:q(3)) )
299  allocate( bspl_d1b(1:deg2(1)+1, 1:q(1)) )
300  allocate( bspl_d2b(1:deg2(2)+1, 1:q(2)) )
301  allocate( bspl_d3b(1:deg2(3)+1, 1:q(3)) )
302 
303  if( present(n_cells_min) .and. present(n_cells_max) )then
304  ind=1+( (n_cells_min(2)-1)+(n_cells_min(3)-1)*n_cells(2) )*&
305  ( ((n_cells(1)-deg1(1))*(deg1(1)+deg2(1)+1)+deg1(1)*(2*deg2(1)+deg1(1)+1))*&
306  (deg1(2)+deg2(2)+1)*(deg1(3)+deg2(3)+1) )
307  begin=n_cells_min
308  limit=n_cells_max
309  else
310  ind=1
311  begin=1
312  limit=n_cells
313  end if
314 
315  call sll_s_spline_fem_sparsity_mixedmass3d_clamped( deg1(:), deg2(:), n_cells, matrix )
316  bspl_d1a=0._f64
317  bspl_d1b=0._f64
318  ! take enough Gauss points so that projection is exact for splines of deg deg
319  ! rescale on [0,1] for compatibility with B-splines
320  xw_gauss_d1 = sll_f_gauss_legendre_points_and_weights( q(1), 0._f64, 1._f64 )
321  ! Compute bsplines at gauss_points
322  do k=1, q(1)
323  call sll_s_uniform_bsplines_eval_basis( deg1(1),xw_gauss_d1(1,k), bspl_d1a(1:deg1(1)+1, k) )
324  call sll_s_uniform_bsplines_eval_basis( deg2(1),xw_gauss_d1(1,k), bspl_d1b(1:deg2(1)+1, k) )
325  end do
326  bspl_d2a=0._f64
327  bspl_d2b=0._f64
328  xw_gauss_d2 = sll_f_gauss_legendre_points_and_weights( q(2), 0._f64, 1._f64 )
329  ! Compute bsplines at gauss_points
330  do k=1, q(2)
331  call sll_s_uniform_bsplines_eval_basis( deg1(2),xw_gauss_d2(1,k), bspl_d2a(1:deg1(2)+1, k) )
332  call sll_s_uniform_bsplines_eval_basis( deg2(2),xw_gauss_d2(1,k), bspl_d2b(1:deg2(2)+1, k) )
333  end do
334  bspl_d3a=0._f64
335  bspl_d3b=0._f64
336  xw_gauss_d3 = sll_f_gauss_legendre_points_and_weights( q(3), 0._f64, 1._f64 )
337  ! Compute bsplines at gauss_points
338  do k=1, q(3)
339  call sll_s_uniform_bsplines_eval_basis( deg1(3),xw_gauss_d3(1,k), bspl_d3a(1:deg1(3)+1, k) )
340  call sll_s_uniform_bsplines_eval_basis( deg2(3),xw_gauss_d3(1,k), bspl_d3b(1:deg2(3)+1, k) )
341  end do
342 
343 
344  !loop over rows of the mass matrix to compute assemble the massline
345  do i3=begin(3), limit(3)
346  do i2=begin(2), limit(2)
347  call sll_s_spline_fem_mixedmass_line_boundary( q, deg1, deg2, profile, [1,i2,i3], n_cells, component, mass_line_b, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1a, bspl_d2a, bspl_d3a, bspl_d1b, bspl_d2b, bspl_d3b, spline1, spline2 )
348 
349  !scale with delta_x=1/n_cells
350  mass_line_b=mass_line_b/real(n_cells(1)*n_cells(2)*n_cells(3),f64)
351  start=ind
352  do i1=1, deg1(1)+deg2(1)
353  call assemble_mixedmass3d_clamped_boundary( deg1(:), deg2(:), n_cells, mass_line_b, matrix, [i1,i2,i3], ind )
354  end do
355  sll_assert( ind == start+((deg1(1)+deg2(1))**2+(2*deg2(1)+deg1(1)-deg1(1)**2)/2)*(deg1(2)+deg2(2)+1)*(deg1(3)+deg2(3)+1) )
356  do i1=deg1(1)+deg2(1)+1, n_cells(1)-deg2(1)
357  call sll_s_spline_fem_mixedmass_line( q, deg1, deg2, profile, [i1-deg1(1),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 )
358  !scale with delta_x=1/n_cells
359  mass_line=mass_line/real(n_cells(1)*n_cells(2)*n_cells(3),f64)
360  call assemble_mixedmass3d_clamped( deg1(:), deg2(:), n_cells, mass_line(:), matrix, [i1,i2,i3], ind )
361  end do
362  call sll_s_spline_fem_mixedmass_line_boundary( q, deg1, deg2, profile, [n_cells(1)+1,i2,i3], n_cells, component, mass_line_b, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1a, bspl_d2a, bspl_d3a, bspl_d1b, bspl_d2b, bspl_d3b, spline1, spline2 )
363 
364  !scale with delta_x=1/n_cells
365  mass_line_b=mass_line_b/real(n_cells(1)*n_cells(2)*n_cells(3),f64)
366  start=ind
367  do i1 = n_cells(1)-deg2(1)+1, n_cells(1)+deg1(1)
368  call assemble_mixedmass3d_clamped_boundary( deg1, deg2, n_cells, mass_line_b, matrix, [i1,i2,i3], ind )
369  end do
370  sll_assert( ind == start+((deg1(1)+deg2(1))**2+(2*deg2(1)+deg1(1)-deg1(1)**2)/2)*(deg1(2)+deg2(2)+1)*(deg1(3)+deg2(3)+1) )
371  end do
372  end do
373 
374  deallocate( xw_gauss_d1 )
375  deallocate( xw_gauss_d2 )
376  deallocate( xw_gauss_d3 )
377  deallocate( bspl_d1a )
378  deallocate( bspl_d2a )
379  deallocate( bspl_d3a )
380  deallocate( bspl_d1b )
381  deallocate( bspl_d2b )
382  deallocate( bspl_d3b )
383 
385 
386 
388  subroutine sll_s_spline_fem_mixedmass_line_boundary( 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, spline1, spline2 )
389  sll_int32, intent( in ) :: q(3)
390  sll_int32, intent( in ) :: deg1(3), deg2(3)
391  procedure(sll_i_profile_function) :: profile
392  sll_int32, intent( in ) :: row(3)
393  sll_int32, intent( in ) :: n_cells(3)
394  sll_int32, intent( in ) :: component(2)
395  sll_real64, intent( out ) :: mass_line( 1:((deg1(1)+deg2(1))**2+(2*deg2(1)+deg1(1)-deg1(1)**2)/2)*(deg1(2)+deg2(2)+1)*(deg1(3)+deg2(3)+1) )
396  sll_real64, intent( in ) :: xw_gauss_d1(2, q(1)), xw_gauss_d2(2, q(2)), xw_gauss_d3(2, q(3))
397  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))
398  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))
399  type(sll_t_spline_pp_1d), intent( in ) :: spline1
400  type(sll_t_spline_pp_1d), intent( in ) :: spline2
401  ! local variables
402  sll_int32 :: int1, int2, int3, j1, j2, j3, k1, k2, k3, interval
403  sll_real64 :: c(3)
404  sll_int32 :: limit(3), ind1(3), ind2(3), ind3(3), ind4(3)
405  sll_real64 :: bspl_b1(1:deg1(1)+1, 1:q(1),1:deg1(1)+deg2(1))
406  sll_real64 :: bspl_b2(1:deg2(1)+1, 1:q(1),1:deg1(1)+deg2(1))
407 
408  mass_line=0._f64
409 
410  do interval = 1, deg1(1)-1
411  do k1 = 1, q(1)
412  do j1 = 1, deg1(1)+1
413  bspl_b1(j1,k1,interval) = sll_f_spline_pp_horner_1d( deg1(1), spline1%poly_coeffs_boundary_left(:,:,interval), xw_gauss_d1(1,k1), j1)
414  end do
415  end do
416  end do
417  if( deg1(1) == 0 ) then
418  do interval = 1, deg2(1)
419  bspl_b1(:,:,interval)=bspl_d1a
420  end do
421  else
422  do interval = deg1(1), deg1(1)+deg2(1)
423  bspl_b1(:,:,interval)=bspl_d1a
424  end do
425  end if
426 
427  do interval = 1, deg2(1)-1
428  do k1 = 1, q(1)
429  do j1 = 1, deg2(1)+1
430  bspl_b2(j1,k1,interval) = sll_f_spline_pp_horner_1d( deg2(1), spline2%poly_coeffs_boundary_left(:,:,interval), xw_gauss_d1(1,k1), j1)
431  end do
432  end do
433  end do
434  if( deg2(1) == 0 ) then
435  do interval = 1, deg1(1)
436  bspl_b2(:,:,interval)=bspl_d1b
437  end do
438  else
439  do interval = deg2(1), deg1(1)+deg2(1)
440  bspl_b2(:,:,interval)=bspl_d1b
441  end do
442  end if
443 
444  if( row(1) <= deg1(1)+deg2(1) )then
445  ind4(1)= 1
446  else if ( row(1) > n_cells(1) - deg2(1) .and. row(1) <= n_cells(1)+deg1(1) )then
447  ind4(1)= -1
448  end if
449 
450 
451  !loop over massline entries in third dimension
452  do j3 = 1, deg1(3)+deg2(3)+1
453  if(j3<=deg2(3))then
454  limit(3)=deg2(3)
455  ind1(3)=deg2(3)+1-j3 !position in massline
456  else
457  limit(3)=deg1(3)+deg2(3)+1
458  ind1(3)=j3!position in massline
459  end if
460  ! loop over spline cells
461  do int3=j3, min(limit(3),j3+deg2(3))
462  if(j3<=deg2(3))then
463  ind2(3)=deg1(3)+1-int3+j3 !spline1
464  ind3(3)=deg2(3)+1-int3 !spline2
465  ind4(3)=int3-j3 !left cellborder
466  else
467  ind2(3)=limit(3)-int3+1 !spline1
468  ind3(3)=deg2(3)+1-int3+j3 !spline2
469  ind4(3)=int3-deg2(3)-1 !left cellborder
470  end if
471  !loop over massline entries in second dimension
472  do j2 = 1, deg1(2)+deg2(2)+1
473  if(j2<=deg2(2))then
474  limit(2)=deg2(2)
475  ind1(2)=deg2(2)+1-j2
476  else
477  limit(2)=deg1(2)+deg2(2)+1
478  ind1(2)=j2
479  end if
480  ! loop over spline cells
481  do int2=j2, min(limit(2),j2+deg2(2))
482  if(j2<=deg2(2))then
483  ind2(2)=deg1(2)+1-int2+j2 !spline1
484  ind3(2)=deg2(2)+1-int2 !spline2
485  ind4(2)=int2-j2 !left cellborder
486  else
487  ind2(2)=limit(2)-int2+1 !spline1
488  ind3(2)=deg2(2)+1-int2+j2 !spline2
489  ind4(2)=int2-deg2(2)-1 !left cellborder
490  end if
491  !loop over massline entries in first dimension
492  !interval
493  do interval = 1, deg1(1)+deg2(1)
494  !row
495  do j1 = interval, min(interval+deg1(1),deg1(1)+deg2(1))
496  !column
497  do int1 = interval, deg2(1)+interval
498  if(j1 <= deg1(1)+1)then
499  ind1(1) = int1 + ((j1-1)*(2*deg2(1)+j1))/2
500  else if(j1 > deg1(1)+1 .and. j1 <= deg1(1)+deg2(1))then
501  ind1(1) = int1 + (j1-deg1(1)-1)*(deg1(1)+deg2(1)) + (deg1(1)*(2*deg2(1)+deg1(1)+1))/2!position in first dimension in massline
502  end if
503  ind2(1) = j1-interval+1 !spline1
504  ind3(1) = int1-interval+1 !spline2
505  ! loop over Gauss points
506  do k3=1, q(3)
507  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)
508  do k2=1, q(2)
509  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)
510  do k1=1, q(1)
511  c(1)=(real(ind4(1),f64)*xw_gauss_d1(1,k1)+real(row(1)-1+ind4(1)*(interval-1),f64))/real(n_cells(1),f64)
512 
513  mass_line(ind1(1)+(ind1(2)-1)*((deg1(1)+deg2(1))**2+(2*deg2(1)+deg1(1)-deg1(1)**2)/2)+(ind1(3)-1)*((deg1(1)+deg2(1))**2+(2*deg2(1)+deg1(1)-deg1(1)**2)/2)*(deg1(2)+deg2(2)+1)) = &
514  mass_line(ind1(1)+(ind1(2)-1)*((deg1(1)+deg2(1))**2+(2*deg2(1)+deg1(1)-deg1(1)**2)/2)+(ind1(3)-1)*((deg1(1)+deg2(1))**2+(2*deg2(1)+deg1(1)-deg1(1)**2)/2)*(deg1(2)+deg2(2)+1)) + &
515  xw_gauss_d1(2,k1)* xw_gauss_d2(2,k2)* xw_gauss_d3(2,k3) *&
516  bspl_b1(ind2(1), k1,interval)*&
517  bspl_d2a(ind2(2), k2)*&
518  bspl_d3a(ind2(3), k3)*&
519  bspl_b2(ind3(1), k1,interval)*&
520  bspl_d2b(ind3(2), k2)*&
521  bspl_d3b(ind3(3), k3)*&
522  profile( c, component )
523  end do
524  end do
525  enddo
526  end do
527  end do
528  enddo
529  end do
530  enddo
531  end do
532  enddo
533 
535 
536 
538  subroutine sll_s_multiply_g_clamped( n_dofs, delta_x, s_deg_0, field_in, field_out )
539  sll_int32, intent( in ) :: n_dofs(3)
540  sll_real64, intent( in ) :: delta_x(3)
541  sll_int32, intent( in ) :: s_deg_0(3)
542  sll_real64, intent( in ) :: field_in(:)
543  sll_real64, intent( out ) :: field_out(:)
544  !local variables
545  sll_real64 :: coef
546  sll_int32 :: stride, stride_end
547  sll_int32 :: ind3d, ind1d
548  sll_int32 :: i,j,k
549 
550  coef = 1.0_f64/ delta_x(1)
551 
552  ind1d = 0
553  ind3d = 0
554  do k = 1, n_dofs(3)
555  do j = 1, n_dofs(2)
556  ind3d = ind3d + 1
557  ind1d = ind1d + 1
558  field_out(ind3d) = real(s_deg_0(1),f64)*coef*( field_in(ind1d+1) )
559  do i = 2, s_deg_0(1)-1 !1, s_deg_0 -1 perfect condutctor BC
560  ind3d = ind3d + 1
561  ind1d = ind1d + 1
562  field_out(ind3d) = real(s_deg_0(1),f64)/real(i,f64)*coef*( field_in(ind1d+1) - field_in(ind1d) )
563  end do
564  do i = s_deg_0(1), n_dofs(1)-s_deg_0(1)
565  ind3d = ind3d + 1
566  ind1d = ind1d + 1
567  field_out(ind3d) = coef*( field_in(ind1d+1) - field_in(ind1d) )
568  end do
569  do i = n_dofs(1)-s_deg_0(1)+1, n_dofs(1)-2 !n_dofs-1 perfect conductor BC
570  ind3d = ind3d + 1
571  ind1d = ind1d + 1
572  field_out(ind3d) = real(s_deg_0(1),f64)/real(n_dofs(1)-i,f64)*coef*( field_in(ind1d+1) - field_in(ind1d) )
573  end do
574  ind3d = ind3d + 1
575  ind1d = ind1d + 1
576  field_out(ind3d) = real(s_deg_0(1),f64)*coef*( - field_in(ind1d) )
577  ind1d = ind1d + 1
578  end do
579  end do
580 
581  coef = 1.0_f64/ delta_x(2)
582  stride = n_dofs(1)
583  stride_end = (1-n_dofs(2))*n_dofs(1)
584 
585  ind1d = 0
586  do k = 1, n_dofs(3)
587  ind3d = ind3d + 1
588  ind1d = ind1d + 1
589  field_out(ind3d) = 0._f64
590  do i = 2, n_dofs(1)-1 !1: n_dofs(1) perfect conductor BC
591  ind3d = ind3d + 1
592  ind1d = ind1d + 1
593  field_out(ind3d) = coef * ( field_in(ind1d) - field_in(ind1d-stride_end) )
594  end do
595  ind3d = ind3d + 1
596  ind1d = ind1d + 1
597  field_out(ind3d) = 0._f64
598 
599  do j = 2, n_dofs(2)
600  ind3d = ind3d + 1
601  ind1d = ind1d + 1
602  field_out(ind3d) = 0._f64
603  do i = 2, n_dofs(1)-1 !1: n_dofs(1) perfect conductor BC
604  ind3d = ind3d + 1
605  ind1d = ind1d + 1
606  field_out(ind3d) = coef * ( field_in(ind1d) - field_in(ind1d-stride) )
607  end do
608  ind3d = ind3d + 1
609  ind1d = ind1d + 1
610  field_out(ind3d) = 0._f64
611  end do
612  end do
613 
614  coef = 1.0_f64/ delta_x(3)
615  stride = n_dofs(1)*n_dofs(2)
616  stride_end = (1-n_dofs(3))*n_dofs(1)*n_dofs(2)
617 
618  ind1d = 0
619  do j = 1, n_dofs(2)
620  ind3d = ind3d + 1
621  ind1d = ind1d + 1
622  field_out(ind3d) = 0._f64
623  do i = 2, n_dofs(1)-1 !1: n_dofs(1) perfect conductor BC
624  ind3d = ind3d + 1
625  ind1d = ind1d + 1
626  field_out(ind3d) = coef * ( field_in(ind1d) - field_in(ind1d-stride_end) )
627  end do
628  ind3d = ind3d + 1
629  ind1d = ind1d + 1
630  field_out(ind3d) = 0._f64
631  end do
632  do k = 2, n_dofs(3)
633  do j = 1, n_dofs(2)
634  ind3d = ind3d + 1
635  ind1d = ind1d + 1
636  field_out(ind3d) = 0._f64
637  do i = 2, n_dofs(1)-1 !1: n_dofs(1) perfect conductor BC
638  ind3d = ind3d + 1
639  ind1d = ind1d + 1
640  field_out(ind3d) = coef * ( field_in(ind1d) - field_in(ind1d-stride) )
641  end do
642  ind3d = ind3d + 1
643  ind1d = ind1d + 1
644  field_out(ind3d) = 0._f64
645  end do
646  end do
647 
648  end subroutine sll_s_multiply_g_clamped
649 
650 
652  subroutine sll_s_multiply_gt_clamped( n_dofs, delta_x, s_deg_0, field_in, field_out )
653  sll_int32, intent( in ) :: n_dofs(3)
654  sll_real64, intent( in ) :: delta_x(3)
655  sll_int32, intent( in ) :: s_deg_0(3)
656  sll_real64, intent( in ) :: field_in(:)
657  sll_real64, intent( out ) :: field_out(:)
658  !local variables
659  sll_real64 :: coef
660  sll_int32 :: stride, stride_end
661  sll_int32 :: ind3d, ind1d
662  sll_int32 :: i,j,k
663 
664 
665  coef = 1.0_f64/ delta_x(1)
666 
667  ind1d = 0
668  ind3d = 0
669  do k = 1, n_dofs(3)
670  do j = 1, n_dofs(2)
671  ind3d = ind3d + 1
672  ind1d = ind1d + 1
673  field_out(ind1d) = 0._f64!- real(s_deg_0(1),f64)*coef*field_in(ind3d) perfect condutctor BC
674  do i = 2, s_deg_0(1)
675  ind3d = ind3d + 1
676  ind1d = ind1d + 1
677  field_out(ind1d) = real(s_deg_0(1),f64)*coef*( field_in(ind3d-1)/real(i-1,f64) - field_in(ind3d)/real(i,f64) )
678  end do
679  do i = s_deg_0(1)+1, n_dofs(1)-s_deg_0(1)
680  ind3d = ind3d + 1
681  ind1d = ind1d + 1
682  field_out(ind1d) = coef*( field_in(ind3d-1) - field_in(ind3d) )
683  end do
684  do i = n_dofs(1)-s_deg_0(1)+1, n_dofs(1)-1
685  ind3d = ind3d + 1
686  ind1d = ind1d + 1
687  field_out(ind1d) = real(s_deg_0(1),f64)*coef*( field_in(ind3d-1)/real(n_dofs(1)+1-i,f64) - field_in(ind3d)/real(n_dofs(1)-i,f64) )
688  end do
689  !ind3d = ind3d + 1
690  ind1d = ind1d + 1
691  field_out(ind1d) = 0._f64!real(s_deg_0(1),f64)*coef*field_in(ind3d)!-1) perfect condutctor BC
692  !ind3d = ind3d - 1
693  end do
694  end do
695 
696 
697  coef = 1.0_f64/ delta_x(2)
698  stride = n_dofs(1)
699  stride_end = (1-n_dofs(2))*n_dofs(1)
700 
701  ind1d = 0
702  do k = 1, n_dofs(3)
703  do j = 1, n_dofs(2)-1
704  ind3d = ind3d + 1
705  ind1d = ind1d + 1
706  field_out(ind1d) = 0._f64
707  do i = 2, n_dofs(1)-1 !1, n_dofs(1) perfect conductor BC
708  ind3d = ind3d + 1
709  ind1d = ind1d + 1
710 
711  field_out(ind1d) = field_out(ind1d) + &
712  coef * ( field_in(ind3d) - field_in(ind3d+stride) )
713 
714  end do
715  ind3d = ind3d + 1
716  ind1d = ind1d + 1
717  field_out(ind1d) = 0._f64
718  end do
719  ind3d = ind3d + 1
720  ind1d = ind1d + 1
721  field_out(ind1d) = 0._f64
722  do i= 2, n_dofs(1)-1 !1, n_dofs(1) perfect conductor BC
723  ind3d = ind3d + 1
724  ind1d = ind1d + 1
725 
726  field_out(ind1d) = field_out(ind1d) + &
727  coef * ( field_in(ind3d) - field_in(ind3d+stride_end) )
728 
729  end do
730  ind3d = ind3d + 1
731  ind1d = ind1d + 1
732  field_out(ind1d) = 0._f64
733  end do
734  coef = 1.0_f64/ delta_x(3)
735  stride = n_dofs(1)*n_dofs(2)
736  stride_end = (1-n_dofs(3))*n_dofs(1)*n_dofs(2)
737 
738  ind1d = 0
739  do k = 1, n_dofs(3)-1
740  do j = 1, n_dofs(2)
741  ind3d = ind3d + 1
742  ind1d = ind1d + 1
743  field_out(ind1d) = 0._f64
744  do i = 2, n_dofs(1)-1 !1, n_dofs(1) perfect conductor BC
745  ind3d = ind3d + 1
746  ind1d = ind1d + 1
747 
748  field_out(ind1d) = field_out(ind1d) + &
749  coef * ( field_in(ind3d) - field_in(ind3d+stride) )
750  end do
751  ind3d = ind3d + 1
752  ind1d = ind1d + 1
753  field_out(ind1d) = 0._f64
754  end do
755  end do
756  do j = 1, n_dofs(2)
757  ind3d = ind3d + 1
758  ind1d = ind1d + 1
759  field_out(ind1d) = 0._f64
760  do i = 2, n_dofs(1)-1 !1, n_dofs(1) perfect conductor BC
761  ind3d = ind3d + 1
762  ind1d = ind1d + 1
763 
764  field_out(ind1d) = field_out(ind1d) + &
765  coef * ( field_in(ind3d) - field_in(ind3d+stride_end) )
766  end do
767  ind3d = ind3d + 1
768  ind1d = ind1d + 1
769  field_out(ind1d) = 0._f64
770  end do
771 
772  end subroutine sll_s_multiply_gt_clamped
773 
774 
776  subroutine sll_s_multiply_c_clamped( n_dofs, delta_x, s_deg_0, field_in, field_out )
777  sll_int32, intent( in ) :: n_dofs(3)
778  sll_real64, intent( in ) :: delta_x(3)
779  sll_int32, intent( in ) :: s_deg_0(3)
780  sll_real64, intent( in ) :: field_in(:)
781  sll_real64, intent( out ) :: field_out(:)
782  ! local variables
783  sll_real64 :: coef(2)
784  sll_int32 :: stride(2), jump(2), indp(2), n_total0, n_total1
785  sll_int32 :: i,j,k, ind3d, ind3d_1, ind3d_2, ind
786 
787  n_total0 = product(n_dofs)
788  n_total1 = (n_dofs(1)-1)*n_dofs(2)*n_dofs(3)
789 
790  ! TODO: Avoid the IF for periodic boundaries
791  ! First component
792  coef(1) = 1.0_f64/ delta_x(2)
793  coef(2) = -1.0_f64/ delta_x(3)
794 
795  stride(1) = n_dofs(1)
796  stride(2) = n_dofs(1)*n_dofs(2)
797 
798  jump(1) = n_total1+n_total0
799  jump(2) = n_total1
800 
801 
802  ind3d = 0
803  do k = 1, n_dofs(3)
804  if (k == 1) then
805  indp(2) = stride(2)*(n_dofs(3)-1)
806  else
807  indp(2) = - stride(2)
808  end if
809  do j = 1, n_dofs(2)
810  if ( j==1 ) then
811  indp(1) = stride(1)*(n_dofs(2)-1)
812  else
813  indp(1) = - stride(1)
814  end if
815  ind3d = ind3d + 1
816  field_out(ind3d) = 0._f64
817  do i = 2, n_dofs(1)-1 !1, n_dofs(1) perfect conductor BC
818  ind3d = ind3d + 1
819 
820  ind3d_1 = ind3d +indp(1)+jump(1)
821  ind3d_2 = ind3d +indp(2)+jump(2)
822 
823  field_out(ind3d) = &
824  coef(1) * ( field_in( ind3d+jump(1) ) -&
825  field_in( ind3d_1 )) + &
826  coef(2) * ( field_in(ind3d+jump(2) ) - &
827  field_in( ind3d_2 ))
828 
829  end do
830  ind3d = ind3d + 1
831  field_out(ind3d) = 0._f64
832  end do
833  end do
834 
835 
836  ! Second component
837  coef(1) = 1.0_f64/ delta_x(3)
838  coef(2) = -1.0_f64/ delta_x(1)
839 
840  stride(1) = (n_dofs(1)-1)*n_dofs(2)
841  stride(2) = 1
842 
843  jump(1) = -n_total0
844  jump(2) = n_total1
845 
846  ind = ind3d
847  do k = 1, n_dofs(3)
848  if (k == 1) then
849  indp(1) = stride(1)*(n_dofs(3)-1)
850  else
851  indp(1) = - stride(1)
852  end if
853  do j = 1, n_dofs(2)
854  ind3d = ind3d + 1
855  ind = ind +1
856  ind3d_1 = ind3d +indp(1)+jump(1)
857  ind3d_2 = ind -stride(2)+jump(2)
858 
859  field_out(ind3d) = &
860  coef(1) * ( field_in( ind3d+jump(1) ) -&
861  field_in( ind3d_1 ) )+ &
862  real(s_deg_0(1),f64)*coef(2)* &
863  ( field_in(ind+jump(2)+1 ) )
864  do i = 2, s_deg_0(1)-1 !1, s_deg_0(1) -1 perfect condutctor BC
865  ind3d = ind3d + 1
866  ind = ind +1
867  ind3d_1 = ind3d +indp(1)+jump(1)
868  ind3d_2 = ind -stride(2)+jump(2)
869 
870  field_out(ind3d) = &
871  coef(1) * ( field_in( ind3d+jump(1) ) -&
872  field_in( ind3d_1 ) )+ &
873  real(s_deg_0(1),f64)/real(i,f64)*coef(2)* &
874  ( field_in(ind+jump(2)+1 ) - &
875  field_in( ind3d_2+1 ) )
876  end do
877  do i = s_deg_0(1), n_dofs(1)-s_deg_0(1)
878  ind3d = ind3d + 1
879  ind = ind +1
880  ind3d_1 = ind3d +indp(1)+jump(1)
881  ind3d_2 = ind -stride(2)+jump(2)
882 
883  field_out(ind3d) = &
884  coef(1) * ( field_in( ind3d+jump(1) ) -&
885  field_in( ind3d_1 ) )+ &
886  coef(2) * ( field_in(ind+jump(2)+1 ) - &
887  field_in( ind3d_2+1 ) )
888  end do
889  do i = n_dofs(1)-s_deg_0(1)+1, n_dofs(1)-2 !n_dofs(1)-1 perfect conductor BC
890  ind3d = ind3d + 1
891  ind = ind +1
892  ind3d_1 = ind3d +indp(1)+jump(1)
893  ind3d_2 = ind -stride(2)+jump(2)
894 
895  field_out(ind3d) = &
896  coef(1) * ( field_in( ind3d+jump(1) ) -&
897  field_in( ind3d_1 ) )+ &
898  real(s_deg_0(1),f64)/real(n_dofs(1)-i,f64) * &
899  coef(2) * ( field_in(ind+jump(2)+1 ) - &
900  field_in( ind3d_2+1 ) )
901  end do
902  ind3d = ind3d + 1
903  ind = ind +1
904  ind3d_1 = ind3d +indp(1)+jump(1)
905  ind3d_2 = ind -stride(2)+jump(2)
906 
907  field_out(ind3d) = &
908  coef(1) * ( field_in( ind3d+jump(1) ) -&
909  field_in( ind3d_1 ) )+ &
910  real(s_deg_0(1),f64) * &
911  coef(2) * ( - field_in( ind3d_2+1 ) )
912  ind = ind + 1
913  end do
914  end do
915 
916  ! Third component
917  coef(1) = 1.0_f64/ delta_x(1)
918  coef(2) = -1.0_f64/ delta_x(2)
919 
920  stride(1) = 1
921  stride(2) = n_dofs(1)-1
922 
923  jump(1) = -n_total0
924  jump(2) = -(n_total0+n_total1)
925 
926 
927  ind = ind3d
928  do k = 1, n_dofs(3)
929  do j = 1, n_dofs(2)
930  if (j == 1) then
931  indp(2) = stride(2)*(n_dofs(2)-1)
932  else
933  indp(2) = - stride(2)
934  end if
935  ind3d = ind3d + 1
936  ind = ind + 1
937  ind3d_1 = ind -stride(1)+jump(1)
938  ind3d_2 = ind3d +indp(2)+jump(2)
939 
940  field_out(ind3d) = &
941  real(s_deg_0(1),f64) * &
942  coef(1) * ( field_in( ind+jump(1)+1 ) )+ &
943  coef(2)*( field_in(ind3d+jump(2) ) - &
944  field_in( ind3d_2 ) )
945  do i = 2, s_deg_0(1)-1 !1, s_deg_0(1) -1 perfect condutctor BC
946  ind3d = ind3d + 1
947  ind = ind + 1
948  ind3d_1 = ind -stride(1)+jump(1)
949  ind3d_2 = ind3d +indp(2)+jump(2)
950 
951  field_out(ind3d) = &
952  real(s_deg_0(1),f64)/real(i,f64) * &
953  coef(1) * ( field_in( ind+jump(1)+1 ) -&
954  field_in( ind3d_1+1 ) )+ &
955  coef(2)*( field_in(ind3d+jump(2) ) - &
956  field_in( ind3d_2 ) )
957  end do
958  do i = s_deg_0(1), n_dofs(1)-s_deg_0(1)
959  ind3d = ind3d + 1
960  ind = ind + 1
961  ind3d_1 = ind -stride(1)+jump(1)
962  ind3d_2 = ind3d +indp(2)+jump(2)
963 
964  field_out(ind3d) = &
965  coef(1) * ( field_in( ind+jump(1)+1 ) -&
966  field_in( ind3d_1+1 ) )+ &
967  coef(2) * ( field_in(ind3d+jump(2) ) - &
968  field_in( ind3d_2 ) )
969  end do
970  do i = n_dofs(1)-s_deg_0(1)+1, n_dofs(1)-2 !n_dofs(1)-1 perfect conductor BC
971  ind3d = ind3d + 1
972  ind = ind + 1
973  ind3d_1 = ind -stride(1)+jump(1)
974  ind3d_2 = ind3d +indp(2)+jump(2)
975 
976  field_out(ind3d) = &
977  real(s_deg_0(1),f64)/real(n_dofs(1)-i,f64) * &
978  coef(1) * ( field_in( ind+jump(1)+1 ) -&
979  field_in( ind3d_1+1 ) )+ &
980  coef(2) * ( field_in(ind3d+jump(2) ) - &
981  field_in( ind3d_2 ) )
982  end do
983  ind3d = ind3d + 1
984  ind = ind + 1
985  ind3d_1 = ind -stride(1)+jump(1)
986  ind3d_2 = ind3d +indp(2)+jump(2)
987 
988  field_out(ind3d) = &
989  real(s_deg_0(1),f64) * &
990  coef(1) * ( - field_in( ind3d_1+1 ) )+ &
991  coef(2) * ( field_in(ind3d+jump(2) ) - &
992  field_in( ind3d_2 ) )
993 
994  ind = ind + 1
995  end do
996  end do
997 
998  end subroutine sll_s_multiply_c_clamped
999 
1000 
1002  subroutine sll_s_multiply_ct_clamped( n_dofs, delta_x, s_deg_0, field_in, field_out )
1003  sll_int32, intent( in ) :: n_dofs(3)
1004  sll_real64, intent( in ) :: delta_x(3)
1005  sll_int32, intent( in ) :: s_deg_0(3)
1006  sll_real64, intent( in ) :: field_in(:)
1007  sll_real64, intent( out ) :: field_out(:)
1008  ! local variables
1009  sll_real64 :: coef(2)
1010  sll_int32 :: stride(2), jump(2), indp(2), n_total0, n_total1
1011  sll_int32 :: i,j,k, ind3d, ind3d_1, ind3d_2, ind
1012 
1013  n_total0 = product(n_dofs)
1014  n_total1 = (n_dofs(1)-1)*n_dofs(2)*n_dofs(3)
1015 
1016  ! TODO: Avoid the IF for periodic boundaries
1017  ! First component
1018  coef(1) = -1.0_f64/ delta_x(2)
1019  coef(2) = 1.0_f64/ delta_x(3)
1020 
1021  stride(1) = n_dofs(1)-1
1022  stride(2) = (n_dofs(1)-1)*n_dofs(2)
1023 
1024  jump(1) = n_total0
1025  jump(2) = n_total0+n_total1
1026 
1027 
1028  ind3d = 0
1029  do k = 1, n_dofs(3)
1030  if (k == n_dofs(3)) then
1031  indp(2) = -stride(2)*(n_dofs(3)-1)
1032  else
1033  indp(2) = stride(2)
1034  end if
1035  do j = 1, n_dofs(2)
1036  if ( j== n_dofs(2)) then
1037  indp(1) = -stride(1)*(n_dofs(2)-1)
1038  else
1039  indp(1) = stride(1)
1040  end if
1041  do i = 1, n_dofs(1)-1
1042  ind3d = ind3d + 1
1043 
1044  ind3d_1 = ind3d +indp(1)+jump(2)
1045  ind3d_2 = ind3d +indp(2)+jump(1)
1046 
1047  field_out(ind3d) = &
1048  coef(1) * ( field_in( ind3d+jump(2) ) -&
1049  field_in( ind3d_1 )) + &
1050  coef(2) * ( field_in(ind3d+jump(1) ) - &
1051  field_in( ind3d_2 ))
1052 
1053  end do
1054  end do
1055  end do
1056 
1057 
1058  ! Second component
1059  coef(1) = -1.0_f64/ delta_x(3)
1060  coef(2) = 1.0_f64/ delta_x(1)
1061 
1062  stride(1) = n_dofs(1)*n_dofs(2)
1063  stride(2) = 1
1064 
1065 
1066  jump(1) = n_total0
1067  jump(2) = -n_total1
1068 
1069  ind = ind3d
1070  do k = 1, n_dofs(3)
1071  if (k == n_dofs(3)) then
1072  indp(1) = -stride(1)*(n_dofs(3)-1)
1073  else
1074  indp(1) = stride(1)
1075  end if
1076  do j = 1, n_dofs(2)
1077  ind3d = ind3d + 1
1078  ind = ind + 1
1079  ind3d_1 = ind3d +indp(1)+jump(2)
1080 
1081  field_out(ind3d) = 0._f64
1082 !!$ coef(1) * ( field_in( ind3d+jump(2) ) -&
1083 !!$ field_in( ind3d_1 ) )+ &
1084 !!$ real(s_deg_0(1),f64) * coef(2) * &
1085 !!$ (- field_in( ind+jump(1) ) )
1086  do i = 2, s_deg_0(1)
1087  ind3d = ind3d + 1
1088  ind = ind + 1
1089  ind3d_1 = ind3d +indp(1)+jump(2)
1090  ind3d_2 = ind -stride(2)+jump(1)
1091  field_out(ind3d) = &
1092  coef(1) * ( field_in( ind3d+jump(2) ) -&
1093  field_in( ind3d_1 ) )+ &
1094  real(s_deg_0(1),f64)*coef(2) * &
1095  ( field_in( ind3d_2 )/real(i-1,f64) - &
1096  field_in( ind+jump(1) )/real(i,f64) )
1097  end do
1098  do i= s_deg_0(1)+1, n_dofs(1)-s_deg_0(1)
1099  ind3d = ind3d + 1
1100  ind = ind + 1
1101  ind3d_1 = ind3d +indp(1)+jump(2)
1102  ind3d_2 = ind -stride(2)+jump(1)
1103 
1104  field_out(ind3d) = &
1105  coef(1) * ( field_in( ind3d+jump(2) ) -&
1106  field_in( ind3d_1 ) )+ &
1107  coef(2) * ( field_in(ind3d_2 ) - &
1108  field_in( ind+jump(1) ))
1109  end do
1110  do i = n_dofs(1)-s_deg_0(1)+1, n_dofs(1)-1
1111  ind3d = ind3d + 1
1112  ind = ind + 1
1113  ind3d_1 = ind3d +indp(1)+jump(2)
1114  ind3d_2 = ind -stride(2)+jump(1)
1115 
1116  field_out(ind3d) = &
1117  coef(1) * ( field_in( ind3d+jump(2) ) -&
1118  field_in( ind3d_1 ) )+ &
1119  real(s_deg_0(1),f64)*coef(2) * &
1120  ( field_in(ind3d_2 )/real(n_dofs(1)+1-i,f64) - &
1121  field_in( ind+jump(1) )/real(n_dofs(1)-i,f64) )
1122  end do
1123  ind3d = ind3d + 1
1124  ind = ind + 1
1125  ind3d_1 = ind3d +indp(1)+jump(2)
1126  ind3d_2 = ind -stride(2)+jump(1)
1127  field_out(ind3d) = 0._f64
1128 !!$ coef(1) * ( field_in( ind3d+jump(2) ) -&
1129 !!$ field_in( ind3d_1 ) )+ &
1130 !!$ real(s_deg_0(1),f64)*coef(2) * &
1131 !!$ field_in(ind3d_2 )
1132  ind = ind - 1
1133  end do
1134  end do
1135 
1136  ! Third component
1137  coef(1) = -1.0_f64/ delta_x(1)
1138  coef(2) = 1.0_f64/ delta_x(2)
1139 
1140  stride(1) = 1
1141  stride(2) = n_dofs(1)
1142 
1143  jump(1) = -(n_total1+n_total0)
1144  jump(2) = -n_total1
1145 
1146  ind = ind3d
1147  do k = 1, n_dofs(3)
1148  do j = 1, n_dofs(2)
1149  if (j == n_dofs(2)) then
1150  indp(2) = -stride(2)*(n_dofs(2)-1)
1151  else
1152  indp(2) = stride(2)
1153  end if
1154  ind3d = ind3d + 1
1155  ind = ind + 1
1156  ind3d_2 = ind3d +indp(2)+jump(1)
1157 
1158  field_out(ind3d) = 0._f64
1159 !!$ real(s_deg_0(1),f64) * coef(1) * &
1160 !!$ ( -field_in( ind+jump(2) ) )+ &
1161 !!$ coef(2) * ( field_in(ind3d+jump(1) ) - &
1162 !!$ field_in( ind3d_2 ))
1163  do i = 2, s_deg_0(1)
1164  ind3d = ind3d + 1
1165  ind = ind + 1
1166  ind3d_1 = ind -stride(1)+jump(2)
1167  ind3d_2 = ind3d +indp(2)+jump(1)
1168 
1169  field_out(ind3d) = &
1170  real(s_deg_0(1),f64) * coef(1) * &
1171  ( field_in( ind3d_1 )/real(i-1,f64) -&
1172  field_in( ind+jump(2) )/real(i,f64) )+ &
1173  coef(2) * ( field_in(ind3d+jump(1) ) - &
1174  field_in( ind3d_2 ))
1175  end do
1176  do i = s_deg_0(1)+1, n_dofs(1)-s_deg_0(1)
1177  ind3d = ind3d + 1
1178  ind = ind + 1
1179  ind3d_1 = ind -stride(1)+jump(2)
1180  ind3d_2 = ind3d +indp(2)+jump(1)
1181 
1182  field_out(ind3d) = &
1183  coef(1) * ( field_in( ind3d_1 ) -&
1184  field_in( ind+jump(2)) )+ &
1185  coef(2) * ( field_in(ind3d+jump(1) ) - &
1186  field_in( ind3d_2 ))
1187 
1188  end do
1189  do i = n_dofs(1)-s_deg_0(1)+1, n_dofs(1)-1
1190  ind3d = ind3d + 1
1191  ind = ind + 1
1192  ind3d_1 = ind -stride(1)+jump(2)
1193  ind3d_2 = ind3d +indp(2)+jump(1)
1194 
1195  field_out(ind3d) = &
1196  real(s_deg_0(1),f64) * coef(1) * &
1197  ( field_in( ind3d_1 )/real(n_dofs(1)+1-i,f64) -&
1198  field_in( ind+jump(2) )/real(n_dofs(1)-i,f64) )+ &
1199  coef(2) * ( field_in(ind3d+jump(1) ) - &
1200  field_in( ind3d_2 ))
1201  end do
1202  ind3d = ind3d + 1
1203  ind = ind + 1
1204  ind3d_1 = ind -stride(1)+jump(2)
1205  ind3d_2 = ind3d +indp(2)+jump(1)
1206 
1207  field_out(ind3d) = 0._f64
1208 !!$ real(s_deg_0(1),f64) * coef(1) * &
1209 !!$ field_in( ind3d_1 ) + &
1210 !!$ coef(2) * ( field_in(ind3d+jump(1) ) - &
1211 !!$ field_in( ind3d_2 ))
1212  ind = ind - 1
1213  end do
1214  end do
1215 
1216  end subroutine sll_s_multiply_ct_clamped
1217 
1218 
1220  subroutine sll_s_multiply_g_clamped_1d( n_dofs, delta_x, s_deg_0, in, out )
1221  sll_int32, intent( in ) :: n_dofs
1222  sll_real64, intent( in ) :: delta_x
1223  sll_int32, intent( in ) :: s_deg_0
1224  sll_real64, intent( in ) :: in(:)
1225  sll_real64, intent( out ) :: out(:)
1226  !local variable
1227  sll_int32 :: i
1228 
1229  out(1) = real(s_deg_0,f64)*( in(2) )/delta_x
1230  do i = 2, s_deg_0-1 !1, s_deg_0 -1 perfect condutctor BC
1231  out(i) = real(s_deg_0,f64)*( in(i+1) - in(i) )/(real(i,f64)*delta_x)
1232  end do
1233  do i = s_deg_0, n_dofs-s_deg_0
1234  out(i) = ( in(i+1) - in(i) )/delta_x
1235  end do
1236  do i = n_dofs-s_deg_0+1, n_dofs-2 !n_dofs-1 perfect conductor BC
1237  out(i) = real(s_deg_0,f64)*( in(i+1) - in(i) )/(real(n_dofs-i,f64)*delta_x)
1238  end do
1239  out( n_dofs-1) = real(s_deg_0,f64)*( - in( n_dofs-1) )/delta_x
1240 
1241  end subroutine sll_s_multiply_g_clamped_1d
1242 
1244  subroutine sll_s_multiply_gt_clamped_1d( n_dofs, delta_x, s_deg_0, in, out )
1245  sll_int32, intent( in ) :: n_dofs
1246  sll_real64, intent( in ) :: delta_x
1247  sll_int32, intent( in ) :: s_deg_0
1248  sll_real64, intent( in ) :: in(:)
1249  sll_real64, intent( out ) :: out(:)
1250  !local variable
1251  sll_int32 :: i
1252 
1253  out(1) = 0._f64!- real(s_deg_0,f64)*in(1)/delta_x perfect condutctor BC
1254  do i = 2, s_deg_0
1255  out(i) = real(s_deg_0,f64)*( in(i-1)/real(i-1,f64) - in(i)/real(i,f64) )/delta_x
1256  end do
1257  do i = s_deg_0+1, n_dofs-s_deg_0
1258  out(i) = ( in(i-1) - in(i) )/delta_x
1259  end do
1260  do i = n_dofs-s_deg_0+1, n_dofs-1
1261  out(i) = real(s_deg_0,f64)*( in(i-1)/real(n_dofs+1-i,f64) - in(i)/real(n_dofs-i,f64) )/delta_x
1262  end do
1263  out(n_dofs) = 0._f64!real(s_deg_0,f64)*in(n_dofs-1)/delta_x perfect condutctor BC
1264 
1265  end subroutine sll_s_multiply_gt_clamped_1d
1266 
1267 
1269 
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)
Utilites for Maxwell solver's with spline finite elements using sparse matrices.
subroutine, public sll_s_multiply_ct_clamped(n_dofs, delta_x, s_deg_0, field_in, field_out)
Multiply by transpose of discrete curl matrix.
subroutine, public sll_s_spline_fem_mixedmass3d_clamped(n_cells, deg1, deg2, component, matrix, profile, spline1, spline2, n_cells_min, n_cells_max)
Set up 3d clamped mixed mass matrix for specific spline degree and profile function.
subroutine, public sll_s_spline_fem_mass3d_clamped(n_cells, deg, component, matrix, profile, spline, n_cells_min, n_cells_max)
Set up 3d clamped mass matrix for specific spline degrees and profile function.
subroutine sll_s_spline_fem_mass_line_boundary(q, deg, profile, row, n_cells, component, mass_line, xw_gauss_d1, xw_gauss_d2, xw_gauss_d3, bspl_d1, bspl_d2, bspl_d3, spline)
subroutine, public sll_s_multiply_g_clamped(n_dofs, delta_x, s_deg_0, field_in, field_out)
Multiply by dicrete gradient matrix.
subroutine, public sll_s_multiply_gt_clamped_1d(n_dofs, delta_x, s_deg_0, in, out)
Multiplication of the input vector in by the transposed clamped derivative matrix G^T.
subroutine, public sll_s_multiply_c_clamped(n_dofs, delta_x, s_deg_0, field_in, field_out)
Multiply by discrete curl matrix.
subroutine, public sll_s_multiply_gt_clamped(n_dofs, delta_x, s_deg_0, field_in, field_out)
Multiply by transpose of dicrete gradient matrix.
subroutine sll_s_spline_fem_mixedmass_line_boundary(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, spline1, spline2)
Computes the mixed mass line for a mass matrix with degree splines.
subroutine, public sll_s_multiply_g_clamped_1d(n_dofs, delta_x, s_deg_0, in, out)
Multiplication of the input vector in by the clamped derivative matrix G.
Helper for spline finite elements utilites.
subroutine, public assemble_mixedmass3d_clamped(deg1, deg2, n_cells, mass_line, matrix, row, ind)
Assemble the given row of the clamped mixed mass matrix.
subroutine, public sll_s_spline_fem_sparsity_mixedmass3d_clamped(deg1, deg2, n_cells, spmat)
Helper function to create sparsity pattern of the 3d clamped mixed mass matrix.
subroutine, public assemble_mass3d_clamped_boundary(deg, n_cells, mass_line, matrix, row, ind)
Assemble the boundary part of the clamped mass matrix.
subroutine, public assemble_mass3d_clamped(deg, n_cells, mass_line, matrix, row, ind)
Assemble the given row of the clamped mass matrix.
subroutine, public assemble_mixedmass3d_clamped_boundary(deg1, deg2, n_cells, mass_line, matrix, row, ind)
Assemble the boundary part of the clamped mixed mass matrix.
subroutine, public sll_s_spline_fem_sparsity_mass3d_clamped(deg, n_cells, spmat)
Helper function to create sparsity pattern of the 3d clamped mass matrix.
Utilites for 3D Maxwell solvers with spline finite elements.
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.
Splines in pp form.
real(kind=f64) function, public sll_f_spline_pp_horner_1d(degree, pp_coeffs, x, index)
Perform a 1d hornerschema on the pp_coeffs at index.
type collecting functions for analytical coordinate mapping
    Report Typos and Errors