
mod
Remainder function which emulates the Fortran "mod" intrinsic function.
Available in version 4.3.0 and later.
Prototype
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/contributed.ncl" ; This library is automatically loaded ; from NCL V6.2.0 onward. ; No need for user to explicitly load. function mod ( n : numeric, ; integer, float, double m : numeric ) return_val : same type and shape as n
Arguments
nScalar or array variable of type integer, float, double.
mScalar or array variable. If an array it must be the same shape as n. Although not required, it is best if it is the same type as n.
Description
NCL has a modulus algebraic operator, % , which requires that the arguments be integers. The mod function is more general. The results are the same as those of the GNU "gfortran" compiler. While the function allows mixed types, it is best to always use n and m of the same type.
Examples
Example 1: Sample usage: numeric results and return types. Note that the returned value is the same numeric type and sign as argument n.
17 % 3 = 2 NCL modulus syntax (integers only) mod(17,3) = 2 type= integer mod(17.5,5.5) = 1 type= float mod(17.5d0,5.5) = 1 type= double mod(17.5d0,5.5d0) = 1 type= double mod(17.5,5.5d0) = 1 type= float mod(17.5, 5 ) = 2.5 type= float mod(17 ,5.5) = 2 type= integer mod(-17,3) = -2 type= integer mod(-17.5,5.5) = -1 type= float mod(-17.5d0,5.5) = -1 type= double mod(-17.5d0,5.5d0)= -1 type= double mod(-17.5,5.5d0) = -1 type= float mod(-17.5, 5 ) = -2.5 type= float mod(-17 ,5.5) = -2 type= integer mod(17,-3) = 2 type= integer mod(17.5,-5.5) = 1 type= float mod(17.5d0,-5.5) = 1 type= double mod(17.5d0,-5.5d0)= 1 type= double mod(17.5,-5.5d0) = 1 type= float mod(17.5, -5 ) = 2.5 type= float mod(17 ,-5.5) = 2 type= integer
Example 2: This example is based on a response by David Allured (NOAA-CIRES) to an ncl-talk@ucar.edu query.
Consider a set of values which are cyclic. Two common examples would be angular coordinates for a circle and longitudes on the entire globe. Let's say data are to be uniquely partitioned into four quadrants: (i) 0-90; (ii) 90-180; (c) 180-270; (d) 270-onward. How can the appropriate indices be determined that account for the cyclic condition?
dlon = 10 nlon = 360/dlon lon = fspan(0, 350,nlon) ; 0,10,20,....,330,340,350 theta = 2*dlon lon_offset = mod (lon + 360 - theta, 360) print(lon_offset) ; 340,350, 0, 10,..., 320,330 iq1 = ind (lon_offset .lt. 90) ; [9]: 2,3,...,8,9,10 iq2 = ind (lon_offset .ge. 90 .and. lon_offset .lt. 180) ; [9]: 11,12,...,18,19 iq3 = ind (lon_offset .ge. 180 .and. lon_offset .lt. 270) ; [9]: 20,21,...,27,28 iq4 = ind (lon_offset .ge. 270) ; [9]: 0, 1,29,30,...,34,35The above method effectively converts the NCL mod function to a true mathematical modulo function for cyclic applications. Understand the difference here:
https://en.wikipedia.org/wiki/Modulo_operationNote: If an application requires overlapping index points in some cases change .lt. to .le. in the iq1/iq2/iq3 statements.
Example 3: The following function returns the unique indices for a user specified number of angular segments:
undef("mod_cyclic_ind") function mod_cyclic_ind(x[*]:numeric, nsec[1]:integer) ; ; Return unique index values for cyclic sequence. ; ; Nomenclature: ; x - angles or longitides ; nsec - number of sections. EG: nsec=4 means quadrants, ; ; https://www.ncl.ucar.edu/Document/Functions/Contributed/mod.shtml ; Examples 2 and 3 ; local nx, dx, ang, theta, xcyc, nind, icyc begin nx = dimsizes(x) if (nx.lt.3) then print("mod_cyclic_ind: more than 3 values needed: nx="+nx) exit end if dx = x(1)-x(0) if (.not.all(x(1:)-x(0:nx-2)).eq.dx) then print("mod_cyclic_ind: values not equally spaced") exit end if ang = 360/nsec theta = 2*dx xcyc = mod (x+360-theta, 360) ; extra 360 degrees prevents negative index values ; for initial (first) section. nind = nx/nsec icyc = new( (/nsec,nind/), integer, "No_FillValue") icyc(0,:) = ind (xcyc .lt. ang) do n=1,nsec-2 icyc(n,:) = ind(xcyc.ge.(n*ang) .and. xcyc.lt.((n+1)*ang)) end do icyc(nsec-1,:) = ind(xcyc .ge. ang*(nsec-1)) icyc@long_name = "cyclic indices" ; meta data for completeness icyc!0 = "section" icyc!1 = "index" return(icyc) end ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; MAIN ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dlon = 10 nlon = 360/dlon lon = fspan(0, 350,nlon) ; 0,10,20,....,330,340,350 ;---test function with nsec=4 :---> Example 2 (quadrants) IQ = mod_cyclic_ind(lon, 4) printVarSummary(IQ) print("") print(IQ(0,:)+" "+IQ(1,:)+" "+IQ(2,:)+" "+IQ(3,:)) print("---") ;---test function with nsec=12 IQ := mod_cyclic_ind(lon,12) ; := is reassignment operator printVarSummary(IQ) print("") print(IQ(0,:)+" "+IQ(1,:)+" "+IQ( 2,:)+" "+IQ( 3,:)+" "+ \ IQ(4,:)+" "+IQ(5,:)+" "+IQ( 6,:)+" "+IQ( 7,:)+" "+ \ IQ(8,:)+" "+IQ(9,:)+" "+IQ(10,:)+" "+IQ(11,:))The output for the above code is:
Variable: IQ Type: integer Total Size: 144 bytes 36 values Number of Dimensions: 2 Dimensions and sizes: [section | 4] x [index | 9] Coordinates: Number Of Attributes: 1 long_name : cyclic indices (0) 2 11 20 0 (1) 3 12 21 1 (2) 4 13 22 29 (3) 5 14 23 30 (4) 6 15 24 31 (5) 7 16 25 32 (6) 8 17 26 33 (7) 9 18 27 34 (8) 10 19 28 35 (0) --- Variable: IQ Type: integer Total Size: 144 bytes 36 values Number of Dimensions: 2 Dimensions and sizes: [section | 12] x [index | 3] Coordinates: Number Of Attributes: 1 long_name : cyclic indices (0) 2 5 8 11 14 17 20 23 26 29 32 0 (1) 3 6 9 12 15 18 21 24 27 30 33 1 (2) 4 7 10 13 16 19 22 25 28 31 34 35