85 character(len=100),
parameter :: PARTMC_VERSION =
"2.3.0"
88 integer,
parameter :: OUTPUT_TYPE_INVALID = 0
91 integer,
parameter :: OUTPUT_TYPE_CENTRAL = 1
94 integer,
parameter :: OUTPUT_TYPE_DIST = 2
97 integer,
parameter :: OUTPUT_TYPE_SINGLE = 3
100 integer,
parameter :: TAG_OUTPUT_STATE_CENTRAL = 4341
102 integer,
parameter :: TAG_OUTPUT_STATE_SINGLE = 4342
110 gas_data, gas_state, env_state, index, time, del_t, i_repeat, &
111 record_removals, record_optical, uuid)
114 character(len=*),
intent(in) :: prefix
116 integer,
intent(in) :: output_type
128 integer,
intent(in) :: index
130 real(kind=dp),
intent(in) :: time
132 real(kind=dp),
intent(in) :: del_t
134 integer,
intent(in) :: i_repeat
136 logical,
intent(in) :: record_removals
138 logical,
intent(in) :: record_optical
140 character(len=PMC_UUID_LEN),
intent(in) :: uuid
142 integer :: rank, n_proc
147 integer :: ierr, status(mpi_status_size), i_proc, position
148 character,
allocatable :: buffer(:)
153 if (output_type == output_type_central)
then
157 call output_state_to_file(prefix, aero_data, aero_state, gas_data, &
158 gas_state, env_state, index, time, del_t, i_repeat, &
159 record_removals, record_optical, uuid, rank, n_proc)
161 do i_proc = 1,(n_proc - 1)
163 index, time, del_t, i_repeat, record_removals, &
164 record_optical, uuid, i_proc)
170 elseif (output_type == output_type_dist)
then
172 call output_state_to_file(prefix, aero_data, aero_state, gas_data, &
173 gas_state, env_state, index, time, del_t, i_repeat, &
174 record_removals, record_optical, uuid, rank, n_proc)
175 elseif (output_type == output_type_single)
then
176 if (n_proc == 1)
then
177 call output_state_to_file(prefix, aero_data, aero_state, gas_data, &
178 gas_state, env_state, index, time, del_t, i_repeat, &
179 record_removals, record_optical, uuid, rank, n_proc)
193 call output_state_to_file(prefix, aero_data, aero_state_write, &
194 gas_data, gas_state_write, env_state_write, index, time, &
195 del_t, i_repeat, record_removals, record_optical, uuid, &
204 call
die_msg(626743323,
"Unknown output_type: " &
214 write_rank, write_n_proc)
217 character(len=*),
intent(out) :: filename
219 character(len=*),
intent(in) :: prefix
221 character(len=*),
intent(in) :: suffix
223 integer,
intent(in),
optional :: index
225 integer,
intent(in),
optional :: i_repeat
227 integer,
intent(in),
optional :: write_rank
229 integer,
intent(in),
optional :: write_n_proc
231 integer :: ncid, use_rank, use_n_proc
232 character(len=100) :: proc_string, index_string, repeat_string
234 if (present(write_rank))
then
235 use_rank = write_rank
239 if (present(write_n_proc))
then
240 use_n_proc = write_n_proc
248 if (present(i_repeat))
write(repeat_string,
'(a,i4.4)')
'_', i_repeat
249 if (use_n_proc > 1)
write(proc_string,
'(a,i4.4)')
'_', (use_rank + 1)
250 if (present(index))
write(index_string,
'(a,i8.8)')
'_', index
251 write(filename,
'(a,a,a,a,a)') trim(prefix), trim(repeat_string), &
252 trim(proc_string), trim(index_string), trim(suffix)
262 integer,
intent(in) :: ncid
264 real(kind=dp),
intent(in) :: time
266 real(kind=dp),
intent(in) :: del_t
268 integer,
intent(in) :: index
271 description=
"time elapsed since simulation start")
273 description=
"current timestep size")
275 description=
"an integer that is 1 on the first timestep, " &
276 //
"2 on the second timestep, etc.")
284 subroutine output_state_to_file(prefix, aero_data, aero_state, gas_data, &
285 gas_state, env_state, index, time, del_t, i_repeat, record_removals, &
286 record_optical, uuid, write_rank, write_n_proc)
289 character(len=*),
intent(in) :: prefix
301 integer,
intent(in) :: index
303 real(kind=dp),
intent(in) :: time
305 real(kind=dp),
intent(in) :: del_t
307 integer,
intent(in) :: i_repeat
309 logical,
intent(in) :: record_removals
311 logical,
intent(in) :: record_optical
313 character(len=PMC_UUID_LEN),
intent(in) :: uuid
315 integer,
intent(in),
optional :: write_rank
317 integer,
intent(in),
optional :: write_n_proc
319 character(len=len(prefix)+100) :: filename
369 call
make_filename(filename, prefix,
".nc", index, i_repeat, write_rank, &
373 "PartMC version " // trim(partmc_version), write_rank, write_n_proc)
376 description=
"repeat number of this simulation (starting from 1)")
378 call env_state_output_netcdf(env_state, ncid)
379 call gas_data_output_netcdf(gas_data, ncid)
380 call gas_state_output_netcdf(gas_state, ncid, gas_data)
381 call aero_data_output_netcdf(aero_data, ncid)
382 call aero_state_output_netcdf(aero_state, ncid, aero_data, &
383 record_removals, record_optical)
387 end subroutine output_state_to_file
402 integer :: buffer_size, max_buffer_size, position, ierr
403 character,
allocatable :: buffer(:)
408 max_buffer_size = max_buffer_size &
410 max_buffer_size = max_buffer_size &
412 max_buffer_size = max_buffer_size &
414 allocate(buffer(max_buffer_size))
419 call
assert(839343839, position <= max_buffer_size)
420 buffer_size = position
421 call mpi_send(buffer, buffer_size, mpi_character, 0, &
422 tag_output_state_central, mpi_comm_world, ierr)
434 time, del_t, i_repeat, record_removals, record_optical, uuid, &
438 character(len=*),
intent(in) :: prefix
444 integer,
intent(in) :: index
446 real(kind=dp),
intent(in) :: time
448 real(kind=dp),
intent(in) :: del_t
450 integer,
intent(in) :: i_repeat
452 logical,
intent(in) :: record_removals
454 logical,
intent(in) :: record_optical
456 character(len=PMC_UUID_LEN),
intent(in) :: uuid
458 integer,
intent(in) :: remote_proc
464 integer :: buffer_size, position, status(mpi_status_size)
465 integer :: n_proc, ierr
466 character,
allocatable :: buffer(:)
469 call
assert(291452117, remote_proc /= 0)
473 call mpi_probe(remote_proc, tag_output_state_central, mpi_comm_world, &
476 call mpi_get_count(status, mpi_character, buffer_size, ierr)
479 allocate(buffer(buffer_size))
480 call mpi_recv(buffer, buffer_size, mpi_character, remote_proc, &
481 tag_output_state_central, mpi_comm_world, status, ierr)
492 call
assert(279581330, position == buffer_size)
495 call output_state_to_file(prefix, aero_data, aero_state, gas_data, &
496 gas_state, env_state, index, time, del_t, i_repeat, &
497 record_removals, record_optical, uuid, remote_proc, n_proc)
509 subroutine input_state(filename, index, time, del_t, i_repeat, uuid, &
510 aero_data, aero_state, gas_data, gas_state, env_state)
513 character(len=*),
intent(in) :: filename
515 integer,
intent(out) :: index
517 real(kind=dp),
intent(out) :: time
519 real(kind=dp),
intent(out) :: del_t
521 integer,
intent(out) :: i_repeat
523 character(len=PMC_UUID_LEN),
intent(out) :: uuid
525 type(aero_data_t),
optional,
intent(inout) :: aero_data
527 type(aero_state_t),
optional,
intent(inout) :: aero_state
529 type(gas_data_t),
optional,
intent(inout) :: gas_data
531 type(gas_state_t),
optional,
intent(inout) :: gas_state
533 type(env_state_t),
optional,
intent(inout) :: env_state
538 "can only call from process 0")
542 call
pmc_nc_check(nf90_get_att(ncid, nf90_global,
"UUID", uuid))
549 if (present(aero_data))
then
551 if (present(aero_state))
then
555 call
assert_msg(289621231, present(aero_state) .eqv. .false., &
556 "cannot input aero_state without aero_data")
559 if (present(gas_data))
then
561 if (present(gas_state))
then
565 call
assert_msg(874298496, present(gas_state) .eqv. .false., &
566 "cannot input gas_state without gas_data")
569 if (present(env_state))
then
583 character(len=*),
intent(in) :: prefix
585 character(len=*),
intent(inout),
allocatable :: filename_list(:)
587 integer :: n_file, index, unit, ios
588 character(len=len(prefix)+100) :: filename
592 "can only call from process 0")
597 do while (.not. done)
598 write(filename,
'(a,a,i8.8,a)') trim(prefix),
'_', index,
'.nc'
599 open(unit=unit, file=filename, status=
'old', iostat=ios)
612 write(filename,
'(a,a,i8.8,a)') trim(prefix),
'_', index,
'.nc'
613 filename_list(index) = filename
624 character(len=*),
intent(in) :: prefix
626 integer,
intent(out) :: n_repeat
628 integer,
intent(out) :: n_index
630 integer :: repeat, index, unit, ios
631 character(len=len(prefix)+100) :: filename
635 "can only call from process 0")
642 do while (.not. done)
644 open(unit=unit, file=filename, status=
'old', iostat=ios)
652 n_repeat = repeat - 1
654 "no files found with prefix: " // trim(prefix))
659 do while (.not. done)
661 open(unit=unit, file=filename, status=
'old', iostat=ios)
677 gas_data, gas_state, env_state, index, time, del_t, uuid)
680 character(len=*),
intent(in) :: prefix
694 integer,
intent(in) :: index
696 real(kind=dp),
intent(in) :: time
698 real(kind=dp),
intent(in) :: del_t
700 character(len=PMC_UUID_LEN),
intent(in) :: uuid
703 character(len=len(prefix)+100) :: filename
705 write(filename,
'(a,a,i8.8,a)') trim(prefix), &
709 "PartMC version " // trim(partmc_version))
713 call env_state_output_netcdf(env_state, ncid)
714 call gas_data_output_netcdf(gas_data, ncid)
715 call gas_state_output_netcdf(gas_state, ncid, gas_data)
716 call aero_data_output_netcdf(aero_data, ncid)
717 call aero_binned_output_netcdf(aero_binned, ncid, bin_grid, &
728 aero_data, aero_binned, gas_data, gas_state, env_state)
731 character(len=*),
intent(in) :: filename
733 integer,
intent(out) :: index
735 real(kind=dp),
intent(out) :: time
737 real(kind=dp),
intent(out) :: del_t
739 character(len=PMC_UUID_LEN),
intent(out) :: uuid
741 type(bin_grid_t),
optional,
intent(inout) :: bin_grid
743 type(aero_data_t),
optional,
intent(inout) :: aero_data
747 type(gas_data_t),
optional,
intent(inout) :: gas_data
749 type(gas_state_t),
optional,
intent(inout) :: gas_state
751 type(env_state_t),
optional,
intent(inout) :: env_state
756 "can only call from process 0")
760 call
pmc_nc_check(nf90_get_att(ncid, nf90_global,
"UUID", uuid))
766 if (present(bin_grid))
then
769 if (present(aero_data))
then
772 if (present(aero_binned))
then
774 present(bin_grid) .and. present(aero_data), &
775 "cannot input aero_binned without bin_grid and aero_data")
780 if (present(gas_data))
then
782 if (present(gas_state))
then
786 call
assert_msg(214545112, present(gas_state) .eqv. .false., &
787 "cannot input gas_state without gas_data")
790 if (present(env_state))
then
802 subroutine spec_file_read_output_type(file, output_type)
807 integer,
intent(out) :: output_type
809 character(len=SPEC_LINE_MAX_VAR_LEN) :: output_type_name
824 if (trim(output_type_name) ==
'central')
then
825 output_type = output_type_central
826 elseif (trim(output_type_name) ==
'dist')
then
827 output_type = output_type_dist
828 elseif (trim(output_type_name) ==
'single')
then
829 output_type = output_type_single
832 "Unknown output type: " // trim(output_type_name))
835 end subroutine spec_file_read_output_type
subroutine recv_output_state_central(prefix, aero_data, gas_data, index, time, del_t, i_repeat, record_removals, record_optical, uuid, remote_proc)
Receive the state for the "central" output method on the root process.
An input file with extra data for printing messages.
subroutine input_state(filename, index, time, del_t, i_repeat, uuid, aero_data, aero_state, gas_data, gas_state, env_state)
Read the current state.
The aero_data_t structure and associated subroutines.
integer function pmc_mpi_pack_size_aero_state(val)
Determines the number of bytes required to pack the given value.
subroutine die_msg(code, error_msg)
Error immediately.
subroutine input_filename_list(prefix, filename_list)
Find all NetCDF (.nc) filenames that match the given prefix.
subroutine pmc_mpi_pack_env_state(buffer, position, val)
Packs the given value into the buffer, advancing position.
subroutine ensure_string_array_size(x, n)
Allocate or reallocate the given array to ensure it is of the given size, without preserving data...
integer function pmc_mpi_pack_size_gas_state(val)
Determines the number of bytes required to pack the given value.
subroutine input_n_files(prefix, n_repeat, n_index)
Find the number of repeats and indices for the given prefix.
subroutine gas_data_input_netcdf(gas_data, ncid)
Read full state.
The env_state_t structure and associated subroutines.
subroutine aero_state_allocate(aero_state)
Allocates aerosol arrays.
subroutine pmc_nc_check(status)
Check the status of a NetCDF function call.
subroutine pmc_nc_read_integer(ncid, var, name, must_be_present)
Read a single integer from a NetCDF file.
subroutine make_filename(filename, prefix, suffix, index, i_repeat, write_rank, write_n_proc)
Make a filename from a given prefix and other information.
subroutine pmc_mpi_pack_gas_state(buffer, position, val)
Packs the given value into the buffer, advancing position.
subroutine aero_state_mpi_gather(aero_state, aero_state_total)
Gathers data from all processes into one aero_state on process 0.
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
subroutine output_state(prefix, output_type, aero_data, aero_state, gas_data, gas_state, env_state, index, time, del_t, i_repeat, record_removals, record_optical, uuid)
Write the current state.
subroutine bin_grid_input_netcdf(bin_grid, ncid, dim_name, scale)
Read full state.
The gas_data_t structure and associated subroutines.
integer function pmc_mpi_size()
Returns the total number of processes.
Common utility subroutines.
Current environment state.
subroutine env_state_deallocate(env_state)
Free all storage.
subroutine send_output_state_central(aero_state, gas_state, env_state)
Send the state for the "central" output method to the root process.
The aero_state_t structure and assocated subroutines.
subroutine pmc_mpi_unpack_env_state(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
integer function pmc_mpi_rank()
Returns the rank of the current process.
Wrapper functions for MPI.
subroutine gas_state_deallocate(gas_state)
Free all storage.
subroutine spec_file_read_string(file, name, var)
Read a string from a spec file that must have a given name.
The gas_state_t structure and associated subroutines.
subroutine gas_state_allocate(gas_state)
Allocate storage for gas species.
subroutine env_state_input_netcdf(env_state, ncid)
Read full state.
subroutine input_sectional(filename, index, time, del_t, uuid, bin_grid, aero_data, aero_binned, gas_data, gas_state, env_state)
Input sectional data.
character(len=pmc_util_convert_string_len) function integer_to_string(val)
Convert an integer to a string format.
The current collection of aerosol particles.
subroutine pmc_mpi_pack_aero_state(buffer, position, val)
Packs the given value into the buffer, advancing position.
1D grid, either logarithmic or linear.
subroutine pmc_mpi_check_ierr(ierr)
Dies if ierr is not ok.
subroutine pmc_nc_write_info(ncid, uuid, source, write_rank, write_n_proc)
Write basic information to a NetCDF file.
subroutine env_state_copy(env_from, env_to)
env_to = env_from
The bin_grid_t structure and associated subroutines.
subroutine aero_state_deallocate(aero_state)
Deallocates a previously allocated aerosol.
subroutine pmc_nc_write_real(ncid, var, name, unit, long_name, standard_name, description)
Write a single real to a NetCDF file.
subroutine pmc_nc_close(ncid)
Close a NetCDF file.
subroutine write_time(ncid, time, del_t, index)
Helper routine to write time variables. Do not call directly.
integer function get_unit()
Returns an available unit number. This should be freed by free_unit().
The aero_binned_t structure and associated subroutines.
subroutine aero_state_input_netcdf(aero_state, ncid, aero_data)
Read full state.
subroutine gas_state_input_netcdf(gas_state, ncid, gas_data)
Read full state.
Wrapper functions for NetCDF. These all take a NetCDF ncid in data mode and return with it again in d...
subroutine spec_file_die_msg(code, file, msg)
Exit with an error message containing filename and line number.
subroutine pmc_nc_open_read(filename, ncid)
Open a NetCDF file for reading.
subroutine aero_data_input_netcdf(aero_data, ncid)
Read full state.
subroutine pmc_mpi_unpack_aero_state(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Current state of the gas mixing ratios in the system.
subroutine aero_binned_input_netcdf(aero_binned, ncid, bin_grid, aero_data)
Read full state.
subroutine pmc_nc_open_write(filename, ncid)
Open a NetCDF file for writing.
subroutine pmc_nc_write_integer(ncid, var, name, unit, long_name, standard_name, description)
Write a single integer to a NetCDF file.
subroutine env_state_reduce_avg(val)
Average val over all processes, with the result only on the root process.
subroutine pmc_nc_read_real(ncid, var, name, must_be_present)
Read a single real from a NetCDF file.
subroutine env_state_allocate(env_state)
Allocate an empty environment.
Aerosol material properties and associated data.
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
subroutine free_unit(unit)
Frees a unit number returned by get_unit().
Write data in NetCDF format.
integer function pmc_mpi_pack_size_env_state(val)
Determines the number of bytes required to pack the given value.
subroutine gas_state_reduce_avg(val)
Average val over all processes, with the result only on the root process.
Aerosol number and volume distributions stored per bin.
subroutine gas_state_copy(from_state, to_state)
Copy to an already allocated to_state.
subroutine output_sectional(prefix, bin_grid, aero_data, aero_binned, gas_data, gas_state, env_state, index, time, del_t, uuid)
Write the current sectional data.
subroutine pmc_mpi_unpack_gas_state(buffer, position, val)
Unpacks the given value from the buffer, advancing position.