MODULE module_positive_definite

  USE module_wrf_error      ! frame

CONTAINS


SUBROUTINE positive_definite_slab( f,                            &
                                   ids, ide, jds, jde, kds, kde, &
                                   ims, ime, jms, jme, kms, kme, &
                                   its, ite, jts, jte, kts, kte)

  IMPLICIT NONE

  ! Arguments
  INTEGER, INTENT(IN   ) :: ids, ide, jds, jde, kds, kde, &
                            ims, ime, jms, jme, kms, kme, &
                            its, ite, jts, jte, kts, kte
  REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(INOUT) :: f

  ! Local variables
  REAL, DIMENSION(:), ALLOCATABLE :: line
  INTEGER :: j, k, i_end, j_end, k_end
  REAL :: fmin, ftotal_pre, rftotal_post

  ! Initialize variables
  i_end = ide-1
  j_end = MIN(jte, jde-1)
  k_end = kte-1
  ! Only do anything if we have to...
  IF (ANY(f(ids:i_end,kts:k_end,jts:j_end) < 0.)) THEN
     ! number of points in the X direction, not including U-stagger
     ALLOCATE(line(ide-ids))
     DO j = jts, j_end
     DO k = kts, kte-1
        !while_lt_0_loop: DO WHILE (ANY(f(ids:i_end,k,j) < 0.))
        f_lt_0: IF (ANY(f(ids:i_end,k,j) < 0.)) THEN
           line(:) = f(ids:i_end,k,j)
           ! This is actually an integration over x assuming dx is constant
           ftotal_pre = SUM(line)
           ! If the total is negative, set everything to 0. and exit
           IF (ftotal_pre < 0.) THEN
              line(:) = 0.
           ELSE
              ! Value to add to array to make sure every element is > 0.
              fmin = MINVAL(line)
              line(:) = line(:) - fmin ! fmin is negative...
              rftotal_post = 1./SUM(line)
              line = line*ftotal_pre*rftotal_post
              ! The following error can naturally occur on 32-bit machines:
              !IF (SUM(line) /= ftotal_pre) THEN
              !   write(wrf_err_message,*) 'ERROR: module_positive_definite, ',&
              !                            'mismatching sums ',j,k,ftotal_pre,&
              !                            SUM(line),fmin,1./rftotal_post
              !   write(*,*) line
              !   CALL wrf_error_fatal( wrf_err_message )
              !END IF
           END IF
           f(ids:i_end,k,j) = line(:)
        END IF f_lt_0
        !END DO while_lt_0_loop
     END DO
     END DO
     DEALLOCATE(line)
  END IF

END SUBROUTINE positive_definite_slab

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


SUBROUTINE positive_definite_sheet( f, f_total, nx, ny )

  IMPLICIT NONE

  ! Arguments
  INTEGER, INTENT(IN   ) :: nx, ny
  REAL, DIMENSION( nx, ny ), INTENT(INOUT) :: f
  REAL, DIMENSION( ny ), INTENT(IN) :: f_total

  ! Local variables
  REAL, DIMENSION(:), ALLOCATABLE :: line
  INTEGER :: iy
  REAL :: fmin, rftotal_post, sum_line
  REAL, PARAMETER :: eps = 1.0e-15

  ! Only do anything if we have to...
  IF (ANY(f < 0.)) THEN
     ALLOCATE(line(nx))
     DO iy = 1, ny
        !while_lt_0_loop: DO WHILE (ANY(f(:,iy) < 0.))
        f_lt_0: IF (ANY(f(:,iy) < 0.)) THEN
           line(:) = f(:,iy)
           ! If the total is negative, set everything to 0. and exit
           IF (f_total(iy) < 0.) THEN
              line(:) = 0.
           ELSE
              ! Value to add to array to make sure every element is > 0.
              fmin = MINVAL(line)
              line(:) = line(:) - fmin ! fmin is negative...
              sum_line = SUM(line)
              IF(sum_line > eps) THEN
                rftotal_post = 1./sum_line
                line = line*f_total(iy)*rftotal_post
              ELSE
                line(:) = 0.
              END IF
              ! The following error can naturally occur on 32-bit machines:
              !IF (SUM(line) /= f_total(iy)) THEN
              !   write(wrf_err_message,*) 'ERROR: module_positive_definite, ',&
              !                            'mismatching sums ',iy,f_total(iy),  &
              !                            SUM(line),fmin,1./rftotal_post
              !   write(*,*) line
              !   CALL wrf_error_fatal( wrf_err_message )
              !END IF
           END IF
           f(:,iy) = line(:)
        END IF f_lt_0
        !END DO while_lt_0_loop
     END DO
     DEALLOCATE(line)
  END IF

END SUBROUTINE positive_definite_sheet

END MODULE module_positive_definite