77! ! flux.
88! <
99module PbstBaseModule
10- use ConstantsModule, only: LINELENGTH, MAXCHARLEN, DZERO, LGP
10+ use ConstantsModule, only: LINELENGTH, MAXCHARLEN, DZERO, LGP, &
11+ LENPACKAGENAME, TABLEFT, TABCENTER, &
12+ LENVARNAME
1113 use KindModule, only: I4B, DP
1214 use NumericalPackageModule, only: NumericalPackageType
1315 use SimModule, only: count_errors, store_error, ustop
1416 use SimVariablesModule, only: errmsg
1517 use TdisModule, only: kper, nper, kstp
1618 use TimeSeriesLinkModule, only: TimeSeriesLinkType
17- use TimeSeriesManagerModule, only: TimeSeriesManagerType, tsmanager_cr, &
18- read_value_or_time_series_adv
19+ use TimeSeriesManagerModule, only: TimeSeriesManagerType, tsmanager_cr
20+ use TableModule, only: TableType, table_cr
1921
2022 implicit none
2123
@@ -24,22 +26,35 @@ module PbstBaseModule
2426 public :: PbstBaseType
2527 public :: pbstbase_da
2628
29+ character (len= LENVARNAME) :: text = ' PBST'
30+
2731 type, abstract, extends(NumericalPackageType) :: PbstBaseType
2832
33+ character (len= 8 ), dimension (:), pointer , contiguous :: status = > null () ! < active, inactive, constant
34+ character (len= LENPACKAGENAME) :: text = ' ' ! < text string for package transport term
2935 integer (I4B), pointer :: ncv = > null () ! < number of control volumes
36+ integer (I4B), dimension (:), pointer , contiguous :: iboundpbst = > null () ! < package ibound
3037 logical , pointer , public :: active = > null () ! < logical indicating if a sensible heat flux object is active
3138 character (len= LINELENGTH), pointer , public :: inputFilename = > null () ! < a particular pbst input file name, could be for sensible heat flux or latent heat flux subpackages, for example
32- type (TimeSeriesManagerType), pointer , private :: tsmanager = > null ()
33-
39+ type (TimeSeriesManagerType), pointer :: tsmanager = > null ()
40+ !
41+ ! -- table objects
42+ type (TableType), pointer :: inputtab = > null () ! < input table object
43+
3444 contains
3545
3646 procedure :: init
3747 procedure :: ar
48+ procedure :: rp
3849 procedure , private :: read_options
3950 procedure :: pbst_options
51+ procedure :: pbst_set_stressperiod
52+ procedure :: subpck_set_stressperiod
4053 procedure (read_option), deferred :: read_option
4154 procedure , private :: pbstbase_allocate_scalars
55+ procedure :: pbst_allocate_arrays
4256 procedure :: da = > pbstbase_da
57+ procedure :: pbst_check_valid
4358
4459 end type PbstBaseType
4560
@@ -68,19 +83,21 @@ function read_option(this, keyword) result(success)
6883 ! !
6984 ! ! Allocate and initialize data members of the object.
7085 ! <
71- subroutine init (this , name_model , pakname , ftype , inunit , iout )
86+ subroutine init (this , name_model , pakname , ftype , inunit , iout , ncv )
7287 ! -- dummy
7388 class(PbstBaseType) :: this
7489 character (len=* ), intent (in ) :: name_model
7590 character (len=* ), intent (in ) :: pakname
7691 character (len=* ), intent (in ) :: ftype
7792 integer (I4B), intent (in ) :: inunit
7893 integer (I4B), intent (in ) :: iout
94+ integer (I4B), target , intent (in ) :: ncv
7995 !
8096 call this% set_names(1 , name_model, pakname, ftype)
8197 call this% pbstbase_allocate_scalars()
8298 this% inunit = inunit
8399 this% iout = iout
100+ this% ncv = > ncv
84101 call this% parser% Initialize(this% inunit, this% iout)
85102 end subroutine init
86103
@@ -91,6 +108,16 @@ end subroutine init
91108 subroutine ar (this )
92109 ! -- dummy
93110 class(PbstBaseType) :: this ! < ShfType object
111+ ! -- formats
112+ character (len=* ), parameter :: fmtapt = &
113+ " (1x,/1x,'SHF -- SENSIBLE HEAT FLUX TRANSPORT PACKAGE, VERSION 1, 3/12/2025', &
114+ &' INPUT READ FROM UNIT ', i0, //)"
115+ !
116+ ! -- print a message identifying the apt package.
117+ write (this% iout, fmtapt) this% inunit
118+ !
119+ ! -- Allocate arrays
120+ ! call this%pbst_allocate_arrays()
94121 !
95122 ! -- Create time series manager
96123 call tsmanager_cr(this% tsmanager, this% iout, &
@@ -100,8 +127,183 @@ subroutine ar(this)
100127 ! -- Read options
101128 call this% read_options()
102129 end subroutine ar
130+
131+ ! > @brief PaBST read and prepare for setting stress period information
132+ ! <
133+ subroutine rp (this )
134+ ! -- module
135+ use TimeSeriesManagerModule, only: read_value_or_time_series_adv
136+ use TdisModule, only: kper, nper
137+ ! -- dummy
138+ class(PbstBaseType) :: this ! < ShfType object
139+ ! -- local
140+ integer (I4B) :: ierr
141+ integer (I4B) :: n
142+ logical :: isfound, endOfBlock
143+ character (len= LINELENGTH) :: title
144+ character (len= LINELENGTH) :: line
145+ integer (I4B) :: itemno
146+ ! -- formats
147+ character (len=* ), parameter :: fmtblkerr = &
148+ &" ('Error. Looking for BEGIN PERIOD iper. Found ', a, ' instead.')"
149+ character (len=* ), parameter :: fmtlsp = &
150+ &" (1X,/1X,'REUSING ',A,'S FROM LAST STRESS PERIOD')"
151+ !
152+ ! -- Set ionper to the stress period number for which a new block of data
153+ ! will be read.
154+ if (this% inunit == 0 ) return
155+ !
156+ ! -- get stress period data
157+ if (this% ionper < kper) then
158+ !
159+ ! -- get period block
160+ call this% parser% GetBlock(' PERIOD' , isfound, ierr, &
161+ supportOpenClose= .true. , &
162+ blockRequired= .false. )
163+ if (isfound) then
164+ !
165+ ! -- read ionper and check for increasing period numbers
166+ call this% read_check_ionper()
167+ else
168+ !
169+ ! -- PERIOD block not found
170+ if (ierr < 0 ) then
171+ ! -- End of file found; data applies for remainder of simulation.
172+ this% ionper = nper + 1
173+ else
174+ ! -- Found invalid block
175+ call this% parser% GetCurrentLine(line)
176+ write (errmsg, fmtblkerr) adjustl (trim (line))
177+ call store_error(errmsg)
178+ call this% parser% StoreErrorUnit()
179+ end if
180+ end if
181+ end if
182+ !
183+ ! -- Read data if ionper == kper
184+ if (this% ionper == kper) then
185+ !
186+ ! -- setup table for period data
187+ if (this% iprpak /= 0 ) then
188+ !
189+ ! -- reset the input table object
190+ title = trim (adjustl (this% text))// ' PACKAGE (' // &
191+ trim (adjustl (this% packName))// ' ) DATA FOR PERIOD'
192+ write (title, ' (a,1x,i6)' ) trim (adjustl (title)), kper
193+ call table_cr(this% inputtab, this% packName, title)
194+ call this% inputtab% table_df(1 , 4 , this% iout, finalize= .FALSE. )
195+ text = ' NUMBER'
196+ call this% inputtab% initialize_column(text, 10 , alignment= TABCENTER)
197+ text = ' KEYWORD'
198+ call this% inputtab% initialize_column(text, 20 , alignment= TABLEFT)
199+ do n = 1 , 2
200+ write (text, ' (a,1x,i6)' ) ' VALUE' , n
201+ call this% inputtab% initialize_column(text, 15 , alignment= TABCENTER)
202+ end do
203+ end if
204+ !
205+ ! -- read data
206+ stressperiod: do
207+ call this% parser% GetNextLine(endOfBlock)
208+ if (endOfBlock) exit
209+ !
210+ ! -- get feature number
211+ itemno = this% parser% GetInteger()
212+ !
213+ ! -- read data from the rest of the line
214+ call this% pbst_set_stressperiod(itemno)
215+ !
216+ ! -- write line to table
217+ if (this% iprpak /= 0 ) then
218+ call this% parser% GetCurrentLine(line)
219+ call this% inputtab% line_to_columns(line)
220+ end if
221+ end do stressperiod
222+ !
223+ if (this% iprpak /= 0 ) then
224+ call this% inputtab% finalize_table()
225+ end if
226+ !
227+ ! -- using stress period data from the previous stress period
228+ else
229+ write (this% iout, fmtlsp) trim (this% filtyp)
230+ end if
231+ !
232+ ! -- write summary of stress period error messages
233+ ierr = count_errors()
234+ if (ierr > 0 ) then
235+ call this% parser% StoreErrorUnit()
236+ end if
237+ end subroutine rp
103238
239+ ! > @brief pbst_set_stressperiod()
240+ ! !
241+ ! ! To be overridden by Pbst sub-packages
242+ ! <
243+ subroutine pbst_set_stressperiod (this , itemno )
244+ ! -- dummy
245+ class(PbstBaseType), intent (inout ) :: this
246+ integer (I4B), intent (in ) :: itemno
247+ ! -- local
248+ integer (I4B) :: ierr
249+ character (len= LINELENGTH) :: text
250+ character (len= LINELENGTH) :: keyword
251+ logical (LGP) :: found
252+ !
253+ ! -- read line
254+ call this% parser% GetStringCaps(keyword)
255+ select case (keyword)
256+ case (' STATUS' )
257+ ierr = this% pbst_check_valid(itemno)
258+ if (ierr /= 0 ) then
259+ goto 999
260+ end if
261+ call this% parser% GetStringCaps(text)
262+ this% status (itemno) = text(1 :8 )
263+ if (text == ' CONSTANT' ) then
264+ this% iboundpbst(itemno) = - 1
265+ else if (text == ' INACTIVE' ) then
266+ this% iboundpbst(itemno) = 0
267+ else if (text == ' ACTIVE' ) then
268+ this% iboundpbst(itemno) = 1
269+ else
270+ write (errmsg, ' (a,a)' ) &
271+ ' Unknown ' // trim (this% text)// ' status keyword: ' , text// ' .'
272+ call store_error(errmsg)
273+ end if
274+ case default
275+ !
276+ ! -- call the specific package to deal with parameters specific to the
277+ ! process
278+ call this% subpck_set_stressperiod(itemno, keyword, found)
279+ ! -- terminate with error if data not valid
280+ if (.not. found) then
281+ write (errmsg, ' (2a)' ) &
282+ ' Unknown ' // trim (adjustl (this% text))// ' data keyword: ' , &
283+ trim (keyword)// ' .'
284+ call store_error(errmsg)
285+ end if
286+ end select
287+ !
288+ ! -- terminate if any errors were detected
289+ 999 if (count_errors() > 0 ) then
290+ call this% parser% StoreErrorUnit()
291+ end if
292+ end subroutine pbst_set_stressperiod
104293
294+ ! > @brief pbst_set_stressperiod()
295+ ! !
296+ ! ! To be overridden by Pbst sub-packages
297+ ! <
298+ subroutine subpck_set_stressperiod (this , itemno , keyword , found )
299+ ! -- dummy
300+ class(PbstBaseType), intent (inout ) :: this
301+ integer (I4B), intent (in ) :: itemno
302+ character (len=* ), intent (in ) :: keyword
303+ logical , intent (inout ) :: found
304+ ! -- to be overwritten by pbst subpackages (or "utilities")
305+ end subroutine subpck_set_stressperiod
306+
105307 ! > @brief Read the SHF-specific options from the OPTIONS block
106308 ! <
107309 subroutine read_options (this )
@@ -110,7 +312,6 @@ subroutine read_options(this)
110312 ! -- local
111313 character (len= LINELENGTH) :: keyword
112314 character (len= MAXCHARLEN) :: fname
113- logical :: isfound
114315 logical :: endOfBlock
115316 logical (LGP) :: found
116317 integer (I4B) :: ierr
@@ -119,11 +320,11 @@ subroutine read_options(this)
119320 &" (4x, 'TIME-SERIES DATA WILL BE READ FROM FILE: ', a)"
120321 !
121322 ! -- Get options block
122- call this% parser% GetBlock(' OPTIONS' , isfound , ierr, &
323+ call this% parser% GetBlock(' OPTIONS' , found , ierr, &
123324 blockRequired= .false. , supportOpenClose= .true. )
124325 !
125326 ! -- Parse options block if detected
126- if (isfound ) then
327+ if (found ) then
127328 write (this% iout, ' (1x,a)' ) &
128329 ' PROCESSING ' // trim (adjustl (this% packName))// ' OPTIONS'
129330 do
@@ -215,6 +416,34 @@ subroutine pbstbase_allocate_scalars(this)
215416 ! -- allocate time series manager
216417 allocate (this% tsmanager)
217418 end subroutine pbstbase_allocate_scalars
419+
420+ ! > @ brief Allocate arrays
421+ ! !
422+ ! ! Allocate base process-based stream temperature package transport arrays
423+ ! <
424+ subroutine pbst_allocate_arrays (this )
425+ ! -- modules
426+ use MemoryManagerModule, only: mem_allocate
427+ ! -- dummy
428+ class(PbstBaseType), intent (inout ) :: this
429+ ! -- local
430+ integer (I4B) :: n
431+ !
432+ ! -- Note: For the time-being, no call to parent class allocation of arrays
433+ ! as is done in tsp-apt.f90, for example. Remember that this class
434+ ! extends NumericalPackage.f90 which doesn't have a standard set of
435+ ! arrays to be allocated, only scalars.
436+ ! call this%BndType%allocate_arrays()
437+ !
438+ ! -- allocate character array for status
439+ allocate (this% status (this% ncv))
440+ !
441+ ! -- initialize arrays
442+ do n = 1 , this% ncv
443+ this% status (n) = ' ACTIVE'
444+ end do
445+ end subroutine pbst_allocate_arrays
446+
218447
219448 ! > @brief Deallocate package memory
220449 ! !
@@ -235,8 +464,39 @@ subroutine pbstbase_da(this)
235464 ! -- deallocate scalars
236465 call mem_deallocate(this% ncv)
237466 !
467+ ! -- deallocate arrays
468+ call mem_deallocate(this% iboundpbst)
469+ !
238470 ! -- Deallocate parent
239471 call this% NumericalPackageType% da()
472+ !
473+ ! -- input table object
474+ if (associated (this% inputtab)) then
475+ call this% inputtab% table_da()
476+ deallocate (this% inputtab)
477+ nullify (this% inputtab)
478+ end if
479+
240480 end subroutine pbstbase_da
481+
482+ ! > @brief Process-based stream temperature transport (or utility) routine
483+ ! !
484+ ! ! Determine if a valid feature number has been specified.
485+ ! <
486+ function pbst_check_valid (this , itemno ) result(ierr)
487+ ! -- return
488+ integer (I4B) :: ierr
489+ ! -- dummy
490+ class(PbstBaseType), intent (inout ) :: this
491+ integer (I4B), intent (in ) :: itemno
492+ ! -- formats
493+ ierr = 0
494+ if (itemno < 1 .or. itemno > this% ncv) then
495+ write (errmsg, ' (a,1x,i6,1x,a,1x,i6)' ) &
496+ ' Featureno ' , itemno, ' must be > 0 and <= ' , this% ncv
497+ call store_error(errmsg)
498+ ierr = 1
499+ end if
500+ end function pbst_check_valid
241501
242502end module PbstBaseModule
0 commit comments