11 #include "sll_assert.h"
12 #include "sll_memory.h"
13 #include "sll_working_precision.h"
38 sll_s_uniform_bsplines_eval_basis
76 sll_real64,
allocatable :: work0(:)
77 sll_real64,
allocatable :: work(:)
78 sll_real64,
allocatable :: work2(:)
97 logical :: adiabatic_electrons = .false.
152 sll_real64,
intent( in ) :: delta_t
153 sll_real64,
intent( in ) :: field_in(:)
154 sll_real64,
intent( inout ) :: field_out(:)
160 call self%mass1_solver%solve( self%work2, self%work )
162 field_out = field_out + delta_t*self%work
170 sll_real64,
intent( in ) :: delta_t
171 sll_real64,
intent( in ) :: field_in(:)
172 sll_real64,
intent( inout ) :: field_out(:)
176 field_out = field_out - delta_t * self%work
184 sll_real64,
intent( in ) :: delta_t
185 sll_real64,
intent( inout ) :: efield(:)
186 sll_real64,
intent( inout ) :: bfield(:)
187 sll_real64,
optional :: betar
191 if(
present(betar) )
then
198 call self%mass2_operator%dot( bfield, self%work )
199 call self%multiply_ct( self%work, self%work2 )
201 self%linear_op_schur_eb%sign = -delta_t**2*factor*0.25_f64
202 call self%linear_op_schur_eb%dot( efield, self%work )
203 self%work = self%work + delta_t*factor*self%work2
209 self%linear_op_schur_eb%sign = delta_t**2*factor*0.25_f64
210 call self%linear_solver_schur_eb%set_guess( efield )
211 call self%linear_solver_schur_eb%solve( self%work, efield)
214 self%work2 = self%work2 + efield
215 call self%compute_b_from_e( delta_t*0.5_f64, self%work2, bfield)
223 sll_real64,
intent( in ) :: field_in(:)
224 sll_real64,
intent( out ) :: field_out(:)
226 call self%poisson_solver%solve( field_in, self%work0 )
228 field_out = -field_out
236 sll_real64,
intent( in ) :: field_in(:)
237 sll_real64,
intent( out ) :: field_out(:)
243 field_out = - field_out
251 sll_real64,
intent( in ) :: current(:)
252 sll_real64,
intent( inout ) :: e(:)
253 sll_int32,
intent( in ),
optional :: component
255 call self%mass1_solver%solve( current, self%work )
264 sll_real64,
intent( in ) :: field_in(:)
265 sll_real64,
intent( inout ) :: field_out(:)
266 sll_real64,
intent( out ) :: efield_dofs(:)
268 call self%mass0_solver%solve( field_in, field_out )
269 call self%multiply_g( field_out, efield_dofs )
270 efield_dofs = -efield_dofs
278 sll_real64,
intent( in ) :: field_in(:)
279 sll_real64,
intent( inout ) :: field_out(:)
280 sll_real64,
intent( out ) :: efield_dofs(:)
282 call self%multiply_gt( field_in, self%work0 )
283 call self%mass0_solver%solve( self%work0, self%work2(1:self%n_total) )
284 field_out = field_out + self%work2(1:self%n_total)
286 call self%multiply_g( field_out, efield_dofs )
287 efield_dofs = -efield_dofs
296 sll_int32,
intent( in ) :: form
297 sll_int32,
intent( in ) :: component
298 sll_real64,
intent( out ) :: coefs_dofs(:)
303 sll_int32 :: degree(3)
306 if ( form == 0 )
then
307 call rhs_zeroform( self, self%s_deg_0, func1, coefs_dofs )
308 elseif (form == 1 )
then
309 degree = self%s_deg_0
310 degree(component) = self%s_deg_1(component)
311 call rhs_oneform( self, degree, func1, func2, func3, component, coefs_dofs )
312 elseif( form == 2)
then
313 degree = self%s_deg_1
314 degree(component) = self%s_deg_0(component)
315 call rhs_twoform( self, degree, func1, func2, func3, component, coefs_dofs )
316 elseif( form == 3)
then
319 print*,
'Wrong form.'
328 sll_int32,
intent( in ) :: deg(3)
330 sll_real64,
intent( out ) :: coefs_dofs(:)
332 sll_int32 :: i1, i2, i3, j1, j2, j3, k1, k2, k3, q(3), counter
333 sll_real64 :: coef, jacobian, c(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(deg+1))
341 allocate(xw_gauss_d1(2, q(1)))
342 allocate(bspl_d1(q(1), deg(1)+1 ))
346 call sll_s_uniform_bsplines_eval_basis(deg(1),xw_gauss_d1(1,k1), scratch(1:deg(1)+1))
347 bspl_d1(k1,:) = scratch(1:deg(1)+1)
350 allocate(xw_gauss_d2(2, q(2)))
351 allocate(bspl_d2(q(2), deg(2)+1))
355 call sll_s_uniform_bsplines_eval_basis(deg(2),xw_gauss_d2(1,k2), scratch(1:deg(2)+1))
356 bspl_d2(k2,:) = scratch(1:deg(2)+1)
359 allocate(xw_gauss_d3(2,q(3)))
360 allocate(bspl_d3(q(3), deg(3)+1 ))
364 call sll_s_uniform_bsplines_eval_basis(deg(3),xw_gauss_d3(1,k3), scratch(1:deg(3)+1) )
365 bspl_d3(k3,:) = scratch(1:deg(3)+1)
371 do i3 = 1, self%n_dofs(3)
372 do i2 = 1, self%n_dofs(2)
373 do i1 = 1, self%n_dofs(1)
381 c(3) = self%delta_x(3) * (xw_gauss_d3(1,k3) + real(i3 + j3 - 2-((i3 + j3 - 2)/self%n_dofs(3)) * self%n_dofs(3),f64))
383 c(2) = self%delta_x(2) * (xw_gauss_d2(1,k2) + real(i2 + j2 - 2-((i2 + j2 - 2)/self%n_dofs(2)) * self%n_dofs(2),f64))
385 c(1) = self%delta_x(1) * (xw_gauss_d1(1,k1) + real(i1 + j1 - 2-((i1 + j1 - 2)/self%n_dofs(1)) * self%n_dofs(1),f64))
386 jacobian = self%map%jacobian( c )
387 coef = coef + xw_gauss_d1(2,k1) * xw_gauss_d2(2,k2) * xw_gauss_d3(2,k3) *&
388 func(self%map%get_x(c) ) * &
389 bspl_d1(k1,deg(1)+2-j1) *&
390 bspl_d2(k2,deg(2)+2-j2) *&
391 bspl_d3(k3,deg(3)+2-j3) * abs(jacobian)
399 coefs_dofs(counter) = coef*self%volume
409 subroutine rhs_oneform( self, deg, func1, func2, func3, component, coefs_dofs )
411 sll_int32,
intent( in ) :: deg(3)
415 sll_int32,
intent( in ) :: component
416 sll_real64,
intent( out ) :: coefs_dofs(:)
418 sll_int32 :: i1, i2, i3,j1, j2, j3, k1, k2, k3, q(3), counter
420 sll_real64 :: coef, jacobian, jmatrix(3,3)
421 sll_real64,
allocatable :: xw_gauss_d1(:,:), xw_gauss_d2(:,:), xw_gauss_d3(:,:)
422 sll_real64,
allocatable :: bspl_d1(:,:), bspl_d2(:,:), bspl_d3(:,:)
423 sll_real64 :: scratch(maxval(deg+1))
428 allocate(xw_gauss_d1(2, q(1)))
429 allocate(bspl_d1(q(1), deg(1)+1 ))
433 call sll_s_uniform_bsplines_eval_basis(deg(1),xw_gauss_d1(1,k1), scratch(1:deg(1)+1))
434 bspl_d1(k1,:) = scratch(1:deg(1)+1)
437 allocate(xw_gauss_d2(2, q(2)))
438 allocate(bspl_d2(q(2), deg(2)+1))
442 call sll_s_uniform_bsplines_eval_basis(deg(2),xw_gauss_d2(1,k2), scratch(1:deg(2)+1))
443 bspl_d2(k2,:) = scratch(1:deg(2)+1)
446 allocate(xw_gauss_d3(2,q(3)))
447 allocate(bspl_d3(q(3), deg(3)+1 ))
451 call sll_s_uniform_bsplines_eval_basis(deg(3),xw_gauss_d3(1,k3), scratch(1:deg(3)+1) )
452 bspl_d3(k3,:) = scratch(1:deg(3)+1)
458 do i3 = 1, self%n_dofs(3)
459 do i2 = 1, self%n_dofs(2)
460 do i1 = 1, self%n_dofs(1)
468 c(3) = self%delta_x(3) * (xw_gauss_d3(1,k3) + real(i3 + j3 - 2, f64))
470 c(2) = self%delta_x(2) * (xw_gauss_d2(1,k2) + real(i2 + j2 - 2, f64))
472 c(1) = self%delta_x(1) * (xw_gauss_d1(1,k1) + real(i1 + j1 - 2, f64))
473 jacobian = self%map%jacobian( c )
474 jmatrix = self%map%jacobian_matrix_inverse_transposed( c )
475 coef = coef + xw_gauss_d1(2,k1)* xw_gauss_d2(2,k2)* xw_gauss_d3(2,k3) *&
476 ( func1( self%map%get_x(c) )*jmatrix(1,component) + &
477 func2( self%map%get_x(c) )*jmatrix(2,component) + &
478 func3( self%map%get_x(c) )*jmatrix(3,component)) * &
479 (bspl_d1(k1,deg(1)+2-j1)*&
480 bspl_d2(k2,deg(2)+2-j2)*&
481 bspl_d3(k3,deg(3)+2-j3)) * abs(jacobian)
489 coefs_dofs(counter) = coef*self%volume
499 subroutine rhs_twoform( self, deg, func1, func2, func3, component, coefs_dofs )
501 sll_int32,
intent( in ) :: deg(3)
505 sll_int32,
intent( in ) :: component
506 sll_real64,
intent( out ) :: coefs_dofs(:)
508 sll_int32 :: i1, i2, i3,j1, j2, j3, k1, k2, k3, q(3), counter
510 sll_real64 :: coef, jmatrix(3,3)
511 sll_real64,
allocatable :: xw_gauss_d1(:,:), xw_gauss_d2(:,:), xw_gauss_d3(:,:)
512 sll_real64,
allocatable :: bspl_d1(:,:), bspl_d2(:,:), bspl_d3(:,:)
513 sll_real64 :: scratch(maxval(deg+1))
518 allocate(xw_gauss_d1(2, q(1)))
519 allocate(bspl_d1(q(1), deg(1)+1 ))
523 call sll_s_uniform_bsplines_eval_basis(deg(1),xw_gauss_d1(1,k1), scratch(1:deg(1)+1))
524 bspl_d1(k1,:) = scratch(1:deg(1)+1)
527 allocate(xw_gauss_d2(2, q(2)))
528 allocate(bspl_d2(q(2), deg(2)+1))
532 call sll_s_uniform_bsplines_eval_basis(deg(2),xw_gauss_d2(1,k2), scratch(1:deg(2)+1))
533 bspl_d2(k2,:) = scratch(1:deg(2)+1)
536 allocate(xw_gauss_d3(2,q(3)))
537 allocate(bspl_d3(q(3), deg(3)+1 ))
541 call sll_s_uniform_bsplines_eval_basis(deg(3),xw_gauss_d3(1,k3), scratch(1:deg(3)+1) )
542 bspl_d3(k3,:) = scratch(1:deg(3)+1)
548 do i3 = 1, self%n_dofs(3)
549 do i2 = 1, self%n_dofs(2)
550 do i1 = 1, self%n_dofs(1)
558 c(3) = self%delta_x(3) * (xw_gauss_d3(1,k3) + real(i3 + j3 - 2, f64))
560 c(2) = self%delta_x(2) * (xw_gauss_d2(1,k2) + real(i2 + j2 - 2, f64))
562 c(1) = self%delta_x(1) * (xw_gauss_d1(1,k1) + real(i1 + j1 - 2, f64))
564 jmatrix = self%map%jacobian_matrix( c ) * sign( 1._f64, self%map%jacobian( c ) )
565 coef = coef + xw_gauss_d1(2,k1)* xw_gauss_d2(2,k2)* xw_gauss_d3(2,k3) *&
566 (func1( self%map%get_x(c) ) * jmatrix(1,component) + &
567 func2( self%map%get_x(c) ) * jmatrix(2,component) + &
568 func3( self%map%get_x(c) ) * jmatrix(3,component)) *&
569 (bspl_d1(k1,deg(1)+2-j1)*&
570 bspl_d2(k2,deg(2)+2-j2)*&
571 bspl_d3(k3,deg(3)+2-j3))
579 coefs_dofs(counter) = coef*self%volume
591 sll_int32,
intent( in ) :: deg(3)
593 sll_real64,
intent( out ) :: coefs_dofs(:)
596 sll_int32 :: i1, i2, i3,j1, j2, j3, k1, k2, k3, q(3), counter
597 sll_real64 :: coef, c(3)
598 sll_real64,
allocatable :: xw_gauss_d1(:,:), xw_gauss_d2(:,:), xw_gauss_d3(:,:)
599 sll_real64,
allocatable :: bspl_d1(:,:), bspl_d2(:,:), bspl_d3(:,:)
604 allocate(xw_gauss_d1(2, q(1)))
605 allocate(bspl_d1(q(1), deg(1)+1 ))
609 call sll_s_uniform_bsplines_eval_basis(deg(1),xw_gauss_d1(1,k1), bspl_d1(k1,:))
612 allocate(xw_gauss_d2(2, q(2)))
613 allocate(bspl_d2(q(2), deg(2)+1))
617 call sll_s_uniform_bsplines_eval_basis(deg(2),xw_gauss_d2(1,k2), bspl_d2(k2,:))
620 allocate(xw_gauss_d3(2,q(3)))
621 allocate(bspl_d3(q(3), deg(3)+1 ))
625 call sll_s_uniform_bsplines_eval_basis(deg(3),xw_gauss_d3(1,k3), bspl_d3(k3,:))
631 do i3 = 1, self%n_dofs(3)
632 do i2 = 1, self%n_dofs(2)
633 do i1 = 1, self%n_dofs(1)
641 c(3) = self%delta_x(3) * (xw_gauss_d3(1,k3) + real(i3 + j3 - 2, f64))
643 c(2) = self%delta_x(2) * (xw_gauss_d2(1,k2) + real(i2 + j2 - 2, f64))
645 c(1) = self%delta_x(1) * (xw_gauss_d1(1,k1) + real(i1 + j1 - 2, f64))
646 coef = coef + xw_gauss_d1(2,k1)* xw_gauss_d2(2,k2)* xw_gauss_d3(2,k3) *&
647 func(self%map%get_x(c) ) * &
648 bspl_d1(k1,deg(1)+2-j1)*&
649 bspl_d2(k2,deg(2)+2-j2)*&
650 bspl_d3(k3,deg(3)+2-j3)
658 coefs_dofs(counter) = coef*self%volume
670 sll_int32,
intent( in ) :: form
671 sll_int32,
intent( in ) :: component
672 sll_real64,
intent( out ) :: coefs_dofs(:)
677 if(
present(func2) .and.
present(func3) )
then
685 call self%mass1_solver%solve( self%work, coefs_dofs )
687 call self%mass2_solver%solve( self%work, coefs_dofs )
689 print*,
'L2projection for', form,
'-form not implemented.'
695 call self%mass0_solver%solve(self%work0, coefs_dofs)
697 print*,
'l2 projection not for single function or component implemented'
708 sll_real64 :: coefs(:)
710 sll_int32 :: component
721 sll_real64 :: coefs1(:)
722 sll_real64 :: coefs2(:)
724 sll_int32,
optional :: component
728 sll_int32 :: istart, iend
730 if ( form == 0 )
then
731 call self%multiply_mass( [form], coefs2, self%work0)
732 r = sum( coefs1*self%work0)
734 if (
present(component))
then
735 istart = 1+(component-1)*self%n_total
736 iend = component*self%n_total
742 r = sum(coefs1(istart:iend)*self%work(istart:iend))
749 subroutine init_3d_trafo( self, domain, n_dofs, s_deg_0, map, mass_tolerance, poisson_tolerance, solver_tolerance, adiabatic_electrons, profile )
751 sll_real64,
intent(in) :: domain(3,2)
752 sll_int32,
intent( in ) :: n_dofs(3)
753 sll_int32,
intent( in ) :: s_deg_0(3)
755 sll_real64,
intent(in),
optional :: mass_tolerance
756 sll_real64,
intent(in),
optional :: poisson_tolerance
757 sll_real64,
intent(in),
optional :: solver_tolerance
758 logical,
intent(in),
optional :: adiabatic_electrons
762 sll_int32 :: deg1(3), deg2(3)
763 sll_real64,
allocatable :: nullspace(:,:)
767 if (
present( mass_tolerance) )
then
768 self%mass_solver_tolerance = mass_tolerance
770 self%mass_solver_tolerance = 1d-12
772 if (
present( poisson_tolerance) )
then
773 self%poisson_solver_tolerance = poisson_tolerance
775 self%poisson_solver_tolerance = 1d-12
777 if (
present( solver_tolerance) )
then
778 self%solver_tolerance = solver_tolerance
780 self%solver_tolerance = 1d-12
783 if(
present( adiabatic_electrons ) )
then
784 self%adiabatic_electrons = adiabatic_electrons
787 if(
present( profile ) )
then
788 self%profile = profile
792 self%n_cells = n_dofs
794 self%n_total = product(n_dofs)
795 self%n_total0 = self%n_total
796 self%n_total1 = self%n_total
798 self%delta_x = 1._f64 / real(n_dofs,f64)
799 self%s_deg_0 = s_deg_0
800 self%s_deg_1 = s_deg_0 - 1
801 self%volume = product(self%delta_x)
804 allocate( self%work0(1:self%n_total) )
805 allocate( self%work(1:self%n_total*3) )
806 allocate( self%work2(1:self%n_total*3) )
811 if(self%adiabatic_electrons)
then
820 deg1(j)=self%s_deg_1(j)
824 deg1(j) = self%s_deg_0(j)
828 if(self%map%flag2d)
then
830 deg1(1)=self%s_deg_1(1)
832 deg2(2) = self%s_deg_1(2)
837 deg1(1) = self%s_deg_0(1)
839 deg2(2) = self%s_deg_0(2)
843 if(self%map%flag3d)
then
846 deg1(j)=self%s_deg_1(j)
848 deg2(modulo(j,3)+1) = self%s_deg_1(modulo(j,3)+1)
854 deg1(j) = self%s_deg_0(j)
856 deg2(modulo(j,3)+1) = self%s_deg_0(modulo(j,3)+1)
863 call self%mass1_operator%create( 3, 3 )
864 call self%mass2_operator%create( 3, 3 )
867 call self%mass1_operator%set( j, j, self%mass1(j,j) )
868 call self%mass2_operator%set( j, j, self%mass2(j,j) )
870 if(self%map%flag2d)
then
871 call self%mass1_operator%set( 1, 2, self%mass1(1, 2) )
872 call self%mass1_operator%set( 2, 1, self%mass1(2, 1) )
873 call self%mass2_operator%set( 1, 2, self%mass2(1, 2) )
874 call self%mass2_operator%set( 2, 1, self%mass2(2, 1) )
875 if(self%map%flag3d)
then
877 call self%mass1_operator%set( j, modulo(j,3)+1, self%mass1(j, modulo(j,3)+1) )
878 call self%mass1_operator%set( modulo(j,3)+1, j, self%mass1(modulo(j,3)+1, j) )
879 call self%mass2_operator%set( j, modulo(j,3)+1, self%mass2(j, modulo(j,3)+1) )
880 call self%mass2_operator%set( modulo(j,3)+1, j, self%mass2(modulo(j,3)+1, j) )
885 call self%preconditioner_fft%init( self%Lx, n_dofs, s_deg_0 )
886 call self%mass0_solver%create( self%mass0 )
887 call self%mass1_solver%create( self%mass1_operator, self%preconditioner_fft%inverse_mass1_3d)
888 call self%mass2_solver%create( self%mass2_operator, self%preconditioner_fft%inverse_mass2_3d)
889 self%mass1_solver%atol = self%mass_solver_tolerance/maxval(self%Lx)
890 self%mass2_solver%atol = self%mass_solver_tolerance/maxval(self%Lx)**2
894 call self%poisson_matrix%create( self%mass1_operator, self%n_dofs, self%delta_x )
896 allocate(nullspace(1,self%n_total))
897 nullspace(1,:) = 1.0_f64
898 call self%poisson_operator%create( self%poisson_matrix, nullspace(:,1:self%n_total), 1 )
900 call self%poisson_solver%create( self%poisson_operator )
901 self%poisson_solver%null_space = .true.
902 self%poisson_solver%atol = self%poisson_solver_tolerance
904 self%poisson_solver%n_maxiter=40000
907 call self%linear_op_schur_eb%create( self%mass1_operator, self%mass2_operator, self%n_total, self%n_dofs, self%delta_x )
908 call self%linear_solver_schur_eb%create( self%linear_op_schur_eb, self%preconditioner_fft%inverse_mass1_3d)
909 self%linear_solver_schur_eb%atol = self%solver_tolerance/maxval(self%Lx)
916 sll_real64,
intent(in) :: x(3)
917 sll_int32,
optional,
intent(in) :: component(:)
919 profile_m0 = self%map%jacobian( x ) * self%profile%rho_0( x(1) )/ self%profile%T_e( x(1) )
925 sll_real64,
intent(in) :: x(3)
926 sll_int32,
optional,
intent(in) :: component(:)
934 sll_real64,
intent(in) :: x(3)
935 sll_int32,
optional,
intent(in) :: component(:)
937 profile_1 = self%map%metric_inverse_single_jacobian( x, component(1), component(1) )
943 sll_real64,
intent(in) :: x(3)
944 sll_int32,
optional,
intent(in) :: component(:)
946 profile_2 = self%map%metric_single_jacobian( x, component(1), component(1) )
952 sll_real64,
intent(in) :: x(3)
953 sll_int32,
optional,
intent(in) :: component(:)
955 profile_m1 = self%map%metric_inverse_single_jacobian( x, component(1), component(2) )
960 sll_real64,
intent(in) :: x(3)
961 sll_int32,
optional,
intent(in) :: component(:)
963 profile_m2 = self%map%metric_single_jacobian( x, component(1), component(2) )
973 sll_real64,
intent(in) :: domain(3,2)
974 sll_int32,
intent( in ) :: n_dofs(3)
975 sll_int32,
intent( in ) :: s_deg_0(3)
977 character(len=*),
intent(in) :: nml_file
978 logical,
intent(in),
optional :: adiabatic_electrons
981 character(len=256) :: file_prefix
982 sll_int32 :: input_file
983 sll_int32 :: io_stat, io_stat0, io_stat1, rank, file_id
984 sll_real64 :: mass_tolerance
985 sll_real64 :: poisson_tolerance
986 sll_real64 :: maxwell_tolerance
988 namelist /output/ file_prefix
989 namelist /maxwell_solver/ mass_tolerance, poisson_tolerance
990 namelist /time_solver/ maxwell_tolerance
994 if(
present( adiabatic_electrons ) )
then
995 self%adiabatic_electrons = adiabatic_electrons
998 if(
present( profile ) )
then
999 self%profile = profile
1003 open(newunit = input_file, file=nml_file, status=
'old',iostat=io_stat)
1004 if (io_stat /= 0)
then
1005 if (rank == 0 )
then
1006 print*,
'sll_m_maxwell_3d_trafo: Input file does not exist. Set default tolerance.'
1007 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1008 write(file_id, *)
'mass solver tolerance:', 1d-12
1009 write(file_id, *)
'poisson solver tolerance:', 1d-12
1012 call self%init( domain, n_dofs, s_deg_0, map )
1014 read(input_file, output,iostat=io_stat0)
1015 read(input_file, maxwell_solver,iostat=io_stat)
1016 read(input_file, time_solver,iostat=io_stat1)
1017 if (io_stat /= 0 .and. io_stat1 /= 0)
then
1018 if (rank == 0 )
then
1019 print*,
'sll_m_maxwell_3d_trafo: Input parameter does not exist. Set default tolerance.'
1020 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1021 write(file_id, *)
'mass solver tolerance:', 1d-12
1022 write(file_id, *)
'poisson solver tolerance:', 1d-12
1025 call self%init( domain, n_dofs, s_deg_0, map )
1026 else if (io_stat /= 0 .and. io_stat1 == 0)
then
1027 call self%init( domain, n_dofs, s_deg_0, map, solver_tolerance=maxwell_tolerance)
1028 else if (io_stat == 0 .and. io_stat1 /= 0)
then
1029 if (rank == 0 )
then
1030 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1031 write(file_id, *)
'mass solver tolerance:', mass_tolerance
1032 write(file_id, *)
'poisson solver tolerance:', poisson_tolerance
1035 call self%init( domain, n_dofs, s_deg_0, map, mass_tolerance, poisson_tolerance )
1037 if (rank == 0 )
then
1038 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1039 write(file_id, *)
'mass solver tolerance:', mass_tolerance
1040 write(file_id, *)
'poisson solver tolerance:', poisson_tolerance
1043 call self%init( domain, n_dofs, s_deg_0, map, mass_tolerance, poisson_tolerance, maxwell_tolerance )
1055 call self%preconditioner_fft%free()
1056 call self%mass0_solver%free()
1057 call self%mass1_solver%free()
1058 call self%mass2_solver%free()
1059 call self%mass1_operator%free()
1060 call self%mass2_operator%free()
1061 call self%poisson_matrix%free()
1062 call self%poisson_solver%free()
1063 call self%poisson_operator%free()
1064 call self%linear_solver_schur_eb%free()
1065 call self%linear_op_schur_eb%free()
1066 deallocate(self%work0)
1067 deallocate(self%work)
1068 deallocate(self%work2)
1076 sll_real64,
intent( in ) :: field_in(:)
1077 sll_real64,
intent( out ) :: field_out(:)
1087 sll_real64,
intent( in ) :: field_in(:)
1088 sll_real64,
intent( out ) :: field_out(:)
1098 sll_real64,
intent( in ) :: field_in(:)
1099 sll_real64,
intent( out ) :: field_out(:)
1109 sll_real64,
intent( in ) :: field_in(:)
1110 sll_real64,
intent( out ) :: field_out(:)
1120 sll_int32,
intent( in ) :: deg(:)
1121 sll_real64,
intent( in ) :: coefs_in(:)
1122 sll_real64,
intent( out ) :: coefs_out(:)
1124 if(
size(deg) == 1 )
then
1125 sll_assert(deg(1)>=0 .and. deg(1)<=2)
1128 call self%mass0%dot( coefs_in, coefs_out )
1130 call self%mass1_operator%dot( coefs_in, coefs_out )
1132 call self%mass2_operator%dot( coefs_in, coefs_out )
1134 print*,
'multiply mass for other form not yet implemented'
1137 else if(
size(deg) == 3 )
then
1147 sll_int32,
intent( in ) :: form
1148 sll_real64,
intent( in ) :: coefs_in(:)
1149 sll_real64,
intent( out ) :: coefs_out(:)
1152 sll_assert(form>=0 .and. form<=2)
1155 call self%mass0_solver%solve( coefs_in, coefs_out )
1157 call self%mass1_solver%solve( coefs_in, coefs_out )
1159 call self%mass2_solver%solve( coefs_in, coefs_out )
1161 print*,
'multiply inverse mass for other form not yet implemented'
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 penalized linear operator
module for conjugate gradient method in pure form
Low level arbitrary degree splines.
Module interfaces for coordinate transformation.
module for Compressed Sparse Row Matrix (CSR)
Module interface to solve Maxwell's equations in 3D.
Module interface to solve Maxwell's equations with coordinate transformation in 3D.
subroutine rhs_zeroform(self, deg, func, coefs_dofs)
Compute $\int f(F(\xi)) N_i(\xi) J_F(\xi) d\xi$ for scalar function f, where $N_i$ is the B-spline st...
subroutine multiply_c(self, field_in, field_out)
Multiply by discrete curl matrix.
subroutine sll_s_compute_rhs_trafo(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 rhs_twoform(self, deg, func1, func2, func3, component, coefs_dofs)
Compute $\int f(F(\xi))\cdot DF(\xi) N_i(\xi) d\xi$ for vector function f, where $N_i$ is the B-splin...
subroutine sll_s_compute_phi_from_rho_3d_trafo(self, field_in, field_out, efield_dofs)
Compute phi from rho_i integrated over the time interval.
subroutine rhs_oneform(self, deg, func1, func2, func3, component, coefs_dofs)
Compute $\int f(F(\xi))\cdot DF^{-T}(\xi) N_i(\xi) J_F(\xi) d\xi$ for vector function f,...
subroutine free_3d_trafo(self)
Finalization.
real(kind=f64) function inner_product_3d_trafo(self, coefs1, coefs2, form, component)
Compute inner product.
subroutine rhs_threeform(self, deg, func, coefs_dofs)
Compute $\int f(F(\xi)) N_i(\xi) d\xi$ for scalar function f, where $N_i$ is the B-spline starting at...
subroutine sll_s_compute_rho_from_e_3d_trafo(self, field_in, field_out)
compute rho from e using weak Gauss law ( rho = G^T M_1 e )
subroutine multiply_g(self, field_in, field_out)
Multiply by dicrete gradient matrix.
subroutine sll_s_compute_curl_part_3d_trafo(self, delta_t, efield, bfield, betar)
Solve curl part of Maxwell's equations.
subroutine multiply_gt(self, field_in, field_out)
Multiply by transpose of dicrete gradient matrix.
real(kind=f64) function l2norm_squared_3d_trafo(self, coefs, form, component)
Compute square of the L2norm.
subroutine sll_s_compute_e_from_b_3d_trafo(self, delta_t, field_in, field_out)
compute E from B using weak Ampere formulation
subroutine sll_s_compute_e_from_j_3d_trafo(self, current, E, component)
Compute E_i from j_i integrated over the time interval using weak Ampere formulation,...
subroutine multiply_mass_inverse_trafo(self, form, coefs_in, coefs_out)
Multiply by the inverse mass matrix.
subroutine l2projection_3d_trafo(self, form, component, coefs_dofs, func1, func2, func3)
Compute the L2 projection of a given function f on periodic splines of given degree.
subroutine init_3d_trafo(self, domain, n_dofs, s_deg_0, map, mass_tolerance, poisson_tolerance, solver_tolerance, adiabatic_electrons, profile)
Initialization.
subroutine sll_s_compute_b_from_e_3d_trafo(self, delta_t, field_in, field_out)
Compute B from E using strong 3D Faraday equation for spline coefficients.
subroutine sll_s_compute_e_from_rho_3d_trafo(self, field_in, field_out)
Compute E_i from rho_i integrated over the time interval using weak Poisson's equation.
subroutine init_from_file_3d_trafo(self, domain, n_dofs, s_deg_0, map, nml_file, adiabatic_electrons, profile)
Initialization from nml file.
subroutine sll_s_compute_phi_from_j_3d_trafo(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_trafo(self, deg, coefs_in, coefs_out)
Multiply by the mass matrix.
subroutine multiply_ct(self, field_in, field_out)
Multiply by transpose of 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.
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)
real(kind=f64) function profile_0(x)
real(kind=f64) function profile_m0(x)
real(kind=f64) function profile_1(x)
real(kind=f64) function profile_m2(x, component)
real(kind=f64) function profile_2(x, component)
real(kind=f64) function profile_m1(x, component)
class for a linear operator_block
class for a linear operator_penalized
class for the cg linear solver
type collecting functions for analytical coordinate mapping