This routine builds up the matrix for least square fit used in linear interpolation.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(tem_matrix_type), | intent(out) | :: | me |
Matrix to fill |
||
integer, | intent(in) | :: |
Number of stencil directions |
|||
integer, | intent(in) | :: | nDims |
Number of dimensions |
||
integer, | intent(in) | :: | nSources |
Number of sources from coarser found |
||
real(kind=rk), | intent(in) | :: | cxDirRK(3,QQ) |
Stencil directions |
||
integer, | intent(in) | :: | neighDir(nSources) |
direction in which sources are found |
||
integer, | intent(in) | :: | nCoeffs |
nUnknown coeffs |
||
logical, | intent(out) | :: | success |
success if false if matrix is singular reduce interpolation order |
subroutine build_matrixLSF_linearIntp(me, QQ, nDims, nSources, cxDirRK, &
& neighDir, nCoeffs, success)
! --------------------------------------------------------------------------
!> Matrix to fill
type(tem_matrix_type), intent(out) :: me
!> Number of stencil directions
integer, intent(in) :: QQ
!> Number of dimensions
integer, intent(in) :: nDims
!> Number of sources from coarser found
integer, intent(in) :: nSources
!> Stencil directions
real(kind=rk), intent(in) :: cxDirRK(3,QQ)
!> direction in which sources are found
integer, intent(in) :: neighDir(nSources)
!> nUnknown coeffs
integer, intent(in) :: nCoeffs
!> success if false if matrix is singular reduce interpolation order
logical, intent(out) :: success
! --------------------------------------------------------------------------
integer :: iDir, iSrc
!> Each row represents a polynomial evaluated at coord of elements in
! stencil directions
type(tem_matrix_type) :: tmp_matrix
real(kind=rk) :: inv_AtA(nCoeffs,nCoeffs), AtA(nCoeffs,nCoeffs)
integer :: errCode
! --------------------------------------------------------------------------
write(dbgUnit(4),"(A)") 'Inside build least square fit matrix for linear'
! me%A = ((A^T)A)^-1*(A^T)
! inv_AtA = ((A^T)A)^-1
call alloc_matrix(tmp_matrix, nSources, nCoeffs)
select case(nDims)
case (1)
do iSrc = 1, nSources
iDir = neighDir(iSrc)
tmp_matrix%A(iSrc,:) = polyLinear_1D( cxDirRK(:,iDir) )
end do
case (2)
do iSrc = 1, nSources
iDir = neighDir(iSrc)
tmp_matrix%A(iSrc,:) = polyLinear_2D( cxDirRK(:,iDir) )
end do
case (3)
do iSrc = 1, nSources
iDir = neighDir(iSrc)
tmp_matrix%A(iSrc,:) = polyLinear_3D( cxDirRK(:,iDir) )
end do
case default
write(logUnit(1),*) 'Unknown nDims for quadratic interpolation'
call tem_abort()
end select
write(dbgUnit(4),"(A)") ' tmp matrix:'
call tem_matrix_dump(tmp_matrix, dbgUnit(4))
flush(dbgUnit(4))
AtA = matmul( transpose(tmp_matrix%A), tmp_matrix%A)
inv_AtA = invert_matrix(AtA, errCode)
if (errCode == 0) then
! matrix_LSF size is transpose of tmp_matrix
call alloc_matrix(me, nCoeffs, nSources)
me%A = matmul( inv_AtA, transpose(tmp_matrix%A) )
success = .true.
else
! singular matrix, reduce interpolation order
call alloc_matrix(me, 1, 1)
success = .false.
return
end if
write(dbgUnit(4),"(A)") ' Matrix LSF:'
call tem_matrix_dump(me, dbgUnit(4))
flush(dbgUnit(4))
end subroutine build_matrixLSF_linearIntp