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)=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)