Newer
Older
module obl_tforcing
!< @brief obl time dependent forcing def.
! --------------------------------------------------------------------------------
! modules used
! --------------------------------------------------------------------------------
#ifdef USE_CONFIG_PARSER
use iso_c_binding, only: C_NULL_CHAR
use config_parser
#endif
! directives list
implicit none
private
! public interface
! --------------------------------------------------------------------------------
public :: set_const_tforcing, set_external_tforcing, set_generic_tforcing
public :: set_config_tforcing
public :: normalize_time_tforcing
public :: deallocate_tforcing
! --------------------------------------------------------------------------------
!> @brief time forcing datatype
type, public :: timeForcingDataType
real, allocatable :: time(:) !< time array [s]
real, allocatable :: fvalue(:) !< value array [*]
integer :: num = 0 !< number of time marks
end type
contains
! --------------------------------------------------------------------------------
subroutine set_const_tforcing(tforcing, fconst)
!> @brief setting const forcing
! ----------------------------------------------------------------------------
type (timeForcingDataType), intent(out) :: tforcing
real, intent(in) :: fconst
real, dimension(1) :: tval, fval
! ----------------------------------------------------------------------------
tval(1) = 0.0
call set_generic_tforcing(tforcing, tval, fval, 1)
end subroutine set_const_tforcing
! --------------------------------------------------------------------------------
subroutine set_external_tforcing(tforcing, filename)
!> @brief setting forcing using file data
! ----------------------------------------------------------------------------
type (timeForcingDataType), intent(out) :: tforcing
integer :: num
real, allocatable :: tval(:), fval(:)
integer :: i
integer :: io, status
real :: val1, val2
! ----------------------------------------------------------------------------
! --- define number of lines in file
open(newunit = io, file = filename, iostat = status, status ='old')
if (status /= 0) then
write(*, *) ' FAILURE! > unable to open file: ', trim(filename)
return
end if
num = 0
status = 0
do while (status.eq.0)
read (io, *, iostat = status) val1, val2
num = num + 1
enddo
num = num - 1
if (num > 0) then
allocate(tval(num), fval(num))
endif
open(newunit = io, file = filename, iostat = status, status = 'old')
if (status /= 0) then
write(*, *) ' FAILURE! > unable to open file: ', trim(filename)
return
end if
do i = 1, num
read(io, *) tval(i), fval(i)
enddo
close(io)
if (num > 0) then
call set_generic_tforcing(tforcing, tval, fval, num)
deallocate(tval, fval)
endif
end subroutine set_external_tforcing
! --------------------------------------------------------------------------------
subroutine set_generic_tforcing(tforcing, tval, fval, num)
!> @brief generic forcing setup
! ----------------------------------------------------------------------------
type (timeForcingDataType), intent(inout) :: tforcing
integer, intent(in) :: num
real, dimension(num), intent(in) :: tval, fval
! ----------------------------------------------------------------------------
!> removing if defined
call deallocate_tforcing(tforcing)
tforcing%num = num
if (num > 0) then
allocate(tforcing%time(num), tforcing%fvalue(num))
tforcing%time(:) = tval(1:num)
tforcing%fvalue(:) = fval(1:num)
endif
end subroutine set_generic_tforcing
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
! --------------------------------------------------------------------------------
subroutine set_config_tforcing(tforcing, tag, ierr)
!> @brief generic forcing setup
! ----------------------------------------------------------------------------
use obl_math, only : char_array2str
type (timeForcingDataType), intent(inout) :: tforcing
integer, intent(out) :: ierr
character(len = *), intent(in) :: tag
real :: fvalue
character, allocatable :: config_field(:)
integer :: status
! ----------------------------------------------------------------------------
ierr = 0 ! = OK
call deallocate_tforcing(tforcing)
#ifdef USE_CONFIG_PARSER
call c_config_is_varname(trim(tag)//".mode"//C_NULL_CHAR, status)
if (status /= 0) then
call c_config_get_string(trim(tag)//".mode"//C_NULL_CHAR, config_field, status)
if (status == 0) then
ierr = 1 ! signal ERROR
return
end if
if (trim(char_array2str(config_field)) == 'const') then
call c_config_get_float(trim(tag)//".value"//C_NULL_CHAR, fvalue, status)
if (status == 0) then
ierr = 1 ! signal ERROR
return
end if
call set_const_tforcing(tforcing, fvalue)
else if (trim(char_array2str(config_field)) == 'ascii') then
call c_config_get_string(trim(tag)//".filename"//C_NULL_CHAR, config_field, status)
if (status == 0) then
ierr = 1 ! signal ERROR
return
end if
call set_external_tforcing(tforcing, char_array2str(config_field))
else
write(*, *) ' FAILURE! > unknown forcing mode: ', trim(char_array2str(config_field))
ierr = 1 ! signal ERROR
return
endif
else
call c_config_is_varname(trim(tag)//C_NULL_CHAR, status)
if (status /= 0) then
call c_config_get_float(trim(tag)//C_NULL_CHAR, fvalue, status)
if (status == 0) then
ierr = 1 ! signal ERROR
return
end if
call set_const_tforcing(tforcing, fvalue)
endif
endif
if (allocated(config_field)) deallocate(config_field)
#endif
end subroutine set_config_tforcing
! --------------------------------------------------------------------------------
subroutine get_value_tforcing(res, t, tforcing)
!> @brief get value at time = t
! ----------------------------------------------------------------------------
type (timeForcingDataType), intent(in) :: tforcing
real, intent(in) :: t
real, intent(out) :: res
! ----------------------------------------------------------------------------
call c_interp_linear(res, t, tforcing%fvalue, tforcing%time, tforcing%num)
! --------------------------------------------------------------------------------
subroutine normalize_time_tforcing(tforcing, coeff)
!> @brief normalize time *= coeff
! ----------------------------------------------------------------------------
type (timeForcingDataType), intent(inout) :: tforcing
real, intent(in) :: coeff
integer :: i
! ----------------------------------------------------------------------------
do i = 1, tforcing%num
tforcing%time(i) = tforcing%time(i) * coeff
end do
end subroutine normalize_time_tforcing
! --------------------------------------------------------------------------------
subroutine deallocate_tforcing(tforcing)
!> @brief free time forcing data
! ----------------------------------------------------------------------------
type (timeForcingDataType), intent(inout) :: tforcing
! ----------------------------------------------------------------------------
if (tforcing%num > 0) then
deallocate(tforcing%time)
deallocate(tforcing%fvalue)
end if
tforcing%num = 0
end subroutine deallocate_tforcing