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_sparse.F90
Go to the documentation of this file.
1 
9 
11  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 #include "sll_assert.h"
13 #include "sll_errors.h"
14 #include "sll_memory.h"
15 #include "sll_working_precision.h"
16 
17  use sll_m_matrix_csr, only: &
19 
20  use sll_m_mapping_3d, only: &
22 
23  use sll_m_splines_pp, only: &
25 
26  use sll_m_spline_fem_utilities, only: &
32 
33  implicit none
34 
35  public :: &
44 
45  private
46  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
47 
48 contains
49 
50  !---------------------------------------------------------------------------!
52  subroutine sll_s_spline_fem_sparsity_mass( degree, n_cells, spmat )
53  sll_int32, intent( in ) :: degree
54  sll_int32, intent( in ) :: n_cells
55  type(sll_t_matrix_csr), intent( out ) :: spmat
56 
57  !local variables
58  sll_int32 :: n_nnz
59  sll_int32 :: n_nnz_per_row
60  sll_int32 :: row, column, ind
61 
62  ! Compute number of non-zero elements
63  n_nnz_per_row = (2*degree+1)
64  n_nnz = n_nnz_per_row*n_cells
65 
66  if (n_cells<2*degree) then
67  sll_error("sll_s_spline_fem_sparsity_mass", "The number of grid cells is smaller than twice the degree. This function is not written for this case")
68  end if
69 
70  ! Create the csr matrix
71  call spmat%create( n_rows=n_cells, n_cols=n_cells, n_nnz=n_nnz )
72 
73  ! Set the row and column vector for the elements (row vector compressed)
74  ! There are n_nnz_per_row elements in each of the rows
75  spmat%arr_ia(1) = 1
76  do row = 2, n_cells+1
77  spmat%arr_ia(row) = spmat%arr_ia(row-1) + n_nnz_per_row
78  end do
79  ! For row i the columns are i-deg, i-deg+1, ..., i, i+1, ... i+deg with periodic boundaries
80 
81  ind = 1
82 !!$ do row = 1, n_cells
83 !!$ do column = row-degree, row+degree
84 !!$ spmat%arr_ja(ind) = modulo(column-1, n_cells)+1
85 !!$ ind = ind+1
86 !!$ end do
87 !!$ end do
88 
89  do row = 1, degree
90  do column = 1, row+degree
91  spmat%arr_ja(ind) = column
92  ind = ind+1
93  end do
94  do column = n_cells+row-degree, n_cells
95  spmat%arr_ja(ind) = column
96  ind = ind+1
97  end do
98  end do
99 
100  do row = degree+1, n_cells-degree
101  do column = row-degree, row+degree
102  spmat%arr_ja(ind) = column
103  ind = ind+1
104  end do
105  end do
106 
107  do row = n_cells-degree+1, n_cells
108  do column = 1, row+degree-n_cells
109  spmat%arr_ja(ind) = column
110  ind = ind+1
111  end do
112  do column = row-degree, n_cells
113  spmat%arr_ja(ind) = column
114  ind = ind+1
115  end do
116  end do
117 
118  spmat%arr_a = 0.0_f64
119 
120  sll_assert( ind == spmat%n_nnz+1 )
121 
122 
123  end subroutine sll_s_spline_fem_sparsity_mass
124 
125 
127  subroutine assemble_mass ( n_cells, degree, mass_line, matrix )
128  sll_int32, intent( in ) :: n_cells
129  sll_int32, intent( in ) :: degree
130  sll_real64, intent( in ) :: mass_line(degree+1)
131  type(sll_t_matrix_csr), intent( inout ) :: matrix
132 
133  !local variables
134  sll_int32 :: row, column, ind
135 
136  ind = 1
137  ! For the first degree rows we need to put the first part to the back due to periodic boundaries
138  do row = 1, degree
139 
140  do column = -row+1, -1
141  matrix%arr_a(1,ind) = mass_line(1-column)
142  ind = ind+1
143  end do
144  matrix%arr_a(1,ind:ind+degree) = mass_line
145  ind = ind+degree+1
146 
147  do column = -degree, -row
148  matrix%arr_a(1,ind) = mass_line(1-column)
149  ind = ind+1
150  end do
151 
152  end do
153 
154  do row = degree+1, n_cells-degree
155 
156  do column = -degree, -1
157  matrix%arr_a(1,ind) = mass_line(1-column)
158  ind = ind+1
159  end do
160  matrix%arr_a(1,ind:ind+degree) = mass_line
161  ind = ind+degree+1
162  end do
163 
164  ! For the last degree rows, we need to put the second part to the front due to periodic boundaries
165  do row = n_cells-degree+1, n_cells
166 
167  do column = n_cells-row+1, degree
168  matrix%arr_a(1,ind) = mass_line(column+1)
169  ind = ind+1
170  end do
171 
172  do column = -degree, -1
173  matrix%arr_a(1,ind) = mass_line(1-column)
174  ind = ind+1
175  end do
176 
177  do column = 0, n_cells-row
178  matrix%arr_a(1,ind) = mass_line(column+1)
179  ind = ind+1
180  end do
181  end do
182 
183  sll_assert( ind == matrix%n_nnz+1)
184 
185 
186  end subroutine assemble_mass
187 
188 
190  subroutine sll_s_spline_fem_mass1d( n_cells, s_deg, mass_line, matrix )
191  sll_int32, intent( in ) :: n_cells
192  sll_int32, intent( in ) :: s_deg
193  sll_real64, intent( in ) :: mass_line(:)
194  type(sll_t_matrix_csr) :: matrix
195 
196  call sll_s_spline_fem_sparsity_mass( s_deg, n_cells, matrix )
197  call assemble_mass( n_cells, s_deg, mass_line, matrix )
198  ! write(24,*) matrix%arr_a(1,:)
199  end subroutine sll_s_spline_fem_mass1d
200 
201 
203  subroutine assemble_mass_full ( n_cells, degree, mass_line, matrix, row, ind )
204  sll_int32, intent( in ) :: n_cells
205  sll_int32, intent( in ) :: degree
206  sll_real64, intent( in ) :: mass_line(2*degree+1)
207  type(sll_t_matrix_csr), intent( inout ) :: matrix
208  sll_int32, intent ( in ) :: row
209  sll_int32, intent(inout) :: ind
210  !local variables
211  sll_int32 :: column
212  ! For the first degree rows we need to put the first part to the back due to periodic boundaries
213  if(row<=degree) then
214  do column = 2-row+degree, degree
215  matrix%arr_a(1,ind) = mass_line(column)
216  ind = ind+1
217  end do
218  matrix%arr_a(1,ind:ind+degree) = mass_line(degree+1:2*degree+1)
219  ind = ind+degree+1
220 
221  do column = 1, degree-row+1
222  matrix%arr_a(1,ind) = mass_line(column)
223  ind = ind+1
224  end do
225  else if(row >= degree+1 .and. row<= n_cells-degree) then
226  matrix%arr_a(1,ind:ind+2*degree)=mass_line
227 
228  ind = ind+2*degree+1
229  ! For the last degree rows, we need to put the second part to the front due to periodic boundaries
230  else if(row >= n_cells-degree+1 .and. row <= n_cells) then
231 
232  do column = n_cells-row+degree+2, 2*degree+1
233  matrix%arr_a(1,ind) = mass_line(column)
234  ind = ind+1
235  end do
236 
237  matrix%arr_a(1,ind:ind+degree) = mass_line(1:degree+1)
238  ind = ind+degree+1
239 
240 
241  do column = 2+degree, n_cells-row+degree+1
242  matrix%arr_a(1,ind) = mass_line(column)
243  ind = ind+1
244  end do
245  else
246  print*, 'error in row in assemble_mass'
247  end if
248 
249  sll_assert( ind == row*(2*degree+1)+1)
250 
251 
252  end subroutine assemble_mass_full
253 
254 
256  Subroutine sll_s_spline_fem_mass1d_full( n_cells, s_deg, matrix, profile)
257  sll_int32, intent( in ) :: n_cells
258  sll_int32, intent( in ) :: s_deg
259  type(sll_t_matrix_csr), intent(out) :: matrix
260  procedure(sll_i_profile_function_1d) :: profile
261  !local variables
262  sll_int32 :: row, ind
263  sll_real64 :: mass_line(2*s_deg+1)
264  call sll_s_spline_fem_sparsity_mass( s_deg, n_cells, matrix )
265  ind=1
266  do row = 1, n_cells
267  call sll_s_spline_fem_mass_line_full( s_deg, profile, mass_line, row, n_cells )
268  !scale with delta_x=1/n_cells
269  mass_line=mass_line/real(n_cells,f64)
270  call assemble_mass_full( n_cells, s_deg, mass_line, matrix, row, ind )
271  end do
272  end subroutine sll_s_spline_fem_mass1d_full
273 
274  !---------------------------------------------------------------------------!
277  subroutine sll_s_maxwell_spline_fem_sparsity_mixedmass( deg1, deg2, n_cells, spmat )
278  sll_int32, intent( in ) :: deg1, deg2
279  sll_int32, intent( in ) :: n_cells
280  type(sll_t_matrix_csr), intent( out ) :: spmat
281 
282  !local variables
283  sll_int32 :: n_nnz
284  sll_int32 :: n_nnz_per_row
285  sll_int32 :: row, column, ind
286 
287  ! Compute number of non-zero elements
288  n_nnz_per_row = deg1+deg2+1
289  n_nnz = n_nnz_per_row*n_cells
290 
291  ! Create the csr matrix
292  call spmat%create( n_rows=n_cells, n_cols=n_cells, n_nnz=n_nnz )
293 
294  ! Set the row and column vector for the elements (row vector compressed)
295  ! There are n_nnz_per_row elements in each of the rows
296  spmat%arr_ia(1) = 1
297  do row = 2, n_cells+1
298  spmat%arr_ia(row) = spmat%arr_ia(row-1) + n_nnz_per_row
299  end do
300  ! For row i the columns are i-deg, i-deg+1, ..., i, i+1, ... i+deg with periodic boundaries
301 
302  ind = 1
303 
304  do row = 1, deg2
305  do column = 1, row+deg1
306  spmat%arr_ja(ind) = column
307  ind = ind+1
308  end do
309  do column = n_cells+row-deg2, n_cells
310  spmat%arr_ja(ind) = column
311  ind = ind+1
312  end do
313  end do
314 
315  do row = deg2+1, n_cells-deg1
316  do column = row-deg2, row+deg1
317  spmat%arr_ja(ind) = column
318  ind = ind+1
319  end do
320  end do
321 
322  do row = n_cells-deg1+1, n_cells
323  do column = 1, row+deg1-n_cells
324  spmat%arr_ja(ind) = column
325  ind = ind+1
326  end do
327  do column = row-deg2, n_cells
328  spmat%arr_ja(ind) = column
329  ind = ind+1
330  end do
331  end do
332 
333  spmat%arr_a = 0.0_f64
334 
335  sll_assert( ind == spmat%n_nnz+1 )
336 
337 
339 
340 
342  subroutine assemble_mixedmass ( n_cells, degree, mass, matrix )
343  sll_int32, intent( in ) :: n_cells
344  sll_int32, intent( in ) :: degree
345  sll_real64, intent( in ) :: mass(degree*2)
346  type(sll_t_matrix_csr), intent( inout ) :: matrix
347 
348  !local variables
349  sll_int32 :: row, ind
350 
351  ind = 1
352  ! For the first degree rows we need to put the first part to the back due to periodic boundaries
353  do row = 1, degree-1
354 
355  matrix%arr_a(1,ind:ind+degree+row-1) = mass(degree-row+1:2*degree)
356  ind = ind + degree+row
357  matrix%arr_a(1,ind:ind+degree-row-1 ) = mass(1:degree-row)
358  ind = ind + degree-row
359  end do
360 
361  do row = degree, n_cells-degree
362  matrix%arr_a(1,ind:ind+degree*2-1) = mass
363  ind = ind + degree*2
364  end do
365 
366  ! For the last degree rows, we need to put the second part to the front due to periodic boundaries
367  do row = n_cells-degree+1, n_cells
368  matrix%arr_a(1,ind:ind+degree+row-n_cells-1 ) = mass(degree+n_cells-row+1:2*degree)
369  ind = ind + degree-n_cells+row
370 
371  matrix%arr_a(1,ind:ind+degree+n_cells-row-1 ) = mass(1:degree+n_cells-row)
372  ind = ind + degree+n_cells-row
373  end do
374 
375  sll_assert( ind == matrix%n_nnz+1)
376 
377 
378  end subroutine assemble_mixedmass
379 
380 
382  subroutine assemble_mixedmass_full ( n_cells, deg1, deg2, mass_line, matrix, row, ind )
383  sll_int32, intent( in ) :: n_cells
384  sll_int32, intent( in ) :: deg1, deg2
385  sll_real64, intent( in ) :: mass_line(deg1+deg2+1)
386  type(sll_t_matrix_csr), intent( inout ) :: matrix
387  sll_int32, intent ( in ) :: row
388  sll_int32, intent(inout) :: ind
389  !local variables
390  sll_int32 :: column
391 
392  ! For the first degree rows we need to put the first part to the back due to periodic boundaries
393 
394  if(row<=deg2) then
395  do column = 2-row+deg2, deg2
396  matrix%arr_a(1,ind) = mass_line(column)
397  ind = ind+1
398  end do
399  matrix%arr_a(1,ind:ind+deg1) = mass_line(deg2+1:deg1+deg2+1)
400  ind = ind+deg1+1
401 
402  do column = 1, deg2-row+1
403  matrix%arr_a(1,ind) = mass_line(column)
404  ind = ind+1
405  end do
406 
407  else if( row > deg2 .and. row <= n_cells-deg1) then
408  matrix%arr_a(1,ind:ind+deg1+deg2) = mass_line
409  ind = ind + deg1+deg2+1
410 
411  ! For the last degree rows, we need to put the second part to the front due to periodic boundaries
412  else if ( row > n_cells-deg1 .and. row <=n_cells) then
413  do column = n_cells-row+deg2+2, deg1+deg2+1
414  matrix%arr_a(1,ind) = mass_line(column)
415  ind = ind+1
416  end do
417 
418  matrix%arr_a(1,ind:ind+deg2) = mass_line(1:deg2+1)
419  ind = ind+deg2+1
420 
421  do column = 2+deg2, n_cells-row+deg2+1
422  matrix%arr_a(1,ind) = mass_line(column)
423  ind = ind+1
424  end do
425  else
426  print*, 'error in row in assemble_mixedmass'
427  end if
428 
429  sll_assert( ind == row*(deg1+deg2+1)+1)
430 
431 
432  end subroutine assemble_mixedmass_full
433 
434 
435  subroutine sll_s_spline_fem_mixedmass1d( n_cells, s_deg, mass_line, matrix )
436  sll_int32, intent( in ) :: n_cells
437  sll_int32, intent( in ) :: s_deg
438  sll_real64, intent( in ) :: mass_line(:)
439  type(sll_t_matrix_csr) :: matrix
440 
441 
442  call sll_s_maxwell_spline_fem_sparsity_mixedmass( s_deg, s_deg-1, n_cells, matrix )
443  call assemble_mixedmass( n_cells, s_deg, mass_line, matrix )
444 
445  end subroutine sll_s_spline_fem_mixedmass1d
446 
447 
448  subroutine sll_s_spline_fem_mixedmass1d_full( n_cells, deg1, deg2, matrix, profile )
449  sll_int32, intent( in ) :: n_cells
450  sll_int32, intent( in ) :: deg1, deg2
451  type(sll_t_matrix_csr), intent(out):: matrix
452  procedure(sll_i_profile_function_1d) :: profile
453  !local variables
454  sll_int32 :: row, ind, s_deg
455  sll_real64 :: mass_line(deg1+deg2+1)
456  sll_real64 :: delta_x
457  delta_x=1._f64/real(n_cells,f64)
458  s_deg = max(deg1,deg2)
459 
460  call sll_s_maxwell_spline_fem_sparsity_mixedmass( deg1, deg2, n_cells, matrix )
461  ind = 1
462  do row = 1, n_cells
463  call sll_s_spline_fem_mixedmass_line_full( deg1, deg2, profile, mass_line, row, n_cells)
464  mass_line=mass_line*delta_x
465  call assemble_mixedmass_full( n_cells, deg1, deg2, mass_line, matrix, row, ind )
466  end do
467  end subroutine sll_s_spline_fem_mixedmass1d_full
468 
469 
471  subroutine sll_s_spline_fem_sparsity_mass_clamped( degree, n_cells, spmat )
472  sll_int32, intent( in ) :: degree
473  sll_int32, intent( in ) :: n_cells
474  type(sll_t_matrix_csr), intent( out ) :: spmat
475  !local variables
476  sll_int32 :: n_nnz
477  sll_int32 :: n_nnz_per_row
478  sll_int32 :: row, column, ind
479 
480  ! Compute number of non-zero elements
481  n_nnz_per_row = (2*degree+1)
482  n_nnz = n_nnz_per_row*(n_cells-degree)+(3*degree**2+degree)
483 
484  ! Create the csr matrix
485  call spmat%create( n_rows=n_cells+degree, n_cols=n_cells+degree, n_nnz=n_nnz )
486 
487  ! Set the row and column vector for the elements (row vector compressed)
488  ! There are n_nnz_per_row elements in each of the rows of the mainblock
489  spmat%arr_ia(1) = 1
490  do row=2, degree+1
491  spmat%arr_ia(row) = spmat%arr_ia(row-1) + degree + row - 1
492  end do
493  do row = degree+2, n_cells+1
494  spmat%arr_ia(row) = spmat%arr_ia(row-1) + n_nnz_per_row
495  end do
496  do row=n_cells+2, n_cells+degree+1
497  spmat%arr_ia(row) = spmat%arr_ia(row-1) + 2*degree + n_cells+2-row
498  end do
499  sll_assert( spmat%arr_ia(n_cells+degree+1) == n_nnz+1 )
500 
501 
502  ! For row i the columns are i-deg, i-deg+1, ..., i, i+1, ... i+deg with clamped boundaries
503  ind = 1
504  do row = 1, degree
505  do column = 1, row+degree
506  spmat%arr_ja(ind) = column
507  ind = ind+1
508  end do
509  end do
510 
511  do row = degree+1, n_cells
512  do column = row-degree, row+degree
513  spmat%arr_ja(ind) = column
514  ind = ind+1
515  end do
516  end do
517 
518  do row = n_cells+1, n_cells+degree
519  do column = row-degree, n_cells+degree
520  spmat%arr_ja(ind) = column
521  ind = ind+1
522  end do
523  end do
524 
525  spmat%arr_a = 0.0_f64
526  sll_assert( maxval(spmat%arr_ja) == spmat%n_cols )
527  sll_assert( ind == spmat%n_nnz+1 )
528 
529 
531 
532 
534  subroutine assemble_mass_clamped ( n_cells, degree, mass_line, mass_line_b, matrix )
535  sll_int32, intent( in ) :: n_cells
536  sll_int32, intent( in ) :: degree
537  sll_real64, intent( in ) :: mass_line(degree+1)
538  sll_real64, intent( in ) :: mass_line_b((degree+1)*degree)
539  type(sll_t_matrix_csr), intent( inout ) :: matrix
540 
541  !local variables
542  sll_int32 :: row, column, ind, q
543 
544  q=degree+1
545 
546  ind = 1
547  ! For the first degree rows we need to use the boundary mass_line
548  do row = 1, degree
549  do column = q-row, degree-1
550  matrix%arr_a(1,ind) = mass_line_b(row+(row+column-q)*degree)
551  ind=ind+1
552  end do
553  matrix%arr_a(1,ind:ind+degree) = mass_line_b((row-1)*q+1:row*q)
554  ind = ind+q
555  end do
556 
557  !first part from boundary mass, rest from normal mass
558  do row = degree+1, 2*degree-1
559  do column = 1, degree+q-row
560  matrix%arr_a(1,ind) = mass_line_b(row+(column-1+row-q)*degree)
561  ind=ind+1
562  end do
563  do column = 2*q-row, degree
564  matrix%arr_a(1,ind) = mass_line(degree+2-column)
565  ind=ind+1
566  end do
567  matrix%arr_a(1,ind:ind+degree) = mass_line
568  ind = ind+q
569  end do
570 
571  do row = 2*degree, n_cells-degree+1
572  do column = -degree, -1
573  matrix%arr_a(1,ind) = mass_line(1-column)
574  ind = ind+1
575  end do
576  matrix%arr_a(1,ind:ind+degree) = mass_line
577  ind = ind+q
578  end do
579 
580  !first part from normal mass, rest from boundary mass
581  do row = 1, degree-1
582  do column = 1, q
583  matrix%arr_a(1,ind) = mass_line(q+1-column)
584  ind = ind+1
585  end do
586  do column = row, degree-2
587  matrix%arr_a(1,ind) = mass_line(2+(column-row))
588  ind=ind+1
589  end do
590  do column = 0, row
591  matrix%arr_a(1,ind) = mass_line_b(q*degree-row-degree*column)
592  ind=ind+1
593  end do
594  end do
595 
596 
597  ! For the last degree rows, we need to use the boundary mass_line
598  do row = 1, degree
599  do column = 1, degree
600  matrix%arr_a(1,ind) = mass_line_b((q-row)*q+1-column)
601  ind=ind+1
602  end do
603  do column = 1, q-row
604  matrix%arr_a(1,ind) = mass_line_b((degree-row)*q+1-(column-1)*degree) !:ind+degree-row
605  ind = ind+1
606  end do
607  end do
608 
609  sll_assert( ind == matrix%n_nnz+1)
610 
611  end subroutine assemble_mass_clamped
612 
614  subroutine sll_s_spline_fem_mass1d_clamped( n_cells, s_deg, mass_line, mass_line_b, matrix )
615  sll_int32, intent( in ) :: n_cells
616  sll_int32, intent( in ) :: s_deg
617  sll_real64, intent( in ) :: mass_line(:)
618  sll_real64, intent( in ) :: mass_line_b(:)
619  type(sll_t_matrix_csr) :: matrix
620 
621  sll_assert( n_cells >= 2*s_deg)
622 
623  call sll_s_spline_fem_sparsity_mass_clamped( s_deg, n_cells, matrix )
624  call assemble_mass_clamped( n_cells, s_deg, mass_line, mass_line_b, matrix )
625 
626  end subroutine sll_s_spline_fem_mass1d_clamped
627 
629  subroutine assemble_mass_clamped_full ( n_cells, deg, mass, mass_b, matrix, row, ind )
630  sll_int32, intent( in ) :: n_cells
631  sll_int32, intent( in ) :: deg
632  sll_real64, intent( in ) :: mass(2*deg+1)
633  sll_real64, intent( in ) :: mass_b((7*deg**2-deg-2)/2)
634  type(sll_t_matrix_csr), intent( inout ) :: matrix
635  sll_int32, intent ( in ) :: row
636  sll_int32, intent(inout) :: ind
637 
638  !local variables
639  sll_int32 :: column, shift1
640 
641  !use boundary mass for first deg rows
642  if(row <= deg) then
643  shift1 = ((row-1)*(2*deg+row))/2
644  do column = 1, deg+row
645  matrix%arr_a(1,ind) = mass_b(column+shift1)
646  ind = ind+1
647  end do
648  else if(row > deg .and. row < 2*deg) then
649  shift1 = (row-deg-1)*(2*deg+1)+(3*deg**2+deg)/2
650  do column = 1, 2*deg+1
651  matrix%arr_a(1,ind) = mass_b(column+shift1)
652  ind = ind+1
653  end do
654  else if( row >= 2*deg .and. row<= n_cells-deg+1) then
655  matrix%arr_a(1,ind:ind+2*deg) = mass
656  ind = ind+2*deg+1
657  !use boundary mass for last deg rows
658  else if(row >= n_cells-deg+2 .and. row <= n_cells) then
659  shift1 = (n_cells-row)*(2*deg+1)+(3*deg**2+deg)/2
660  do column = 2*deg+1,1,-1
661  matrix%arr_a(1,ind)=mass_b(column+shift1)
662  ind = ind+1
663  end do
664  else if(row > n_cells .and. row <= n_cells+deg) then
665  shift1 = ((n_cells+deg-row)*(2*deg+n_cells+deg+1-row))/2
666  do column = deg+1+n_cells+deg-row,1,-1
667  matrix%arr_a(1,ind) = mass_b(column+shift1)
668  ind = ind+1
669  end do
670  else
671  print*, 'ERROR in assemble mass_full_clamped'
672  end if
673 
674  end subroutine assemble_mass_clamped_full
675 
676 
678  subroutine sll_s_spline_fem_mass1d_clamped_full( n_cells, deg, spline, matrix, profile)
679  sll_int32, intent( in ) :: n_cells
680  sll_int32, intent( in ) :: deg
681  type(sll_t_spline_pp_1d), intent(in) :: spline
682  type(sll_t_matrix_csr), intent(out) :: matrix
683  procedure(sll_i_profile_function_1d) :: profile
684  !local variables
685  sll_int32 :: row, ind, begin
686  sll_real64 :: mass_line(2*deg+1)
687  sll_real64 :: mass_line_b((7*deg**2-deg-2)/2)
688 
689  call sll_s_spline_fem_sparsity_mass_clamped( deg, n_cells, matrix )
690 
691  call sll_s_spline_fem_mass_line_boundary_full ( deg, profile, spline, 1, n_cells, mass_line_b )
692  mass_line_b = mass_line_b/real(n_cells,f64)
693 
694  ind=1
695  begin=ind
696  do row = 1, 2*deg-1
697  call assemble_mass_clamped_full( n_cells, deg, mass_line, mass_line_b, matrix, row, ind )
698  end do
699  sll_assert( ind == begin+(7*deg**2-deg-2)/2 )
700  do row = 2*deg, n_cells-deg+1
701  call sll_s_spline_fem_mass_line_full( deg, profile, mass_line, row-deg, n_cells )
702  !scale with delta_x=1/n_cells
703  mass_line = mass_line/real(n_cells,f64)
704  begin=ind
705  call assemble_mass_clamped_full( n_cells, deg, mass_line, mass_line_b, matrix, row, ind )
706  sll_assert( ind == begin+(2*deg+1) )
707  end do
708 
709  call sll_s_spline_fem_mass_line_boundary_full ( deg, profile, spline, n_cells+1, n_cells, mass_line_b )
710  mass_line_b = mass_line_b/real(n_cells,f64)
711  begin=ind
712  do row = n_cells-deg+2, n_cells+deg
713  call assemble_mass_clamped_full( n_cells, deg, mass_line, mass_line_b, matrix, row, ind )
714  end do
715  sll_assert( ind == begin+(7*deg**2-deg-2)/2 )
716  sll_assert( ind == matrix%n_nnz+1)
718 
719 
720  !---------------------------------------------------------------------------!
723  subroutine sll_s_maxwell_spline_fem_sparsity_mixedmass_clamped( deg1, deg2, n_cells, spmat )
724  sll_int32, intent( in ) :: deg1, deg2
725  sll_int32, intent( in ) :: n_cells
726  type(sll_t_matrix_csr), intent( out ) :: spmat
727  !local variables
728  sll_int32 :: n_nnz
729  sll_int32 :: n_nnz_per_row
730  sll_int32 :: row, column, ind
731 
732  ! Compute number of non-zero elements
733  n_nnz_per_row = deg1+deg2+1
734  n_nnz = n_nnz_per_row*(n_cells-deg1)+deg1*(2*deg2+deg1+1)
735 
736  ! Create the csr matrix
737  call spmat%create( n_rows=n_cells+deg1, n_cols=n_cells+deg2, n_nnz=n_nnz )
738 
739  ! Set the row and column vector for the elements (row vector compressed)
740  spmat%arr_ia(1) = 1
741  do row = 2, deg1+1
742  spmat%arr_ia(row) = spmat%arr_ia(row-1) + deg2 + row - 1
743  end do
744  do row = deg1+2, n_cells+1
745  spmat%arr_ia(row) = spmat%arr_ia(row-1) + n_nnz_per_row
746  end do
747  do row = n_cells+2, n_cells+deg1+1
748  spmat%arr_ia(row) = spmat%arr_ia(row-1) + deg1+deg2 + n_cells+2-row
749  end do
750  sll_assert( spmat%arr_ia(n_cells+deg1+1) == n_nnz+1 )
751 
752  ind = 1
753  do row = 1, deg1
754  do column = 1, row+deg2
755  spmat%arr_ja(ind) = column
756  ind = ind+1
757  end do
758  end do
759  do row = deg1+1, n_cells
760  do column = row-deg1, row+deg2
761  spmat%arr_ja(ind) = column
762  ind = ind+1
763  end do
764  end do
765  do row = n_cells+1, n_cells +deg1
766  do column = row-deg1, n_cells+deg2
767  spmat%arr_ja(ind) = column
768  ind = ind+1
769  end do
770  end do
771 
772  spmat%arr_a = 0.0_f64
773 
774  sll_assert( ind == spmat%n_nnz+1 )
775 
776 
778 
779 
781  subroutine assemble_mixedmass_clamped_full( n_cells, deg1, deg2, mass_line, matrix, row, ind )
782  sll_int32, intent( in ) :: n_cells
783  sll_int32, intent( in ) :: deg1, deg2
784  sll_real64, intent( in ) :: mass_line(deg1+deg2+1)
785  type(sll_t_matrix_csr), intent( inout ) :: matrix
786  sll_int32, intent ( in ) :: row
787  sll_int32, intent(inout) :: ind
788 
789  if(row > deg1+deg2 .and. row <= n_cells-deg2) then
790  matrix%arr_a(1,ind:ind+deg1+deg2)=mass_line
791  ind = ind+deg1+deg2+1
792  else
793  sll_error('assemble','error in row in assemble1_mixedmass_clamped')
794  end if
795 
796  end subroutine assemble_mixedmass_clamped_full
797 
798 
800  subroutine assemble_mixedmass_clamped_boundary( n_cells, deg1, deg2, mass_line, matrix, row, ind )
801  sll_int32, intent( in ) :: n_cells
802  sll_int32, intent( in ) :: deg1, deg2
803  sll_real64, intent( in ) :: mass_line( (deg1+deg2)**2+(2*deg2+deg1-deg1**2)/2 )
804  type(sll_t_matrix_csr), intent( inout ) :: matrix
805  sll_int32, intent ( in ) :: row
806  sll_int32, intent(inout) :: ind
807  !local variables
808  sll_int32 :: column, shift1
809 
810  !use boundary mass for first deg1 rows
811  if(row<=deg1) then
812  shift1 = ((row-1)*(2*deg2+row))/2
813  do column = 1, deg2+row
814  matrix%arr_a(1,ind) = mass_line(column+shift1)
815  ind = ind+1
816  end do
817  else if(row > deg1 .and. row <= deg1+deg2) then
818  shift1 = (row-deg1-1)*(deg1+deg2+1)+(deg1*(2*deg2+deg1+1))/2
819  do column = 1, deg1+deg2+1
820  matrix%arr_a(1,ind) = mass_line(column+shift1)
821  ind = ind+1
822  end do
823 
824  !use boundary mass for last deg1 rows
825  else if(row >= n_cells-deg2+1 .and. row <= n_cells) then
826  shift1 = (n_cells-row)*(deg1+deg2+1)+(deg1*(2*deg2+deg1+1))/2
827  do column = deg1+deg2+1,1,-1
828  matrix%arr_a(1,ind)=mass_line(column+shift1)
829  ind = ind+1
830  end do
831  else if(row > n_cells .and. row <= n_cells+deg1) then
832  shift1 = ((n_cells+deg1-row)*(2*deg2+n_cells+deg1+1-row))/2
833  do column = deg2+1+n_cells+deg1-row,1,-1
834  matrix%arr_a(1,ind) = mass_line(column+shift1)
835  ind = ind+1
836  end do
837  else
838  sll_error('assemble','error in row in assemble_mass')
839  end if
840 
842 
843 
845  subroutine sll_s_spline_fem_mixedmass1d_clamped_full( n_cells, deg1, deg2, matrix, profile, spline1, spline2 )
846  sll_int32, intent( in ) :: n_cells
847  sll_int32, intent( in ) :: deg1, deg2
848  type(sll_t_matrix_csr), intent(out):: matrix
849  procedure(sll_i_profile_function_1d) :: profile
850  type(sll_t_spline_pp_1d), intent( in ) :: spline1
851  type(sll_t_spline_pp_1d), intent( in ) :: spline2
852  !local variables
853  sll_int32 :: row, ind
854  sll_real64 :: mass_line(deg1+deg2+1)
855  sll_real64 :: mass_line_b( (deg1+deg2)**2+(2*deg2+deg1-deg1**2)/2 )
856  sll_real64 :: delta_x
857 
858  delta_x = 1._f64/real(n_cells,f64)
859 
860  call sll_s_maxwell_spline_fem_sparsity_mixedmass_clamped( deg1, deg2, n_cells, matrix )
861 
862  call sll_s_spline_fem_mixedmass_line_boundary( deg1, deg2, profile, spline1, spline2, 1, n_cells, mass_line_b )
863  !scale with delta_x=1/n_cells
864  mass_line_b = mass_line_b*delta_x
865 
866  ind = 1
867  do row = 1, deg1+deg2
868  call assemble_mixedmass_clamped_boundary( n_cells, deg1, deg2, mass_line_b, matrix, row, ind )
869  end do
870  do row = deg1+deg2+1, n_cells-deg2
871  call sll_s_spline_fem_mixedmass_line_full( deg1, deg2, profile, mass_line, row-deg1, n_cells)
872  !scale with delta_x=1/n_cells
873  mass_line=mass_line*delta_x
874  call assemble_mixedmass_clamped_full( n_cells, deg1, deg2, mass_line, matrix, row, ind )
875  end do
876 
877  call sll_s_spline_fem_mixedmass_line_boundary ( deg1, deg2, profile, spline1, spline2, n_cells+1, n_cells, mass_line_b )
878  !scale with delta_x=1/n_cells
879  mass_line_b = mass_line_b*delta_x
880  do row = n_cells-deg2+1, n_cells+deg1
881  call assemble_mixedmass_clamped_boundary( n_cells, deg1, deg2, mass_line_b, matrix, row, ind )
882  end do
883  sll_assert( ind == matrix%n_nnz+1)
885 
886 
Module interfaces for coordinate transformation.
module for Compressed Sparse Row Matrix (CSR)
Utilites for Maxwell solver's with spline finite elements using sparse matrix linear solvers.
subroutine, public sll_s_spline_fem_sparsity_mass(degree, n_cells, spmat)
Helper function to create sparsity pattern of the mass matrix.
subroutine sll_s_maxwell_spline_fem_sparsity_mixedmass_clamped(deg1, deg2, n_cells, spmat)
Helper function to create sparsity pattern of the mass matrix with mixed degree deg1 and deg2.
subroutine assemble_mass_clamped(n_cells, degree, mass_line, mass_line_b, matrix)
Assemble the clamped mass matrix.
subroutine, public sll_s_spline_fem_mass1d(n_cells, s_deg, mass_line, matrix)
Set up 1d mass matrix (sparsity pattern and values)
subroutine assemble_mass_full(n_cells, degree, mass_line, matrix, row, ind)
Assemble the given row of a sparse matrix for a full mass line.
subroutine assemble_mixedmass_full(n_cells, deg1, deg2, mass_line, matrix, row, ind)
Assemble the given row of a mixed mass matrix for a full mass_line.
subroutine, public sll_s_spline_fem_mass1d_clamped_full(n_cells, deg, spline, matrix, profile)
Set up 1d mass matrix for specific spline degree and profile function.
subroutine assemble_mixedmass(n_cells, degree, mass, matrix)
Assemble the mixed mass matrix.
subroutine, public sll_s_spline_fem_mixedmass1d_clamped_full(n_cells, deg1, deg2, matrix, profile, spline1, spline2)
Set up 1d mixed mass matrix for specific spline degrees and profile function.
subroutine, public sll_s_spline_fem_mixedmass1d_full(n_cells, deg1, deg2, matrix, profile)
subroutine sll_s_spline_fem_sparsity_mass_clamped(degree, n_cells, spmat)
Helper function to create sparsity pattern of the clamped mass matrix.
subroutine, public sll_s_spline_fem_mixedmass1d(n_cells, s_deg, mass_line, matrix)
subroutine assemble_mass_clamped_full(n_cells, deg, mass, mass_b, matrix, row, ind)
Assemble the given row of a sparse matrix for a full mass line.
subroutine sll_s_maxwell_spline_fem_sparsity_mixedmass(deg1, deg2, n_cells, spmat)
Helper function to create sparsity pattern of the mass matrix with mixed degree deg1 and deg2.
subroutine assemble_mixedmass_clamped_boundary(n_cells, deg1, deg2, mass_line, matrix, row, ind)
Assemble the boundary part of a mixed mass matrix.
subroutine, public sll_s_spline_fem_mass1d_clamped(n_cells, s_deg, mass_line, mass_line_b, matrix)
Set up 1d mass matrix (sparsity pattern and values)
subroutine assemble_mixedmass_clamped_full(n_cells, deg1, deg2, mass_line, matrix, row, ind)
Assemble the given row of a mixed mass matrix for a full mass_line.
subroutine, public sll_s_spline_fem_mass1d_full(n_cells, s_deg, matrix, profile)
Set up 1d mass matrix for specific spline degree and profile function.
subroutine assemble_mass(n_cells, degree, mass_line, matrix)
Assemble sparse matrix for mass matrix.
Utilites for Maxwell solver's with spline finite elements.
subroutine, public sll_s_spline_fem_mass_line_boundary_full(deg, profile, spline, row, n_cells, mass_line)
Function computing the boundary part for a mass matrix with clamped splines of degree (full version w...
subroutine, public sll_s_spline_fem_mixedmass_line_full(deg1, deg2, profile, mass_line, cell, n_cells)
Helper function to find line of mass matrix ( N_i^p N_j^{p-1}))
subroutine, public sll_s_spline_fem_mixedmass_line_boundary(deg1, deg2, profile, spline1, spline2, row, n_cells, mass_line)
Function computing the boundary part for a mass matrix with clamped splines of degree (full version w...
subroutine, public sll_s_spline_fem_mass_line_full(deg, profile, mass_line, row, n_cells)
Helper function to find line of mass matrix (full version without symmetry part)
Splines in pp form.
type collecting functions for analytical coordinate mapping
    Report Typos and Errors