Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_spline_matrix_dense.F90
Go to the documentation of this file.
1 
5 
7 
8 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 #include "sll_assert.h"
10 #include "sll_errors.h"
11 
12  use sll_m_working_precision, only: f64
13 
14  use sll_m_spline_matrix_base, only: &
16 
17  use iso_fortran_env, only: output_unit
18 
19  implicit none
20 
22 
23  private
24 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
25 
27  integer, parameter :: wp = f64
28 
29  !-----------------------------------------------------------------------------
31  !-----------------------------------------------------------------------------
33 
34  integer :: n
35  integer, allocatable :: ipiv(:)
36  real(wp), allocatable :: a(:, :)
37 
38  contains
39 
40  procedure :: init => s_spline_matrix_dense__init
41  procedure :: set_element => s_spline_matrix_dense__set_element
42  procedure :: factorize => s_spline_matrix_dense__factorize
43  procedure :: solve_inplace => s_spline_matrix_dense__solve_inplace
44  procedure :: write => s_spline_matrix_dense__write
45  procedure :: free => s_spline_matrix_dense__free
46 
48 
49  !-----------------------------------------------------------------------------
50  ! Interfaces to LAPACK subroutines (www.netlib.org/lapack)
51  !-----------------------------------------------------------------------------
52  interface
53 
54  ! LU factorization of a general M-by-N matrix A using partial pivoting
55  ! with row interchanges
56  subroutine dgetrf(m, n, a, lda, ipiv, info)
57  integer, intent(in) :: m ! number of rows
58  integer, intent(in) :: n ! number of columns
59  double precision, intent(inout) :: a(lda, n) ! M-by-N matrix
60  integer, intent(in) :: lda ! leading dimension of A
61  integer, intent(out) :: ipiv(min(m, n))! pivot indices
62  integer, intent(out) :: info ! 0 if successful
63  end subroutine dgetrf
64 
65  ! Solution of the linear system A*X=B or A^T*X=B with a general N-by-N
66  ! matrix A using the LU factorization computed by DGETRF
67  subroutine dgetrs(trans, n, nrhs, a, lda, ipiv, b, ldb, info)
68  character(len=1), intent(in) :: trans ! form of system of eqns.
69  integer, intent(in) :: n ! order of matrix A
70  integer, intent(in) :: nrhs ! no. of right hand sides
71  double precision, intent(in) :: a(lda, n) ! LU factors (A=P*L*U)
72  integer, intent(in) :: lda ! leading dimension of A
73  integer, intent(in) :: ipiv(n) ! pivot indices
74  double precision, intent(inout) :: b(ldb, nrhs) ! B on entry, X on exit
75  integer, intent(in) :: ldb ! leading dimension of B
76  integer, intent(out) :: info ! 0 if successful
77  end subroutine dgetrs
78 
79  end interface
80 
81 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
82 contains
83 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
84 
85  !-----------------------------------------------------------------------------
86  subroutine s_spline_matrix_dense__init(self, n)
87  class(sll_t_spline_matrix_dense), intent(out) :: self
88  integer, intent(in) :: n
89 
90  sll_assert(n > 0)
91 
92  self%n = n
93  allocate (self%ipiv(n))
94  allocate (self%a(n, n))
95  self%a(:, :) = 0.0_wp
96 
97  end subroutine s_spline_matrix_dense__init
98 
99  !-----------------------------------------------------------------------------
100  subroutine s_spline_matrix_dense__set_element(self, i, j, a_ij)
101  class(sll_t_spline_matrix_dense), intent(inout) :: self
102  integer, intent(in) :: i
103  integer, intent(in) :: j
104  real(wp), intent(in) :: a_ij
105 
106  self%a(i, j) = a_ij
107 
109 
110  !-----------------------------------------------------------------------------
112  class(sll_t_spline_matrix_dense), intent(inout) :: self
113 
114  integer :: info
115 
116  character(len=*), parameter :: &
117  this_sub_name = "sll_t_spline_matrix_dense % factorize"
118  character(len=256) :: err_msg
119 
120  sll_assert(size(self%a, 1) == self%n)
121  sll_assert(size(self%a, 2) == self%n)
122 
123  ! Perform LU decomposition using Lapack (A=PLU)
124  call dgetrf(self%n, self%n, self%a, self%n, self%ipiv, info)
125 
126  if (info < 0) then
127  write (err_msg, '(i0,a)') abs(info), "-th argument had an illegal value"
128  sll_error(this_sub_name, err_msg)
129  else if (info > 0) then
130  write (err_msg, "('U(',i0,',',i0,')',a)") info, info, &
131  " is exactly zero. The factorization has been completed, but the factor" &
132  //" U is exactly singular, and division by zero will occur if it is used to" &
133  //" solve a system of equations."
134  sll_error(this_sub_name, err_msg)
135  end if
136 
137  end subroutine s_spline_matrix_dense__factorize
138 
139  !-----------------------------------------------------------------------------
141  class(sll_t_spline_matrix_dense), intent(in) :: self
142  real(wp), intent(inout) :: bx(:)
143 
144  integer :: info
145 
146  character(len=*), parameter :: &
147  this_sub_name = "sll_t_spline_matrix_dense % solve_inplace"
148  character(len=256) :: err_msg
149 
150  sll_assert(size(self%a, 1) == self%n)
151  sll_assert(size(self%a, 2) == self%n)
152  sll_assert(size(bx) == self%n)
153 
154  ! Solve linear system PLU*x=b using Lapack
155  call dgetrs('N', self%n, 1, self%a, self%n, self%ipiv, bx, self%n, info)
156 
157  if (info < 0) then
158  write (err_msg, '(i0,a)') abs(info), "-th argument had an illegal value"
159  sll_error(this_sub_name, err_msg)
160  end if
161 
163 
164  !-----------------------------------------------------------------------------
165  subroutine s_spline_matrix_dense__write(self, unit, fmt)
166  class(sll_t_spline_matrix_dense), intent(in) :: self
167  integer, optional, intent(in) :: unit
168  character(len=*), optional, intent(in) :: fmt
169 
170  integer :: i
171  integer :: unit_loc
172  character(len=32) :: fmt_loc
173 
174  if (present(unit)) then
175  unit_loc = unit
176  else
177  unit_loc = output_unit
178  end if
179 
180  if (present(fmt)) then
181  fmt_loc = fmt
182  else
183  fmt_loc = 'es9.1'
184  end if
185 
186  write (fmt_loc, '(a)') "('(',i0,'"//trim(fmt_loc)//")')"
187  write (fmt_loc, fmt_loc) size(self%a, 2)
188 
189  do i = 1, size(self%a, 1)
190  write (unit_loc, fmt_loc) self%a(i, :)
191  end do
192 
193  end subroutine s_spline_matrix_dense__write
194 
195  !-----------------------------------------------------------------------------
197  class(sll_t_spline_matrix_dense), intent(inout) :: self
198 
199  self%n = -1
200  if (allocated(self%ipiv)) deallocate (self%ipiv)
201  if (allocated(self%a)) deallocate (self%a)
202 
203  end subroutine s_spline_matrix_dense__free
204 
205 end module sll_m_spline_matrix_dense
Abstract class for small matrix library with basic operations: set matrix element,...
Derived type for dense matrices.
subroutine s_spline_matrix_dense__solve_inplace(self, bx)
integer, parameter wp
Working precision.
subroutine s_spline_matrix_dense__init(self, n)
subroutine s_spline_matrix_dense__write(self, unit, fmt)
subroutine s_spline_matrix_dense__set_element(self, i, j, a_ij)
Module to select the kind parameter.
integer, parameter, public f64
f64 is the kind type for 64-bit reals (double precision)
    Report Typos and Errors