136 integer(kind=i_kind) :: size_state_per_cell
138 integer(kind=i_kind) :: n_cells = 1
140 real(kind=
dp),
allocatable :: init_state(:)
143 logical :: split_gas_aero = .false.
145 real(kind=
dp) :: rel_tol = 0.0
148 real(kind=
dp),
allocatable :: abs_tol(:)
150 integer(kind=i_kind),
allocatable :: var_type(:)
158 logical :: core_is_initialized = .false.
160 logical :: solver_is_initialized = .false.
206 generic :: initialize_update_object => &
214 generic :: update_data => &
257 character(len=*),
intent(in),
optional :: input_file_path
259 integer(kind=i_kind),
optional :: n_cells
262 allocate(new_obj%mechanism(0))
264 allocate(new_obj%aero_phase(0))
265 allocate(new_obj%aero_rep(0))
266 allocate(new_obj%sub_model(0))
268 if (
present(n_cells))
then
269 new_obj%n_cells=n_cells
272 if (
present(input_file_path))
then
273 call new_obj%load_files(trim(input_file_path))
307 character(len=*),
intent(in) :: input_file_path
310 type(json_core),
target :: json
311 type(json_file) :: j_file
312 type(json_value),
pointer :: j_obj, j_next
314 logical(kind=json_lk) :: found, valid
315 character(kind=json_ck, len=:),
allocatable :: unicode_str_val
316 character(kind=json_ck, len=:),
allocatable :: json_err_msg
317 integer(kind=json_ik) :: i_file, num_files
318 type(
string_t),
allocatable :: file_list(:)
319 logical :: file_exists
322 call j_file%initialize()
323 call j_file%get_core(json)
324 call assert_msg(600888426, trim(input_file_path).ne.
"", &
325 "Received empty string for file path")
326 inquire( file=trim(input_file_path), exist=file_exists )
327 call assert_msg(433777575, file_exists,
"Cannot find file: "//&
328 trim(input_file_path))
329 call j_file%load_file(filename = trim(input_file_path))
332 call j_file%get(
'camp-files(1)', j_obj, found)
334 "Could not find camp-files object in input file: "// &
336 call json%validate(j_obj, valid, json_err_msg)
338 call die_msg(959537834,
"Bad JSON format in file '"// &
339 trim(input_file_path)//
"': "//trim(json_err_msg))
341 call j_file%info(
'camp-files', n_children = num_files)
343 "No file names were found in "//input_file_path)
346 allocate(file_list(num_files))
351 do while (
associated(j_obj))
352 call json%get(j_obj, unicode_str_val)
353 file_list(i_file)%string = unicode_str_val
355 call json%get_next(j_obj, j_next)
360 call j_file%destroy()
363 call this%load(file_list)
366 call warn_msg(171627969,
"No support for input files.");
423 subroutine load(this, input_file_path)
428 type(
string_t),
allocatable,
intent(in) :: input_file_path(:)
430 integer(kind=i_kind) :: i_file, cell
432 type(json_core),
pointer :: json
433 type(json_file) :: j_file
434 type(json_value),
pointer :: j_obj, j_next
436 logical(kind=json_lk) :: valid
437 character(kind=json_ck, len=:),
allocatable :: unicode_str_val
438 character(kind=json_ck, len=:),
allocatable :: json_err_msg
439 character(len=:),
allocatable :: str_val
440 real(kind=json_rk) :: real_val
441 logical :: file_exists, found
451 logical :: sub_model_placed
452 integer(kind=i_kind) :: i_sub_model, j_sub_model
470 do i_file = 1,
size(input_file_path)
473 call j_file%initialize()
474 call j_file%get_core(json)
475 call assert_msg(366175417,
allocated(input_file_path(i_file)%string), &
476 "Received non-allocated string for file path")
477 call assert_msg(936390222, trim(input_file_path(i_file)%string).ne.
"", &
478 "Received empty string for file path")
479 inquire( file=input_file_path(i_file)%string, exist=file_exists )
480 call assert_msg(910660557, file_exists,
"Cannot file file: "// &
481 input_file_path(i_file)%string)
482 call j_file%load_file(filename = input_file_path(i_file)%string)
485 call j_file%get(
'camp-data(1)', j_obj)
486 call json%validate(j_obj, valid, json_err_msg)
488 call die_msg(560270545,
"Bad JSON format in file '"// &
489 trim(input_file_path(i_file)%string)//
"': "// &
492 do while (
associated(j_obj))
496 call json%get(j_obj,
'type', unicode_str_val, found)
498 "Missing type in json input file "// &
499 input_file_path(i_file)%string)
500 str_val = unicode_str_val
505 if (str_val.eq.
'MECHANISM')
then
506 call json%get(j_obj,
'name', unicode_str_val, found)
508 "Missing mechanism name in file "// &
509 input_file_path(i_file)%string)
510 str_val = unicode_str_val
514 if (.not.this%get_mechanism(str_val, mech_ptr))
then
515 call this%add_mechanism(str_val)
516 call assert(105816325, this%get_mechanism(str_val, mech_ptr))
518 call mech_ptr%load(json, j_obj)
521 else if (str_val.eq.
'CHEM_SPEC')
then
522 call this%chem_spec_data%load(json, j_obj)
527 else if (str_val(1:8).eq.
'AERO_REP')
then
528 aero_rep_ptr%val => aero_rep_factory%load(json, j_obj)
529 str_val = aero_rep_ptr%val%name()
533 if (this%get_aero_rep(str_val, existing_aero_rep_ptr))
then
534 deallocate(aero_rep_ptr%val)
535 call existing_aero_rep_ptr%load(json, j_obj)
537 allocate(new_aero_rep(
size(this%aero_rep)+1))
538 new_aero_rep(1:
size(this%aero_rep)) = &
539 this%aero_rep(1:
size(this%aero_rep))
540 new_aero_rep(
size(new_aero_rep))%val => aero_rep_ptr%val
541 call this%aero_rep(:)%dereference()
542 deallocate(this%aero_rep)
543 this%aero_rep => new_aero_rep
544 call aero_rep_ptr%dereference()
550 else if (str_val.eq.
'AERO_PHASE')
then
552 call aero_phase%load(json, j_obj)
553 str_val = aero_phase%name()
557 if (this%get_aero_phase(str_val, existing_aero_phase))
then
558 deallocate(aero_phase)
559 call existing_aero_phase%load(json, j_obj)
561 allocate(new_aero_phase(
size(this%aero_phase)+1))
562 new_aero_phase(1:
size(this%aero_phase)) = &
563 this%aero_phase(1:
size(this%aero_phase))
564 new_aero_phase(
size(new_aero_phase))%val => aero_phase
565 call this%aero_phase(:)%dereference()
566 deallocate(this%aero_phase)
567 this%aero_phase => new_aero_phase
573 else if (str_val(1:9).eq.
'SUB_MODEL')
then
574 sub_model_ptr%val => sub_model_factory%load(json, j_obj)
575 str_val = sub_model_ptr%val%name()
579 if (this%get_sub_model(str_val, existing_sub_model_ptr))
then
580 deallocate(sub_model_ptr%val)
581 call existing_sub_model_ptr%load(json, j_obj)
583 sub_model_placed = .false.
584 allocate(new_sub_model(
size(this%sub_model)+1))
586 do i_sub_model = 1,
size(this%sub_model)
587 if (.not.sub_model_placed .and. &
588 sub_model_ptr%val%priority() < &
589 this%sub_model(i_sub_model)%val%priority())
then
590 sub_model_placed = .true.
591 new_sub_model(j_sub_model)%val => sub_model_ptr%val
592 j_sub_model = j_sub_model + 1
594 new_sub_model(j_sub_model) = &
595 this%sub_model(i_sub_model)
596 j_sub_model = j_sub_model + 1
598 if (.not.sub_model_placed)
then
599 new_sub_model(j_sub_model)%val => sub_model_ptr%val
601 call this%sub_model(:)%dereference()
602 deallocate(this%sub_model)
603 this%sub_model => new_sub_model
604 call sub_model_ptr%dereference()
610 else if (str_val.eq.
'RELATIVE_TOLERANCE')
then
611 call json%get(j_obj,
'value', real_val, found)
613 "Missing value for relative tolerance")
614 call assert_msg(162564706, real_val.gt.0.0.and.real_val.lt.1.0, &
615 "Invalid relative tolerance: "// &
617 this%rel_tol = real(real_val, kind=
dp)
622 else if (str_val.eq.
'SPLIT_GAS_AERO')
then
623 this%split_gas_aero = .true.
630 "Received invalid json input object type: "//str_val)
635 call json%get_next(j_next, j_obj)
639 call j_file%destroy()
646 call warn_msg(350136328,
"No support for input files.");
662 integer(kind=i_kind) :: i_mech, i_phase, i_aero_rep, i_sub_model
663 integer(kind=i_kind) :: i_state_var, i_spec, i_cell
667 integer(kind=i_kind) :: i_state_elem, i_name
670 character(len=:),
allocatable :: spec_name
672 type(
string_t),
allocatable :: gas_spec_names(:)
674 type(
string_t),
allocatable :: unique_names(:)
677 call assert_msg(157261665, .not.this%core_is_initialized, &
678 "Attempting to initialize a camp_core_t object twice.")
681 call this%chem_spec_data%initialize()
687 do i_phase = 1,
size(this%aero_phase)
688 call assert(254948966,
associated(this%aero_phase(i_phase)%val))
689 call this%aero_phase(i_phase)%val%initialize(this%chem_spec_data)
693 do i_aero_rep = 1,
size(this%aero_rep)
694 call assert(251590193,
associated(this%aero_rep(i_aero_rep)%val))
695 call this%aero_rep(i_aero_rep)%val%initialize(this%aero_phase, &
697 i_state_var = i_state_var + this%aero_rep(i_aero_rep)%val%size()
701 do i_sub_model = 1,
size(this%sub_model)
702 call assert(565644925,
associated(this%sub_model(i_sub_model)%val))
703 call this%sub_model(i_sub_model)%val%initialize(this%aero_rep, &
704 this%aero_phase, this%chem_spec_data)
708 this%size_state_per_cell = i_state_var - 1
711 do i_mech = 1,
size(this%mechanism)
712 call this%mechanism(i_mech)%val%initialize(this%chem_spec_data, &
713 this%aero_rep, this%n_cells)
717 allocate(this%abs_tol(this%size_state_per_cell))
718 allocate(this%var_type(this%size_state_per_cell))
725 this%chem_spec_data%get_spec_names(spec_phase = &
727 do i_spec = 1,
size(gas_spec_names)
728 i_state_var = i_state_var + 1
730 this%chem_spec_data%get_abs_tol(gas_spec_names(i_spec)%string, &
731 this%abs_tol(i_state_var)))
733 this%chem_spec_data%get_type(gas_spec_names(i_spec)%string, &
734 this%var_type(i_state_var)))
738 do i_aero_rep = 1,
size(this%aero_rep)
742 call assert(666823548,
associated(this%aero_rep(i_aero_rep)%val))
743 unique_names = this%aero_rep(i_aero_rep)%val%unique_names()
744 do i_spec = 1, this%aero_rep(i_aero_rep)%val%size()
745 i_state_var = i_state_var + 1
746 spec_name = this%aero_rep(i_aero_rep)%val%spec_name( &
749 this%chem_spec_data%get_abs_tol(
spec_name, &
750 this%abs_tol(i_state_var)))
752 this%chem_spec_data%get_type(
spec_name, &
753 this%var_type(i_state_var)))
760 call assert_msg(501609702, i_state_var.eq.this%size_state_per_cell, &
761 "Internal error. Filled "//trim(
to_string(i_state_var))// &
762 " of "//trim(
to_string(this%size_state_per_cell))// &
763 " elements of absolute tolerance and variable type arrays")
765 this%core_is_initialized = .true.
768 allocate(this%init_state(this%size_state_per_cell * this%n_cells))
771 this%init_state(:) = 0.0
774 do i_cell = 0, this%n_cells - 1
775 do i_aero_rep = 1,
size(this%aero_rep)
777 rep => this%aero_rep(i_aero_rep)%val
784 i_state_elem = rep%spec_state_id(
unique_names(i_name)%string)
785 this%init_state(i_state_elem + i_cell * this%size_state_per_cell) = &
829 character(len=*),
intent(in) :: aero_phase_name
833 integer(kind=i_kind) :: i_aero_phase
837 if (.not.
associated(this%aero_phase))
return
838 do i_aero_phase = 1,
size(this%aero_phase)
839 if (this%aero_phase(i_aero_phase)%val%name().eq.aero_phase_name)
then
841 aero_phase => this%aero_phase(i_aero_phase)%val
851 logical function get_aero_rep(this, aero_rep_name, aero_rep)
result (found)
856 character(len=*),
intent(in) :: aero_rep_name
860 integer(kind=i_kind) :: i_aero_rep
864 if (.not.
associated(this%aero_rep))
return
865 do i_aero_rep = 1,
size(this%aero_rep)
866 if (this%aero_rep(i_aero_rep)%val%name().eq.trim(aero_rep_name))
then
867 aero_rep => this%aero_rep(i_aero_rep)%val
886 chem_spec_data => this%chem_spec_data
887 if (
associated(chem_spec_data)) found = .true.
899 character(len=*),
intent(in) :: mech_name
903 integer(kind=i_kind) :: i_mech
907 if (.not.
associated(this%mechanism))
return
908 do i_mech = 1,
size(this%mechanism)
909 if (this%mechanism(i_mech)%val%name().eq.mech_name)
then
911 mechanism => this%mechanism(i_mech)%val
927 character(len=*),
intent(in) :: sub_model_name
931 integer(kind=i_kind) :: i_sub_model
935 if (.not.
associated(this%sub_model))
return
936 do i_sub_model = 1,
size(this%sub_model)
937 if (this%sub_model(i_sub_model)%val%name().eq.sub_model_name)
then
938 sub_model => this%sub_model(i_sub_model)%val
970 integer(kind=i_kind),
intent(in) :: spec_id
972 call assert_msg( 374310824, spec_id .ge. 1 .and. &
973 spec_id .le.
size( this%abs_tol ), &
974 "Species id out of bounds: "// &
997 allocate(new_state%state_var, source=this%init_state)
1014 type(
env_state_t),
optional,
target,
intent(in) :: env_state
1017 if (this%n_cells.eq.1)
then
1020 call assert_msg(386790682, .not.
present(env_state), &
1021 "Cannot use a single env_state_t object to create "// &
1022 "a new camp_state_t in a multi-cell system")
1027 allocate(new_state%state_var, source=this%init_state)
1041 call assert_msg(629102639,
allocated(this%init_state), &
1042 "Trying to get the size of the state array before "// &
1043 "initializing the camp_core")
1059 call assert_msg(175845182,
allocated(this%init_state), &
1060 "Trying to get the size of the state array before "// &
1061 "initializing the camp_core")
1079 integer(kind=i_kind) :: i_aero_rep
1080 type(
string_t),
allocatable :: new_names(:), temp_list(:)
1085 if( .not.
associated( this%aero_rep ) )
return
1086 do i_aero_rep = 1,
size( this%aero_rep )
1087 new_names = this%aero_rep( i_aero_rep )%val%unique_names( )
1088 if( .not.
allocated( new_names ) ) cycle
1089 if(
size( new_names ).eq.0 ) cycle
1090 allocate( temp_list(
size(
unique_names ) +
size( new_names ) ) )
1092 temp_list(
size(
unique_names ) + 1 :
size( temp_list ) ) = &
1097 if(
allocated( new_names ) )
deallocate( new_names )
1098 if(
allocated( temp_list ) )
deallocate( temp_list )
1112 character(len=*),
intent(in) ::
spec_name
1114 integer(kind=i_kind),
intent(inout) :: state_id
1116 integer(kind=i_kind) :: i_spec, i_aero_rep
1119 i_spec = this%chem_spec_data%gas_state_id(
spec_name )
1120 do i_aero_rep = 1,
size( this%aero_rep )
1121 if( i_spec .eq. 0 ) &
1122 i_spec = this%aero_rep( i_aero_rep )%val%spec_state_id(
spec_name )
1125 if( i_spec .gt. 0 )
then
1140 call assert_msg(662920365, .not.this%solver_is_initialized, &
1141 "Attempting to initialize the solver twice.")
1144 if (this%split_gas_aero)
then
1151 if (this%rel_tol.ne.real(0.0, kind=
dp))
then
1152 this%solver_data_gas%rel_tol = this%rel_tol
1153 this%solver_data_aero%rel_tol = this%rel_tol
1157 call this%solver_data_gas%initialize( &
1167 call this%solver_data_aero%initialize( &
1183 if (this%rel_tol.ne.0.0)
then
1184 this%solver_data_gas_aero%rel_tol = this%rel_tol
1188 call this%solver_data_gas_aero%initialize( &
1201 this%solver_is_initialized = .true.
1213 if(
associated( this%solver_data_gas ) ) &
1214 deallocate( this%solver_data_gas )
1215 if(
associated( this%solver_data_aero ) ) &
1216 deallocate( this%solver_data_aero )
1217 if(
associated( this%solver_data_gas_aero ) ) &
1218 deallocate( this%solver_data_gas_aero )
1236 call assert_msg( 962343826, .not. this%is_solver_initialized( ), &
1237 "Cannot initialize update data objects after the "// &
1238 "solver has been initialized." )
1239 call factory%initialize_update_data(aero_rep, update_data)
1257 call assert_msg( 166064689, .not. this%is_solver_initialized( ), &
1258 "Cannot initialize update data objects after the "// &
1259 "solver has been initialized." )
1260 call factory%initialize_update_data(rxn, update_data)
1278 call assert_msg( 771607586, .not. this%is_solver_initialized( ), &
1279 "Cannot initialize update data objects after the "// &
1280 "solver has been initialized." )
1281 call factory%initialize_update_data(sub_model, update_data)
1299 if (
associated(this%solver_data_gas)) &
1300 call this%solver_data_gas%update_aero_rep_data(update_data)
1301 if (
associated(this%solver_data_aero)) &
1302 call this%solver_data_aero%update_aero_rep_data(update_data)
1303 if (
associated(this%solver_data_gas_aero)) &
1304 call this%solver_data_gas_aero%update_aero_rep_data(update_data)
1321 if (
associated(this%solver_data_gas)) &
1322 call this%solver_data_gas%update_rxn_data(update_data)
1323 if (
associated(this%solver_data_aero)) &
1324 call this%solver_data_aero%update_rxn_data(update_data)
1325 if (
associated(this%solver_data_gas_aero)) &
1326 call this%solver_data_gas_aero%update_rxn_data(update_data)
1341 if (
associated(this%solver_data_gas)) &
1342 call this%solver_data_gas%update_sub_model_data(update_data)
1343 if (
associated(this%solver_data_aero)) &
1344 call this%solver_data_aero%update_sub_model_data(update_data)
1345 if (
associated(this%solver_data_gas_aero)) &
1346 call this%solver_data_gas_aero%update_sub_model_data(update_data)
1353 subroutine solve(this, camp_state, time_step, rxn_phase, solver_stats)
1362 type(
camp_state_t),
intent(inout),
target :: camp_state
1364 real(kind=
dp),
intent(in) :: time_step
1368 integer(kind=i_kind),
intent(in),
optional :: rxn_phase
1370 type(
solver_stats_t),
intent(inout),
optional,
target :: solver_stats
1373 integer(kind=i_kind) :: phase
1377 call assert_msg(593328365, this%solver_is_initialized, &
1378 "Trying to solve system with uninitialized solver" )
1381 if (
present(rxn_phase))
then
1388 call camp_state%update_env_state( )
1392 solver => this%solver_data_gas
1394 solver => this%solver_data_aero
1396 solver => this%solver_data_gas_aero
1398 call die_msg(704896254,
"Invalid rxn phase specified for chemistry "// &
1403 call assert_msg(730097030,
associated(solver),
"Invalid solver requested")
1406 if (
present(solver_stats))
then
1407 call solver%solve(camp_state, real(0.0, kind=
dp), time_step, &
1410 call solver%solve(camp_state, real(0.0, kind=
dp), time_step)
1413 end subroutine solve
1423 integer,
intent(in),
optional :: comm
1429 integer(kind=i_kind) :: i_mech, i_phase, i_rep, i_sub_model, l_comm
1432 if (
present(comm))
then
1435 l_comm = mpi_comm_world
1438 call assert_msg(143374295, this%core_is_initialized, &
1439 "Trying to get the buffer size of an uninitialized core.")
1445 do i_mech = 1,
size(this%mechanism)
1448 do i_phase = 1,
size(this%aero_phase)
1451 do i_rep = 1,
size(this%aero_rep)
1452 aero_rep => this%aero_rep(i_rep)%val
1456 do i_sub_model = 1,
size(this%sub_model)
1457 sub_model => this%sub_model(i_sub_model)%val
1482 character,
intent(inout) :: buffer(:)
1484 integer,
intent(inout) :: pos
1486 integer,
intent(in),
optional :: comm
1493 integer(kind=i_kind) :: i_mech, i_phase, i_rep, i_sub_model, &
1494 prev_position, l_comm
1496 if (
present(comm))
then
1499 l_comm = mpi_comm_world
1502 call assert_msg(143374295, this%core_is_initialized, &
1503 "Trying to pack an uninitialized core.")
1510 do i_mech = 1,
size(this%mechanism)
1511 call this%mechanism(i_mech)%val%bin_pack(buffer, pos, l_comm)
1513 do i_phase = 1,
size(this%aero_phase)
1514 call this%aero_phase(i_phase)%val%bin_pack(buffer, pos, l_comm)
1516 do i_rep = 1,
size(this%aero_rep)
1517 aero_rep => this%aero_rep(i_rep)%val
1518 call aero_rep_factory%bin_pack(aero_rep, buffer, pos, l_comm)
1521 do i_sub_model = 1,
size(this%sub_model)
1522 sub_model => this%sub_model(i_sub_model)%val
1523 call sub_model_factory%bin_pack(sub_model, buffer, pos, l_comm)
1534 pos - prev_position <= this%pack_size(l_comm))
1547 character,
intent(inout) :: buffer(:)
1549 integer,
intent(inout) :: pos
1551 integer,
intent(in),
optional :: comm
1556 integer(kind=i_kind) :: i_mech, i_phase, i_rep, i_sub_model, &
1557 prev_position, num_mech, num_phase, num_rep, num_sub_model, &
1560 if (
present(comm))
then
1563 l_comm = mpi_comm_world
1574 allocate(this%mechanism(num_mech))
1575 allocate(this%aero_phase(num_phase))
1576 allocate(this%aero_rep(num_rep))
1577 allocate(this%sub_model(num_sub_model))
1578 do i_mech = 1, num_mech
1580 call this%mechanism(i_mech)%val%bin_unpack(buffer, pos, l_comm)
1582 do i_phase = 1, num_phase
1584 call this%aero_phase(i_phase)%val%bin_unpack(buffer, pos, l_comm)
1586 do i_rep = 1, num_rep
1587 this%aero_rep(i_rep)%val => aero_rep_factory%bin_unpack(buffer, pos, l_comm)
1589 do i_sub_model = 1, num_sub_model
1590 this%sub_model(i_sub_model)%val => &
1591 sub_model_factory%bin_unpack(buffer, pos, l_comm)
1600 this%core_is_initialized = .true.
1602 pos - prev_position <= this%pack_size(l_comm))
1615 integer(kind=i_kind),
intent(in),
optional :: file_unit
1617 logical,
intent(in),
optional :: solver_data_only
1619 integer(kind=i_kind) :: i_gas_spec, i_spec, j_spec, i_phase, i_aero_rep, i_mech
1620 integer(kind=i_kind) :: i_sub_model, i_solver_spec
1621 integer(kind=i_kind) :: f_unit
1622 type(
string_t),
allocatable :: state_names(:), rep_spec_names(:)
1628 if (
present(file_unit)) f_unit = file_unit
1629 if (
present(solver_data_only)) sd_only = solver_data_only
1631 write(f_unit,*)
"*********************"
1632 write(f_unit,*)
"** CAMP core data **"
1633 write(f_unit,*)
"*********************"
1634 if (.not.sd_only )
then
1635 write(f_unit,*)
"Number of grid cells to solve simultaneously: ", &
1637 write(f_unit,*)
"Relative integration tolerance: ", this%rel_tol
1638 call this%chem_spec_data%print(f_unit)
1639 write(f_unit,*)
"*** Aerosol Phases ***"
1640 do i_phase=1,
size(this%aero_phase)
1641 call this%aero_phase(i_phase)%val%print(f_unit)
1643 write(f_unit,*)
"*** Aerosol Representations ***"
1644 do i_aero_rep=1,
size(this%aero_rep)
1645 write(f_unit,*)
"Aerosol representation ", i_aero_rep
1646 call this%aero_rep(i_aero_rep)%val%print(f_unit)
1648 write(f_unit,*)
"*** Sub Models ***"
1649 do i_sub_model=1,
size(this%sub_model)
1650 write(f_unit,*)
"Sub model: ", i_sub_model
1651 call this%sub_model(i_sub_model)%val%print(f_unit)
1653 write(f_unit,*)
"*** Mechanisms ***"
1654 write(f_unit,*)
"Number of mechanisms: ",
size(this%mechanism)
1655 do i_mech=1,
size(this%mechanism)
1656 call this%mechanism(i_mech)%val%print(f_unit)
1658 write(f_unit,*)
"*** State Array ***"
1659 write(f_unit,*)
"Number of species on the state array per grid cell: ", &
1660 this%size_state_per_cell
1661 allocate(state_names(this%size_state_per_cell))
1663 do i_gas_spec = 1, &
1666 state_names(i_spec)%string = &
1667 this%chem_spec_data%gas_state_name(i_gas_spec)
1669 write(f_unit,*)
"Gas-phase species: ", i_spec
1670 do i_aero_rep = 1,
size(this%aero_rep)
1671 rep_spec_names = this%aero_rep(i_aero_rep)%val%unique_names()
1672 call assert(620697091,
allocated(rep_spec_names))
1673 call assert(787495222,
size(rep_spec_names).gt.0)
1674 forall (j_spec=1:
size(rep_spec_names)) &
1675 state_names(i_spec+j_spec)%string = &
1676 rep_spec_names(j_spec)%string
1677 i_spec = i_spec +
size(rep_spec_names)
1678 write(f_unit,*)
"Aerosol rep ", &
1679 this%aero_rep(i_aero_rep)%val%rep_name, &
1680 " species: ",
size(rep_spec_names)
1681 deallocate(rep_spec_names)
1683 do i_spec = 1,
size(state_names)
1684 write(f_unit,*) i_spec-1, state_names(i_spec)%string
1687 write(f_unit,*)
"*** Solver Data ***"
1688 write(f_unit,*)
"Relative tolerance:", this%rel_tol
1689 write(f_unit,*)
" Solver id | Absolute Tolerance "// &
1692 do i_spec = 1,
size(state_names)
1694 write(f_unit,*) i_solver_spec,
"|", this%abs_tol(i_spec),
"| ", &
1695 state_names(i_spec)%string
1696 i_solver_spec = i_solver_spec + 1
1700 deallocate(state_names)
1705 if (
associated(this%solver_data_gas)) &
1706 call this%solver_data_gas%print()
1707 if (
associated(this%solver_data_gas_aero)) &
1708 call this%solver_data_gas_aero%print()
1722 if (
associated(this%mechanism)) &
1723 deallocate(this%mechanism)
1724 if (
associated(this%chem_spec_data)) &
1725 deallocate(this%chem_spec_data)
1726 if (
associated(this%sub_model)) &
1727 deallocate(this%sub_model)
1728 if (
associated(this%aero_rep)) &
1729 deallocate(this%aero_rep)
1730 if (
associated(this%aero_phase)) &
1731 deallocate(this%aero_phase)
1732 if (
allocated(this%abs_tol)) &
1733 deallocate(this%abs_tol)
1734 if (
allocated(this%var_type)) &
1735 deallocate(this%var_type)
1736 if (
associated(this%solver_data_gas)) &
1737 deallocate(this%solver_data_gas)
1738 if (
associated(this%solver_data_aero)) &
1739 deallocate(this%solver_data_aero)
1740 if (
associated(this%solver_data_gas_aero)) &
1741 deallocate(this%solver_data_gas_aero)
1753 character(len=*),
intent(in) :: phase_name
1757 allocate(new_aero_phase(
size(this%aero_phase)+1))
1759 new_aero_phase(1:
size(this%aero_phase)) = &
1760 this%aero_phase(1:
size(this%aero_phase))
1764 deallocate(this%aero_phase)
1765 this%aero_phase => new_aero_phase
1777 character(len=*),
intent(in) :: rep_name
1783 allocate(new_aero_rep(
size(this%aero_rep)+1))
1785 new_aero_rep(1:
size(this%aero_rep)) = &
1786 this%aero_rep(1:
size(this%aero_rep))
1787 new_aero_rep(
size(new_aero_rep))%val => aero_rep_factory%create(rep_name)
1789 call this%aero_rep(:)%dereference()
1790 deallocate(this%aero_rep)
1791 this%aero_rep => new_aero_rep
1803 character(len=*),
intent(in) :: mech_name
1807 allocate(new_mechanism(
size(this%mechanism)+1))
1809 new_mechanism(1:
size(this%mechanism)) = &
1810 this%mechanism(1:
size(this%mechanism))
1814 call this%mechanism(:)%dereference()
1815 deallocate(this%mechanism)
1816 this%mechanism => new_mechanism
1828 character(len=*),
intent(in) :: sub_model_name
1833 allocate(new_sub_model(
size(this%sub_model)+1))
1835 new_sub_model(1:
size(this%sub_model)) = &
1836 this%sub_model(1:
size(this%sub_model))
1837 new_sub_model(
size(new_sub_model))%val => &
1838 sub_model_factory%create(sub_model_name)
1840 deallocate(this%sub_model)
1841 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.