2 ! Author(s)/Contact(s):
7 ! Parameters: <Specify typical arguments passed>
9 ! <list file names and briefly describe the data they include>
11 ! <list file names and briefly describe the information they include>
14 ! <list exit condition or error codes returned >
15 ! If appropriate, descriptive troubleshooting instructions or
16 ! likely causes for failures could be mentioned here with the
17 ! appropriate error code
19 ! User controllable options: <if applicable>
21 module module_nudging_utils
23 real :: totalNudgeTime
24 integer :: sysClockCountRate, sysClockCountMax
25 character(len=4) :: clockType
29 !===================================================================================================
30 ! NOTE for whichUtilites
31 ! whUniLoop was fastest for single index searches.
32 ! I still havent tested multiple index searches (which and whichLoop)
35 !===================================================================================================
37 ! functions: whichPack and whichLoop
38 ! Author(s)/Contact(s):
39 ! James L McCreight <jamesmcc><ucar><edu>
41 ! Identify indices in a vector which are TRUE, reutrns zero length vector
42 ! if there are no matches.
44 ! 6/04/15 -Created, JLM.
50 ! User controllable options: None.
52 ! JLM: Recent catastrophic failure reported for pack on ifort, with work arround.
53 ! JLM: https://software.intel.com/en-us/forums/topic/559308#comments
55 subroutine whichPack(theMask, which, nWhich)
57 logical, allocatable, intent(in), dimension(:) :: theMask
58 integer, intent(out), dimension(:) :: which
59 integer, intent(out) :: nwhich
63 nWhich = sum( (/ (1, ii=1,size(theMask)) /), mask=theMask)
64 if(nWhich .gt. size(which)) then
68 which(1:nWhich) = pack( (/ (ii, ii=1,size(theMask)) /), mask=theMask)
69 end subroutine whichPack
71 subroutine whichLoop(theMask, which, nWhich)
73 logical, intent(in), dimension(:) :: theMask
74 integer, intent(out), dimension(:) :: which
75 integer, intent(out) :: nwhich
81 if(nWhich .gt. size(which)) then
91 end subroutine whichLoop
93 !===================================================================================================
96 ! Author(s)/Contact(s):
97 ! James L McCreight <jamesmcc><ucar><edu>
99 ! Identify THE index in a logical vector which is TRUE. Returns
100 ! -1 if not unique or none are true.
102 ! 6/04/15 -Created, JLM.
108 ! User controllable options: None.
111 function whUnique(theMask, unsafe)
113 integer :: whUnique !! return value
114 logical, allocatable, dimension(:), intent(in) :: theMask
115 logical, optional, intent(in) :: unsafe
116 integer, allocatable, dimension(:) :: whUniques
117 integer :: i, nMatches
118 if(present(unsafe)) then
119 !whUniques=pack( (/ (i, i=1,size(theMask)) /), mask= theMask)
120 !whUnique = whUniques(1)
121 whUnique=sum( (/ (i, i=1,size(theMask)) /), mask= theMask)
123 nMatches = sum( (/ (1, i=1,size(theMask)) /), mask= theMask )
124 if (nMatches .gt. 1 .OR. nMatches .eq. 0) then
127 whUnique=sum( (/ (i, i=1,size(theMask)) /), mask= theMask)
130 end function whUnique
133 !===================================================================================================
136 ! Author(s)/Contact(s):
137 ! James L McCreight <jamesmcc><ucar><edu>
139 ! Simply returns the first match, no check for uniques. On gfortran this
140 ! was the fastest of the bunch even/especially for max indices on huge arrays.
142 ! 6/04/15 -Created, JLM.
148 ! User controllable options: None.
151 function whUniLoop(theMask)
153 integer :: whUniLoop !! return value
154 logical, allocatable, dimension(:), intent(in) :: theMask
157 do ii=1,size(theMask)
163 end function whUniLoop
165 !===================================================================================================
168 ! Author(s)/Contact(s):
169 ! James L McCreight <jamesmcc><ucar><edu>
171 ! Identify the indices of elements in a first vector which are present in the
172 ! second vector, returns 0 for no matches. This can be slow, it's a double do/for loop.
174 ! 6/04/15 -Created, JLM.
180 ! User controllable options: None.
181 ! Notes: Can be slow, use with caution.
183 ! parallelize this? ||||||||||||||||||||||||||||||||||
184 subroutine whichInLoop(vecToSearch, vecToMatch, which, nWhich)
186 character(len=15), intent(in), dimension(:) :: vecToSearch
187 character(len=15), intent(in), dimension(:) :: vecToMatch
188 integer, intent(out), dimension(:) :: which
189 integer, intent(out) :: nWhich
193 do ii=1,size(vecToSearch)
194 do jj=1,size(vecToMatch)
195 if(trim(adjustl(vecToSearch(ii))) .eq. trim(adjustl(vecToMatch(jj)))) then
202 end subroutine whichInLoop
205 ! parallelize this? ||||||||||||||||||||||||||||||||||
206 subroutine whichInLoop2(vecToSearch, vecToMatch, which, nWhich)
208 character(len=15), intent(in), dimension(:) :: vecToSearch
209 character(len=15), intent(in), dimension(:) :: vecToMatch
210 integer, intent(out), dimension(:) :: which
211 integer, intent(out) :: nWhich
215 do ii=1,size(vecToSearch)
216 if(any(vecToMatch .eq. vecToSearch(ii))) then
221 end subroutine whichInLoop2
224 !===================================================================================================
227 ! Author(s)/Contact(s):
228 ! James L McCreight <jamesmcc><ucar><edu>
230 ! Tally up the total cpu or wall time used by nudging.
232 ! 8/20/15 -Created, JLM.
235 ! start, end: real times for end-diff timing & accumulation
236 ! sectionLabel: prints a message with the timing for the section
237 ! print*, 'Ndg: ' // sectionLabel // '(seconds ' // trim(clockType) // ' time):', diff
238 ! optional - accum: accumulate this towards the overall time or simply print the above
239 ! message? Do not accum for nested sections of code, but still give the diagnostic.
243 ! User controllable options: None.
245 subroutine accum_nudging_time(start, end, sectionLabel, accum)
247 real, intent(in) :: start, end
248 character(len=*), intent(in) :: sectionLabel
249 logical, optional, intent(in):: accum
250 logical :: accumLocal
253 if(present(accum)) accumLocal = accum
255 if(clockType.eq.'wall') then
256 if(diff .lt. 0) diff = diff + sysClockCountMax
257 diff=diff/sysClockCountRate
259 if (accumLocal) totalNudgeTime = totalNudgeTime + diff
261 print*,'Ndg: Timing: ' // sectionLabel // ' (' // trim(clockType) // ' time, seconds):', diff
263 if(accumLocal) print*,'Ndg: Timing: accum totalNudgeTime: ',totalNudgeTime
264 end subroutine accum_nudging_time
267 !===================================================================================================
270 ! Author(s)/Contact(s):
271 ! James L McCreight <jamesmcc><ucar><edu>
273 ! Return your choice of cpu time or wall time
275 ! 8/20/15 -Created, JLM.
281 ! User controllable options: None.
283 subroutine nudging_timer(time)
285 real, intent(inout) :: time
287 if(clockType.eq.'cpu') call cpu_time(time)
288 if(clockType.eq.'wall') then
289 call system_clock(count=count)
292 end subroutine nudging_timer
295 !===================================================================================================
296 end module module_nudging_utils