11 use netcdf
, only : nf90_noerr, nf90_global, nf90_nowrite, nf90_inquire_attribute, nf90_open, nf90_strerror, &
12 nf90_inq_dimid, nf90_inquire_dimension, nf90_inq_varid, nf90_get_var, nf90_inquire, nf90_close, nf90_get_att
22 character(len=*),
parameter :: &
23 time_key =
"time", & !< NetCDF data time key
59 type(model_state_type),
intent(inout),
target :: current_state
64 if (.not. current_state%passive_q .and. current_state%number_q_fields > 0)
then 65 if (.not.
allocated(current_state%cq))
then 66 allocate(current_state%cq(current_state%number_q_fields))
67 current_state%cq=0.0_default_precision
69 iqv = get_q_index(standard_q_names%VAPOUR,
'setfluxlook')
70 current_state%cq(
iqv) = ratio_mol_wts-1.0
73 if (current_state%use_surface_boundary_conditions)
then 74 if (current_state%type_of_surface_boundary_conditions == prescribed_surface_fluxes)
then 75 if (current_state%use_time_varying_surface_values)
then 79 /(current_state%global_grid%configuration%vertical%rho(1)*cp)
81 /(current_state%global_grid%configuration%vertical%rho(1)*rlvap)
84 current_state%fbuoy=0.
85 if(.not. current_state%passive_th) current_state%fbuoy=&
86 current_state%global_grid%configuration%vertical%buoy_co(1)*current_state%surface_temperature_flux
87 if(.not. current_state%passive_q .and. current_state%number_q_fields > 0)
then 88 current_state%fbuoy=current_state%fbuoy+current_state%cq(
iqv)*current_state%surface_vapour_flux*g
91 current_state%theta_surf=0.0_default_precision
92 current_state%surface_vapour_mixing_ratio=0.0_default_precision
94 else if (current_state%type_of_surface_boundary_conditions == prescribed_surface_values)
then 97 if (current_state%use_time_varying_surface_values)
then 103 if (current_state%saturated_surface)
then 104 current_state%surface_vapour_mixing_ratio = qsaturation(
surface_temperatures(1),current_state%surface_pressure*0.01)
111 (current_state%surface_reference_pressure/current_state%surface_pressure)**r_over_cp
112 current_state%theta_virtual_surf = current_state%theta_surf
113 if (.not. current_state%passive_q .and. current_state%number_q_fields > 0)
then 114 current_state%theta_virtual_surf = current_state%theta_surf + &
115 current_state%global_grid%configuration%vertical%thref(2)* &
116 current_state%cq(
iqv)*current_state%surface_vapour_mixing_ratio
120 current_state%cmbc=betam*current_state%global_grid%configuration%vertical%zn(2)*g*&
121 von_karman_constant/current_state%theta_virtual_surf
122 current_state%rcmbc=1.0_default_precision/current_state%cmbc
123 current_state%ellmocon=current_state%theta_virtual_surf/(g*von_karman_constant)
131 type(model_state_type),
intent(inout),
target :: current_state
133 if (current_state%use_surface_boundary_conditions)
then 134 if (current_state%use_time_varying_surface_values)
then 143 type(model_state_type),
intent(inout),
target :: current_state
145 integer I, ik, iters(current_state%lookup_table_entries)
146 real(kind=DEFAULT_PRECISION) :: smth, &
149 if (current_state%fbuoy .le. 0.0_default_precision)
return 150 current_state%velmax=100.0_default_precision
151 current_state%velmin=0.1_default_precision
152 current_state%aloginv=1.0_default_precision/log(current_state%velmax/current_state%velmin)
153 smth=0.1_default_precision
154 do ik=1, current_state%lookup_table_entries
155 current_state%lookup_table_velocity(ik)=current_state%velmin*(current_state%velmax/current_state%velmin)**&
156 (
real(ik-1)/
real(current_state%lookup_table_entries-1))
157 current_state%lookup_table_ustr(ik)=current_state%lookup_table_velocity(ik)*&
158 current_state%global_grid%configuration%vertical%vk_on_zlogm
159 if (current_state%fbuoy .gt. 0.0_default_precision)
then 162 iters(ik)=iters(ik)+1
163 ob=-current_state%lookup_table_ustr(ik)**3/(von_karman_constant*current_state%fbuoy)
164 x1=sqrt(sqrt(1.-gammam*(current_state%global_grid%configuration%vertical%zn(2)+z0)/ob))
165 x0=sqrt(sqrt(1.-gammam*z0/ob))
166 current_state%lookup_table_ustr(ik)=(1.-smth)*current_state%lookup_table_ustr(ik) + smth*&
167 (von_karman_constant*current_state%lookup_table_velocity(ik)) / &
168 (current_state%global_grid%configuration%vertical%zlogm-(2.0_default_precision*&
169 log((x1+1.0_default_precision)/(x0+1.0_default_precision)) + log((x1*x1+1.0_default_precision)/&
170 (x0*x0+1.0_default_precision)) + 2.0_default_precision*atan(x0) -2.0_default_precision*atan(x1)))
174 current_state%cneut=current_state%lookup_table_ustr(current_state%lookup_table_entries)/&
175 current_state%lookup_table_velocity(current_state%lookup_table_entries)
176 current_state%cfc=current_state%lookup_table_ustr(1)*current_state%lookup_table_velocity(1)**convective_limit
180 type(model_state_type),
intent(inout),
target :: current_state
182 real(kind=DEFAULT_PRECISION):: crelax,&
186 dvelustr(current_state%lookup_table_entries), ob, x1, x0
189 if (current_state%fbuoynew .le. 0.0_default_precision)
then 190 current_state%fbuoy=current_state%fbuoynew
199 if (nit .gt. 10 .or. (current_state%fbuoynew .gt. 0.0_default_precision .and. &
200 current_state%fbuoy .le. 0.0_default_precision))
then 201 current_state%fbuoy=current_state%fbuoynew
205 crelax=1./sqrt(
real(nit))
206 dfb=(current_state%fbuoynew-current_state%fbuoy)/
real(nit)
208 current_state%fbuoy=current_state%fbuoy+dfb
209 do ik=2, current_state%lookup_table_entries-1
210 dvelustr(ik)=log(current_state%lookup_table_velocity(ik+1)/current_state%lookup_table_velocity(ik-1))&
211 /log(current_state%lookup_table_ustr(ik+1)/current_state%lookup_table_ustr(ik-1))
213 dvelustr(1)=log(current_state%lookup_table_velocity(2)/current_state%lookup_table_velocity(1))/&
214 log(current_state%lookup_table_ustr(2)/current_state%lookup_table_ustr(1))
215 dvelustr(current_state%lookup_table_entries)=log(current_state%lookup_table_velocity(current_state%lookup_table_entries)/&
216 current_state%lookup_table_velocity(current_state%lookup_table_entries-1))/&
217 log(current_state%lookup_table_ustr(current_state%lookup_table_entries)/&
218 current_state%lookup_table_ustr(current_state%lookup_table_entries-1))
219 do ik=1, current_state%lookup_table_entries
221 ob=-current_state%lookup_table_ustr(ik)**3/(von_karman_constant*current_state%fbuoy)
222 x1=sqrt(sqrt(1.-gammam*(current_state%global_grid%configuration%vertical%zn(2)+z0)/ob))
223 x0=sqrt(sqrt(1.-gammam*z0/ob))
224 velnew=(current_state%lookup_table_ustr(ik)/von_karman_constant)*(current_state%global_grid%configuration%vertical%zlogm-&
225 (2.0_default_precision*log((x1+1.0_default_precision)/(x0+1.0_default_precision)) + &
226 log((x1*x1+1.0_default_precision)/(x0*x0+1.0_default_precision)) + 2.0_default_precision*atan(x0) &
227 -2.0_default_precision*atan(x1)))
229 current_state%lookup_table_ustr(ik)=current_state%lookup_table_ustr(ik)/&
230 (velnew/current_state%lookup_table_velocity(ik))**(crelax/dvelustr(ik))
233 current_state%cneut=current_state%lookup_table_ustr(current_state%lookup_table_entries)/&
234 current_state%lookup_table_velocity(current_state%lookup_table_entries)
235 current_state%cfc=current_state%lookup_table_ustr(1)*current_state%lookup_table_velocity(1)**convective_limit
236 current_state%fbuoy=current_state%fbuoynew
240 type(model_state_type),
intent(inout),
target :: current_state
242 real(kind=DEFAULT_PRECISION) :: surface_temp
244 if (current_state%type_of_surface_boundary_conditions == prescribed_surface_fluxes)
then 249 current_state%time, current_state%surface_temperature_flux, &
250 extrapolate=
'constant')
254 current_state%time, current_state%surface_vapour_flux, &
255 extrapolate=
'constant')
258 current_state%fbuoynew=0.0_default_precision
259 if (.not. current_state%passive_th) current_state%fbuoynew=&
260 current_state%global_grid%configuration%vertical%buoy_co(1)*current_state%surface_temperature_flux
261 if (.not. current_state%passive_q)
then 262 current_state%fbuoynew=current_state%fbuoynew+current_state%cq(
iqv)*current_state%surface_vapour_flux*g
265 else if (current_state%type_of_surface_boundary_conditions == prescribed_surface_values)
then 270 current_state%time, surface_temp, &
271 extrapolate=
'constant')
274 if (current_state%saturated_surface)
then 275 current_state%surface_vapour_mixing_ratio = qsaturation(surface_temp,current_state%surface_pressure*0.01)
279 current_state%time, current_state%surface_vapour_mixing_ratio, &
280 extrapolate=
'constant')
284 current_state%theta_surf = surface_temp*&
285 (current_state%surface_reference_pressure/current_state%surface_pressure)**r_over_cp
286 current_state%theta_virtual_surf = current_state%theta_surf
287 if (.not. current_state%passive_q)
then 288 current_state%theta_virtual_surf = current_state%theta_surf + &
289 current_state%global_grid%configuration%vertical%thref(2)* &
290 current_state%cq(
iqv)*current_state%surface_vapour_mixing_ratio
294 current_state%cmbc=betam*current_state%global_grid%configuration%vertical%zn(2)*g*&
295 von_karman_constant/current_state%theta_virtual_surf
296 current_state%rcmbc=1.0_default_precision/current_state%cmbc
297 current_state%ellmocon=current_state%theta_virtual_surf/(g*von_karman_constant)
304 type(model_state_type),
intent(inout),
target :: current_state
308 integer :: ncid, time_dim
309 integer :: number_input_humidities
312 current_state%use_surface_boundary_conditions= &
313 options_get_logical(current_state%options_database,
"use_surface_boundary_conditions")
315 if (current_state%use_surface_boundary_conditions)
then 316 current_state%type_of_surface_boundary_conditions=options_get_integer(current_state%options_database, &
317 "type_of_surface_boundary_conditions")
318 current_state%use_time_varying_surface_values=options_get_logical(current_state%options_database, &
319 "use_time_varying_surface_values")
321 current_state%saturated_surface = .true.
323 input_file=options_get_string(current_state%options_database,
"surface_conditions_file")
326 if (current_state%use_time_varying_surface_values)
then 331 if (current_state%type_of_surface_boundary_conditions == prescribed_surface_fluxes)
then 339 number_input_humidities=0
340 else if (current_state%type_of_surface_boundary_conditions == prescribed_surface_values)
then 346 call options_get_real_array(current_state%options_database,
"surface_temperatures",
surface_temperatures)
347 call options_get_real_array(current_state%options_database,
"surface_humidities",
surface_humidities)
348 number_input_humidities=options_get_array_size(current_state%options_database,
"surface_humidities")
352 if (log_get_logging_level() .ge. log_debug)
then 353 call log_master_log(log_debug,
"Reading in surface boundary conditions from:"//trim(
input_file) )
360 number_input_humidities=0
366 if (number_input_humidities>0)current_state%saturated_surface=.false.
372 allocate(current_state%lookup_table_velocity(current_state%lookup_table_entries), &
373 current_state%lookup_table_ustr(current_state%lookup_table_entries))
383 integer,
intent(in) :: ncid
384 integer,
intent(out) :: time_dim
385 integer :: time_dimid
389 call check_status(nf90_inquire_dimension(ncid, time_dimid, len=time_dim))
398 subroutine read_variables(filename, ncid, time_dim, time, surface_temperatures, surface_humidities, &
399 surface_latent_heat_flux, surface_sensible_heat_flux )
400 character(*),
intent(in) :: filename
401 integer,
intent(in) :: ncid, time_dim
402 real(kind=DEFAULT_PRECISION),
dimension(:),
allocatable,
intent(inout) :: time
403 real(kind=DEFAULT_PRECISION),
dimension(:),
allocatable,
intent(inout) :: surface_temperatures
404 real(kind=DEFAULT_PRECISION),
dimension(:),
allocatable,
intent(inout) :: surface_humidities
405 real(kind=DEFAULT_PRECISION),
dimension(:),
allocatable,
intent(inout) :: surface_latent_heat_flux
406 real(kind=DEFAULT_PRECISION),
dimension(:),
allocatable,
intent(inout) :: surface_sensible_heat_flux
408 integer :: status, variable_id
414 status=nf90_inq_varid(ncid,
time_key, variable_id)
415 if (status==nf90_noerr)
then 416 allocate(time(time_dim))
419 call log_log(log_error,
"No recognized time variable found in"//trim(filename))
423 if (status==nf90_noerr)
then 424 allocate(surface_temperatures(time_dim))
429 if (status==nf90_noerr)
then 430 allocate(surface_humidities(time_dim))
435 if (status==nf90_noerr)
then 436 allocate(surface_latent_heat_flux(time_dim))
441 if (status==nf90_noerr)
then 442 allocate(surface_sensible_heat_flux(time_dim))
454 integer,
intent(in) :: ncid
455 character(len=*),
intent(in) :: key
456 real(kind=DEFAULT_PRECISION),
dimension(:),
intent(inout),
optional :: data1d
457 real(kind=DEFAULT_PRECISION),
dimension(:,:,:),
intent(inout),
optional :: data3d
459 integer :: variable_id
460 real(kind=DEFAULT_PRECISION),
dimension(:,:,:),
allocatable :: sdata
462 call check_status(nf90_inq_varid(ncid, key, variable_id))
464 if (.not.
present(data1d) .and. .not.
present(data3d))
return 466 if (
present(data1d))
then 467 call check_status(nf90_get_var(ncid, variable_id, data1d))
470 allocate(sdata(
size(data3d,1),
size(data3d,3),
size(data3d,2)))
471 call check_status(nf90_get_var(ncid, variable_id, sdata))
472 data3d(:,:,:)=reshape(sdata(:,:,:),(/
size(data3d,1),
size(data3d,2),
size(data3d,3)/))
481 integer,
intent(in) :: status
483 if (status /= nf90_noerr)
then 484 call log_log(log_error,
"NetCDF returned error code of "//trim(nf90_strerror(status)))
character(len= *), parameter time_key
NetCDF data time key.
integer function, public options_get_array_size(options_database, key)
Gets the size of the array held in the options database corresponding to a specific key...
integer, parameter lookup_entries
Number of entries for MO lookup tables.
subroutine set_look(current_state)
subroutine change_look(current_state)
type(standard_q_names_type), public standard_q_names
character(len= *), parameter surface_humidities_key
NetCDF data surface_humidities.
integer, parameter max_surface_inputs
Specifies the maximum number of surface inputs through configuration file Inputs through netcdf files...
integer, parameter, public log_error
Only log ERROR messages.
character(len=string_length) function, public options_get_string(options_database, key, index)
Retrieves a string value from the database that matches the provided key.
subroutine read_dimensions(ncid, time_dim)
Reads the dimensions from the NetCDF file.
character(max_file_len) input_file
subroutine initialisation_callback(current_state)
subroutine interpolate_point_linear_1d(zvals, vals, z, f, extrapolate)
Does a simple 1d linear interpolation to a point.
subroutine read_single_variable(ncid, key, data1d, data3d)
Reads a single variable out of a NetCDF file.
integer, parameter, public default_precision
MPI communication type which we use for the prognostic and calculation data.
integer, parameter, public z_index
Grid index parameters.
character(len= *), parameter surface_lhf_key
NetCDF data surface_latent_heat_flux.
Contains common definitions for the data and datatypes used by MONC.
The ModelState which represents the current state of a run.
real(kind=default_precision), dimension(:), allocatable surface_latent_heat_flux
subroutine, public log_master_log(level, message)
Will log just from the master process.
integer, parameter, public log_debug
Log DEBUG, INFO, WARNING and ERROR messages.
Description of a component.
integer, parameter, public prescribed_surface_fluxes
character(len= *), parameter surface_temperatures_key
NetCDF data surface_temperatures.
subroutine read_variables(filename, ncid, time_dim, time, surface_temperatures, surface_humidities, surface_latent_heat_flux, surface_sensible_heat_flux)
Reads the variables from the NetCDF KiD model file.
Saturation physics functionality which is used throughout the code.
character(len= *), parameter surface_shf_key
NetCDF data surface_sensible_heat_flux.
subroutine, public log_log(level, message, str)
Logs a message at the specified level. If the level is above the current level then the message is ig...
Scientific constant values used throughout simulations. Each has a default value and this can be over...
Map data structure that holds string (length 20 maximum) key value pairs.
This manages the Q variables and specifically the mapping between names and the index that they are s...
real(kind=default_precision) max_change_buoyancy_flux
Interfaces and types that MONC components must specify.
real(kind=default_precision), dimension(:), allocatable surface_sensible_heat_flux
Collection data structures.
integer, parameter, public log_warn
Log WARNING and ERROR messages.
real(kind=default_precision) function, public qsaturation(temperature, pressure)
Function to return the saturation mixing ratio over water based on tetans formular QS=3...
integer, parameter, public prescribed_surface_values
real(kind=default_precision) function, public options_get_real(options_database, key, index)
Retrieves a real value from the database that matches the provided key.
real(kind=default_precision), dimension(:), allocatable surface_boundary_input_times
Functionality to support the different types of grid and abstraction between global grids and local o...
integer function, public options_get_integer(options_database, key, index)
Retrieves an integer value from the database that matches the provided key.
Manages the options database. Contains administration functions and deduce runtime options from the c...
integer, parameter, public log_info
Log INFO, WARNING and ERROR messages.
logical function, public options_get_logical(options_database, key, index)
Retrieves a logical value from the database that matches the provided key.
subroutine check_status(status)
Will check a NetCDF status and write to log_log error any decoded statuses.
real(kind=default_precision), dimension(:), allocatable surface_humidities
subroutine set_flux(current_state)
subroutine, public options_get_real_array(options_database, key, array_data, from, to)
Retrieves an entire (or subset) real array.
The model state which represents the current state of a run.
integer function, public log_get_logging_level()
Retrieves the current logging level.
real(kind=default_precision), dimension(:), allocatable surface_temperatures
integer, parameter max_file_len
Maximum length of surface condition input filename.
subroutine read_configuration(current_state)
integer function, public get_q_index(name, assigning_component)
Add in a new entry into the register if the name does not already exist or return the index of the pr...
subroutine timestep_callback(current_state)
type(component_descriptor_type) function, public setfluxlook_get_descriptor()
Descriptor of this component for registration.