This routine builds up the matrix for least square fit used in quadratic interpolation. We extract momentum information completely on the view of the source coordinate system Set the right hand side of the equation system Solve the problem, where b = rhs, x = coefficients Ax = b overdetermined, solve the least Square fit problem (A^T)Ax = (A^T)b x = ((A^T)A)^-1(A^T)b Solve linear system of equation with inverted matrix. Size of matrix: (nCoeffs, QQ) matrix_LSF = ((A^T)A)^-1(A^T)
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_quadIntp(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 quadratic'
! 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,:) = polyQuadratic_1D( cxDirRK(:,iDir) )
end do
case (2)
do iSrc = 1, nSources
iDir = neighDir(iSrc)
tmp_matrix%A(iSrc,:) = polyQuadratic_2D( cxDirRK(:,iDir) )
end do
case (3)
do iSrc = 1, nSources
iDir = neighDir(iSrc)
tmp_matrix%A(iSrc,:) = polyQuadratic_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))
!write(*,*) 'Matrix_LSF '
!do iDir = 1, nCoeffs
! write(*,*) 'iDir ', iDir, me%A(iDir, :)
!end do
end subroutine build_matrixLSF_quadIntp