12 #include "sll_assert.h"
13 #include "sll_memory.h"
14 #include "sll_working_precision.h"
45 sll_s_uniform_bsplines_eval_basis
88 sll_real64,
allocatable :: work0(:)
89 sll_real64,
allocatable :: work(:)
90 sll_real64,
allocatable :: work3d(:,:,:)
91 sll_real64,
allocatable :: work2(:)
92 sll_real64,
allocatable :: work_d1(:)
93 sll_real64,
allocatable :: work_d2_in(:)
94 sll_real64,
allocatable :: work_d2_out(:)
95 sll_real64,
allocatable :: work_d3_in(:)
96 sll_real64,
allocatable :: work_d3_out(:)
116 logical :: adiabatic_electrons = .false.
172 sll_real64,
intent(in) :: delta_t
173 sll_real64,
intent(in) :: field_in(:)
174 sll_real64,
intent(inout) :: field_out(:)
176 call self%mass2_operator%dot( field_in, self%work )
179 call self%mass1_solver%solve( self%work2, self%work )
181 field_out = field_out + delta_t*self%work
190 sll_real64,
intent(in) :: delta_t
191 sll_real64,
intent(in) :: field_in(:)
192 sll_real64,
intent(inout) :: field_out(:)
196 field_out = field_out - delta_t * self%work
204 sll_real64,
intent( in ) :: delta_t
205 sll_real64,
intent( inout ) :: efield(:)
206 sll_real64,
intent( inout ) :: bfield(:)
207 sll_real64,
optional :: betar
211 if(
present(betar) )
then
218 call self%mass2_operator%dot( bfield, self%work )
219 call self%multiply_ct( self%work, self%work2 )
221 self%linear_op_schur_eb%sign = -delta_t**2*factor*0.25_f64
222 call self%linear_op_schur_eb%dot( efield, self%work )
223 self%work = self%work + delta_t*factor*self%work2
229 self%linear_op_schur_eb%sign = delta_t**2*factor*0.25_f64
230 call self%linear_solver_schur_eb%set_guess( efield )
231 call self%linear_solver_schur_eb%solve( self%work, efield)
234 self%work2 = self%work2 + efield
235 call self%compute_b_from_e( delta_t*0.5_f64, self%work2, bfield)
243 sll_real64,
intent( in ) :: field_in(:)
244 sll_real64,
intent( out ) :: field_out(:)
247 call self%poisson_solver%solve( field_in, self%work(1:self%n_total) )
248 call multiply_g(self, self%work(1:self%n_total), field_out)
249 field_out = -field_out
257 sll_real64,
intent( in ) :: field_in(:)
258 sll_real64,
intent( out ) :: field_out(:)
260 call self%mass1_operator%dot( field_in, self%work )
263 field_out = - field_out
271 sll_real64,
intent( in ) :: current(:)
272 sll_real64,
intent( inout ) :: e(:)
273 sll_int32,
intent( in ),
optional :: component
275 if(
present(component))
then
276 call self%mass_1_solver(component)%solve( current, self%work(1:self%n_total) )
277 e = e - self%work(1:self%n_total)
279 call self%mass1_solver%solve( current, self%work )
289 sll_real64,
intent( in ) :: field_in(:)
290 sll_real64,
intent( inout ) :: field_out(:)
291 sll_real64,
intent( out ) :: efield_dofs(:)
293 call self%mass0_solver%solve( field_in, field_out )
294 call self%multiply_g( field_out, efield_dofs )
295 efield_dofs = -efield_dofs
303 sll_real64,
intent( in ) :: field_in(:)
304 sll_real64,
intent( inout ) :: field_out(:)
305 sll_real64,
intent( out ) :: efield_dofs(:)
309 call self%multiply_gt( field_in, self%work0 )
310 call self%mass0_solver%solve( self%work0, self%work(1:self%n_total) )
311 field_out = field_out + self%work(1:self%n_total)
313 call self%multiply_g( field_out, efield_dofs )
314 efield_dofs = -efield_dofs
323 sll_int32,
intent( in ) :: form
324 sll_int32,
intent( in ) :: component
325 sll_real64,
intent( out ) :: coefs_dofs(:)
330 sll_int32 :: i1, i2, i3,j1, j2, j3, k1, k2, k3, q(3), counter
331 sll_int32 :: degree(3)
334 sll_real64,
allocatable :: xw_gauss_d1(:,:), xw_gauss_d2(:,:), xw_gauss_d3(:,:)
335 sll_real64,
allocatable :: bspl_d1(:,:), bspl_d2(:,:), bspl_d3(:,:)
336 sll_real64 :: scratch(maxval(self%s_deg_0+1))
339 if ( form == 0 )
then
340 degree = self%s_deg_0
341 elseif (form == 1 )
then
342 degree = self%s_deg_0
343 degree(component) = self%s_deg_1(component)
344 elseif( form == 2)
then
345 degree = self%s_deg_1
346 degree(component) = self%s_deg_0(component)
347 elseif( form == 3)
then
348 degree = self%s_deg_1
350 print*,
'Wrong form.'
356 allocate(xw_gauss_d1(2,q(1)))
357 allocate(bspl_d1(q(1), degree(1)+1))
361 call sll_s_uniform_bsplines_eval_basis(degree(1),xw_gauss_d1(1,k1), scratch(1:degree(1)+1))
362 bspl_d1(k1,:) = scratch(1:degree(1)+1)
365 allocate(xw_gauss_d2(2,q(2)))
366 allocate(bspl_d2(q(2), degree(2)+1))
370 call sll_s_uniform_bsplines_eval_basis(degree(2),xw_gauss_d2(1,k2), scratch(1:degree(2)+1))
371 bspl_d2(k2,:) = scratch(1:degree(2)+1)
374 allocate(xw_gauss_d3(2,q(3)))
375 allocate(bspl_d3(q(3), degree(3)+1))
379 call sll_s_uniform_bsplines_eval_basis(degree(3),xw_gauss_d3(1,k3), scratch(1:degree(3)+1))
380 bspl_d3(k3,:) = scratch(1:degree(3)+1)
385 do i3 = 1, self%n_dofs(3)
386 do i2 = 1, self%n_dofs(2)
387 do i1 = 1, self%n_dofs(1)
390 do j3 = 1, degree(3)+1
391 do j2 = 1, degree(2)+1
392 do j1 = 1, degree(1)+1
395 c(3) = self%delta_x(3)*(xw_gauss_d3(1,k3) + real(i3 + j3 - 2,f64))
397 c(2) = self%delta_x(2)*(xw_gauss_d2(1,k2) + real(i2 + j2 - 2,f64))
399 c(1) = self%delta_x(1)*(xw_gauss_d1(1,k1) + real(i1 + j1 - 2,f64))
400 coef = coef + xw_gauss_d1(2,k1)* xw_gauss_d2(2,k2)* &
403 bspl_d1(k1,degree(1)+2-j1)*&
404 bspl_d2(k2,degree(2)+2-j2)*&
405 bspl_d3(k3,degree(3)+2-j3)
414 coefs_dofs(counter) = coef*self%volume
426 sll_int32,
intent( in ) :: form
427 sll_int32,
intent( in ) :: component
428 sll_real64,
intent( out ) :: coefs_dofs(:)
438 call self%mass0_solver%solve( self%work(1:self%n_total), coefs_dofs )
440 call self%mass_1_solver(component)%solve( self%work(1:self%n_total), coefs_dofs )
442 call self%mass_2_solver(component)%solve( self%work(1:self%n_total), coefs_dofs )
444 print*,
'L2projection for', form,
'-form not implemented.'
449 subroutine compute_dofs(self, form, component, coefs_dofs, func1, func2, func3 )
451 sll_int32,
intent( in ) :: form
452 sll_int32,
intent( in ) :: component
453 sll_real64,
intent( out ) :: coefs_dofs(:)
466 print*,
'projection for', form,
'-form not implemented.'
476 sll_real64,
intent( out ) :: coefs_dofs(:)
478 sll_int32 :: i1, i2, i3, j, q, ind
479 sll_real64 :: c(3), e(3)
480 sll_real64,
allocatable :: xw_gauss(:,:)
484 allocate(xw_gauss(2,q))
488 do i3 = 1, self%n_dofs(3)
489 c(3) = self%delta_x(3)* real(i3-1,f64)
490 do i2 = 1, self%n_dofs(2)
491 c(2) = self%delta_x(2)* real(i2-1,f64)
492 do i1 = 1, self%n_dofs(1)
493 c(1) = self%delta_x(1)* real(i1-1,f64)
496 e(1) = self%delta_x(1)* (xw_gauss(1,q) + real(i1-1,f64) )
497 e(2) = self%delta_x(2)* (xw_gauss(1,q) + real(i2-1,f64) )
498 e(3) = self%delta_x(3)* (xw_gauss(1,q) + real(i3-1,f64) )
499 coefs_dofs(ind) = coefs_dofs(ind) + self%delta_x(1)*xw_gauss(2,j)*c(1)*func1([e(1),c(2),c(3)])
500 coefs_dofs(ind+self%n_total) = coefs_dofs(ind+self%n_total) + self%delta_x(2)*xw_gauss(2,j)*c(2)*func2([c(1),e(2),c(3)])
501 coefs_dofs(ind+2*self%n_total) = coefs_dofs(ind+2*self%n_total) + self%delta_x(3)*xw_gauss(2,j)*c(3)*func3([c(1),c(2),e(3)])
513 sll_real64 :: coefs(:)
515 sll_int32 :: component
528 sll_real64 :: coefs1(:)
529 sll_real64 :: coefs2(:)
531 sll_int32,
optional :: component
536 if ( form == 0 )
then
538 call self%multiply_mass( [0], coefs2, self%work0 )
539 elseif (form == 1 )
then
543 elseif( form == 2)
then
547 elseif( form == 3)
then
551 print*,
'Wrong form.'
555 r = sum(coefs1*self%work0)
561 subroutine init_3d_fem( self, domain, n_dofs, s_deg_0, mass_tolerance, poisson_tolerance, solver_tolerance, adiabatic_electrons, profile )
563 sll_real64,
intent(in) :: domain(3,2)
564 sll_int32,
intent(in) :: n_dofs(3)
565 sll_int32,
intent(in) :: s_deg_0(3)
566 sll_real64,
intent(in),
optional :: mass_tolerance
567 sll_real64,
intent(in),
optional :: poisson_tolerance
568 sll_real64,
intent(in),
optional :: solver_tolerance
569 logical,
intent(in),
optional :: adiabatic_electrons
573 sll_real64,
allocatable :: mass_line_0(:), mass_line_1(:), mass_line_mixed(:)
574 sll_real64,
allocatable :: nullspace(:,:)
576 if (
present( mass_tolerance) )
then
577 self%mass_solver_tolerance = mass_tolerance
579 self%mass_solver_tolerance = 1d-12
581 if (
present( poisson_tolerance) )
then
582 self%poisson_solver_tolerance = poisson_tolerance
584 self%poisson_solver_tolerance = 1d-12
587 if (
present( solver_tolerance) )
then
588 self%solver_tolerance = solver_tolerance
590 self%solver_tolerance = 1d-12
593 if(
present( adiabatic_electrons ) )
then
594 self%adiabatic_electrons = adiabatic_electrons
597 if(
present( profile ) )
then
598 self%profile = profile
601 self%n_cells = n_dofs
603 self%n_total = product(n_dofs)
604 self%n_total0 = self%n_total
605 self%n_total1 = self%n_total
607 self%Lx = domain(:,2) - domain(:,1)
608 self%delta_x = self%Lx / real(n_dofs, f64)
609 self%s_deg_0 = s_deg_0
610 self%s_deg_1 = s_deg_0 - 1
612 self%volume = product(self%delta_x)
615 allocate( self%work3d(n_dofs(1), n_dofs(2), n_dofs(3)) )
616 allocate( self%work0(self%n_total) )
617 allocate( self%work(self%n_total*3) )
618 allocate( self%work2(self%n_total*3) )
619 allocate( self%work_d1( n_dofs(1) ) )
620 allocate( self%work_d2_in( n_dofs(2) ) )
621 allocate( self%work_d2_out( n_dofs(2) ) )
622 allocate( self%work_d3_in( n_dofs(3) ) )
623 allocate( self%work_d3_out( n_dofs(3) ) )
630 allocate( mass_line_0(s_deg_0(j)+1) )
631 allocate( mass_line_1(s_deg_0(j)) )
632 allocate( mass_line_mixed(s_deg_0(j)*2) )
641 self%mass1d(1,j)%arr_a = self%mass1d(1,j)%arr_a*self%delta_x(j)
642 self%mass1d(2,j)%arr_a = self%mass1d(2,j)%arr_a*self%delta_x(j)
643 call self%mass1d_solver(1,j)%create( self%mass1d(1,j) )
644 call self%mass1d_solver(2,j)%create( self%mass1d(2,j) )
649 deallocate( mass_line_0 )
650 deallocate( mass_line_1 )
651 deallocate( mass_line_mixed )
656 self%mass1d_solver(k,j)%atol = self%mass_solver_tolerance
662 call self%mass_1_solver(1)%create( linear_solver_a=self%mass1d_solver(2,1), &
663 linear_solver_b=self%mass1d_solver(1,2), &
664 linear_solver_c=self%mass1d_solver(1,3) )
665 call self%mass_1_solver(2)%create( linear_solver_a=self%mass1d_solver(1,1), &
666 linear_solver_b=self%mass1d_solver(2,2), &
667 linear_solver_c=self%mass1d_solver(1,3) )
668 call self%mass_1_solver(3)%create( linear_solver_a=self%mass1d_solver(1,1), &
669 linear_solver_b=self%mass1d_solver(1,2), &
670 linear_solver_c=self%mass1d_solver(2,3))
671 call self%mass_2_solver(1)%create( linear_solver_a=self%mass1d_solver(1,1), &
672 linear_solver_b=self%mass1d_solver(2,2), &
673 linear_solver_c=self%mass1d_solver(2,3) )
674 call self%mass_2_solver(2)%create( linear_solver_a=self%mass1d_solver(2,1), &
675 linear_solver_b=self%mass1d_solver(1,2), &
676 linear_solver_c=self%mass1d_solver(2,3) )
677 call self%mass_2_solver(3)%create( linear_solver_a=self%mass1d_solver(2,1), &
678 linear_solver_b=self%mass1d_solver(2,2), &
679 linear_solver_c=self%mass1d_solver(1,3) )
682 if(self%adiabatic_electrons)
then
687 call self%mass0_solver%create( self%mass0 )
688 self%mass0_solver%atol = self%mass_solver_tolerance
691 call self%mass1(1)%create( linop_a=self%mass1d(1,3), &
692 linop_b=self%mass1d(1,2), &
693 linop_c=self%mass1d(2,1) )
694 call self%mass1(2)%create( linop_a=self%mass1d(1,3), &
695 linop_b=self%mass1d(2,2), &
696 linop_c=self%mass1d(1,1) )
697 call self%mass1(3)%create( linop_a=self%mass1d(2,3), &
698 linop_b=self%mass1d(1,2), &
699 linop_c=self%mass1d(1,1))
701 call self%mass2(1)%create( linop_a=self%mass1d(2,3), &
702 linop_b=self%mass1d(2,2), &
703 linop_c=self%mass1d(1,1) )
704 call self%mass2(2)%create( linop_a=self%mass1d(2,3), &
705 linop_b=self%mass1d(1,2), &
706 linop_c=self%mass1d(2,1) )
707 call self%mass2(3)%create( linop_a=self%mass1d(1,3), &
708 linop_b=self%mass1d(2,2), &
709 linop_c=self%mass1d(2,1))
711 call self%mass1_operator%create( 3, 3 )
712 call self%mass2_operator%create( 3, 3 )
714 call self%mass1_operator%set( j, j, self%mass1(j) )
715 call self%mass2_operator%set( j, j, self%mass2(j) )
717 call self%preconditioner_fft%init( self%Lx, n_dofs, s_deg_0 )
718 call self%mass1_solver%create( self%mass1_operator, self%preconditioner_fft%inverse_mass1_3d)
719 self%mass1_solver%atol = self%mass_solver_tolerance
722 call self%poisson_matrix%create( self%mass1_operator, self%n_dofs, self%delta_x )
724 allocate(nullspace(1,1:3*self%n_total))
725 nullspace(1,:) = 1.0_f64
726 call self%poisson_operator%create( linear_operator=self%poisson_matrix, vecs=nullspace(:,1:self%n_total), n_dim_nullspace=1 )
728 call self%poisson_solver%create( self%poisson_operator )
729 self%poisson_solver%null_space = .true.
730 self%poisson_solver%atol = self%poisson_solver_tolerance
732 self%poisson_solver%n_maxiter=40000
736 call self%linear_op_schur_eb%create( self%mass1_operator, self%mass2_operator, self%n_total, self%n_dofs, self%delta_x )
737 call self%linear_solver_schur_eb%create( self%linear_op_schur_eb, self%preconditioner_fft%inverse_mass1_3d )
738 self%linear_solver_schur_eb%atol = self%solver_tolerance
745 sll_real64,
intent(in) :: x(3)
746 sll_int32,
optional,
intent(in) :: component(:)
748 profile_m0 = product(self%Lx) * self%profile%rho_0( x(1) )/self%profile%T_e( x(1) )
754 sll_real64,
intent(in) :: x(3)
755 sll_int32,
optional,
intent(in) :: component(:)
768 sll_real64,
intent(in) :: domain(3,2)
769 sll_int32,
intent(in) :: n_dofs(3)
770 sll_int32,
intent(in) :: s_deg_0(3)
771 character(len=*),
intent(in) :: nml_file
772 logical,
intent(in),
optional :: adiabatic_electrons
775 character(len=256) :: file_prefix
776 sll_int32 :: input_file
777 sll_int32 :: io_stat, io_stat0, io_stat1, rank, file_id
778 sll_real64 :: mass_tolerance
779 sll_real64 :: poisson_tolerance
780 sll_real64 :: maxwell_tolerance
782 namelist /output/ file_prefix
783 namelist /maxwell_solver/ mass_tolerance, poisson_tolerance
785 namelist /time_solver/ maxwell_tolerance
789 if(
present( adiabatic_electrons ) )
then
790 self%adiabatic_electrons = adiabatic_electrons
793 if(
present( profile ) )
then
794 self%profile = profile
798 open(newunit = input_file, file=nml_file, status=
'old',iostat=io_stat)
799 if (io_stat /= 0)
then
801 print*,
'sll_m_maxwell_3d_fem: Input file does not exist. Set default tolerance.'
802 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
803 write(file_id, *)
'mass solver tolerance:', 1d-12
804 write(file_id, *)
'poisson solver tolerance:', 1d-12
807 call self%init( domain, n_dofs, s_deg_0 )
809 read(input_file, output,iostat=io_stat0)
810 read(input_file, maxwell_solver,iostat=io_stat)
811 read(input_file, time_solver,iostat=io_stat1)
812 if (io_stat /= 0)
then
814 print*,
'sll_m_maxwell_3d_fem: Input parameter does not exist. Set default tolerance.'
815 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
816 write(file_id, *)
'mass solver tolerance:', 1d-12
817 write(file_id, *)
'poisson solver tolerance:', 1d-12
820 call self%init( domain, n_dofs, s_deg_0 )
823 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
824 write(file_id, *)
'mass solver tolerance:', mass_tolerance
825 write(file_id, *)
'poisson solver tolerance:', poisson_tolerance
828 call self%init( domain, n_dofs, s_deg_0, mass_tolerance, poisson_tolerance, maxwell_tolerance )
843 call self%poisson_solver%free()
844 call self%poisson_operator%free()
845 call self%poisson_matrix%free
847 call self%mass_1_solver(j)%free()
848 call self%mass_2_solver(j)%free()
849 call self%mass1d_solver(1,j)%free()
850 call self%mass1d_solver(2,j)%free()
851 call self%mass1d(1,j)%free()
852 call self%mass1d(2,j)%free()
853 call self%mass1d(3,j)%free()
855 call self%mass1_solver%free()
856 call self%mass1_operator%free()
857 call self%mass2_operator%free()
859 call self%mass1(j)%free()
860 call self%mass2(j)%free()
863 call self%linear_solver_schur_eb%free()
864 call self%linear_op_schur_eb%free()
866 deallocate( self%work3d )
867 deallocate( self%work0 )
868 deallocate( self%work )
869 deallocate( self%work2 )
870 deallocate( self%work_d1 )
871 deallocate( self%work_d2_in )
872 deallocate( self%work_d2_out )
873 deallocate( self%work_d3_in )
874 deallocate( self%work_d3_out )
882 sll_real64,
intent( in ) :: field_in(:)
883 sll_real64,
intent( out ) :: field_out(:)
893 sll_real64,
intent( in ) :: field_in(:)
894 sll_real64,
intent( out ) :: field_out(:)
904 sll_real64,
intent( in ) :: field_in(:)
905 sll_real64,
intent( out ) :: field_out(:)
915 sll_real64,
intent( in ) :: field_in(:)
916 sll_real64,
intent( out ) :: field_out(:)
926 sll_int32,
intent( in ) :: deg(:)
927 sll_real64,
intent( in ) :: coefs_in(:)
928 sll_real64,
intent( out ) :: coefs_out(:)
931 if(
size(deg) ==1 )
then
934 call self%mass0%dot( coefs_in, coefs_out )
936 call self%mass1_operator%dot( coefs_in, coefs_out )
938 call self%mass2_operator%dot( coefs_in, coefs_out )
940 print*,
'multiply mass for other form not yet implemented'
943 else if(
size(deg) == 3 )
then
953 sll_int32,
intent( in ) :: deg(:)
954 sll_real64,
intent( in ) :: coefs_in(:)
955 sll_real64,
intent( out ) :: coefs_out(:)
957 sll_int32 :: i,j,k,istart,iend
959 if( deg(1) == 0 )
then
960 call self%mass0%dot( coefs_in, coefs_out )
963 iend = self%n_dofs(1)
964 do k=1,self%n_dofs(3)
965 do j=1,self%n_dofs(2)
967 call self%mass1d(deg(1),1)%dot( coefs_in(istart:iend), self%work_d1 )
968 self%work3d(:,j,k) = self%work_d1
970 iend = iend + self%n_dofs(1)
974 do k=1,self%n_dofs(3)
975 do i =1,self%n_dofs(1)
976 self%work_d2_in = self%work3d(i,:,k)
977 call self%mass1d(deg(2),2)%dot( self%work_d2_in, self%work_d2_out )
978 self%work3d(i,:,k) = self%work_d2_out
983 do j=1,self%n_dofs(2)
984 do i =1,self%n_dofs(1)
985 self%work_d3_in = self%work3d(i,j,:)
986 call self%mass1d(deg(3),3)%dot( self%work_d3_in, self%work_d3_out )
987 do k=1,self%n_dofs(3)
988 coefs_out(istart+(k-1)*self%n_dofs(1)*self%n_dofs(2)) = self%work_d3_out(k)
1002 sll_int32,
intent( in ) :: form
1003 sll_real64,
intent( in ) :: coefs_in(:)
1004 sll_real64,
intent( out ) :: coefs_out(:)
1006 sll_int32 :: comp, istart, iend
1011 istart = 1+(comp-1)*self%n_total
1012 iend = comp*self%n_total
1013 call self%mass_1_solver(comp)%solve( coefs_in(istart:iend), coefs_out(istart:iend) )
1017 istart = 1+(comp-1)*self%n_total
1018 iend = comp*self%n_total
1019 call self%mass_2_solver(comp)%solve( coefs_in(istart:iend), coefs_out(istart:iend) )
1022 print*,
'multiply inverse mass for other form not yet implemented'
1033 sll_real64,
intent( in ) :: efield_dofs(:)
1034 sll_real64,
intent( in ) :: bfield_dofs(:)
1035 sll_real64,
intent( out ) :: energy
1037 sll_real64 :: field_energy(6)
1040 field_energy(1) = self%l2norm_squared &
1041 ( efield_dofs(1:self%n_total), 1, 1 )
1042 field_energy(2) = self%l2norm_squared &
1043 ( efield_dofs(self%n_total+1:2*self%n_total), 1, 2 )
1044 field_energy(3) = self%l2norm_squared &
1045 ( efield_dofs(2*self%n_total+1:3*self%n_total), 1, 3 )
1046 field_energy(4) = self%l2norm_squared &
1047 ( bfield_dofs(1:self%n_total), 2, 1 )
1048 field_energy(5) = self%l2norm_squared &
1049 ( bfield_dofs(self%n_total+1:2*self%n_total), 2, 2 )
1050 field_energy(6) =self%l2norm_squared &
1051 ( bfield_dofs(2*self%n_total+1:3*self%n_total), 2, 3 )
1054 energy = 0.5_f64*sum(field_energy)
integer(kind=i32) function, public sll_f_get_collective_rank(col)
Determines the rank of the calling process in the communicator.
type(sll_t_collective_t), pointer, public sll_v_world_collective
Control of subset assignment. Processes with the same color are in the same new communicator.
Gauss-Legendre integration.
real(kind=f64) function, dimension(2, 1:npoints), public sll_f_gauss_legendre_points_and_weights(npoints, a, b)
Returns a 2d array of size (2,npoints) containing gauss-legendre points and weights in the interval [...
module for a block linear operator
module for a linear operator of kronecker solver
module for a penalized linear operator
module for conjugate gradient method in pure form
module for kronecker linear solver
Low level arbitrary degree splines.
module for Compressed Sparse Row Matrix (CSR)
Module interface to solve Maxwell's equations in 3D.
Module interface to solve Maxwell's equations in 3D The linear systems are solved using iterative lin...
subroutine multiply_ct(self, field_in, field_out)
Multiply by transpose of discrete curl matrix.
subroutine free_3d_fem(self)
Finalization.
subroutine multiply_mass_inverse_3dkron(self, form, coefs_in, coefs_out)
Multiply by the inverse mass matrix.
subroutine multiply_g(self, field_in, field_out)
Multiply by dicrete gradient matrix.
subroutine sll_compute_edge_integral(self, func1, func2, func3, coefs_dofs)
subroutine multiply_gt(self, field_in, field_out)
Multiply by transpose of dicrete gradient matrix.
real(kind=f64) function inner_product_3d_fem(self, coefs1, coefs2, form, component)
Compute inner product.
subroutine init_from_file_3d_fem(self, domain, n_dofs, s_deg_0, nml_file, adiabatic_electrons, profile)
Initialization from nml file.
subroutine sll_s_compute_e_from_j_3d_fem(self, current, E, component)
Compute E_i from j_i integrated over the time interval using weak Ampere formulation.
subroutine sll_s_compute_e_from_rho_3d_fem(self, field_in, field_out)
Compute E_i from rho_i integrated over the time interval using weak Poisson's equation.
real(kind=f64) function l2norm_squared_3d_fem(self, coefs, form, component)
Compute square of the L2norm.
subroutine sll_s_compute_b_from_e_3d_fem(self, delta_t, field_in, field_out)
Compute Bz from Ey using strong 1D Faraday equation for spline coefficients $B_z^{new}(x_j) = B_z^{ol...
subroutine multiply_mass_3d_fem(self, deg, coefs_in, coefs_out)
Multiply by the mass matrix.
subroutine sll_s_compute_rhs_fem(self, form, component, coefs_dofs, func1, func2, func3)
Compute the FEM right-hand-side for a given function f and periodic splines of given degree Its compo...
subroutine sll_s_compute_phi_from_rho_3d_fem(self, field_in, field_out, efield_dofs)
Compute phi from rho_i integrated over the time interval.
subroutine sll_s_compute_curl_part_3d_fem(self, delta_t, efield, bfield, betar)
Solve curl part of Maxwell's equations.
subroutine compute_field_energy(self, efield_dofs, bfield_dofs, energy)
Compute field energy.
subroutine l2projection_3d_fem(self, form, component, coefs_dofs, func1, func2, func3)
Compute the L2 projection of a given function f on periodic splines of given degree.
subroutine sll_s_compute_rho_from_e_3d_fem(self, field_in, field_out)
compute rho from e using weak Gauss law ( rho = G^T M_1 e )
subroutine init_3d_fem(self, domain, n_dofs, s_deg_0, mass_tolerance, poisson_tolerance, solver_tolerance, adiabatic_electrons, profile)
Initialization.
subroutine sll_s_compute_phi_from_j_3d_fem(self, field_in, field_out, efield_dofs)
Compute phi from j_i integrated over the time interval, delta_t is already included.
subroutine multiply_mass_3dkron(self, deg, coefs_in, coefs_out)
Multiply by the mass matrix.
subroutine sll_s_compute_e_from_b_3d_fem(self, delta_t, field_in, field_out)
compute Ey from Bz using weak Ampere formulation
subroutine compute_dofs(self, form, component, coefs_dofs, func1, func2, func3)
subroutine multiply_c(self, field_in, field_out)
Multiply by discrete curl matrix.
Module interface to solve Maxwell's equations with coordinate transformation in 3D The linear systems...
functions for initial profile of the particle distribution function
Utilites for 3D Maxwell solvers with spline finite elements.
subroutine, public sll_s_spline_fem_mass3d(n_cells, deg, component, matrix, profile, n_cells_min, n_cells_max)
Set up 3d mass matrix for specific spline degrees and profile function.
subroutine, public sll_s_spline_fem_mixedmass3d(n_cells, deg1, deg2, component, matrix, profile, n_cells_min, n_cells_max)
Set up 3d mixed mass matrix for specific spline degree and profile function.
Utilites for Maxwell solver's with spline finite elements using sparse matrix linear solvers.
subroutine, public sll_s_spline_fem_mass1d(n_cells, s_deg, mass_line, matrix)
Set up 1d mass matrix (sparsity pattern and values)
subroutine, public sll_s_spline_fem_mixedmass1d(n_cells, s_deg, mass_line, matrix)
Utilites for Maxwell solver's with spline finite elements.
subroutine, public sll_s_multiply_g(n_dofs, delta_x, field_in, field_out)
Multiply by dicrete gradient matrix (3d version)
subroutine, public sll_s_multiply_c(n_dofs, delta_x, field_in, field_out)
Multiply by discrete curl matrix.
subroutine, public sll_s_multiply_ct(n_dofs, delta_x, field_in, field_out)
Multiply by transpose of discrete curl matrix.
subroutine, public sll_s_multiply_gt(n_dofs, delta_x, field_in, field_out)
Multiply by transpose of dicrete gradient matrix (3d version)
subroutine, public sll_s_spline_fem_mixedmass_line(deg, mass_line)
Helper function to find line of mass matrix ( N_i^p N_j^{p-1}))
subroutine, public sll_s_spline_fem_mass_line(degree, mass_line)
Computes the mass line for a mass matrix with degree splines.
real(kind=f64) function profile_0(x)
real(kind=f64) function profile_m0(x)
class for a linear operator_block
class for a linear operator
class for a linear operator_penalized
class for the cg linear solver
class for the kronecker linear solver