MODFLOW 6 version 6.9.0.dev0
USGS Modular Hydrologic Model
Loading...
Searching...
No Matches
TimeArraySeries.f90
Go to the documentation of this file.
2
7 use mathutilmodule, only: is_close
9 use kindmodule, only: dp, i4b
10 use listmodule, only: listtype
12 use simvariablesmodule, only: errmsg
17 use, intrinsic :: iso_fortran_env, only: iostat_end
18
19 implicit none
20 private
23
25 ! -- Public members
26 character(len=LENTIMESERIESNAME), public :: name = ''
27 ! -- Private members
28 integer(I4B), private :: inunit = 0
29 integer(I4B), private :: iout = 0
30 integer(I4B), private :: imethod = undefined
31 real(dp), private :: sfac = done
32 character(len=LINELENGTH), private :: datafile = ''
33 logical, private :: autodeallocate = .true.
34 type(listtype), pointer, private :: list => null()
35 character(len=LENMODELNAME) :: modelname
36 type(blockparsertype), private :: parser
37
38 contains
39
40 ! -- Public procedures
41 procedure, public :: tas_init
42 procedure, public :: getaveragevalues
43 procedure, public :: getinunit
44 procedure, public :: da => tas_da
45 ! -- Private procedures
46 procedure, private :: get_integrated_values
47 procedure, private :: get_latest_preceding_node
48 procedure, private :: get_values_at_time
49 procedure, private :: get_surrounding_records
50 procedure, private :: read_next_array
51 procedure, private :: deallocatebackward
52 end type timearrayseriestype
53
54contains
55
56 ! -- Constructor for TimeArraySeriesType
57
58 !> @brief Allocate a new TimeArraySeriesType object.
59 !<
60 subroutine constructtimearrayseries(newTas, filename)
61 ! -- dummy
62 type(timearrayseriestype), pointer, intent(out) :: newtas
63 character(len=*), intent(in) :: filename
64 ! -- local
65 logical :: lex
66 ! -- formats
6710 format('Error: Time-array-series file "', a, '" does not exist.')
68 !
69 ! -- Allocate a new object of type TimeArraySeriesType
70 allocate (newtas)
71 allocate (newtas%list)
72 !
73 ! -- Ensure that input file exists
74 inquire (file=filename, exist=lex)
75 if (.not. lex) then
76 write (errmsg, 10) trim(filename)
77 call store_error(errmsg, terminate=.true.)
78 end if
79 newtas%datafile = filename
80 end subroutine constructtimearrayseries
81
82 ! -- Public procedures
83
84 !> @brief Initialize the time array series
85 !<
86 subroutine tas_init(this, fname, modelname, iout, tasname, autoDeallocate)
87 ! -- dummy
88 class(timearrayseriestype), intent(inout) :: this
89 character(len=*), intent(in) :: fname
90 character(len=*), intent(in) :: modelname
91 integer(I4B), intent(in) :: iout
92 character(len=*), intent(inout) :: tasname
93 logical, optional, intent(in) :: autoDeallocate
94 ! -- local
95 integer(I4B) :: istatus
96 integer(I4B) :: ierr
97 integer(I4B) :: inunit
98 character(len=40) :: keyword, keyvalue
99 logical :: found, continueread, endOfBlock
100 !
101 ! -- initialize some variables
102 if (present(autodeallocate)) this%autoDeallocate = autodeallocate
103 this%dataFile = fname
104 allocate (this%list)
105 !
106 ! -- assign members
107 this%modelname = modelname
108 this%iout = iout
109 !
110 ! -- open time-array series input file
111 inunit = getunit()
112 this%inunit = inunit
113 call openfile(inunit, 0, fname, 'TAS6')
114 !
115 ! -- initialize block parser
116 call this%parser%Initialize(this%inunit, this%iout)
117 !
118 ! -- read ATTRIBUTES block
119 continueread = .false.
120 ierr = 0
121 !
122 ! -- get BEGIN line of ATTRIBUTES block
123 call this%parser%GetBlock('ATTRIBUTES', found, ierr, &
124 supportopenclose=.true.)
125 if (.not. found) then
126 errmsg = 'Error: Attributes block not found in file: '// &
127 trim(fname)
128 call store_error(errmsg)
129 call this%parser%StoreErrorUnit()
130 end if
131 !
132 ! -- parse ATTRIBUTES entries
133 do
134 ! -- read line from input
135 call this%parser%GetNextLine(endofblock)
136 if (endofblock) exit
137 !
138 ! -- get the keyword
139 call this%parser%GetStringCaps(keyword)
140 !
141 ! -- get the word following the keyword (the key value)
142 call this%parser%GetStringCaps(keyvalue)
143 select case (keyword)
144 case ('NAME')
145 this%Name = keyvalue
146 tasname = keyvalue
147 case ('METHOD')
148 select case (keyvalue)
149 case ('STEPWISE')
150 this%iMethod = stepwise
151 case ('LINEAR')
152 this%iMethod = linear
153 case default
154 errmsg = 'Unknown interpolation method: "'//trim(keyvalue)//'"'
155 call store_error(errmsg)
156 call this%parser%StoreErrorUnit()
157 end select
158 case ('AUTODEALLOCATE')
159 this%autoDeallocate = (keyvalue == 'TRUE')
160 case ('SFAC')
161 read (keyvalue, *, iostat=istatus) this%sfac
162 if (istatus /= 0) then
163 errmsg = 'Error reading numeric SFAC value from "'//trim(keyvalue) &
164 //'"'
165 call store_error(errmsg)
166 call this%parser%StoreErrorUnit()
167 end if
168 case default
169 errmsg = 'Unknown option found in ATTRIBUTES block: "'// &
170 trim(keyword)//'"'
171 call store_error(errmsg)
172 call this%parser%StoreErrorUnit()
173 end select
174 end do
175 !
176 ! -- ensure that NAME and METHOD have been specified
177 if (this%Name == '') then
178 errmsg = 'Name not specified for time array series in file: '// &
179 trim(this%dataFile)
180 call store_error(errmsg)
181 call this%parser%StoreErrorUnit()
182 end if
183 if (this%iMethod == undefined) then
184 errmsg = 'Interpolation method not specified for time'// &
185 ' array series in file: '//trim(this%dataFile)
186 call store_error(errmsg)
187 call this%parser%StoreErrorUnit()
188 end if
189 !
190 ! -- handle any errors encountered so far
191 if (count_errors() > 0) then
192 errmsg = 'Error(s) encountered initializing time array series from file: ' &
193 //trim(this%dataFile)
194 call store_error(errmsg)
195 call this%parser%StoreErrorUnit()
196 end if
197 !
198 ! -- try to read first time array into linked list
199 if (.not. this%read_next_array()) then
200 errmsg = 'Error encountered reading time-array data from file: '// &
201 trim(this%dataFile)
202 call store_error(errmsg)
203 call this%parser%StoreErrorUnit()
204 end if
205 end subroutine tas_init
206
207 !> @brief Populate an array time-weighted average value for a specified time
208 !! span
209 !<
210 subroutine getaveragevalues(this, nvals, values, time0, time1)
211 ! -- dummy
212 class(timearrayseriestype), intent(inout) :: this
213 integer(I4B), intent(in) :: nvals
214 real(DP), dimension(nvals), intent(inout) :: values
215 real(DP), intent(in) :: time0
216 real(DP), intent(in) :: time1
217 ! -- local
218 integer(I4B) :: i
219 real(DP) :: timediff
220 !
221 timediff = time1 - time0
222 if (timediff > 0) then
223 call this%get_integrated_values(nvals, values, time0, time1)
224 do i = 1, nvals
225 values(i) = values(i) / timediff
226 end do
227 else
228 ! -- time0 and time1 are the same, so skip the integration step.
229 call this%get_values_at_time(nvals, values, time0)
230 end if
231 end subroutine getaveragevalues
232
233 !> @brief Return unit number
234 !<
235 function getinunit(this)
236 ! -- return
237 integer(I4B) :: getinunit
238 ! -- dummy
239 class(timearrayseriestype) :: this
240 !
241 getinunit = this%inunit
242 end function getinunit
243
244 ! -- Private procedures
245
246 !> @brief Get surrounding records
247 !<
248 subroutine get_surrounding_records(this, time, taEarlier, taLater)
249 ! -- dummy
250 class(timearrayseriestype), intent(inout) :: this
251 real(DP), intent(in) :: time
252 type(timearraytype), pointer, intent(inout) :: taEarlier
253 type(timearraytype), pointer, intent(inout) :: taLater
254 ! -- local
255 real(DP) :: time0, time1
256 type(listnodetype), pointer :: currNode => null()
257 type(listnodetype), pointer :: node0 => null()
258 type(listnodetype), pointer :: node1 => null()
259 type(timearraytype), pointer :: ta => null(), ta0 => null(), ta1 => null()
260 class(*), pointer :: obj
261 !
262 taearlier => null()
263 talater => null()
264 !
265 if (associated(this%list%firstNode)) then
266 currnode => this%list%firstNode
267 end if
268 !
269 ! -- If the next node is earlier than time of interest, advance along
270 ! linked list until the next node is later than time of interest.
271 do
272 if (associated(currnode)) then
273 if (associated(currnode%nextNode)) then
274 obj => currnode%nextNode%GetItem()
275 ta => castastimearraytype(obj)
276 if (ta%taTime <= time) then
277 currnode => currnode%nextNode
278 else
279 exit
280 end if
281 else
282 ! -- read another array
283 if (.not. this%read_next_array()) exit
284 end if
285 else
286 exit
287 end if
288 end do
289 !
290 if (associated(currnode)) then
291 !
292 ! -- find earlier record
293 node0 => currnode
294 obj => node0%GetItem()
295 ta0 => castastimearraytype(obj)
296 time0 = ta0%taTime
297 do while (time0 > time)
298 if (associated(node0%prevNode)) then
299 node0 => node0%prevNode
300 obj => node0%GetItem()
301 ta0 => castastimearraytype(obj)
302 time0 = ta0%taTime
303 else
304 exit
305 end if
306 end do
307 !
308 ! -- find later record
309 node1 => currnode
310 obj => node1%GetItem()
311 ta1 => castastimearraytype(obj)
312 time1 = ta1%taTime
313 do while (time1 < time)
314 if (associated(node1%nextNode)) then
315 node1 => node1%nextNode
316 obj => node1%GetItem()
317 ta1 => castastimearraytype(obj)
318 time1 = ta1%taTime
319 else
320 ! -- get next array
321 if (.not. this%read_next_array()) then
322 ! -- end of file reached, so exit loop
323 exit
324 end if
325 end if
326 end do
327 !
328 end if
329 !
330 if (time0 <= time) taearlier => ta0
331 if (time1 >= time) talater => ta1
332 end subroutine get_surrounding_records
333
334 !> @brief Read next time array from input file and append to list
335 !<
336 logical function read_next_array(this)
337 ! -- modules
338 use constantsmodule, only: lenmempath
342 ! -- dummy
343 class(timearrayseriestype), intent(inout) :: this
344 ! -- local
345 integer(I4B) :: i, ierr, istart, istat, istop, lloc, nrow, ncol, &
346 nodesperlayer
347 logical :: lopen, isfound
348 type(timearraytype), pointer :: ta => null()
349 character(len=LENMEMPATH) :: mempath
350 integer(I4B), dimension(:), contiguous, pointer :: mshape
351 !
352 ! -- initialize
353 istart = 1
354 istat = 0
355 istop = 1
356 lloc = 1
357 nullify (mshape)
358 !
359 ! -- create mempath to model input context where MODEL_SHAPE is
360 ! -- stored during static DIS loading
361 mempath = create_mem_path(component=this%modelname, context=idm_context)
362 !
363 ! -- set mshape pointer
364 call mem_setptr(mshape, 'MODEL_SHAPE', mempath)
365 !
366 ! Get dimensions for supported discretization type
367 if (size(mshape) == 2) then
368 nodesperlayer = mshape(2)
369 nrow = 1
370 ncol = mshape(2)
371 else if (size(mshape) == 3) then
372 nodesperlayer = mshape(2) * mshape(3)
373 nrow = mshape(2)
374 ncol = mshape(3)
375 else
376 errmsg = 'Time array series is not supported for selected &
377 &discretization type.'
378 call store_error(errmsg)
379 call this%parser%StoreErrorUnit()
380 end if
381 !
382 read_next_array = .false.
383 inquire (unit=this%inunit, opened=lopen)
384 if (lopen) then
385 call constructtimearray(ta, this%modelname)
386 ! -- read a time and an array from the input file
387 ! -- Get a TIME block and read the time
388 call this%parser%GetBlock('TIME', isfound, ierr, &
389 supportopenclose=.false.)
390 if (isfound) then
391 ta%taTime = this%parser%GetDouble()
392 ! -- Read the array
393 call readarray(this%parser%iuactive, ta%taArray, this%Name, &
394 size(mshape), ncol, nrow, 1, nodesperlayer, &
395 this%iout, 0, 0)
396 !
397 ! -- multiply values by sfac
398 do i = 1, nodesperlayer
399 ta%taArray(i) = ta%taArray(i) * this%sfac
400 end do
401 !
402 ! -- append the new time array to the list
403 call addtimearraytolist(this%list, ta)
404 read_next_array = .true.
405 !
406 ! -- make sure block is closed
407 call this%parser%terminateblock()
408 end if
409 end if
410 end function read_next_array
411
412 !> @brief Return an array of values for a specified time, same units as
413 !! time-series values
414 !<
415 subroutine get_values_at_time(this, nvals, values, time)
416 ! -- dummy
417 class(timearrayseriestype), intent(inout) :: this
418 integer(I4B), intent(in) :: nvals
419 real(DP), dimension(nvals), intent(inout) :: values
420 real(DP), intent(in) :: time ! time of interest
421 ! -- local
422 integer(I4B) :: i, ierr
423 real(DP) :: ratio, time0, time1, timediff, timediffi, val0, val1, &
424 valdiff
425 type(timearraytype), pointer :: taEarlier => null()
426 type(timearraytype), pointer :: taLater => null()
427 ! -- formats
42810 format('Error getting array at time ', g10.3, &
429 ' for time-array series "', a, '"')
430 !
431 ierr = 0
432 call this%get_surrounding_records(time, taearlier, talater)
433 if (associated(taearlier)) then
434 if (associated(talater)) then
435 ! -- values are available for both earlier and later times
436 if (this%iMethod == stepwise) then
437 ! -- Just populate values from elements of earlier time array
438 values = taearlier%taArray
439 elseif (this%iMethod == linear) then
440 ! -- perform linear interpolation
441 time0 = taearlier%taTime
442 time1 = talater%tatime
443 timediff = time1 - time0
444 timediffi = time - time0
445 if (timediff > 0) then
446 ratio = timediffi / timediff
447 else
448 ! -- should not happen if TS does not contain duplicate times
449 ratio = 0.5d0
450 end if
451 ! -- Iterate through all elements and perform interpolation.
452 do i = 1, nvals
453 val0 = taearlier%taArray(i)
454 val1 = talater%taArray(i)
455 valdiff = val1 - val0
456 values(i) = val0 + (ratio * valdiff)
457 end do
458 else
459 ierr = 1
460 end if
461 else
462 if (is_close(taearlier%taTime, time)) then
463 values = taearlier%taArray
464 else
465 ! -- Only earlier time is available, and it is not time of interest;
466 ! however, if method is STEPWISE, use value for earlier time.
467 if (this%iMethod == stepwise) then
468 values = taearlier%taArray
469 else
470 ierr = 1
471 end if
472 end if
473 end if
474 else
475 if (associated(talater)) then
476 if (is_close(talater%taTime, time)) then
477 values = talater%taArray
478 else
479 ! -- only later time is available, and it is not time of interest
480 ierr = 1
481 end if
482 else
483 ! -- Neither earlier nor later time is available.
484 ! This should never happen!
485 ierr = 1
486 end if
487 end if
488 !
489 if (ierr > 0) then
490 write (errmsg, 10) time, trim(this%Name)
491 call store_error(errmsg)
492 call store_error_unit(this%inunit)
493 end if
494 end subroutine get_values_at_time
495
496 !> @brief Populates an array with integrated values for a specified time span
497 !!
498 !! Units: (ts-value-unit)*time
499 !<
500 subroutine get_integrated_values(this, nvals, values, time0, time1)
501 ! -- dummy
502 class(timearrayseriestype), intent(inout) :: this
503 integer(I4B), intent(in) :: nvals
504 real(DP), dimension(nvals), intent(inout) :: values
505 real(DP), intent(in) :: time0
506 real(DP), intent(in) :: time1
507 ! -- local
508 integer(I4B) :: i
509 real(DP) :: area, currTime, nextTime, ratio0, ratio1, t0, &
510 t01, t1, timediff, value, value0, value1, valuediff
511 logical :: ldone
512 type(listnodetype), pointer :: precNode => null()
513 type(listnodetype), pointer :: currNode => null(), nextnode => null()
514 type(timearraytype), pointer :: currRecord => null(), nextrecord => null()
515 class(*), pointer :: currObj => null(), nextobj => null()
516 ! -- formats
51710 format('Error encountered while performing integration', &
518 ' for time-array series "', a, '" for time interval: ', &
519 g12.5, ' to ', g12.5)
520 !
521 values = dzero
522 value = dzero
523 ldone = .false.
524 t1 = -done
525 call this%get_latest_preceding_node(time0, precnode)
526 if (associated(precnode)) then
527 currnode => precnode
528 do while (.not. ldone)
529 currobj => currnode%GetItem()
530 currrecord => castastimearraytype(currobj)
531 currtime = currrecord%taTime
532 if (currtime < time1) then
533 if (.not. associated(currnode%nextNode)) then
534 ! -- try to read the next array
535 if (.not. this%read_next_array()) then
536 write (errmsg, 10) trim(this%Name), time0, time1
537 call store_error(errmsg)
538 call store_error_unit(this%inunit)
539 end if
540 end if
541 if (associated(currnode%nextNode)) then
542 nextnode => currnode%nextNode
543 nextobj => nextnode%GetItem()
544 nextrecord => castastimearraytype(nextobj)
545 nexttime = nextrecord%taTime
546 ! -- determine lower and upper limits of time span of interest
547 ! within current interval
548 if (currtime >= time0) then
549 t0 = currtime
550 else
551 t0 = time0
552 end if
553 if (nexttime <= time1) then
554 t1 = nexttime
555 else
556 t1 = time1
557 end if
558 ! -- For each element, find area of rectangle
559 ! or trapezoid delimited by t0 and t1.
560 t01 = t1 - t0
561 select case (this%iMethod)
562 case (stepwise)
563 do i = 1, nvals
564 ! -- compute area of a rectangle
565 value0 = currrecord%taArray(i)
566 area = value0 * t01
567 ! -- add area to integrated value
568 values(i) = values(i) + area
569 end do
570 case (linear)
571 do i = 1, nvals
572 ! -- compute area of a trapezoid
573 timediff = nexttime - currtime
574 ratio0 = (t0 - currtime) / timediff
575 ratio1 = (t1 - currtime) / timediff
576 valuediff = nextrecord%taArray(i) - currrecord%taArray(i)
577 value0 = currrecord%taArray(i) + ratio0 * valuediff
578 value1 = currrecord%taArray(i) + ratio1 * valuediff
579 area = 0.5d0 * t01 * (value0 + value1)
580 ! -- add area to integrated value
581 values(i) = values(i) + area
582 end do
583 end select
584 else
585 write (errmsg, 10) trim(this%Name), time0, time1
586 call store_error(errmsg)
587 call store_error('(Probable programming error)', terminate=.true.)
588 end if
589 else
590 ! Current node time = time1 so should be done
591 ldone = .true.
592 end if
593 !
594 ! -- Are we done yet?
595 if (t1 >= time1) then
596 ldone = .true.
597 else
598 if (.not. associated(currnode%nextNode)) then
599 ! -- try to read the next array
600 if (.not. this%read_next_array()) then
601 write (errmsg, 10) trim(this%Name), time0, time1
602 call store_error(errmsg)
603 call this%parser%StoreErrorUnit()
604 end if
605 end if
606 if (associated(currnode%nextNode)) then
607 currnode => currnode%nextNode
608 else
609 write (errmsg, 10) trim(this%Name), time0, time1
610 call store_error(errmsg)
611 call store_error('(Probable programming error)', terminate=.true.)
612 end if
613 end if
614 end do
615 end if
616 !
617 if (this%autoDeallocate) then
618 if (associated(precnode)) then
619 if (associated(precnode%prevNode)) then
620 call this%DeallocateBackward(precnode%prevNode)
621 end if
622 end if
623 end if
624 end subroutine get_integrated_values
625
626 !> @brief Deallocate fromNode and all previous nodes in list;
627 !! reassign firstNode
628 !<
629 subroutine deallocatebackward(this, fromNode)
630 ! -- dummy
631 class(timearrayseriestype), intent(inout) :: this
632 type(listnodetype), pointer, intent(inout) :: fromNode
633 !
634 ! -- local
635 type(listnodetype), pointer :: current => null()
636 type(listnodetype), pointer :: prev => null()
637 type(timearraytype), pointer :: ta => null()
638 class(*), pointer :: obj => null()
639 !
640 if (associated(fromnode)) then
641 ! -- reassign firstNode
642 if (associated(fromnode%nextNode)) then
643 this%list%firstNode => fromnode%nextNode
644 else
645 this%list%firstNode => null()
646 end if
647 ! -- deallocate fromNode and all previous nodes
648 current => fromnode
649 do while (associated(current))
650 prev => current%prevNode
651 obj => current%GetItem()
652 ta => castastimearraytype(obj)
653 ! -- Deallocate the contents of this time array,
654 ! then remove it from the list
655 call ta%da()
656 call this%list%RemoveNode(current, .true.)
657 current => prev
658 end do
659 fromnode => null()
660 end if
661 end subroutine deallocatebackward
662
663 !> @brief Return pointer to ListNodeType object for the node representing
664 !! the latest preceding time in the time series
665 !<
666 subroutine get_latest_preceding_node(this, time, tslNode)
667 ! -- dummy
668 class(timearrayseriestype), intent(inout) :: this
669 real(DP), intent(in) :: time
670 type(listnodetype), pointer, intent(inout) :: tslNode
671 ! -- local
672 real(DP) :: time0
673 type(listnodetype), pointer :: currNode => null()
674 type(listnodetype), pointer :: node0 => null()
675 type(timearraytype), pointer :: ta => null()
676 type(timearraytype), pointer :: ta0 => null()
677 class(*), pointer :: obj => null()
678 !
679 tslnode => null()
680 if (associated(this%list%firstNode)) then
681 currnode => this%list%firstNode
682 else
683 call store_error('probable programming error in &
684 &get_latest_preceding_node', &
685 terminate=.true.)
686 end if
687 !
688 continue
689 ! -- If the next node is earlier than time of interest, advance along
690 ! linked list until the next node is later than time of interest.
691 do
692 if (associated(currnode)) then
693 if (associated(currnode%nextNode)) then
694 obj => currnode%nextNode%GetItem()
695 ta => castastimearraytype(obj)
696 if (ta%taTime < time .or. is_close(ta%taTime, time)) then
697 currnode => currnode%nextNode
698 else
699 exit
700 end if
701 else
702 ! -- read another record
703 if (.not. this%read_next_array()) exit
704 end if
705 else
706 exit
707 end if
708 end do
709 !
710 if (associated(currnode)) then
711 !
712 ! -- find earlier record
713 node0 => currnode
714 obj => node0%GetItem()
715 ta0 => castastimearraytype(obj)
716 time0 = ta0%taTime
717 do while (time0 > time)
718 if (associated(node0%prevNode)) then
719 node0 => node0%prevNode
720 obj => node0%GetItem()
721 ta0 => castastimearraytype(obj)
722 time0 = ta0%taTime
723 else
724 exit
725 end if
726 end do
727 end if
728 !
729 if (time0 <= time) tslnode => node0
730 end subroutine get_latest_preceding_node
731
732 !> @brief Deallocate memory
733 !<
734 subroutine tas_da(this)
735 ! -- dummy
736 class(timearrayseriestype), intent(inout) :: this
737 ! -- local
738 integer :: i, n
739 type(timearraytype), pointer :: ta => null()
740 !
741 ! -- Deallocate contents of each time array in list
742 n = this%list%Count()
743 do i = 1, n
744 ta => gettimearrayfromlist(this%list, i)
745 call ta%da()
746 end do
747 !
748 ! -- Deallocate the list of time arrays
749 call this%list%Clear(.true.)
750 deallocate (this%list)
751 end subroutine tas_da
752
753 ! -- Procedures not type-bound
754
755 !> @brief Cast an unlimited polymorphic object as class(TimeArraySeriesType)
756 !<
757 function castastimearrayseriestype(obj) result(res)
758 ! -- dummy
759 class(*), pointer, intent(inout) :: obj
760 ! -- return
761 type(timearrayseriestype), pointer :: res
762 !
763 res => null()
764 if (.not. associated(obj)) return
765 !
766 select type (obj)
767 type is (timearrayseriestype)
768 res => obj
769 end select
770 end function castastimearrayseriestype
771
772 !> @brief Get time array from list
773 !<
774 function gettimearrayseriesfromlist(list, indx) result(res)
775 ! -- dummy
776 type(listtype), intent(inout) :: list
777 integer, intent(in) :: indx
778 ! -- return
779 type(timearrayseriestype), pointer :: res
780 ! -- local
781 class(*), pointer :: obj
782 !
783 obj => list%GetItem(indx)
784 res => castastimearrayseriestype(obj)
785 end function gettimearrayseriesfromlist
786
787end module timearrayseriesmodule
This module contains block parser methods.
integer(i4b) function getunit(this)
@ brief Get the unit number
This module contains simulation constants.
Definition Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition Constants.f90:45
integer(i4b), parameter lenmodelname
maximum length of the model name
Definition Constants.f90:22
integer(i4b), parameter lentimeseriesname
maximum length of a time series name
Definition Constants.f90:42
@ undefined
undefined interpolation
@ linear
linear interpolation
@ stepwise
stepwise interpolation
real(dp), parameter dzero
real constant zero
Definition Constants.f90:65
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition Constants.f90:27
real(dp), parameter done
real constant 1
Definition Constants.f90:76
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
This module defines variable data types.
Definition kind.f90:8
subroutine deallocatebackward(this, fromnode)
Deallocate fromNode and all previous nodes, and reassign firstNode.
Definition List.f90:166
pure logical function, public is_close(a, b, rtol, atol, symmetric)
Check if a real value is approximately equal to another.
Definition MathUtil.f90:46
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
This module contains simulation methods.
Definition Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition Sim.f90:59
subroutine, public store_error_unit(iunit, terminate)
Store the file unit number.
Definition Sim.f90:169
This module contains simulation variables.
character(len=maxcharlen) errmsg
error message string
character(len=linelength) idm_context
integer(i4b) iout
file unit number for simulation output
subroutine, public constructtimearray(newta, modelname)
Construct time array.
Definition TimeArray.f90:36
type(timearraytype) function, pointer, public castastimearraytype(obj)
Cast an unlimited polymorphic object as TimeArrayType.
Definition TimeArray.f90:77
type(timearraytype) function, pointer, public gettimearrayfromlist(list, indx)
Retrieve a time array from a list.
subroutine, public addtimearraytolist(list, timearray)
Add a time array to a to list.
Definition TimeArray.f90:94
subroutine tas_init(this, fname, modelname, iout, tasname, autodeallocate)
Initialize the time array series.
subroutine get_surrounding_records(this, time, taearlier, talater)
Get surrounding records.
subroutine getaveragevalues(this, nvals, values, time0, time1)
Populate an array time-weighted average value for a specified time span.
subroutine tas_da(this)
Deallocate memory.
subroutine get_values_at_time(this, nvals, values, time)
Return an array of values for a specified time, same units as time-series values.
subroutine get_latest_preceding_node(this, time, tslnode)
Return pointer to ListNodeType object for the node representing the latest preceding time in the time...
type(timearrayseriestype) function, pointer, public gettimearrayseriesfromlist(list, indx)
Get time array from list.
subroutine get_integrated_values(this, nvals, values, time0, time1)
Populates an array with integrated values for a specified time span.
subroutine, public constructtimearrayseries(newtas, filename)
Allocate a new TimeArraySeriesType object.
type(timearrayseriestype) function, pointer, public castastimearrayseriestype(obj)
Cast an unlimited polymorphic object as class(TimeArraySeriesType).
integer(i4b) function getinunit(this)
Return unit number.
logical function read_next_array(this)
Read next time array from input file and append to list.
A generic heterogeneous doubly-linked list.
Definition List.f90:14