Skip to content

Commit b4f0dc3

Browse files
committed
wip: add readonly and output attrs to memory variables
1 parent be42aa4 commit b4f0dc3

4 files changed

Lines changed: 71 additions & 10 deletions

File tree

src/Utilities/Memory/Memory.F90

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ module MemoryTypeModule
2525
integer(I4B) :: element_size = 0 !< byte size of an element; string length
2626
integer(I4B) :: set_handler_idx = 0 !< index of side effect handler for external access
2727
logical(LGP) :: master = .true. !< master copy, others point to this one
28+
logical(LGP) :: readonly = .false. !< when true, API consumers may not write this variable
29+
logical(LGP) :: output = .false. !< when true, this variable is user-facing simulation output
2830
character(len=:), pointer :: strsclr => null() !< pointer to the character string
2931
logical(LGP), pointer :: logicalsclr => null() !< pointer to the logical
3032
integer(I4B), pointer :: intsclr => null() !< pointer to the integer

src/Utilities/Memory/MemoryManager.f90

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module MemoryManagerModule
3131
public :: mem_write_usage
3232
public :: mem_da
3333
public :: mem_set_print_option
34+
public :: mem_set_attributes
3435
public :: get_from_memorystore
3536

3637
public :: get_mem_type
@@ -328,6 +329,27 @@ subroutine get_from_memorystore(name, mem_path, mt, found, check)
328329
end if
329330
end subroutine get_from_memorystore
330331

332+
!> @brief Set the readonly and/or output attributes on an existing memory entry
333+
!!
334+
!! Mutates attributes on an already-allocated MemoryType entry, looked up by name and
335+
!! memory path. Omitted attributes are left unchanged. Intended to be called once, after
336+
!! a variable has been allocated, to annotate it per the DFN memory catalog; it does not
337+
!! itself allocate anything.
338+
!<
339+
subroutine mem_set_attributes(name, mem_path, readonly, output)
340+
character(len=*), intent(in) :: name !< variable name
341+
character(len=*), intent(in) :: mem_path !< path where the variable is stored
342+
logical(LGP), intent(in), optional :: readonly !< when true, mark the variable read-only
343+
logical(LGP), intent(in), optional :: output !< when true, mark the variable as output
344+
! -- local
345+
type(MemoryType), pointer :: mt => null()
346+
logical(LGP) :: found
347+
! -- code
348+
call get_from_memorystore(name, mem_path, mt, found)
349+
if (present(readonly)) mt%readonly = readonly
350+
if (present(output)) mt%output = output
351+
end subroutine mem_set_attributes
352+
331353
!> @brief Issue allocation error message and stop program execution
332354
!<
333355
subroutine allocate_error(varname, mem_path, istat, isize)

srcbmi/mf6bmi.f90

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ module mf6bmi
2727
use CharacterStringModule
2828
use MemoryManagerModule, only: mem_setptr, get_mem_elem_size, get_isize, &
2929
get_mem_rank, get_mem_shape, get_mem_type, &
30-
memorystore
30+
get_from_memorystore, memorystore
3131
use MemoryContainerIteratorModule, only: MemoryContainerIteratorType
3232
use MemoryTypeModule, only: MemoryType
3333
use MemoryHelperModule, only: create_mem_address
@@ -199,42 +199,63 @@ end function get_time_step
199199

200200
!> @brief Get the number of input variables in the simulation
201201
!!
202-
!! This concerns all variables stored in the memory manager
202+
!! Counts variables stored in the memory manager that are not marked
203+
!! read-only, i.e. those an API consumer may write.
203204
!<
204205
function get_input_item_count(count) result(bmi_status) &
205206
bind(C, name="get_input_item_count")
206207
!DIR$ ATTRIBUTES DLLEXPORT :: get_input_item_count
207208
! -- dummy variables
208209
integer(kind=c_int), intent(out) :: count !< the number of input variables
209210
integer(kind=c_int) :: bmi_status !< BMI status code
211+
! -- local variables
212+
type(MemoryContainerIteratorType), allocatable :: itr
213+
type(MemoryType), pointer :: mt => null()
210214

211-
count = memorystore%count()
215+
count = 0
216+
itr = memorystore%iterator()
217+
do while (itr%has_next())
218+
call itr%next()
219+
mt => itr%value()
220+
if (.not. mt%readonly) count = count + 1
221+
end do
212222

213223
bmi_status = BMI_SUCCESS
214224

215225
end function get_input_item_count
216226

217227
!> @brief Get the number of output variables in the simulation
218228
!!
219-
!! This concerns all variables stored in the memory manager
229+
!! Counts variables stored in the memory manager that are marked
230+
!! as output.
220231
!<
221232
function get_output_item_count(count) result(bmi_status) &
222233
bind(C, name="get_output_item_count")
223234
!DIR$ ATTRIBUTES DLLEXPORT :: get_output_item_count
224235
! -- dummy variables
225236
integer(kind=c_int), intent(out) :: count !< the number of output variables
226237
integer(kind=c_int) :: bmi_status !< BMI status code
238+
! -- local variables
239+
type(MemoryContainerIteratorType), allocatable :: itr
240+
type(MemoryType), pointer :: mt => null()
227241

228-
count = memorystore%count()
242+
count = 0
243+
itr = memorystore%iterator()
244+
do while (itr%has_next())
245+
call itr%next()
246+
mt => itr%value()
247+
if (mt%output) count = count + 1
248+
end do
229249

230250
bmi_status = BMI_SUCCESS
231251

232252
end function get_output_item_count
233253

234254
!> @brief Returns all input variables in the simulation
235255
!!
236-
!! This functions returns the full address for all variables in the
237-
!! memory manager
256+
!! This function returns the full address for every variable in the
257+
!! memory manager that is not marked read-only, i.e. those an API
258+
!! consumer may write.
238259
!!
239260
!! The array @p c_names should be pre-allocated of proper size:
240261
!!
@@ -262,6 +283,7 @@ function get_input_var_names(c_names) result(bmi_status) &
262283
do while (itr%has_next())
263284
call itr%next()
264285
mt => itr%value()
286+
if (mt%readonly) cycle
265287
var_address = create_mem_address(mt%path, mt%name)
266288
do i = 1, len(trim(var_address))
267289
c_names(start + i - 1) = var_address(i:i)
@@ -276,9 +298,9 @@ end function get_input_var_names
276298

277299
!> @brief Returns all output variables in the simulation
278300
!!
279-
!! This function works analogously to get_input_var_names(),
280-
!! and currently returns the same set of memory variables,
281-
!! which is all of them!
301+
!! This function works analogously to get_input_var_names(), but returns
302+
!! the full address for every variable in the memory manager that is
303+
!! marked as output.
282304
!<
283305
function get_output_var_names(c_names) result(bmi_status) &
284306
bind(C, name="get_output_var_names")
@@ -297,6 +319,7 @@ function get_output_var_names(c_names) result(bmi_status) &
297319
do while (itr%has_next())
298320
call itr%next()
299321
mt => itr%value()
322+
if (.not. mt%output) cycle
300323
var_address = create_mem_address(mt%path, mt%name)
301324
do i = 1, len(trim(var_address))
302325
c_names(start + i - 1) = var_address(i:i)
@@ -913,6 +936,8 @@ function set_value(c_var_address, c_arr_ptr) result(bmi_status) &
913936
character(len=LENMEMTYPE) :: mem_type
914937
character(len=LENVARNAME) :: var_name
915938
logical(LGP) :: valid
939+
logical(LGP) :: found
940+
type(MemoryType), pointer :: mt => null()
916941

917942
bmi_status = BMI_SUCCESS
918943

@@ -922,6 +947,16 @@ function set_value(c_var_address, c_arr_ptr) result(bmi_status) &
922947
return
923948
end if
924949

950+
call get_from_memorystore(var_name, mem_path, mt, found, check=.false.)
951+
if (found) then
952+
if (mt%readonly) then
953+
write (bmi_last_error, fmt_readonly_var) trim(var_name)
954+
call report_bmi_error(bmi_last_error)
955+
bmi_status = BMI_FAILURE
956+
return
957+
end if
958+
end if
959+
925960
call get_mem_type(var_name, mem_path, mem_type)
926961

927962
if (index(mem_type, "DOUBLE") /= 0) then

srcbmi/mf6bmiError.f90

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ module mf6bmiError
3434
character(len=*), parameter :: fmt_invalid_mem_access = & !< Invalid memory access, args: variable name
3535
"('Fatal BMI Error, invalid access of memory &
3636
&for variable: ', a)"
37+
character(len=*), parameter :: fmt_readonly_var = & !< Write to read-only variable, args: variable name
38+
"('BMI Error, variable is read-only: ', a)"
3739
character(len=*), parameter :: fmt_fail_cvg_sol = & !< Solution failed to converge, args: detail
3840
"('BMI Error, Numerical Solution ', i3, &
3941
&' failed to converge')"

0 commit comments

Comments
 (0)