MODFLOW 6  version 6.7.0.dev2
USGS Modular Hydrologic Model
PseudoInverse.f90
Go to the documentation of this file.
2  use kindmodule, only: dp, i4b
3  use constantsmodule, only: dprec
4 
5  use svdmodule, only: svd
6 
7  implicit none
8  private
9 
10  public :: pinv
11 
12 contains
13 
14  !!> @brief Computes the Moore-Penrose pseudoinverse of a matrix using SVD.
15  !!
16  !! This function computes the pseudoinverse \‍(A^+\‍) of the input matrix \‍(A\‍) using
17  !! the singular value decomposition (SVD). Small singular values (less than `DPREC`)
18  !! are set to zero to improve numerical stability. The pseudoinverse is useful for
19  !! solving least-squares problems and for handling rank-deficient or non-square matrices.
20  !!
21  !! The result satisfies:
22  !! B = V * Sigma^+ * U^T
23  !! where \‍(A = U \Sigma V^T\‍) is the SVD of \‍(A\‍), and \‍(\Sigma^+\‍) is the diagonal matrix
24  !! with reciprocals of the nonzero singular values.
25  !<
26  function pinv(A) result(B)
27  ! -- dummy
28  real(dp), intent(in) :: a(:, :)
29  real(dp) :: b(size(a, dim=2), size(a, dim=1)) !! The pseudoinverse of A (size n x m, where A is m x n)
30  ! -- locals
31  integer(I4B) :: m, n
32  integer(I4B) :: pos
33  real(dp), dimension(:, :), allocatable :: u
34  real(dp), dimension(:, :), allocatable :: vt
35  real(dp), dimension(:, :), allocatable :: sigma
36 
37  m = size(a, dim=1)
38  n = size(a, dim=2)
39 
40  CALL svd(a, u, sigma, vt)
41 
42  ! Transform Sigma to its Sigma^+
43  do pos = 1, min(m, n)
44  if (dabs(sigma(pos, pos)) < dprec) then
45  sigma(pos, pos) = 0.0_dp
46  else
47  sigma(pos, pos) = 1.0_dp / sigma(pos, pos)
48  end if
49  end do
50 
51  b = matmul(transpose(vt), matmul(transpose(sigma), transpose(u)))
52 
53  end function pinv
54 
55 end module pseudoinversemodule
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dprec
real constant machine precision
Definition: Constants.f90:120
This module defines variable data types.
Definition: kind.f90:8
real(dp) function, dimension(size(a, dim=2), size(a, dim=1)), public pinv(A)
pure subroutine, public svd(A, U, S, VT)
Singular Value Decomposition.