12 #include "sll_assert.h"
13 #include "sll_errors.h"
14 #include "sll_memory.h"
15 #include "sll_working_precision.h"
53 sll_int32,
intent( in ) :: degree
54 sll_int32,
intent( in ) :: n_cells
59 sll_int32 :: n_nnz_per_row
60 sll_int32 :: row, column, ind
63 n_nnz_per_row = (2*degree+1)
64 n_nnz = n_nnz_per_row*n_cells
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")
71 call spmat%create( n_rows=n_cells, n_cols=n_cells, n_nnz=n_nnz )
77 spmat%arr_ia(row) = spmat%arr_ia(row-1) + n_nnz_per_row
90 do column = 1, row+degree
91 spmat%arr_ja(ind) = column
94 do column = n_cells+row-degree, n_cells
95 spmat%arr_ja(ind) = column
100 do row = degree+1, n_cells-degree
101 do column = row-degree, row+degree
102 spmat%arr_ja(ind) = column
107 do row = n_cells-degree+1, n_cells
108 do column = 1, row+degree-n_cells
109 spmat%arr_ja(ind) = column
112 do column = row-degree, n_cells
113 spmat%arr_ja(ind) = column
118 spmat%arr_a = 0.0_f64
120 sll_assert( ind == spmat%n_nnz+1 )
128 sll_int32,
intent( in ) :: n_cells
129 sll_int32,
intent( in ) :: degree
130 sll_real64,
intent( in ) :: mass_line(degree+1)
134 sll_int32 :: row, column, ind
140 do column = -row+1, -1
141 matrix%arr_a(1,ind) = mass_line(1-column)
144 matrix%arr_a(1,ind:ind+degree) = mass_line
147 do column = -degree, -row
148 matrix%arr_a(1,ind) = mass_line(1-column)
154 do row = degree+1, n_cells-degree
156 do column = -degree, -1
157 matrix%arr_a(1,ind) = mass_line(1-column)
160 matrix%arr_a(1,ind:ind+degree) = mass_line
165 do row = n_cells-degree+1, n_cells
167 do column = n_cells-row+1, degree
168 matrix%arr_a(1,ind) = mass_line(column+1)
172 do column = -degree, -1
173 matrix%arr_a(1,ind) = mass_line(1-column)
177 do column = 0, n_cells-row
178 matrix%arr_a(1,ind) = mass_line(column+1)
183 sll_assert( ind == matrix%n_nnz+1)
191 sll_int32,
intent( in ) :: n_cells
192 sll_int32,
intent( in ) :: s_deg
193 sll_real64,
intent( in ) :: mass_line(:)
204 sll_int32,
intent( in ) :: n_cells
205 sll_int32,
intent( in ) :: degree
206 sll_real64,
intent( in ) :: mass_line(2*degree+1)
208 sll_int32,
intent ( in ) :: row
209 sll_int32,
intent(inout) :: ind
214 do column = 2-row+degree, degree
215 matrix%arr_a(1,ind) = mass_line(column)
218 matrix%arr_a(1,ind:ind+degree) = mass_line(degree+1:2*degree+1)
221 do column = 1, degree-row+1
222 matrix%arr_a(1,ind) = mass_line(column)
225 else if(row >= degree+1 .and. row<= n_cells-degree)
then
226 matrix%arr_a(1,ind:ind+2*degree)=mass_line
230 else if(row >= n_cells-degree+1 .and. row <= n_cells)
then
232 do column = n_cells-row+degree+2, 2*degree+1
233 matrix%arr_a(1,ind) = mass_line(column)
237 matrix%arr_a(1,ind:ind+degree) = mass_line(1:degree+1)
241 do column = 2+degree, n_cells-row+degree+1
242 matrix%arr_a(1,ind) = mass_line(column)
246 print*,
'error in row in assemble_mass'
249 sll_assert( ind == row*(2*degree+1)+1)
257 sll_int32,
intent( in ) :: n_cells
258 sll_int32,
intent( in ) :: s_deg
262 sll_int32 :: row, ind
263 sll_real64 :: mass_line(2*s_deg+1)
269 mass_line=mass_line/real(n_cells,f64)
278 sll_int32,
intent( in ) :: deg1, deg2
279 sll_int32,
intent( in ) :: n_cells
284 sll_int32 :: n_nnz_per_row
285 sll_int32 :: row, column, ind
288 n_nnz_per_row = deg1+deg2+1
289 n_nnz = n_nnz_per_row*n_cells
292 call spmat%create( n_rows=n_cells, n_cols=n_cells, n_nnz=n_nnz )
297 do row = 2, n_cells+1
298 spmat%arr_ia(row) = spmat%arr_ia(row-1) + n_nnz_per_row
305 do column = 1, row+deg1
306 spmat%arr_ja(ind) = column
309 do column = n_cells+row-deg2, n_cells
310 spmat%arr_ja(ind) = column
315 do row = deg2+1, n_cells-deg1
316 do column = row-deg2, row+deg1
317 spmat%arr_ja(ind) = column
322 do row = n_cells-deg1+1, n_cells
323 do column = 1, row+deg1-n_cells
324 spmat%arr_ja(ind) = column
327 do column = row-deg2, n_cells
328 spmat%arr_ja(ind) = column
333 spmat%arr_a = 0.0_f64
335 sll_assert( ind == spmat%n_nnz+1 )
343 sll_int32,
intent( in ) :: n_cells
344 sll_int32,
intent( in ) :: degree
345 sll_real64,
intent( in ) :: mass(degree*2)
349 sll_int32 :: row, ind
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
361 do row = degree, n_cells-degree
362 matrix%arr_a(1,ind:ind+degree*2-1) = mass
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
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
375 sll_assert( ind == matrix%n_nnz+1)
383 sll_int32,
intent( in ) :: n_cells
384 sll_int32,
intent( in ) :: deg1, deg2
385 sll_real64,
intent( in ) :: mass_line(deg1+deg2+1)
387 sll_int32,
intent ( in ) :: row
388 sll_int32,
intent(inout) :: ind
395 do column = 2-row+deg2, deg2
396 matrix%arr_a(1,ind) = mass_line(column)
399 matrix%arr_a(1,ind:ind+deg1) = mass_line(deg2+1:deg1+deg2+1)
402 do column = 1, deg2-row+1
403 matrix%arr_a(1,ind) = mass_line(column)
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
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)
418 matrix%arr_a(1,ind:ind+deg2) = mass_line(1:deg2+1)
421 do column = 2+deg2, n_cells-row+deg2+1
422 matrix%arr_a(1,ind) = mass_line(column)
426 print*,
'error in row in assemble_mixedmass'
429 sll_assert( ind == row*(deg1+deg2+1)+1)
436 sll_int32,
intent( in ) :: n_cells
437 sll_int32,
intent( in ) :: s_deg
438 sll_real64,
intent( in ) :: mass_line(:)
449 sll_int32,
intent( in ) :: n_cells
450 sll_int32,
intent( in ) :: deg1, deg2
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)
464 mass_line=mass_line*delta_x
472 sll_int32,
intent( in ) :: degree
473 sll_int32,
intent( in ) :: n_cells
477 sll_int32 :: n_nnz_per_row
478 sll_int32 :: row, column, ind
481 n_nnz_per_row = (2*degree+1)
482 n_nnz = n_nnz_per_row*(n_cells-degree)+(3*degree**2+degree)
485 call spmat%create( n_rows=n_cells+degree, n_cols=n_cells+degree, n_nnz=n_nnz )
491 spmat%arr_ia(row) = spmat%arr_ia(row-1) + degree + row - 1
493 do row = degree+2, n_cells+1
494 spmat%arr_ia(row) = spmat%arr_ia(row-1) + n_nnz_per_row
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
499 sll_assert( spmat%arr_ia(n_cells+degree+1) == n_nnz+1 )
505 do column = 1, row+degree
506 spmat%arr_ja(ind) = column
511 do row = degree+1, n_cells
512 do column = row-degree, row+degree
513 spmat%arr_ja(ind) = column
518 do row = n_cells+1, n_cells+degree
519 do column = row-degree, n_cells+degree
520 spmat%arr_ja(ind) = column
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 )
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)
542 sll_int32 :: row, column, ind, q
549 do column = q-row, degree-1
550 matrix%arr_a(1,ind) = mass_line_b(row+(row+column-q)*degree)
553 matrix%arr_a(1,ind:ind+degree) = mass_line_b((row-1)*q+1:row*q)
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)
563 do column = 2*q-row, degree
564 matrix%arr_a(1,ind) = mass_line(degree+2-column)
567 matrix%arr_a(1,ind:ind+degree) = mass_line
571 do row = 2*degree, n_cells-degree+1
572 do column = -degree, -1
573 matrix%arr_a(1,ind) = mass_line(1-column)
576 matrix%arr_a(1,ind:ind+degree) = mass_line
583 matrix%arr_a(1,ind) = mass_line(q+1-column)
586 do column = row, degree-2
587 matrix%arr_a(1,ind) = mass_line(2+(column-row))
591 matrix%arr_a(1,ind) = mass_line_b(q*degree-row-degree*column)
599 do column = 1, degree
600 matrix%arr_a(1,ind) = mass_line_b((q-row)*q+1-column)
604 matrix%arr_a(1,ind) = mass_line_b((degree-row)*q+1-(column-1)*degree)
609 sll_assert( ind == matrix%n_nnz+1)
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(:)
621 sll_assert( n_cells >= 2*s_deg)
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)
635 sll_int32,
intent ( in ) :: row
636 sll_int32,
intent(inout) :: ind
639 sll_int32 :: column, shift1
643 shift1 = ((row-1)*(2*deg+row))/2
644 do column = 1, deg+row
645 matrix%arr_a(1,ind) = mass_b(column+shift1)
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)
654 else if( row >= 2*deg .and. row<= n_cells-deg+1)
then
655 matrix%arr_a(1,ind:ind+2*deg) = mass
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)
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)
671 print*,
'ERROR in assemble mass_full_clamped'
679 sll_int32,
intent( in ) :: n_cells
680 sll_int32,
intent( in ) :: deg
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)
692 mass_line_b = mass_line_b/real(n_cells,f64)
699 sll_assert( ind == begin+(7*deg**2-deg-2)/2 )
700 do row = 2*deg, n_cells-deg+1
703 mass_line = mass_line/real(n_cells,f64)
706 sll_assert( ind == begin+(2*deg+1) )
710 mass_line_b = mass_line_b/real(n_cells,f64)
712 do row = n_cells-deg+2, n_cells+deg
715 sll_assert( ind == begin+(7*deg**2-deg-2)/2 )
716 sll_assert( ind == matrix%n_nnz+1)
724 sll_int32,
intent( in ) :: deg1, deg2
725 sll_int32,
intent( in ) :: n_cells
729 sll_int32 :: n_nnz_per_row
730 sll_int32 :: row, column, ind
733 n_nnz_per_row = deg1+deg2+1
734 n_nnz = n_nnz_per_row*(n_cells-deg1)+deg1*(2*deg2+deg1+1)
737 call spmat%create( n_rows=n_cells+deg1, n_cols=n_cells+deg2, n_nnz=n_nnz )
742 spmat%arr_ia(row) = spmat%arr_ia(row-1) + deg2 + row - 1
744 do row = deg1+2, n_cells+1
745 spmat%arr_ia(row) = spmat%arr_ia(row-1) + n_nnz_per_row
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
750 sll_assert( spmat%arr_ia(n_cells+deg1+1) == n_nnz+1 )
754 do column = 1, row+deg2
755 spmat%arr_ja(ind) = column
759 do row = deg1+1, n_cells
760 do column = row-deg1, row+deg2
761 spmat%arr_ja(ind) = column
765 do row = n_cells+1, n_cells +deg1
766 do column = row-deg1, n_cells+deg2
767 spmat%arr_ja(ind) = column
772 spmat%arr_a = 0.0_f64
774 sll_assert( ind == spmat%n_nnz+1 )
782 sll_int32,
intent( in ) :: n_cells
783 sll_int32,
intent( in ) :: deg1, deg2
784 sll_real64,
intent( in ) :: mass_line(deg1+deg2+1)
786 sll_int32,
intent ( in ) :: row
787 sll_int32,
intent(inout) :: ind
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
793 sll_error(
'assemble',
'error in row in assemble1_mixedmass_clamped')
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 )
805 sll_int32,
intent ( in ) :: row
806 sll_int32,
intent(inout) :: ind
808 sll_int32 :: column, shift1
812 shift1 = ((row-1)*(2*deg2+row))/2
813 do column = 1, deg2+row
814 matrix%arr_a(1,ind) = mass_line(column+shift1)
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)
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)
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)
838 sll_error(
'assemble',
'error in row in assemble_mass')
846 sll_int32,
intent( in ) :: n_cells
847 sll_int32,
intent( in ) :: deg1, deg2
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
858 delta_x = 1._f64/real(n_cells,f64)
864 mass_line_b = mass_line_b*delta_x
867 do row = 1, deg1+deg2
870 do row = deg1+deg2+1, n_cells-deg2
873 mass_line=mass_line*delta_x
879 mass_line_b = mass_line_b*delta_x
880 do row = n_cells-deg2+1, n_cells+deg1
883 sll_assert( ind == matrix%n_nnz+1)
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)
type collecting functions for analytical coordinate mapping
arbitrary degree 1d spline