3 #include "sll_assert.h" 
   43       sll_pure 
function i_fun_rhs(x) 
result(rhs)
 
   45          real(
wp), 
intent(in) :: x(2)
 
   47       end function i_fun_rhs
 
   53       integer :: mm, n1, n2, ncells1, ncells2
 
   65       real(
wp), 
allocatable :: quad_points_eta1(:, :)
 
   66       real(
wp), 
allocatable :: quad_points_eta2(:, :)
 
   69       real(
wp), 
allocatable :: data_1d_eta1(:, :, :, :)
 
   70       real(
wp), 
allocatable :: data_1d_eta2(:, :, :, :)
 
   73       real(
wp), 
allocatable :: int_volume(:, :, :, :)
 
   74       real(
wp), 
allocatable :: inv_metric(:, :, :, :, :, :)
 
   75       real(
wp), 
allocatable :: data_2d_rhs(:, :, :, :)
 
   78       real(
wp), 
allocatable :: a(:, :)
 
   79       real(
wp), 
allocatable :: m(:, :)
 
   80       real(
wp), 
allocatable :: ap(:, :)
 
   81       real(
wp), 
allocatable :: mp(:, :)
 
   84       real(
wp), 
allocatable :: l(:, :)
 
   87       real(
wp), 
allocatable :: b(:)
 
   88       real(
wp), 
allocatable :: bp(:)
 
   91       real(
wp), 
allocatable :: x(:)
 
   92       real(
wp), 
allocatable :: xp(:)
 
  108       real(
wp) :: tol = 1.0e-14_wp  
 
  109       logical  :: verbose = .false. 
 
  119       generic   :: solve => solve_1, solve_2
 
  138       class(sll_c_bsplines), 
target, 
intent(in) :: bsplines_eta1
 
  139       class(sll_c_bsplines), 
target, 
intent(in) :: bsplines_eta2
 
  140       real(wp), 
allocatable, 
intent(in) :: breaks_eta1(:)
 
  141       real(wp), 
allocatable, 
intent(in) :: breaks_eta2(:)
 
  143       real(wp), 
optional, 
intent(in) :: tol
 
  144       logical, 
optional, 
intent(in) :: verbose
 
  150       real(wp), 
allocatable :: quad_weights_eta1(:, :)
 
  151       real(wp), 
allocatable :: quad_weights_eta2(:, :)
 
  154       integer  :: i, j, k, idx, k1, k2, q1, q2, p1, p2
 
  155       real(wp) :: cx, cy, jdet, eta(2), jmat(2, 2)
 
  157       if (
present(tol)) self%tol = tol
 
  158       if (
present(verbose)) self%verbose = verbose
 
  161       self%mapping => mapping
 
  164       call polar_bsplines%init(bsplines_eta1, bsplines_eta2, mapping)
 
  167       self%n1 = bsplines_eta1%nbasis
 
  168       self%n2 = bsplines_eta2%nbasis
 
  175       self%Nk1 = 
size(breaks_eta1) - 1
 
  176       self%Nk2 = 
size(breaks_eta2) - 1
 
  179       p1 = bsplines_eta1%degree
 
  180       p2 = bsplines_eta2%degree
 
  186       associate(n1 => self%n1, &
 
  188                  nn => 3 + (self%n1 - 2)*self%n2, &
 
  195          allocate (self%quad_points_eta1(nq1, nk1))
 
  196          allocate (self%quad_points_eta2(nq2, nk2))
 
  199          allocate (quad_weights_eta1(nq1, nk1))
 
  200          allocate (quad_weights_eta2(nq2, nk2))
 
  203          allocate (self%data_1d_eta1(nq1, 2, 1 + p1, nk1))
 
  204          allocate (self%data_1d_eta2(nq2, 2, 1 + p2, nk2))
 
  207          allocate (self%int_volume(nq1, nq2, nk1, nk2))
 
  208          allocate (self%inv_metric(nq1, nq2, nk1, nk2, 2, 2))
 
  209          allocate (self%data_2d_rhs(nq1, nq2, nk1, nk2))
 
  212          allocate (self%L(2*n2, 3))
 
  215          allocate (self%A(n1*n2, n1*n2))
 
  216          allocate (self%M(n1*n2, n1*n2))
 
  219          allocate (self%b(n1*n2))
 
  222          allocate (self%x(n1*n2))
 
  225          allocate (self%Ap(nn, nn))
 
  226          allocate (self%Mp(nn, nn))
 
  229          allocate (self%bp(nn))
 
  232          allocate (self%xp(nn))
 
  257                call bsplines_eta1%eval_basis_and_n_derivs( &
 
  258                   x=self%quad_points_eta1(q1, k1), &
 
  260                   derivs=self%data_1d_eta1(q1, :, :, k1), &
 
  268                call bsplines_eta2%eval_basis_and_n_derivs( &
 
  269                   x=self%quad_points_eta2(q2, k2), &
 
  271                   derivs=self%data_1d_eta2(q2, :, :, k2), &
 
  286                      eta = [self%quad_points_eta1(q1, k1), self%quad_points_eta2(q2, k2)]
 
  288                      jdet = mapping%jdet(eta)
 
  289                      jmat = mapping%jmat(eta)
 
  292                      self%int_volume(q1, q2, k1, k2) = abs(jdet)*quad_weights_eta1(q1, k1)*quad_weights_eta2(q2, k2)
 
  295                      self%inv_metric(q1, q2, k1, k2, 1, 1) = jmat(1, 2)**2 + jmat(2, 2)**2
 
  296                      self%inv_metric(q1, q2, k1, k2, 1, 2) = -jmat(1, 1)*jmat(1, 2) - jmat(2, 1)*jmat(2, 2)
 
  297                      self%inv_metric(q1, q2, k1, k2, 2, 1) = self%inv_metric(q1, q2, k1, k2, 1, 2) 
 
  298                      self%inv_metric(q1, q2, k1, k2, 2, 2) = jmat(1, 1)**2 + jmat(2, 1)**2
 
  299                      self%inv_metric(q1, q2, k1, k2, :, :) = self%inv_metric(q1, q2, k1, k2, :, :)/jdet**2
 
  314             k = modulo((i - 1), n2) + 1
 
  316             cx = mapping%spline_2d_x1%bcoef(j, k)
 
  317             cy = mapping%spline_2d_x2%bcoef(j, k)
 
  319             self%L(i, 1) = polar_bsplines%eval_l0(cx, cy)
 
  320             self%L(i, 2) = polar_bsplines%eval_l1(cx, cy)
 
  321             self%L(i, 3) = polar_bsplines%eval_l2(cx, cy)
 
  329          call self%assembler%init(n1, n2, self%weak_form)
 
  330          call self%projector%init(n1, n2, self%L)
 
  342                call self%assembler%add_element_mat( &
 
  358          call self%projector%change_basis_matrix(self%A, self%Ap)
 
  359          call self%projector%change_basis_matrix(self%M, self%Mp)
 
  365          idx = 3 + (n1 - 3)*n2
 
  368          call self%Ap_linop%init(idx, idx)
 
  369          self%Ap_linop%A = self%Ap(:idx, :idx)
 
  373          allocate (self%xp_vecsp%array(
size(self%xp(:idx))), source=self%xp(:idx))
 
  376          call self%cjsolver%init( &
 
  378             verbose=self%verbose, &
 
  379             template_vector=self%xp_vecsp)
 
  383       call polar_bsplines%free()
 
  390       procedure(i_fun_rhs)                                 :: rhs
 
  391       type(sll_t_spline_2d), 
intent(inout) :: sol
 
  394       integer  :: idx, k1, k2, q1, q2
 
  395       real(wp) :: eta(2), x(2)
 
  397       associate(n1 => self%n1, &
 
  399                  nn => 3 + (self%n1 - 2)*self%n2, &
 
  411                      eta = [self%quad_points_eta1(q1, k1), self%quad_points_eta2(q2, k2)]
 
  413                      x = self%mapping%eval(eta)
 
  415                      self%data_2d_rhs(q1, q2, k1, k2) = rhs(x)
 
  431                call self%assembler%add_element_rhs( &
 
  446          call self%projector%change_basis_vector(self%b, self%bp)
 
  452          idx = 3 + (n1 - 3)*n2
 
  455          allocate (self%bp_vecsp%array(
size(self%bp(:idx))), source=self%bp(:idx))
 
  458          call self%cjsolver%solve( &
 
  464          self%xp(:idx) = self%xp_vecsp%array
 
  470          call self%projector%change_basis_vector_inv(self%xp, self%x)
 
  472          sol%bcoef = reshape(self%x, (/n2, n1/))
 
  481       type(sll_t_spline_2d), 
intent(in) :: rhs
 
  482       type(sll_t_spline_2d), 
intent(inout) :: sol
 
  484       integer :: idx, i, i1, i2
 
  486       associate(n1 => self%n1, n2 => self%n2)
 
  492                self%b(i) = rhs%bcoef(i1, i2)
 
  497          self%b = matmul(self%M, self%b)
 
  500          call self%projector%change_basis_vector(self%b, self%bp)
 
  506          idx = 3 + (n1 - 3)*n2
 
  509          allocate (self%bp_vecsp%array(
size(self%bp(:idx))), source=self%bp(:idx))
 
  512          call self%cjsolver%solve( &
 
  518          self%xp(:idx) = self%xp_vecsp%array
 
  524          call self%projector%change_basis_vector_inv(self%xp, self%x)
 
  526          sol%bcoef = reshape(self%x, (/n2, n1/))
 
  536       deallocate (self%quad_points_eta1)
 
  537       deallocate (self%quad_points_eta2)
 
  538       deallocate (self%data_1d_eta1)
 
  539       deallocate (self%data_1d_eta2)
 
  540       deallocate (self%int_volume)
 
  541       deallocate (self%inv_metric)
 
  550       call self%projector%free()
 
  552       call self%cjsolver%free()
 
  553       call self%Ap_linop%free()
 
  554       deallocate (self%bp_vecsp%array)
 
  555       deallocate (self%xp_vecsp%array)
 
Access point to B-splines of arbitrary degree providing factory function.
 
Gauss-Legendre integration.
 
real(kind=f64) function, dimension(1:npoints), public sll_f_gauss_legendre_points(npoints, a, b)
 
real(kind=f64) function, dimension(1:npoints), public sll_f_gauss_legendre_weights(npoints, a, b)
 
subroutine s_poisson_2d_fem_sps_dense__init(self, bsplines_eta1, bsplines_eta2, breaks_eta1, breaks_eta2, mapping, tol, verbose)
 
subroutine s_poisson_2d_fem_sps_dense__free(self)
 
subroutine s_poisson_2d_fem_sps_dense__solve_2(self, rhs, sol)
 
subroutine s_poisson_2d_fem_sps_dense__solve_1(self, rhs, sol)
 
Module for tensor-product 2D splines.
 
Vector space for wrapping 1D Fortran real arrays.
 
Module to select the kind parameter.
 
integer, parameter, public f64
f64 is the kind type for 64-bit reals (double precision)
 
Type containing new 2D polar basis functions.
 
Concrete type, discrete singular mapping.
 
Vector space for wrapping 1D Fortran real arrays.