! This is a Ferret external function. Given an input scalar or field A, ! and an input scalar or field P, computes A-FLOOR(A/P)*P. ! Uses the f90 MODULO function. ! ! In this subroutine we provide information about ! the function. The user configurable information ! consists of the following: ! ! descr Text description of the function ! ! num_args Required number of arguments ! ! axis_inheritance Type of axis for the result ! ( CUSTOM, IMPLIED_BY_ARGS, NORMAL, ABSTRACT ) ! CUSTOM - user defined axis ! IMPLIED_BY_ARGS - same axis as the incoming argument ! NORMAL - the result is normal to this axis ! ABSTRACT - an axis which only has index values ! ! piecemeal_ok For memory optimization: ! axes where calculation may be performed piecemeal ! ( YES, NO ) ! ! ! For each argument we provide the following information: ! ! name Text name for an argument ! ! unit Text units for an argument ! ! desc Text description of an argument ! ! axis_influence Are this argument's axes the same as the result grid? ! ( YES, NO ) ! ! axis_extend How much does Ferret need to extend arg limits relative to result ! subroutine modulo_init(id) implicit none ! use glenn carver's f90 version of ef includes include 'ferret_cmn/EF_Util_f90.inc' integer :: id, arg CALL ef_version_test(ef_version) !********************************************************************** ! USER CONFIGURABLE PORTION | ! | ! V call ef_set_desc(id, 'A-FLOOR(A/P)*P') call ef_set_num_args(id, 2) call ef_set_has_vari_args(id, NO) call ef_set_axis_inheritance(id, IMPLIED_BY_ARGS, & IMPLIED_BY_ARGS,IMPLIED_BY_ARGS,IMPLIED_BY_ARGS) call ef_set_piecemeal_ok(id, YES, YES, YES, YES) arg = 1 call ef_set_arg_name(id, arg, 'A') call ef_set_arg_desc(id, arg, 'Input data') call ef_set_axis_influence(id, arg, YES, YES, YES, YES) arg = 2 call ef_set_arg_name(id, arg, 'P') call ef_set_arg_desc(id, arg, 'Modulo length') call ef_set_axis_influence(id, arg, YES, YES, YES, YES) ! ^ ! | ! USER CONFIGURABLE PORTION | !*********************************************************************** end subroutine modulo_init ! ! In this subroutine we compute the result ! subroutine modulo_compute(id, arg_1, arg_2, result) implicit none include 'ferret_cmn/EF_Util_f90.inc' include 'ferret_cmn/EF_mem_subsc_f90.inc' real :: bad_flag(EF_MAX_ARGS), bad_flag_result real :: arg_1(mem1lox:mem1hix, mem1loy:mem1hiy, mem1loz:mem1hiz, mem1lot:mem1hit) real :: arg_2(mem2lox:mem2hix, mem2loy:mem2hiy, mem2loz:mem2hiz, mem2lot:mem2hit) real :: result(memreslox:memreshix, memresloy:memreshiy, memresloz:memreshiz, memreslot:memreshit) ! After initialization, the 'res_' arrays contain indexing information ! for the result axes. The 'arg_' arrays will contain the indexing ! information for each variable's axes. integer :: res_lo_ss(4), res_hi_ss(4), res_incr(4) integer :: arg_lo_ss(4,EF_MAX_ARGS), arg_hi_ss(4,EF_MAX_ARGS),& arg_incr(4,EF_MAX_ARGS) !********************************************************************** ! USER CONFIGURABLE PORTION | ! | ! V integer :: id, i, j, k, l integer :: i1, j1, k1, l1 integer :: i2, j2, k2, l2 CALL ef_get_res_subscripts(id, res_lo_ss, res_hi_ss, res_incr) CALL ef_get_arg_subscripts(id, arg_lo_ss, arg_hi_ss, arg_incr) CALL ef_get_bad_flags(id, bad_flag, bad_flag_result) i1 = arg_lo_ss(X_AXIS,ARG1) i2 = arg_lo_ss(X_AXIS,ARG2) do i=res_lo_ss(X_AXIS), res_hi_ss(X_AXIS) j1 = arg_lo_ss(Y_AXIS,ARG1) j2 = arg_lo_ss(Y_AXIS,ARG2) do j=res_lo_ss(Y_AXIS), res_hi_ss(Y_AXIS) k1 = arg_lo_ss(Z_AXIS,ARG1) k2 = arg_lo_ss(Z_AXIS,ARG2) do k=res_lo_ss(Z_AXIS), res_hi_ss(Z_AXIS) l1 = arg_lo_ss(T_AXIS,ARG1) l2 = arg_lo_ss(T_AXIS,ARG2) do l=res_lo_ss(T_AXIS), res_hi_ss(T_AXIS) if ( arg_1(i1,j1,k1,l1) == bad_flag(1) .or. & arg_2(i2,j2,k2,l2) == bad_flag(2) .or. & arg_2(i2,j2,k2,l2) == 0.) then result(i,j,k,l) = bad_flag_result else result(i,j,k,l) = modulo(arg_1(i1,j1,k1,l1),arg_2(i2,j2,k2,l2)) endif l1 = l1 + arg_incr(T_AXIS,ARG1) l2 = l2 + arg_incr(T_AXIS,ARG2) enddo k1 = k1 + arg_incr(Z_AXIS,ARG1) k2 = k2 + arg_incr(Z_AXIS,ARG2) enddo j1 = j1 + arg_incr(Y_AXIS,ARG1) j2 = j2 + arg_incr(Y_AXIS,ARG2) enddo i1 = i1 + arg_incr(X_AXIS,ARG1) i2 = i2 + arg_incr(X_AXIS,ARG2) enddo ! | ! USER CONFIGURABLE PORTION | !********************************************************************** !--------------------------------------------------------------------- end subroutine modulo_compute