137 integer(kind=i_kind) :: size_state_per_cell
139 integer(kind=i_kind) :: n_cells = 1
141 real(kind=
dp),
allocatable :: init_state(:)
146 real(kind=
dp) :: rel_tol = 0.0
149 real(kind=
dp),
allocatable :: abs_tol(:)
151 integer(kind=i_kind),
allocatable :: var_type(:)
159 logical :: core_is_initialized = .
false.
161 logical :: solver_is_initialized = .
false.
207 generic :: initialize_update_object => &
215 generic :: update_data => &
258 character(len=*),
intent(in),
optional :: input_file_path
260 integer(kind=i_kind),
optional :: n_cells
263 allocate(new_obj%mechanism(0))
265 allocate(new_obj%aero_phase(0))
266 allocate(new_obj%aero_rep(0))
267 allocate(new_obj%sub_model(0))
269 if (
present(n_cells))
then
270 new_obj%n_cells=n_cells
273 if (
present(input_file_path))
then
274 call new_obj%load_files(trim(input_file_path))
308 character(len=*),
intent(in) :: input_file_path
311 type(json_core),
target :: json
312 type(json_file) :: j_file
313 type(json_value),
pointer :: j_obj, j_next
315 logical(kind=json_lk) :: found, valid
316 character(kind=json_ck, len=:),
allocatable :: unicode_str_val
317 character(kind=json_ck, len=:),
allocatable :: json_err_msg
318 integer(kind=json_ik) :: i_file, num_files
319 type(
string_t),
allocatable :: file_list(:)
320 logical :: file_exists
323 call j_file%initialize()
324 call j_file%get_core(json)
325 call assert_msg(600888426, trim(input_file_path).ne.
"", &
326 "Received empty string for file path")
327 inquire( file=trim(input_file_path), exist=file_exists )
328 call assert_msg(433777575, file_exists,
"Cannot find file: "//&
329 trim(input_file_path))
330 call j_file%load_file(filename = trim(input_file_path))
333 call j_file%get(
'camp-files(1)', j_obj, found)
335 "Could not find camp-files object in input file: "// &
337 call json%validate(j_obj, valid, json_err_msg)
339 call die_msg(959537834,
"Bad JSON format in file '"// &
340 trim(input_file_path)//
"': "//trim(json_err_msg))
342 call j_file%info(
'camp-files', n_children = num_files)
344 "No file names were found in "//input_file_path)
347 allocate(file_list(num_files))
352 do while (
associated(j_obj))
353 call json%get(j_obj, unicode_str_val)
354 file_list(i_file)%string = unicode_str_val
356 call json%get_next(j_obj, j_next)
361 call j_file%destroy()
364 call this%load(file_list)
367 call warn_msg(171627969,
"No support for input files.");
424 subroutine load(this, input_file_path)
429 type(
string_t),
allocatable,
intent(in) :: input_file_path(:)
431 integer(kind=i_kind) :: i_file, cell
433 type(json_core),
pointer :: json
434 type(json_file) :: j_file
435 type(json_value),
pointer :: j_obj, j_next
437 logical(kind=json_lk) :: valid
438 character(kind=json_ck, len=:),
allocatable :: unicode_str_val
439 character(kind=json_ck, len=:),
allocatable :: json_err_msg
440 character(len=:),
allocatable :: str_val
441 real(kind=json_rk) :: real_val
442 logical :: file_exists, found
452 logical :: sub_model_placed
453 integer(kind=i_kind) :: i_sub_model, j_sub_model
471 do i_file = 1,
size(input_file_path)
474 call j_file%initialize()
475 call j_file%get_core(json)
476 call assert_msg(366175417,
allocated(input_file_path(i_file)%string), &
477 "Received non-allocated string for file path")
478 call assert_msg(936390222, trim(input_file_path(i_file)%string).ne.
"", &
479 "Received empty string for file path")
480 inquire( file=input_file_path(i_file)%string, exist=file_exists )
481 call assert_msg(910660557, file_exists,
"Cannot file file: "// &
482 input_file_path(i_file)%string)
483 call j_file%load_file(filename = input_file_path(i_file)%string)
486 call j_file%get(
'camp-data(1)', j_obj)
487 call json%validate(j_obj, valid, json_err_msg)
489 call die_msg(560270545,
"Bad JSON format in file '"// &
490 trim(input_file_path(i_file)%string)//
"': "// &
493 do while (
associated(j_obj))
497 call json%get(j_obj,
'type', unicode_str_val, found)
499 "Missing type in json input file "// &
500 input_file_path(i_file)%string)
501 str_val = unicode_str_val
506 if (str_val.eq.
'MECHANISM')
then
507 call json%get(j_obj,
'name', unicode_str_val, found)
509 "Missing mechanism name in file "// &
510 input_file_path(i_file)%string)
511 str_val = unicode_str_val
515 if (.not.this%get_mechanism(str_val, mech_ptr))
then
516 call this%add_mechanism(str_val)
517 call assert(105816325, this%get_mechanism(str_val, mech_ptr))
519 call mech_ptr%load(json, j_obj)
522 else if (str_val.eq.
'CHEM_SPEC')
then
523 call this%chem_spec_data%load(json, j_obj)
528 else if (str_val(1:8).eq.
'AERO_REP')
then
529 aero_rep_ptr%val => aero_rep_factory%load(json, j_obj)
530 str_val = aero_rep_ptr%val%name()
534 if (this%get_aero_rep(str_val, existing_aero_rep_ptr))
then
535 deallocate(aero_rep_ptr%val)
536 call existing_aero_rep_ptr%load(json, j_obj)
538 allocate(new_aero_rep(
size(this%aero_rep)+1))
539 new_aero_rep(1:
size(this%aero_rep)) = &
540 this%aero_rep(1:
size(this%aero_rep))
541 new_aero_rep(
size(new_aero_rep))%val => aero_rep_ptr%val
542 call this%aero_rep(:)%dereference()
543 deallocate(this%aero_rep)
544 this%aero_rep => new_aero_rep
545 call aero_rep_ptr%dereference()
551 else if (str_val.eq.
'AERO_PHASE')
then
553 call aero_phase%load(json, j_obj)
554 str_val = aero_phase%name()
558 if (this%get_aero_phase(str_val, existing_aero_phase))
then
559 deallocate(aero_phase)
560 call existing_aero_phase%load(json, j_obj)
562 allocate(new_aero_phase(
size(this%aero_phase)+1))
563 new_aero_phase(1:
size(this%aero_phase)) = &
564 this%aero_phase(1:
size(this%aero_phase))
565 new_aero_phase(
size(new_aero_phase))%val => aero_phase
566 call this%aero_phase(:)%dereference()
567 deallocate(this%aero_phase)
568 this%aero_phase => new_aero_phase
574 else if (str_val(1:9).eq.
'SUB_MODEL')
then
575 sub_model_ptr%val => sub_model_factory%load(json, j_obj)
576 str_val = sub_model_ptr%val%name()
580 if (this%get_sub_model(str_val, existing_sub_model_ptr))
then
581 deallocate(sub_model_ptr%val)
582 call existing_sub_model_ptr%load(json, j_obj)
584 sub_model_placed = .
false.
585 allocate(new_sub_model(
size(this%sub_model)+1))
587 do i_sub_model = 1,
size(this%sub_model)
588 if (.not.sub_model_placed .and. &
589 sub_model_ptr%val%priority() < &
590 this%sub_model(i_sub_model)%val%priority())
then
591 sub_model_placed = .
true.
592 new_sub_model(j_sub_model)%val => sub_model_ptr%val
593 j_sub_model = j_sub_model + 1
595 new_sub_model(j_sub_model) = &
596 this%sub_model(i_sub_model)
597 j_sub_model = j_sub_model + 1
599 if (.not.sub_model_placed)
then
600 new_sub_model(j_sub_model)%val => sub_model_ptr%val
602 call this%sub_model(:)%dereference()
603 deallocate(this%sub_model)
604 this%sub_model => new_sub_model
605 call sub_model_ptr%dereference()
611 else if (str_val.eq.
'RELATIVE_TOLERANCE')
then
612 call json%get(j_obj,
'value', real_val, found)
614 "Missing value for relative tolerance")
615 call assert_msg(162564706, real_val.gt.0.0.and.real_val.lt.1.0, &
616 "Invalid relative tolerance: "// &
618 this%rel_tol = real(real_val, kind=
dp)
623 else if (str_val.eq.
'SPLIT_GAS_AERO')
then
624 this%split_gas_aero = .
true.
631 "Received invalid json input object type: "//str_val)
636 call json%get_next(j_next, j_obj)
640 call j_file%destroy()
647 call warn_msg(350136328,
"No support for input files.");
663 integer(kind=i_kind) :: i_mech, i_phase, i_aero_rep, i_sub_model
664 integer(kind=i_kind) :: i_state_var, i_spec, i_cell
668 integer(kind=i_kind) :: i_state_elem, i_name
671 character(len=:),
allocatable :: spec_name
673 type(
string_t),
allocatable :: gas_spec_names(:)
675 type(
string_t),
allocatable :: unique_names(:)
678 call assert_msg(157261665, .not.this%core_is_initialized, &
679 "Attempting to initialize a camp_core_t object twice.")
682 call this%chem_spec_data%initialize()
688 do i_phase = 1,
size(this%aero_phase)
689 call assert(254948966,
associated(this%aero_phase(i_phase)%val))
690 call this%aero_phase(i_phase)%val%initialize(this%chem_spec_data)
694 do i_aero_rep = 1,
size(this%aero_rep)
695 call assert(251590193,
associated(this%aero_rep(i_aero_rep)%val))
696 call this%aero_rep(i_aero_rep)%val%initialize(this%aero_phase, &
698 i_state_var = i_state_var + this%aero_rep(i_aero_rep)%val%size()
702 do i_sub_model = 1,
size(this%sub_model)
703 call assert(565644925,
associated(this%sub_model(i_sub_model)%val))
704 call this%sub_model(i_sub_model)%val%initialize(this%aero_rep, &
705 this%aero_phase, this%chem_spec_data)
709 this%size_state_per_cell = i_state_var - 1
712 do i_mech = 1,
size(this%mechanism)
713 call this%mechanism(i_mech)%val%initialize(this%chem_spec_data, &
714 this%aero_rep, this%n_cells)
718 allocate(this%abs_tol(this%size_state_per_cell))
719 allocate(this%var_type(this%size_state_per_cell))
726 this%chem_spec_data%get_spec_names(spec_phase = &
728 do i_spec = 1,
size(gas_spec_names)
729 i_state_var = i_state_var + 1
731 this%chem_spec_data%get_abs_tol(gas_spec_names(i_spec)%string, &
732 this%abs_tol(i_state_var)))
734 this%chem_spec_data%get_type(gas_spec_names(i_spec)%string, &
735 this%var_type(i_state_var)))
739 do i_aero_rep = 1,
size(this%aero_rep)
743 call assert(666823548,
associated(this%aero_rep(i_aero_rep)%val))
744 unique_names = this%aero_rep(i_aero_rep)%val%unique_names()
745 do i_spec = 1, this%aero_rep(i_aero_rep)%val%size()
746 i_state_var = i_state_var + 1
747 spec_name = this%aero_rep(i_aero_rep)%val%spec_name( &
750 this%chem_spec_data%get_abs_tol(
spec_name, &
751 this%abs_tol(i_state_var)))
753 this%chem_spec_data%get_type(
spec_name, &
754 this%var_type(i_state_var)))
761 call assert_msg(501609702, i_state_var.eq.this%size_state_per_cell, &
762 "Internal error. Filled "//trim(
to_string(i_state_var))// &
763 " of "//trim(
to_string(this%size_state_per_cell))// &
764 " elements of absolute tolerance and variable type arrays")
766 this%core_is_initialized = .
true.
769 allocate(this%init_state(this%size_state_per_cell * this%n_cells))
772 this%init_state(:) = 0.0
775 do i_cell = 0, this%n_cells - 1
776 do i_aero_rep = 1,
size(this%aero_rep)
778 rep => this%aero_rep(i_aero_rep)%val
785 i_state_elem = rep%spec_state_id(
unique_names(i_name)%string)
786 this%init_state(i_state_elem + i_cell * this%size_state_per_cell) = &
830 character(len=*),
intent(in) :: aero_phase_name
834 integer(kind=i_kind) :: i_aero_phase
838 if (.not.
associated(this%aero_phase))
return
839 do i_aero_phase = 1,
size(this%aero_phase)
840 if (this%aero_phase(i_aero_phase)%val%name().eq.aero_phase_name)
then
842 aero_phase => this%aero_phase(i_aero_phase)%val
852 logical function get_aero_rep(this, aero_rep_name, aero_rep)
result (found)
857 character(len=*),
intent(in) :: aero_rep_name
861 integer(kind=i_kind) :: i_aero_rep
865 if (.not.
associated(this%aero_rep))
return
866 do i_aero_rep = 1,
size(this%aero_rep)
867 if (this%aero_rep(i_aero_rep)%val%name().eq.trim(aero_rep_name))
then
868 aero_rep => this%aero_rep(i_aero_rep)%val
887 chem_spec_data => this%chem_spec_data
888 if (
associated(chem_spec_data)) found = .
true.
900 character(len=*),
intent(in) :: mech_name
904 integer(kind=i_kind) :: i_mech
908 if (.not.
associated(this%mechanism))
return
909 do i_mech = 1,
size(this%mechanism)
910 if (this%mechanism(i_mech)%val%name().eq.mech_name)
then
912 mechanism => this%mechanism(i_mech)%val
928 character(len=*),
intent(in) :: sub_model_name
932 integer(kind=i_kind) :: i_sub_model
936 if (.not.
associated(this%sub_model))
return
937 do i_sub_model = 1,
size(this%sub_model)
938 if (this%sub_model(i_sub_model)%val%name().eq.sub_model_name)
then
939 sub_model => this%sub_model(i_sub_model)%val
971 integer(kind=i_kind),
intent(in) :: spec_id
973 call assert_msg( 374310824, spec_id .ge. 1 .and. &
974 spec_id .le.
size( this%abs_tol ), &
975 "Species id out of bounds: "// &
998 allocate(new_state%state_var, source=this%init_state)
1015 type(
env_state_t),
optional,
target,
intent(in) :: env_state
1018 if (this%n_cells.eq.1)
then
1021 call assert_msg(386790682, .not.
present(env_state), &
1022 "Cannot use a single env_state_t object to create "// &
1023 "a new camp_state_t in a multi-cell system")
1028 allocate(new_state%state_var, source=this%init_state)
1042 call assert_msg(629102639,
allocated(this%init_state), &
1043 "Trying to get the size of the state array before "// &
1044 "initializing the camp_core")
1060 call assert_msg(175845182,
allocated(this%init_state), &
1061 "Trying to get the size of the state array before "// &
1062 "initializing the camp_core")
1080 integer(kind=i_kind) :: i_aero_rep
1081 type(
string_t),
allocatable :: new_names(:), temp_list(:)
1086 if( .not.
associated( this%aero_rep ) )
return
1087 do i_aero_rep = 1,
size( this%aero_rep )
1088 new_names = this%aero_rep( i_aero_rep )%val%unique_names( )
1089 if( .not.
allocated( new_names ) ) cycle
1090 if(
size( new_names ).eq.0 ) cycle
1091 allocate( temp_list(
size(
unique_names ) +
size( new_names ) ) )
1093 temp_list(
size(
unique_names ) + 1 :
size( temp_list ) ) = &
1098 if(
allocated( new_names ) )
deallocate( new_names )
1099 if(
allocated( temp_list ) )
deallocate( temp_list )
1113 character(len=*),
intent(in) ::
spec_name
1115 integer(kind=i_kind),
intent(inout) :: state_id
1117 integer(kind=i_kind) :: i_spec, i_aero_rep
1120 i_spec = this%chem_spec_data%gas_state_id(
spec_name )
1121 do i_aero_rep = 1,
size( this%aero_rep )
1122 if( i_spec .eq. 0 ) &
1123 i_spec = this%aero_rep( i_aero_rep )%val%spec_state_id(
spec_name )
1126 if( i_spec .gt. 0 )
then
1141 call assert_msg(662920365, .not.this%solver_is_initialized, &
1142 "Attempting to initialize the solver twice.")
1145 if (this%split_gas_aero)
then
1152 if (this%rel_tol.ne.real(0.0, kind=
dp))
then
1153 this%solver_data_gas%rel_tol = this%rel_tol
1154 this%solver_data_aero%rel_tol = this%rel_tol
1158 call this%solver_data_gas%initialize( &
1168 call this%solver_data_aero%initialize( &
1184 if (this%rel_tol.ne.0.0)
then
1185 this%solver_data_gas_aero%rel_tol = this%rel_tol
1189 call this%solver_data_gas_aero%initialize( &
1202 this%solver_is_initialized = .
true.
1214 if(
associated( this%solver_data_gas ) ) &
1215 deallocate( this%solver_data_gas )
1216 if(
associated( this%solver_data_aero ) ) &
1217 deallocate( this%solver_data_aero )
1218 if(
associated( this%solver_data_gas_aero ) ) &
1219 deallocate( this%solver_data_gas_aero )
1237 call assert_msg( 962343826, .not. this%is_solver_initialized( ), &
1238 "Cannot initialize update data objects after the "// &
1239 "solver has been initialized." )
1240 call factory%initialize_update_data(aero_rep, update_data)
1258 call assert_msg( 166064689, .not. this%is_solver_initialized( ), &
1259 "Cannot initialize update data objects after the "// &
1260 "solver has been initialized." )
1261 call factory%initialize_update_data(rxn, update_data)
1279 call assert_msg( 771607586, .not. this%is_solver_initialized( ), &
1280 "Cannot initialize update data objects after the "// &
1281 "solver has been initialized." )
1282 call factory%initialize_update_data(sub_model, update_data)
1300 if (
associated(this%solver_data_gas)) &
1301 call this%solver_data_gas%update_aero_rep_data(update_data)
1302 if (
associated(this%solver_data_aero)) &
1303 call this%solver_data_aero%update_aero_rep_data(update_data)
1304 if (
associated(this%solver_data_gas_aero)) &
1305 call this%solver_data_gas_aero%update_aero_rep_data(update_data)
1322 if (
associated(this%solver_data_gas)) &
1323 call this%solver_data_gas%update_rxn_data(update_data)
1324 if (
associated(this%solver_data_aero)) &
1325 call this%solver_data_aero%update_rxn_data(update_data)
1326 if (
associated(this%solver_data_gas_aero)) &
1327 call this%solver_data_gas_aero%update_rxn_data(update_data)
1342 if (
associated(this%solver_data_gas)) &
1343 call this%solver_data_gas%update_sub_model_data(update_data)
1344 if (
associated(this%solver_data_aero)) &
1345 call this%solver_data_aero%update_sub_model_data(update_data)
1346 if (
associated(this%solver_data_gas_aero)) &
1347 call this%solver_data_gas_aero%update_sub_model_data(update_data)
1354 subroutine solve(this, camp_state, time_step, rxn_phase, solver_stats)
1363 type(
camp_state_t),
intent(inout),
target :: camp_state
1365 real(kind=
dp),
intent(in) :: time_step
1369 integer(kind=i_kind),
intent(in),
optional :: rxn_phase
1371 type(
solver_stats_t),
intent(inout),
optional,
target :: solver_stats
1374 integer(kind=i_kind) :: phase
1378 call assert_msg(593328365, this%solver_is_initialized, &
1379 "Trying to solve system with uninitialized solver" )
1382 if (
present(rxn_phase))
then
1389 call camp_state%update_env_state( )
1393 solver => this%solver_data_gas
1395 solver => this%solver_data_aero
1397 solver => this%solver_data_gas_aero
1399 call die_msg(704896254,
"Invalid rxn phase specified for chemistry "// &
1404 call assert_msg(730097030,
associated(solver),
"Invalid solver requested")
1407 if (
present(solver_stats))
then
1408 call solver%solve(camp_state, real(0.0, kind=
dp), time_step, &
1411 call solver%solve(camp_state, real(0.0, kind=
dp), time_step)
1414 end subroutine solve
1424 integer,
intent(in),
optional :: comm
1430 integer(kind=i_kind) :: i_mech, i_phase, i_rep, i_sub_model, l_comm
1433 if (
present(comm))
then
1436 l_comm = mpi_comm_world
1439 call assert_msg(143374295, this%core_is_initialized, &
1440 "Trying to get the buffer size of an uninitialized core.")
1446 do i_mech = 1,
size(this%mechanism)
1449 do i_phase = 1,
size(this%aero_phase)
1452 do i_rep = 1,
size(this%aero_rep)
1453 aero_rep => this%aero_rep(i_rep)%val
1457 do i_sub_model = 1,
size(this%sub_model)
1458 sub_model => this%sub_model(i_sub_model)%val
1483 character,
intent(inout) :: buffer(:)
1485 integer,
intent(inout) :: pos
1487 integer,
intent(in),
optional :: comm
1494 integer(kind=i_kind) :: i_mech, i_phase, i_rep, i_sub_model, &
1495 prev_position, l_comm
1497 if (
present(comm))
then
1500 l_comm = mpi_comm_world
1503 call assert_msg(143374295, this%core_is_initialized, &
1504 "Trying to pack an uninitialized core.")
1511 do i_mech = 1,
size(this%mechanism)
1512 call this%mechanism(i_mech)%val%bin_pack(buffer, pos, l_comm)
1514 do i_phase = 1,
size(this%aero_phase)
1515 call this%aero_phase(i_phase)%val%bin_pack(buffer, pos, l_comm)
1517 do i_rep = 1,
size(this%aero_rep)
1518 aero_rep => this%aero_rep(i_rep)%val
1519 call aero_rep_factory%bin_pack(aero_rep, buffer, pos, l_comm)
1522 do i_sub_model = 1,
size(this%sub_model)
1523 sub_model => this%sub_model(i_sub_model)%val
1524 call sub_model_factory%bin_pack(sub_model, buffer, pos, l_comm)
1535 pos - prev_position <= this%pack_size(l_comm))
1548 character,
intent(inout) :: buffer(:)
1550 integer,
intent(inout) :: pos
1552 integer,
intent(in),
optional :: comm
1557 integer(kind=i_kind) :: i_mech, i_phase, i_rep, i_sub_model, &
1558 prev_position, num_mech, num_phase, num_rep, num_sub_model, &
1561 if (
present(comm))
then
1564 l_comm = mpi_comm_world
1575 allocate(this%mechanism(num_mech))
1576 allocate(this%aero_phase(num_phase))
1577 allocate(this%aero_rep(num_rep))
1578 allocate(this%sub_model(num_sub_model))
1579 do i_mech = 1, num_mech
1581 call this%mechanism(i_mech)%val%bin_unpack(buffer, pos, l_comm)
1583 do i_phase = 1, num_phase
1585 call this%aero_phase(i_phase)%val%bin_unpack(buffer, pos, l_comm)
1587 do i_rep = 1, num_rep
1588 this%aero_rep(i_rep)%val => aero_rep_factory%bin_unpack(buffer, pos, l_comm)
1590 do i_sub_model = 1, num_sub_model
1591 this%sub_model(i_sub_model)%val => &
1592 sub_model_factory%bin_unpack(buffer, pos, l_comm)
1601 this%core_is_initialized = .
true.
1603 pos - prev_position <= this%pack_size(l_comm))
1616 integer(kind=i_kind),
intent(in),
optional :: file_unit
1618 logical,
intent(in),
optional :: solver_data_only
1620 integer(kind=i_kind) :: i_gas_spec, i_spec, j_spec, i_phase, i_aero_rep, i_mech
1621 integer(kind=i_kind) :: i_sub_model, i_solver_spec
1622 integer(kind=i_kind) :: f_unit
1623 type(
string_t),
allocatable :: state_names(:), rep_spec_names(:)
1629 if (
present(file_unit)) f_unit = file_unit
1630 if (
present(solver_data_only)) sd_only = solver_data_only
1632 write(f_unit,*)
"*********************"
1633 write(f_unit,*)
"** CAMP core data **"
1634 write(f_unit,*)
"*********************"
1635 if (.not.sd_only )
then
1636 write(f_unit,*)
"Number of grid cells to solve simultaneously: ", &
1638 write(f_unit,*)
"Relative integration tolerance: ", this%rel_tol
1639 call this%chem_spec_data%print(f_unit)
1640 write(f_unit,*)
"*** Aerosol Phases ***"
1641 do i_phase=1,
size(this%aero_phase)
1642 call this%aero_phase(i_phase)%val%print(f_unit)
1644 write(f_unit,*)
"*** Aerosol Representations ***"
1645 do i_aero_rep=1,
size(this%aero_rep)
1646 write(f_unit,*)
"Aerosol representation ", i_aero_rep
1647 call this%aero_rep(i_aero_rep)%val%print(f_unit)
1649 write(f_unit,*)
"*** Sub Models ***"
1650 do i_sub_model=1,
size(this%sub_model)
1651 write(f_unit,*)
"Sub model: ", i_sub_model
1652 call this%sub_model(i_sub_model)%val%print(f_unit)
1654 write(f_unit,*)
"*** Mechanisms ***"
1655 write(f_unit,*)
"Number of mechanisms: ",
size(this%mechanism)
1656 do i_mech=1,
size(this%mechanism)
1657 call this%mechanism(i_mech)%val%print(f_unit)
1659 write(f_unit,*)
"*** State Array ***"
1660 write(f_unit,*)
"Number of species on the state array per grid cell: ", &
1661 this%size_state_per_cell
1662 allocate(state_names(this%size_state_per_cell))
1664 do i_gas_spec = 1, &
1667 state_names(i_spec)%string = &
1668 this%chem_spec_data%gas_state_name(i_gas_spec)
1670 write(f_unit,*)
"Gas-phase species: ", i_spec
1671 do i_aero_rep = 1,
size(this%aero_rep)
1672 rep_spec_names = this%aero_rep(i_aero_rep)%val%unique_names()
1673 call assert(620697091,
allocated(rep_spec_names))
1674 call assert(787495222,
size(rep_spec_names).gt.0)
1675 forall (j_spec=1:
size(rep_spec_names)) &
1676 state_names(i_spec+j_spec)%string = &
1677 rep_spec_names(j_spec)%string
1678 i_spec = i_spec +
size(rep_spec_names)
1679 write(f_unit,*)
"Aerosol rep ", &
1680 this%aero_rep(i_aero_rep)%val%rep_name, &
1681 " species: ",
size(rep_spec_names)
1682 deallocate(rep_spec_names)
1684 do i_spec = 1,
size(state_names)
1685 write(f_unit,*) i_spec-1, state_names(i_spec)%string
1688 write(f_unit,*)
"*** Solver Data ***"
1689 write(f_unit,*)
"Relative tolerance:", this%rel_tol
1690 write(f_unit,*)
" Solver id | Absolute Tolerance "// &
1693 do i_spec = 1,
size(state_names)
1695 write(f_unit,*) i_solver_spec,
"|", this%abs_tol(i_spec),
"| ", &
1696 state_names(i_spec)%string
1697 i_solver_spec = i_solver_spec + 1
1701 deallocate(state_names)
1706 if (
associated(this%solver_data_gas)) &
1707 call this%solver_data_gas%print()
1708 if (
associated(this%solver_data_gas_aero)) &
1709 call this%solver_data_gas_aero%print()
1723 if (
associated(this%mechanism)) &
1724 deallocate(this%mechanism)
1725 if (
associated(this%chem_spec_data)) &
1726 deallocate(this%chem_spec_data)
1727 if (
associated(this%sub_model)) &
1728 deallocate(this%sub_model)
1729 if (
associated(this%aero_rep)) &
1730 deallocate(this%aero_rep)
1731 if (
associated(this%aero_phase)) &
1732 deallocate(this%aero_phase)
1733 if (
allocated(this%abs_tol)) &
1734 deallocate(this%abs_tol)
1735 if (
allocated(this%var_type)) &
1736 deallocate(this%var_type)
1737 if (
associated(this%solver_data_gas)) &
1738 deallocate(this%solver_data_gas)
1739 if (
associated(this%solver_data_aero)) &
1740 deallocate(this%solver_data_aero)
1741 if (
associated(this%solver_data_gas_aero)) &
1742 deallocate(this%solver_data_gas_aero)
1754 character(len=*),
intent(in) :: phase_name
1758 allocate(new_aero_phase(
size(this%aero_phase)+1))
1760 new_aero_phase(1:
size(this%aero_phase)) = &
1761 this%aero_phase(1:
size(this%aero_phase))
1765 deallocate(this%aero_phase)
1766 this%aero_phase => new_aero_phase
1778 character(len=*),
intent(in) :: rep_name
1784 allocate(new_aero_rep(
size(this%aero_rep)+1))
1786 new_aero_rep(1:
size(this%aero_rep)) = &
1787 this%aero_rep(1:
size(this%aero_rep))
1788 new_aero_rep(
size(new_aero_rep))%val => aero_rep_factory%create(rep_name)
1790 call this%aero_rep(:)%dereference()
1791 deallocate(this%aero_rep)
1792 this%aero_rep => new_aero_rep
1804 character(len=*),
intent(in) :: mech_name
1808 allocate(new_mechanism(
size(this%mechanism)+1))
1810 new_mechanism(1:
size(this%mechanism)) = &
1811 this%mechanism(1:
size(this%mechanism))
1815 call this%mechanism(:)%dereference()
1816 deallocate(this%mechanism)
1817 this%mechanism => new_mechanism
1829 character(len=*),
intent(in) :: sub_model_name
1834 allocate(new_sub_model(
size(this%sub_model)+1))
1836 new_sub_model(1:
size(this%sub_model)) = &
1837 this%sub_model(1:
size(this%sub_model))
1838 new_sub_model(
size(new_sub_model))%val => &
1839 sub_model_factory%create(sub_model_name)
1841 deallocate(this%sub_model)
1842 this%sub_model => new_sub_model
Initialize the aerosol representation data, validating component data and loading any required inform...
Get the non-unique name of a chemical species by its unique name.
Get a species id on the camp_camp_state::camp_state_t::state_var array by unique name....
Get a list of unique names for each element on the camp_camp_state::camp_state_t::state_var array for...
Update aerosol representation data.
Interface for to_string functions.
The abstract aero_phase_data_t structure and associated subroutines.
elemental subroutine finalize(this)
Finalize the aerosol phase data.
subroutine bin_unpack(this, buffer, pos, comm)
Unpack the given value from the buffer, advancing position.
type(aero_phase_data_t) function, pointer constructor(phase_name, init_size)
Constructor for aero_phase_data_t.
subroutine bin_pack(this, buffer, pos, comm)
Pack the given value to the buffer, advancing position.
subroutine load(this, json, j_obj)
Load species from an input file.
integer(kind=i_kind) function pack_size(this, comm)
Determine the size of a binary required to pack the aerosol representation data.
subroutine do_print(this, file_unit)
Print out the aerosol phase data.
The abstract aero_rep_data_t structure and associated subroutines.
The aero_rep_factory_t type and associated subroutines.
The camp_core_t structure and associated subroutines.
subroutine initialize_aero_rep_update_object(this, aero_rep, update_data)
Initialize an update data object for an aerosol representation.
subroutine add_aero_rep(this, rep_name)
Add a aerosol representation to the model data.
subroutine add_sub_model(this, sub_model_name)
Add a sub-model to the model data.
logical function get_aero_phase(this, aero_phase_name, aero_phase)
Get a pointer to an aerosol phase by name.
subroutine free_solver(this)
Free the solver memory.
real(kind=dp) function get_rel_tol(this)
Get the relative tolerance for the solver.
integer(kind=i_kind) function state_size(this)
Get the size of the state array.
subroutine solve(this, camp_state, time_step, rxn_phase, solver_stats)
Integrate the chemical mechanism.
subroutine add_mechanism(this, mech_name)
Add a chemical mechanism to the model data.
logical function is_initialized(this)
Inidicate whether the core has been initialized.
subroutine add_aero_phase(this, phase_name)
Add a aerosol phase to the model data.
subroutine initialize_rxn_update_object(this, rxn, update_data)
Initialize an update data object for a reaction.
logical function get_mechanism(this, mech_name, mechanism)
Get a pointer to a mechanism by name.
logical function get_aero_rep(this, aero_rep_name, aero_rep)
Get a pointer to an aerosol representation by name.
real(kind=dp) function get_abs_tol(this, spec_id)
Get the absolute tolerance for a species on the state array.
logical function get_sub_model(this, sub_model_name, sub_model)
Find an sub-model by name.
type(camp_state_t) function, pointer new_state_one_cell(this, env_state)
Get a model state variable based on the this set of model data This is also called for multi-cell sys...
logical function is_solver_initialized(this)
Inidicate whether the solver has been initialized.
type(camp_state_t) function, pointer new_state_multi_cell(this, env_states)
Get a model state variable based on the this set of model data.
logical function get_chem_spec_data(this, chem_spec_data)
Get a pointer to the chemical species data.
subroutine initialize_sub_model_update_object(this, sub_model, update_data)
Initialize an update data object for a sub model.
subroutine load_files(this, input_file_path)
Load a set of model data files.
integer(kind=i_kind) function state_size_per_cell(this)
Get the size of the state array for each grid cell.
The camp_solver_data_t structure and associated subroutines.
The camp_state_t structure and associated subroutines.
The chem_spec_data_t structure and associated subroutines.
integer(kind=i_kind), parameter, public chem_spec_activity_coeff
integer(kind=i_kind), parameter, public chem_spec_gas_phase
integer(kind=i_kind), parameter, public chem_spec_variable
integer, parameter dp
Kind of a double precision real number.
integer, parameter i_kind
Kind of an integer.
The env_state_t structure and associated subroutines.
The mechanism_data_t structure and associated subroutines.
Wrapper functions for MPI.
subroutine camp_mpi_pack_integer_array(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
subroutine camp_mpi_pack_real(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
subroutine camp_mpi_pack_real_array(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
subroutine camp_mpi_unpack_integer_array(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
subroutine camp_mpi_pack_logical(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
subroutine camp_mpi_unpack_integer(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
subroutine camp_mpi_unpack_logical(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
integer function camp_mpi_pack_size_real_array(val, comm)
Determines the number of bytes required to pack the given value.
integer function camp_mpi_pack_size_integer_array(val, comm)
Determines the number of bytes required to pack the given value.
integer function camp_mpi_pack_size_logical(val, comm)
Determines the number of bytes required to pack the given value.
subroutine camp_mpi_pack_integer(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
integer function camp_mpi_pack_size_integer(val, comm)
Determines the number of bytes required to pack the given value.
subroutine camp_mpi_unpack_real(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
integer function camp_mpi_pack_size_real(val, comm)
Determines the number of bytes required to pack the given value.
subroutine camp_mpi_unpack_real_array(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
The rxn_data_t structure and associated subroutines.
integer(kind=i_kind), parameter, public gas_rxn
Gas-phase reaction.
integer(kind=i_kind), parameter, public gas_aero_rxn
Mixed-phase (gas and aerosol) reaction.
integer(kind=i_kind), parameter, public aero_rxn
Aerosol-phase reaction.
The abstract rxn_factory_t structure and associated subroutines.
The solver_stats_t type and associated subroutines.
The abstract sub_model_data_t structure and associated subroutines.
The sub_model_factory_t type and associated subroutines.
Common utility subroutines.
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
subroutine die_msg(code, error_msg)
Error immediately.
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
subroutine warn_msg(code, warning_msg, already_warned)
Prints a warning message.
Pointer type for building arrays.
Pointer to aero_rep_data_t extending types.
Abstract aerosol representation data type.
Factory type for aerosol representations.
Current environment state.
Pointer type for building arrays.
Abstract reaction data type.
Factory type for chemical reactions.
Pointer to sub_model_data_t extending types.
Abstract sub-model data type.
Factory type for sub-models.
String type for building arrays of string of various size.