regr_conserv_m.f90 Source File


This file depends on

sourcefile~~regr_conserv_m.f90~~EfferentGraph sourcefile~regr_conserv_m.f90 regr_conserv_m.f90 sourcefile~assert_eq_m.f90 assert_eq_m.f90 sourcefile~regr_conserv_m.f90->sourcefile~assert_eq_m.f90 sourcefile~interpolation.f90 interpolation.f90 sourcefile~regr_conserv_m.f90->sourcefile~interpolation.f90 sourcefile~assert_m.f90 assert_m.f90 sourcefile~regr_conserv_m.f90->sourcefile~assert_m.f90

Files dependent on this one

sourcefile~~regr_conserv_m.f90~~AfferentGraph sourcefile~regr_conserv_m.f90 regr_conserv_m.f90 sourcefile~regr_pr_o3_m.f90 regr_pr_o3_m.f90 sourcefile~regr_pr_o3_m.f90->sourcefile~regr_conserv_m.f90 sourcefile~regr_lat_time_coefoz_m.f90~2 regr_lat_time_coefoz_m.f90 sourcefile~regr_lat_time_coefoz_m.f90~2->sourcefile~regr_conserv_m.f90 sourcefile~regr_lat_time_coefoz_m.f90 regr_lat_time_coefoz_m.f90 sourcefile~regr_lat_time_coefoz_m.f90->sourcefile~regr_conserv_m.f90 sourcefile~regr_horiz_time_climoz_m.f90 regr_horiz_time_climoz_m.f90 sourcefile~regr_horiz_time_climoz_m.f90->sourcefile~regr_conserv_m.f90 sourcefile~regr_pr_o3_m.f90~2 regr_pr_o3_m.f90 sourcefile~regr_pr_o3_m.f90~2->sourcefile~regr_conserv_m.f90 sourcefile~regr_pr_time_av_m.f90 regr_pr_time_av_m.f90 sourcefile~regr_pr_time_av_m.f90->sourcefile~regr_conserv_m.f90 sourcefile~regr_pr_time_av_m.f90~2 regr_pr_time_av_m.f90 sourcefile~regr_pr_time_av_m.f90~2->sourcefile~regr_conserv_m.f90 sourcefile~regr_horiz_time_climoz_m.f90~2 regr_horiz_time_climoz_m.f90 sourcefile~regr_horiz_time_climoz_m.f90~2->sourcefile~regr_conserv_m.f90 sourcefile~etat0dyn_netcdf.f90 etat0dyn_netcdf.F90 sourcefile~etat0dyn_netcdf.f90->sourcefile~regr_pr_o3_m.f90 sourcefile~etat0dyn_netcdf.f90->sourcefile~regr_lat_time_coefoz_m.f90 sourcefile~physiq_mod.f90 physiq_mod.F90 sourcefile~physiq_mod.f90->sourcefile~regr_horiz_time_climoz_m.f90 sourcefile~physiq_mod.f90->sourcefile~regr_pr_time_av_m.f90 sourcefile~phytrac_mod.f90 phytrac_mod.f90 sourcefile~physiq_mod.f90->sourcefile~phytrac_mod.f90 sourcefile~phyetat0_mod.f90 phyetat0_mod.F90 sourcefile~physiq_mod.f90->sourcefile~phyetat0_mod.f90 sourcefile~phys_output_write_mod.f90 phys_output_write_mod.F90 sourcefile~physiq_mod.f90->sourcefile~phys_output_write_mod.f90 sourcefile~physiqex_mod.f90 physiqex_mod.F90 sourcefile~physiq_mod.f90->sourcefile~physiqex_mod.f90 sourcefile~diag_slp.f90 diag_slp.f90 sourcefile~physiq_mod.f90->sourcefile~diag_slp.f90 sourcefile~phys_output_mod.f90 phys_output_mod.F90 sourcefile~physiq_mod.f90->sourcefile~phys_output_mod.f90 sourcefile~regr_pr_comb_coefoz_m.f90~2 regr_pr_comb_coefoz_m.f90 sourcefile~regr_pr_comb_coefoz_m.f90~2->sourcefile~regr_pr_time_av_m.f90 sourcefile~regr_pr_comb_coefoz_m.f90 regr_pr_comb_coefoz_m.f90 sourcefile~regr_pr_comb_coefoz_m.f90->sourcefile~regr_pr_time_av_m.f90 sourcefile~etat0phys_netcdf.f90 etat0phys_netcdf.f90 sourcefile~etat0phys_netcdf.f90->sourcefile~regr_horiz_time_climoz_m.f90 sourcefile~physiq_mod.f90~2 physiq_mod.F90 sourcefile~physiq_mod.f90~2->sourcefile~regr_horiz_time_climoz_m.f90 sourcefile~physiq_mod.f90~2->sourcefile~regr_pr_time_av_m.f90 sourcefile~physiq_mod.f90~2->sourcefile~phytrac_mod.f90 sourcefile~physiq_mod.f90~2->sourcefile~phyetat0_mod.f90 sourcefile~physiq_mod.f90~2->sourcefile~phys_output_write_mod.f90 sourcefile~physiq_mod.f90~2->sourcefile~physiqex_mod.f90 sourcefile~physiq_mod.f90~2->sourcefile~diag_slp.f90 sourcefile~physiq_mod.f90~2->sourcefile~phys_output_mod.f90 sourcefile~old_lmdz1d.f90 old_lmdz1d.f90 sourcefile~old_lmdz1d.f90->sourcefile~physiq_mod.f90 sourcefile~traclmdz_mod.f90 traclmdz_mod.f90 sourcefile~traclmdz_mod.f90->sourcefile~regr_pr_comb_coefoz_m.f90 sourcefile~o3_chem_m.f90 o3_chem_m.f90 sourcefile~traclmdz_mod.f90->sourcefile~o3_chem_m.f90 sourcefile~traclmdz_mod.f90~2 traclmdz_mod.f90 sourcefile~traclmdz_mod.f90~2->sourcefile~regr_pr_comb_coefoz_m.f90 sourcefile~traclmdz_mod.f90~2->sourcefile~o3_chem_m.f90 sourcefile~ce0l.f90 ce0l.F90 sourcefile~ce0l.f90->sourcefile~etat0dyn_netcdf.f90 sourcefile~ce0l.f90->sourcefile~etat0phys_netcdf.f90 sourcefile~callphysiq_mod.f90~2 callphysiq_mod.f90 sourcefile~callphysiq_mod.f90~2->sourcefile~physiq_mod.f90 sourcefile~o3_chem_m.f90->sourcefile~regr_pr_comb_coefoz_m.f90 sourcefile~o3_chem_m.f90~2 o3_chem_m.f90 sourcefile~o3_chem_m.f90~2->sourcefile~regr_pr_comb_coefoz_m.f90 sourcefile~scm.f90 scm.f90 sourcefile~scm.f90->sourcefile~physiq_mod.f90 sourcefile~callphysiq_mod.f90 callphysiq_mod.f90 sourcefile~callphysiq_mod.f90->sourcefile~physiq_mod.f90 sourcefile~lsc_scav.f90 lsc_scav.f90 sourcefile~lsc_scav.f90->sourcefile~traclmdz_mod.f90 sourcefile~lsc_scav_orig.f90~2 lsc_scav_orig.f90 sourcefile~lsc_scav_orig.f90~2->sourcefile~traclmdz_mod.f90 sourcefile~calfis.f90 calfis.f90 sourcefile~calfis.f90->sourcefile~callphysiq_mod.f90 sourcefile~phytrac_mod.f90->sourcefile~traclmdz_mod.f90 sourcefile~cltracrn.f90~2 cltracrn.f90 sourcefile~cltracrn.f90~2->sourcefile~traclmdz_mod.f90 sourcefile~phyredem.f90 phyredem.F90 sourcefile~phyredem.f90->sourcefile~traclmdz_mod.f90 sourcefile~initrrnpb.f90 initrrnpb.f90 sourcefile~initrrnpb.f90->sourcefile~traclmdz_mod.f90 sourcefile~lsc_scav_orig.f90 lsc_scav_orig.f90 sourcefile~lsc_scav_orig.f90->sourcefile~traclmdz_mod.f90 sourcefile~phyetat0_mod.f90->sourcefile~traclmdz_mod.f90 sourcefile~radio_decay.f90 radio_decay.f90 sourcefile~radio_decay.f90->sourcefile~traclmdz_mod.f90 sourcefile~initrrnpb.f90~2 initrrnpb.f90 sourcefile~initrrnpb.f90~2->sourcefile~traclmdz_mod.f90 sourcefile~lsc_scav_spl.f90 lsc_scav_spl.f90 sourcefile~lsc_scav_spl.f90->sourcefile~traclmdz_mod.f90 sourcefile~phytrac_mod.f90~2 phytrac_mod.f90 sourcefile~phytrac_mod.f90~2->sourcefile~traclmdz_mod.f90 sourcefile~radio_decay.f90~2 radio_decay.f90 sourcefile~radio_decay.f90~2->sourcefile~traclmdz_mod.f90 sourcefile~lsc_scav_spl.f90~2 lsc_scav_spl.f90 sourcefile~lsc_scav_spl.f90~2->sourcefile~traclmdz_mod.f90 sourcefile~lsc_scav.f90~2 lsc_scav.f90 sourcefile~lsc_scav.f90~2->sourcefile~traclmdz_mod.f90 sourcefile~cltracrn.f90 cltracrn.f90 sourcefile~cltracrn.f90->sourcefile~traclmdz_mod.f90 sourcefile~phys_output_write_mod.f90->sourcefile~phytrac_mod.f90 sourcefile~physiqex_mod.f90~2 physiqex_mod.F90 sourcefile~physiqex_mod.f90~2->sourcefile~phyetat0_mod.f90 sourcefile~phys_output_write_mod.f90~2 phys_output_write_mod.F90 sourcefile~phys_output_write_mod.f90~2->sourcefile~phytrac_mod.f90 sourcefile~physiqex_mod.f90->sourcefile~phyetat0_mod.f90 sourcefile~diag_slp.f90->sourcefile~phys_output_write_mod.f90 sourcefile~phys_output_mod.f90->sourcefile~phys_output_write_mod.f90 sourcefile~phys_output_mod.f90~2 phys_output_mod.F90 sourcefile~phys_output_mod.f90~2->sourcefile~phys_output_write_mod.f90 sourcefile~diag_slp.f90~2 diag_slp.f90 sourcefile~diag_slp.f90~2->sourcefile~phys_output_write_mod.f90 sourcefile~recmwf_aero.f90 recmwf_aero.F90 sourcefile~recmwf_aero.f90->sourcefile~phys_output_mod.f90 sourcefile~recmwf_aero.f90~2 recmwf_aero.F90 sourcefile~recmwf_aero.f90~2->sourcefile~phys_output_mod.f90 sourcefile~sw_aeroar4.f90 sw_aeroAR4.f90 sourcefile~sw_aeroar4.f90->sourcefile~phys_output_mod.f90 sourcefile~sw_aeroar4.f90~2 sw_aeroAR4.f90 sourcefile~sw_aeroar4.f90~2->sourcefile~phys_output_mod.f90

Contents

Source Code


Source Code

MODULE regr_conserv_m

  USE assert_eq_m,   ONLY: assert_eq
  USE assert_m,      ONLY: assert
  USE interpolation, ONLY: locate

  IMPLICIT NONE

! Purpose: Each procedure regrids a piecewise linear function (not necessarily
!          continuous) by averaging it. This is a conservative regridding.
!          The regridding operation is done along dimension "ix" of the input
!          field "vs". Input are positions of cell edges.
! Remarks:
!   * The target grid should be included in the source grid:
!     no extrapolation is allowed.
!   * Field on target grid "vt" has same rank, slopes and averages as "vs".
!   * If optional argument "slope" is not given, 0 is assumed for slopes.
!     Then the regridding is first order instead of second.
!   * "vs" and "vt" have the same dimensions except Nr. ix (ns for vs, nt for vt)

! Argument                         Type         Description
!-------------------------------------------------------------------------------
!  INTEGER, INTENT(IN)  :: ix      Scalar       dimension regridded <=rank(vs)
!  REAL,    INTENT(IN)  :: vs(*)   Rank>=1      averages in source grid cells
!  REAL,    INTENT(IN)  :: xs(:)   Vector(ns+1) edges of source grid, asc. order
!  REAL,    INTENT(IN)  :: xt(:)   Vector(nt+1) edges of target grid, asc. order
!  REAL,    INTENT(OUT) :: vt(*)   Rank>=1      regridded field
! [REAL,    INTENT(IN)  :: slope]  Rank>=1      slopes in source grid cells

  INTERFACE regr_conserv
    ! The procedures differ only from the rank of the input/output fields.
    MODULE PROCEDURE regr1_conserv, regr2_conserv, regr3_conserv, &
                     regr4_conserv, regr5_conserv
  END INTERFACE

  PRIVATE
  PUBLIC :: regr_conserv

CONTAINS

!-------------------------------------------------------------------------------
!
SUBROUTINE regr1_conserv(ix, vs, xs, xt, vt, slope)
!
!-------------------------------------------------------------------------------
! Arguments:
  INTEGER,        INTENT(IN)  :: ix
  REAL,           INTENT(IN)  :: vs(:)
  REAL,           INTENT(IN)  :: xs(:), xt(:)
  REAL,           INTENT(OUT) :: vt(:)
  REAL, OPTIONAL, INTENT(IN)  :: slope(:)
!-------------------------------------------------------------------------------
! Local variables:
  INTEGER :: is, it, ns, nt
  REAL    :: co, idt
  LOGICAL :: lslope
!-------------------------------------------------------------------------------
  lslope=PRESENT(slope)
  CALL check_size(ix,SHAPE(vs),SHAPE(vt),xs,xt,ns,nt)
  is=locate(xs,xt(1))                    !--- 1<= is <= ns (no extrapolation)
  vt(:)=0.
  DO it=1, nt; idt=1./(xt(it+1)-xt(it))
    IF(xt(it+1)<=xs(is+1)) THEN          !--- xs(is)<=xt(it)<=xt(it+1)<=xs(is+1)
      CALL mean_lin(xt(it),xt(it+1))
    ELSE
      CALL mean_lin(xt(it),xs(is+1)); is=is+1
      DO WHILE(xs(is+1)<xt(it+1))        !--- 1<=is<=ns-1
      CALL mean_lin(xs(is),xs(is+1)); is=is+1
      END DO
      CALL mean_lin(xs(is),xt(it+1))     !--- 1<=is<=ns
    END IF
    IF(xs(is+1)==xt(it+1)) is=is+1       !--- 1<=is<=ns .OR. it==nt
  END DO

CONTAINS

!-------------------------------------------------------------------------------
SUBROUTINE mean_lin(a,b)  ! mean [a,b] of the linear function in [xs(is),xs(is+1)]
!-------------------------------------------------------------------------------
! Arguments:
  REAL, INTENT(IN)    :: a, b
!-------------------------------------------------------------------------------
  IF(lslope.AND.(a/=xs(is).OR.b/=xs(is+1))) THEN; co=0.
    IF(a==xt(it  )) co=co+xt(it  )-xs(is  )
    IF(b==xt(it+1)) co=co+xt(it+1)-xs(is+1)
    vt(it) = vt(it)+idt*(b-a)*(vs(is)+co*slope(is)/2.)
  ELSE
    vt(it) = vt(it)+idt*(b-a)* vs(is)
  END IF

END SUBROUTINE mean_lin
!-------------------------------------------------------------------------------

END SUBROUTINE regr1_conserv
!
!-------------------------------------------------------------------------------


!-------------------------------------------------------------------------------
!
SUBROUTINE regr2_conserv(ix, vs, xs, xt, vt, slope)
!
!-------------------------------------------------------------------------------
! Arguments:
  INTEGER,        INTENT(IN)  :: ix
  REAL,           INTENT(IN)  :: vs(:,:)
  REAL,           INTENT(IN)  :: xs(:), xt(:)
  REAL,           INTENT(OUT) :: vt(:,:)
  REAL, OPTIONAL, INTENT(IN)  :: slope(:,:)
!-------------------------------------------------------------------------------
! Local variables:
  INTEGER :: is, it, ns, nt
  REAL    :: co, idt
  LOGICAL :: lslope
!-------------------------------------------------------------------------------
  lslope=PRESENT(slope)
  CALL check_size(ix,SHAPE(vs),SHAPE(vt),xs,xt,ns,nt)
  is=locate(xs,xt(1)) ! 1 <= is <= ns, because we forbid extrapolation
  vt(:,:)=0.
  DO it=1, nt; idt=1./(xt(it+1)-xt(it))
    IF(xt(it+1)<=xs(is+1)) THEN          !--- xs(is)<=xt(it)<=xt(it+1)<=xs(is+1)
      CALL mean_lin(xt(it),xt(it+1))
    ELSE
      CALL mean_lin(xt(it),xs(is+1)); is=is+1
      DO WHILE(xs(is+1)<xt(it+1))        !--- 1<=is<=ns-1
      CALL mean_lin(xs(is),xs(is+1)); is=is+1
      END DO
      CALL mean_lin(xs(is),xt(it+1))     !--- 1<=is<=ns
    END IF
    IF(xs(is+1)==xt(it+1)) is=is+1       !--- 1<=is<=ns .OR. it==nt
  END DO

CONTAINS

!-------------------------------------------------------------------------------
SUBROUTINE mean_lin(a,b)  ! mean [a,b] of the linear function in [xs(is),xs(is+1)]
!-------------------------------------------------------------------------------
! Arguments:
  REAL, INTENT(IN)    :: a, b
!-------------------------------------------------------------------------------
  IF(lslope.AND.(a/=xs(is).OR.b/=xs(is+1))) THEN; co=0.
    IF(a==xt(it  )) co=co+xt(it  )-xs(is  )
    IF(b==xt(it+1)) co=co+xt(it+1)-xs(is+1)
    IF(ix==1) vt(it,:) = vt(it,:)+idt*(b-a)*(vs(is,:)+co*slope(is,:)/2.)
    IF(ix==2) vt(:,it) = vt(:,it)+idt*(b-a)*(vs(:,is)+co*slope(:,is)/2.)
  ELSE
    IF(ix==1) vt(it,:) = vt(it,:)+idt*(b-a)* vs(is,:)
    IF(ix==2) vt(:,it) = vt(:,it)+idt*(b-a)* vs(:,is)
  END IF

END SUBROUTINE mean_lin
!-------------------------------------------------------------------------------

END SUBROUTINE regr2_conserv
!
!-------------------------------------------------------------------------------


!-------------------------------------------------------------------------------
!
SUBROUTINE regr3_conserv(ix, vs, xs, xt, vt, slope)
!
!-------------------------------------------------------------------------------
! Arguments:
  INTEGER,        INTENT(IN)  :: ix
  REAL,           INTENT(IN)  :: vs(:,:,:)
  REAL,           INTENT(IN)  :: xs(:), xt(:)
  REAL,           INTENT(OUT) :: vt(:,:,:)
  REAL, OPTIONAL, INTENT(IN)  :: slope(:,:,:)
!-------------------------------------------------------------------------------
! Local variables:
  INTEGER :: is, it, ns, nt
  REAL    :: co, idt
  LOGICAL :: lslope
!-------------------------------------------------------------------------------
  lslope=PRESENT(slope)
  CALL check_size(ix,SHAPE(vs),SHAPE(vt),xs,xt,ns,nt)
  is=locate(xs,xt(1)) ! 1 <= is <= ns, because we forbid extrapolation
  vt(:,:,:)=0.
  DO it=1, nt; idt=1./(xt(it+1)-xt(it))
    IF(xt(it+1)<=xs(is+1)) THEN          !--- xs(is)<=xt(it)<=xt(it+1)<=xs(is+1)
      CALL mean_lin(xt(it),xt(it+1))
    ELSE
      CALL mean_lin(xt(it),xs(is+1)); is=is+1
      DO WHILE(xs(is+1)<xt(it+1))        !--- 1<=is<=ns-1
      CALL mean_lin(xs(is),xs(is+1)); is=is+1
      END DO
      CALL mean_lin(xs(is),xt(it+1))     !--- 1<=is<=ns
    END IF
    IF(xs(is+1)==xt(it+1)) is=is+1       !--- 1<=is<=ns .OR. it==nt
  END DO

CONTAINS

!-------------------------------------------------------------------------------
SUBROUTINE mean_lin(a,b)  ! mean [a,b] of the linear function in [xs(is),xs(is+1)]
!-------------------------------------------------------------------------------
! Arguments:
  REAL, INTENT(IN)    :: a, b
!-------------------------------------------------------------------------------
  IF(lslope.AND.(a/=xs(is).OR.b/=xs(is+1))) THEN; co=0.
    IF(a==xt(it  )) co=co+xt(it  )-xs(is  )
    IF(b==xt(it+1)) co=co+xt(it+1)-xs(is+1)
    IF(ix==1) vt(it,:,:) = vt(it,:,:)+idt*(b-a)*(vs(is,:,:)+co*slope(is,:,:)/2.)
    IF(ix==2) vt(:,it,:) = vt(:,it,:)+idt*(b-a)*(vs(:,is,:)+co*slope(:,is,:)/2.)
    IF(ix==3) vt(:,:,it) = vt(:,:,it)+idt*(b-a)*(vs(:,:,is)+co*slope(:,:,is)/2.)
  ELSE
    IF(ix==1) vt(it,:,:) = vt(it,:,:)+idt*(b-a)* vs(is,:,:)
    IF(ix==2) vt(:,it,:) = vt(:,it,:)+idt*(b-a)* vs(:,is,:)
    IF(ix==3) vt(:,:,it) = vt(:,:,it)+idt*(b-a)* vs(:,:,is)
  END IF

END SUBROUTINE mean_lin
!-------------------------------------------------------------------------------

END SUBROUTINE regr3_conserv
!
!-------------------------------------------------------------------------------


!-------------------------------------------------------------------------------
!
SUBROUTINE regr4_conserv(ix, vs, xs, xt, vt, slope)
!
!-------------------------------------------------------------------------------
! Arguments:
  INTEGER,        INTENT(IN)  :: ix
  REAL,           INTENT(IN)  :: vs(:,:,:,:)
  REAL,           INTENT(IN)  :: xs(:), xt(:)
  REAL,           INTENT(OUT) :: vt(:,:,:,:)
  REAL, OPTIONAL, INTENT(IN)  :: slope(:,:,:,:)
!-------------------------------------------------------------------------------
! Local variables:
  INTEGER :: is, it, ns, nt
  REAL    :: co, idt
  LOGICAL :: lslope
!-------------------------------------------------------------------------------
  lslope=PRESENT(slope)
  CALL check_size(ix,SHAPE(vs),SHAPE(vt),xs,xt,ns,nt)
  is=locate(xs,xt(1)) ! 1 <= is <= ns, because we forbid extrapolation
  vt(:,:,:,:)=0.
  DO it=1, nt; idt=1./(xt(it+1)-xt(it))
    IF(xt(it+1)<=xs(is+1)) THEN          !--- xs(is)<=xt(it)<=xt(it+1)<=xs(is+1)
      CALL mean_lin(xt(it),xt(it+1))
    ELSE
      CALL mean_lin(xt(it),xs(is+1)); is=is+1
      DO WHILE(xs(is+1)<xt(it+1))        !--- 1<=is<=ns-1
      CALL mean_lin(xs(is),xs(is+1)); is=is+1
      END DO
      CALL mean_lin(xs(is),xt(it+1))     !--- 1<=is<=ns
    END IF
    IF(xs(is+1)==xt(it+1)) is=is+1       !--- 1<=is<=ns .OR. it==nt
  END DO

CONTAINS

!-------------------------------------------------------------------------------
SUBROUTINE mean_lin(a,b)  ! mean [a,b] of the linear function in [xs(is),xs(is+1)]
!-------------------------------------------------------------------------------
! Arguments:
  REAL, INTENT(IN) :: a, b
!-------------------------------------------------------------------------------
  IF(lslope.AND.(a/=xs(is).OR.b/=xs(is+1))) THEN; co=0.
    IF(a==xt(it  )) co=co+xt(it  )-xs(is  )
    IF(b==xt(it+1)) co=co+xt(it+1)-xs(is+1)
    IF(ix==1) vt(it,:,:,:) = vt(it,:,:,:)+idt*(b-a)*(vs(is,:,:,:)+co*slope(is,:,:,:)/2.)
    IF(ix==2) vt(:,it,:,:) = vt(:,it,:,:)+idt*(b-a)*(vs(:,is,:,:)+co*slope(:,is,:,:)/2.)
    IF(ix==3) vt(:,:,it,:) = vt(:,:,it,:)+idt*(b-a)*(vs(:,:,is,:)+co*slope(:,:,is,:)/2.)
    IF(ix==4) vt(:,:,:,it) = vt(:,:,:,it)+idt*(b-a)*(vs(:,:,:,is)+co*slope(:,:,:,is)/2.)
  ELSE
    IF(ix==1) vt(it,:,:,:) = vt(it,:,:,:)+idt*(b-a)* vs(is,:,:,:)
    IF(ix==2) vt(:,it,:,:) = vt(:,it,:,:)+idt*(b-a)* vs(:,is,:,:)
    IF(ix==3) vt(:,:,it,:) = vt(:,:,it,:)+idt*(b-a)* vs(:,:,is,:)
    IF(ix==4) vt(:,:,:,it) = vt(:,:,:,it)+idt*(b-a)* vs(:,:,:,is)
  END IF

END SUBROUTINE mean_lin
!-------------------------------------------------------------------------------

END SUBROUTINE regr4_conserv
!
!-------------------------------------------------------------------------------


!-------------------------------------------------------------------------------
!
SUBROUTINE regr5_conserv(ix, vs, xs, xt, vt, slope)
!
!-------------------------------------------------------------------------------
! Arguments:
  INTEGER,        INTENT(IN)  :: ix
  REAL,           INTENT(IN)  :: vs(:,:,:,:,:)
  REAL,           INTENT(IN)  :: xs(:), xt(:)
  REAL,           INTENT(OUT) :: vt(:,:,:,:,:)
  REAL, OPTIONAL, INTENT(IN)  :: slope(:,:,:,:,:)
!-------------------------------------------------------------------------------
! Local variables:
  INTEGER :: is, it, ns, nt
  REAL    :: co, idt
  LOGICAL :: lslope
!-------------------------------------------------------------------------------
  lslope=PRESENT(slope)
  CALL check_size(ix,SHAPE(vs),SHAPE(vt),xs,xt,ns,nt)
  is=locate(xs,xt(1)) ! 1 <= is <= ns, because we forbid extrapolation
  vt(:,:,:,:,:)=0.
  DO it=1, nt; idt=1./(xt(it+1)-xt(it))
    IF(xt(it+1)<=xs(is+1)) THEN          !--- xs(is)<=xt(it)<=xt(it+1)<=xs(is+1)
      CALL mean_lin(xt(it),xt(it+1))
    ELSE
      CALL mean_lin(xt(it),xs(is+1)); is=is+1
      DO WHILE(xs(is+1)<xt(it+1))        !--- 1<=is<=ns-1
      CALL mean_lin(xs(is),xs(is+1)); is=is+1
      END DO
      CALL mean_lin(xs(is),xt(it+1))     !--- 1<=is<=ns
    END IF
    IF(xs(is+1)==xt(it+1)) is=is+1     !--- 1<=is<=ns .OR. it==nt
  END DO

CONTAINS

!-------------------------------------------------------------------------------
SUBROUTINE mean_lin(a,b)  ! mean [a,b] of the linear function in [xs(is),xs(is+1)]
!-------------------------------------------------------------------------------
! Arguments:
  REAL, INTENT(IN) :: a, b
!-------------------------------------------------------------------------------
  IF(lslope.AND.(a/=xs(is).OR.b/=xs(is+1))) THEN; co=0.
    IF(a==xt(it  )) co=co+xt(it  )-xs(is  )
    IF(b==xt(it+1)) co=co+xt(it+1)-xs(is+1)
    IF(ix==1) vt(it,:,:,:,:) = vt(it,:,:,:,:)+idt*(b-a)*(vs(is,:,:,:,:)+co*slope(is,:,:,:,:)/2.)
    IF(ix==2) vt(:,it,:,:,:) = vt(:,it,:,:,:)+idt*(b-a)*(vs(:,is,:,:,:)+co*slope(:,is,:,:,:)/2.)
    IF(ix==3) vt(:,:,it,:,:) = vt(:,:,it,:,:)+idt*(b-a)*(vs(:,:,is,:,:)+co*slope(:,:,is,:,:)/2.)
    IF(ix==4) vt(:,:,:,it,:) = vt(:,:,:,it,:)+idt*(b-a)*(vs(:,:,:,is,:)+co*slope(:,:,:,is,:)/2.)
    IF(ix==5) vt(:,:,:,:,it) = vt(:,:,:,:,it)+idt*(b-a)*(vs(:,:,:,:,is)+co*slope(:,:,:,:,is)/2.)
  ELSE
    IF(ix==1) vt(it,:,:,:,:) = vt(it,:,:,:,:)+idt*(b-a)* vs(is,:,:,:,:)
    IF(ix==2) vt(:,it,:,:,:) = vt(:,it,:,:,:)+idt*(b-a)* vs(:,is,:,:,:)
    IF(ix==3) vt(:,:,it,:,:) = vt(:,:,it,:,:)+idt*(b-a)* vs(:,:,is,:,:)
    IF(ix==4) vt(:,:,:,it,:) = vt(:,:,:,it,:)+idt*(b-a)* vs(:,:,:,is,:)
    IF(ix==5) vt(:,:,:,:,it) = vt(:,:,:,:,it)+idt*(b-a)* vs(:,:,:,:,is)
  END IF

END SUBROUTINE mean_lin
!-------------------------------------------------------------------------------

END SUBROUTINE regr5_conserv
!
!-------------------------------------------------------------------------------


!-------------------------------------------------------------------------------
!
SUBROUTINE check_size(ix,svs,svt,xs,xt,ns,nt)
!
!-------------------------------------------------------------------------------
! Arguments:
  INTEGER, INTENT(IN)  :: ix, svs(:), svt(:)
  REAL,    INTENT(IN)  :: xs(:), xt(:)
  INTEGER, INTENT(OUT) :: ns,    nt
!-------------------------------------------------------------------------------
! Local variables:
  INTEGER :: rk, is, ii, n
  CHARACTER(LEN=80) :: sub, msg
!-------------------------------------------------------------------------------
  WRITE(sub,'(a,2i0,a)')"regr",SIZE(svs),ix,"_conserv"
  rk=assert_eq(SIZE(svs),SIZE(svt),TRIM(sub)//': inconsistent ranks')
  WRITE(msg,'(a,2(i0,a))')TRIM(sub)//": ix (",ix,") exceeds field rank (",rk,")"
  CALL assert(ix>=1.AND.ix<=rk,msg)
  ii=0
  DO is=1,rk; IF(is==ix) CYCLE
    WRITE(msg,'(a,i0)')TRIM(sub)//" n",is
    n=assert_eq(svs(is),svt(is),msg)
    ii=ii+1
  END DO
  ns=assert_eq(svs(ix),SIZE(xs)-1,TRIM(sub)//" ns")
  nt=assert_eq(svt(ix),SIZE(xt)-1,TRIM(sub)//" nt")

  !--- Quick check on sort order:
  CALL assert(xs(1)<xs(2), TRIM(sub)//": xs bad order")
  CALL assert(xt(1)<xt(2), TRIM(sub)//": xt bad order")
  CALL assert(xs(1)<=xt(1).AND.xt(nt+1)<=xs(ns+1), TRIM(sub)//": extrapolation")

END SUBROUTINE check_size
!
!-------------------------------------------------------------------------------


END MODULE regr_conserv_m