135 integer(kind=i_kind) :: size_state_per_cell
137 integer(kind=i_kind) :: n_cells = 1
139 real(kind=
dp),
allocatable :: init_state(:)
142 logical :: split_gas_aero = .false.
144 real(kind=
dp) :: rel_tol = 0.0
147 real(kind=
dp),
allocatable :: abs_tol(:)
149 integer(kind=i_kind),
allocatable :: var_type(:)
157 logical :: core_is_initialized = .false.
159 logical :: solver_is_initialized = .false.
205 generic :: initialize_update_object => &
213 generic :: update_data => &
256 character(len=*),
intent(in),
optional :: input_file_path
258 integer(kind=i_kind),
optional :: n_cells
261 allocate(new_obj%mechanism(0))
263 allocate(new_obj%aero_phase(0))
264 allocate(new_obj%aero_rep(0))
265 allocate(new_obj%sub_model(0))
267 if (
present(n_cells))
then
268 new_obj%n_cells=n_cells
271 if (
present(input_file_path))
then
272 call new_obj%load_files(trim(input_file_path))
306 character(len=*),
intent(in) :: input_file_path
309 type(json_core),
target :: json
310 type(json_file) :: j_file
311 type(json_value),
pointer :: j_obj, j_next
313 logical(kind=json_lk) :: found, valid
314 character(kind=json_ck, len=:),
allocatable :: unicode_str_val
315 character(kind=json_ck, len=:),
allocatable :: json_err_msg
316 integer(kind=json_ik) :: i_file, num_files
317 type(
string_t),
allocatable :: file_list(:)
318 logical :: file_exists
321 call j_file%initialize()
322 call j_file%get_core(json)
323 call assert_msg(600888426, trim(input_file_path).ne.
"", &
324 "Received empty string for file path")
325 inquire( file=trim(input_file_path), exist=file_exists )
326 call assert_msg(433777575, file_exists,
"Cannot find file: "//&
327 trim(input_file_path))
328 call j_file%load_file(filename = trim(input_file_path))
331 call j_file%get(
'camp-files(1)', j_obj, found)
333 "Could not find camp-files object in input file: "// &
335 call json%validate(j_obj, valid, json_err_msg)
337 call die_msg(959537834,
"Bad JSON format in file '"// &
338 trim(input_file_path)//
"': "//trim(json_err_msg))
340 call j_file%info(
'camp-files', n_children = num_files)
342 "No file names were found in "//input_file_path)
345 allocate(file_list(num_files))
350 do while (
associated(j_obj))
351 call json%get(j_obj, unicode_str_val)
352 file_list(i_file)%string = unicode_str_val
354 call json%get_next(j_obj, j_next)
359 call j_file%destroy()
362 call this%load(file_list)
365 call warn_msg(171627969,
"No support for input files.");
422 subroutine load(this, input_file_path)
427 type(
string_t),
allocatable,
intent(in) :: input_file_path(:)
429 integer(kind=i_kind) :: i_file, cell
431 type(json_core),
pointer :: json
432 type(json_file) :: j_file
433 type(json_value),
pointer :: j_obj, j_next
435 logical(kind=json_lk) :: valid
436 character(kind=json_ck, len=:),
allocatable :: unicode_str_val
437 character(kind=json_ck, len=:),
allocatable :: json_err_msg
438 character(len=:),
allocatable :: str_val
439 real(kind=json_rk) :: real_val
440 logical :: file_exists, found
450 logical :: sub_model_placed
451 integer(kind=i_kind) :: i_sub_model, j_sub_model
469 do i_file = 1,
size(input_file_path)
472 call j_file%initialize()
473 call j_file%get_core(json)
474 call assert_msg(366175417,
allocated(input_file_path(i_file)%string), &
475 "Received non-allocated string for file path")
476 call assert_msg(936390222, trim(input_file_path(i_file)%string).ne.
"", &
477 "Received empty string for file path")
478 inquire( file=input_file_path(i_file)%string, exist=file_exists )
479 call assert_msg(910660557, file_exists,
"Cannot file file: "// &
480 input_file_path(i_file)%string)
481 call j_file%load_file(filename = input_file_path(i_file)%string)
484 call j_file%get(
'camp-data(1)', j_obj)
485 call json%validate(j_obj, valid, json_err_msg)
487 call die_msg(560270545,
"Bad JSON format in file '"// &
488 trim(input_file_path(i_file)%string)//
"': "// &
491 do while (
associated(j_obj))
495 call json%get(j_obj,
'type', unicode_str_val, found)
497 "Missing type in json input file "// &
498 input_file_path(i_file)%string)
499 str_val = unicode_str_val
504 if (str_val.eq.
'MECHANISM')
then
505 call json%get(j_obj,
'name', unicode_str_val, found)
507 "Missing mechanism name in file "// &
508 input_file_path(i_file)%string)
509 str_val = unicode_str_val
513 if (.not.this%get_mechanism(str_val, mech_ptr))
then
514 call this%add_mechanism(str_val)
515 call assert(105816325, this%get_mechanism(str_val, mech_ptr))
517 call mech_ptr%load(json, j_obj)
520 else if (str_val.eq.
'CHEM_SPEC')
then
521 call this%chem_spec_data%load(json, j_obj)
526 else if (str_val(1:8).eq.
'AERO_REP')
then
527 aero_rep_ptr%val => aero_rep_factory%load(json, j_obj)
528 str_val = aero_rep_ptr%val%name()
532 if (this%get_aero_rep(str_val, existing_aero_rep_ptr))
then
533 deallocate(aero_rep_ptr%val)
534 call existing_aero_rep_ptr%load(json, j_obj)
536 allocate(new_aero_rep(
size(this%aero_rep)+1))
537 new_aero_rep(1:
size(this%aero_rep)) = &
538 this%aero_rep(1:
size(this%aero_rep))
539 new_aero_rep(
size(new_aero_rep))%val => aero_rep_ptr%val
540 call this%aero_rep(:)%dereference()
541 deallocate(this%aero_rep)
542 this%aero_rep => new_aero_rep
543 call aero_rep_ptr%dereference()
549 else if (str_val.eq.
'AERO_PHASE')
then
551 call aero_phase%load(json, j_obj)
552 str_val = aero_phase%name()
556 if (this%get_aero_phase(str_val, existing_aero_phase))
then
557 deallocate(aero_phase)
558 call existing_aero_phase%load(json, j_obj)
560 allocate(new_aero_phase(
size(this%aero_phase)+1))
561 new_aero_phase(1:
size(this%aero_phase)) = &
562 this%aero_phase(1:
size(this%aero_phase))
563 new_aero_phase(
size(new_aero_phase))%val => aero_phase
564 call this%aero_phase(:)%dereference()
565 deallocate(this%aero_phase)
566 this%aero_phase => new_aero_phase
572 else if (str_val(1:9).eq.
'SUB_MODEL')
then
573 sub_model_ptr%val => sub_model_factory%load(json, j_obj)
574 str_val = sub_model_ptr%val%name()
578 if (this%get_sub_model(str_val, existing_sub_model_ptr))
then
579 deallocate(sub_model_ptr%val)
580 call existing_sub_model_ptr%load(json, j_obj)
582 sub_model_placed = .false.
583 allocate(new_sub_model(
size(this%sub_model)+1))
585 do i_sub_model = 1,
size(this%sub_model)
586 if (.not.sub_model_placed .and. &
587 sub_model_ptr%val%priority() < &
588 this%sub_model(i_sub_model)%val%priority())
then
589 sub_model_placed = .true.
590 new_sub_model(j_sub_model)%val => sub_model_ptr%val
591 j_sub_model = j_sub_model + 1
593 new_sub_model(j_sub_model) = &
594 this%sub_model(i_sub_model)
595 j_sub_model = j_sub_model + 1
597 if (.not.sub_model_placed)
then
598 new_sub_model(j_sub_model)%val => sub_model_ptr%val
600 call this%sub_model(:)%dereference()
601 deallocate(this%sub_model)
602 this%sub_model => new_sub_model
603 call sub_model_ptr%dereference()
609 else if (str_val.eq.
'RELATIVE_TOLERANCE')
then
610 call json%get(j_obj,
'value', real_val, found)
612 "Missing value for relative tolerance")
613 call assert_msg(162564706, real_val.gt.0.0.and.real_val.lt.1.0, &
614 "Invalid relative tolerance: "// &
616 this%rel_tol = real(real_val, kind=
dp)
621 else if (str_val.eq.
'SPLIT_GAS_AERO')
then
622 this%split_gas_aero = .true.
629 "Received invalid json input object type: "//str_val)
634 call json%get_next(j_next, j_obj)
638 call j_file%destroy()
645 call warn_msg(350136328,
"No support for input files.");
661 integer(kind=i_kind) :: i_mech, i_phase, i_aero_rep, i_sub_model
662 integer(kind=i_kind) :: i_state_var, i_spec, i_cell
666 integer(kind=i_kind) :: i_state_elem, i_name
669 character(len=:),
allocatable :: spec_name
671 type(
string_t),
allocatable :: gas_spec_names(:)
673 type(
string_t),
allocatable :: unique_names(:)
676 call assert_msg(157261665, .not.this%core_is_initialized, &
677 "Attempting to initialize a camp_core_t object twice.")
680 call this%chem_spec_data%initialize()
686 do i_phase = 1,
size(this%aero_phase)
687 call assert(254948966,
associated(this%aero_phase(i_phase)%val))
688 call this%aero_phase(i_phase)%val%initialize(this%chem_spec_data)
692 do i_aero_rep = 1,
size(this%aero_rep)
693 call assert(251590193,
associated(this%aero_rep(i_aero_rep)%val))
694 call this%aero_rep(i_aero_rep)%val%initialize(this%aero_phase, &
696 i_state_var = i_state_var + this%aero_rep(i_aero_rep)%val%size()
700 do i_sub_model = 1,
size(this%sub_model)
701 call assert(565644925,
associated(this%sub_model(i_sub_model)%val))
702 call this%sub_model(i_sub_model)%val%initialize(this%aero_rep, &
703 this%aero_phase, this%chem_spec_data)
707 this%size_state_per_cell = i_state_var - 1
710 do i_mech = 1,
size(this%mechanism)
711 call this%mechanism(i_mech)%val%initialize(this%chem_spec_data, &
712 this%aero_phase, this%aero_rep, this%n_cells)
716 allocate(this%abs_tol(this%size_state_per_cell))
717 allocate(this%var_type(this%size_state_per_cell))
724 this%chem_spec_data%get_spec_names(spec_phase = &
726 do i_spec = 1,
size(gas_spec_names)
727 i_state_var = i_state_var + 1
729 this%chem_spec_data%get_abs_tol(gas_spec_names(i_spec)%string, &
730 this%abs_tol(i_state_var)))
732 this%chem_spec_data%get_type(gas_spec_names(i_spec)%string, &
733 this%var_type(i_state_var)))
737 do i_aero_rep = 1,
size(this%aero_rep)
741 call assert(666823548,
associated(this%aero_rep(i_aero_rep)%val))
742 unique_names = this%aero_rep(i_aero_rep)%val%unique_names()
743 do i_spec = 1, this%aero_rep(i_aero_rep)%val%size()
744 i_state_var = i_state_var + 1
745 spec_name = this%aero_rep(i_aero_rep)%val%spec_name( &
748 this%chem_spec_data%get_abs_tol(
spec_name, &
749 this%abs_tol(i_state_var)))
751 this%chem_spec_data%get_type(
spec_name, &
752 this%var_type(i_state_var)))
759 call assert_msg(501609702, i_state_var.eq.this%size_state_per_cell, &
760 "Internal error. Filled "//trim(
to_string(i_state_var))// &
761 " of "//trim(
to_string(this%size_state_per_cell))// &
762 " elements of absolute tolerance and variable type arrays")
764 this%core_is_initialized = .true.
767 allocate(this%init_state(this%size_state_per_cell * this%n_cells))
770 this%init_state(:) = 0.0
773 do i_cell = 0, this%n_cells - 1
774 do i_aero_rep = 1,
size(this%aero_rep)
776 rep => this%aero_rep(i_aero_rep)%val
783 i_state_elem = rep%spec_state_id(
unique_names(i_name)%string)
784 this%init_state(i_state_elem + i_cell * this%size_state_per_cell) = &
828 character(len=*),
intent(in) :: aero_phase_name
832 integer(kind=i_kind) :: i_aero_phase
836 if (.not.
associated(this%aero_phase))
return
837 do i_aero_phase = 1,
size(this%aero_phase)
838 if (this%aero_phase(i_aero_phase)%val%name().eq.aero_phase_name)
then
840 aero_phase => this%aero_phase(i_aero_phase)%val
850 logical function get_aero_rep(this, aero_rep_name, aero_rep)
result (found)
855 character(len=*),
intent(in) :: aero_rep_name
859 integer(kind=i_kind) :: i_aero_rep
863 if (.not.
associated(this%aero_rep))
return
864 do i_aero_rep = 1,
size(this%aero_rep)
865 if (this%aero_rep(i_aero_rep)%val%name().eq.trim(aero_rep_name))
then
866 aero_rep => this%aero_rep(i_aero_rep)%val
885 chem_spec_data => this%chem_spec_data
886 if (
associated(chem_spec_data)) found = .true.
898 character(len=*),
intent(in) :: mech_name
902 integer(kind=i_kind) :: i_mech
906 if (.not.
associated(this%mechanism))
return
907 do i_mech = 1,
size(this%mechanism)
908 if (this%mechanism(i_mech)%val%name().eq.mech_name)
then
910 mechanism => this%mechanism(i_mech)%val
926 character(len=*),
intent(in) :: sub_model_name
930 integer(kind=i_kind) :: i_sub_model
934 if (.not.
associated(this%sub_model))
return
935 do i_sub_model = 1,
size(this%sub_model)
936 if (this%sub_model(i_sub_model)%val%name().eq.sub_model_name)
then
937 sub_model => this%sub_model(i_sub_model)%val
969 integer(kind=i_kind),
intent(in) :: spec_id
971 call assert_msg( 374310824, spec_id .ge. 1 .and. &
972 spec_id .le.
size( this%abs_tol ), &
973 "Species id out of bounds: "// &
996 allocate(new_state%state_var, source=this%init_state)
1013 type(
env_state_t),
optional,
target,
intent(in) :: env_state
1016 if (this%n_cells.eq.1)
then
1019 call assert_msg(386790682, .not.
present(env_state), &
1020 "Cannot use a single env_state_t object to create "// &
1021 "a new camp_state_t in a multi-cell system")
1026 allocate(new_state%state_var, source=this%init_state)
1040 call assert_msg(629102639,
allocated(this%init_state), &
1041 "Trying to get the size of the state array before "// &
1042 "initializing the camp_core")
1058 call assert_msg(175845182,
allocated(this%init_state), &
1059 "Trying to get the size of the state array before "// &
1060 "initializing the camp_core")
1078 integer(kind=i_kind) :: i_aero_rep
1079 type(
string_t),
allocatable :: new_names(:), temp_list(:)
1084 if( .not.
associated( this%aero_rep ) )
return
1085 do i_aero_rep = 1,
size( this%aero_rep )
1086 new_names = this%aero_rep( i_aero_rep )%val%unique_names( )
1087 if( .not.
allocated( new_names ) ) cycle
1088 if(
size( new_names ).eq.0 ) cycle
1089 allocate( temp_list(
size(
unique_names ) +
size( new_names ) ) )
1091 temp_list(
size(
unique_names ) + 1 :
size( temp_list ) ) = &
1096 if(
allocated( new_names ) )
deallocate( new_names )
1097 if(
allocated( temp_list ) )
deallocate( temp_list )
1111 character(len=*),
intent(in) ::
spec_name
1113 integer(kind=i_kind),
intent(inout) :: state_id
1115 integer(kind=i_kind) :: i_spec, i_aero_rep
1118 i_spec = this%chem_spec_data%gas_state_id(
spec_name )
1119 do i_aero_rep = 1,
size( this%aero_rep )
1120 if( i_spec .eq. 0 ) &
1121 i_spec = this%aero_rep( i_aero_rep )%val%spec_state_id(
spec_name )
1124 if( i_spec .gt. 0 )
then
1139 call assert_msg(662920365, .not.this%solver_is_initialized, &
1140 "Attempting to initialize the solver twice.")
1143 if (this%split_gas_aero)
then
1150 if (this%rel_tol.ne.real(0.0, kind=
dp))
then
1151 this%solver_data_gas%rel_tol = this%rel_tol
1152 this%solver_data_aero%rel_tol = this%rel_tol
1156 call this%solver_data_gas%initialize( &
1166 call this%solver_data_aero%initialize( &
1182 if (this%rel_tol.ne.0.0)
then
1183 this%solver_data_gas_aero%rel_tol = this%rel_tol
1187 call this%solver_data_gas_aero%initialize( &
1200 this%solver_is_initialized = .true.
1212 if(
associated( this%solver_data_gas ) ) &
1213 deallocate( this%solver_data_gas )
1214 if(
associated( this%solver_data_aero ) ) &
1215 deallocate( this%solver_data_aero )
1216 if(
associated( this%solver_data_gas_aero ) ) &
1217 deallocate( this%solver_data_gas_aero )
1235 call assert_msg( 962343826, .not. this%is_solver_initialized( ), &
1236 "Cannot initialize update data objects after the "// &
1237 "solver has been initialized." )
1238 call factory%initialize_update_data(aero_rep, update_data)
1256 call assert_msg( 166064689, .not. this%is_solver_initialized( ), &
1257 "Cannot initialize update data objects after the "// &
1258 "solver has been initialized." )
1259 call factory%initialize_update_data(rxn, update_data)
1277 call assert_msg( 771607586, .not. this%is_solver_initialized( ), &
1278 "Cannot initialize update data objects after the "// &
1279 "solver has been initialized." )
1280 call factory%initialize_update_data(sub_model, update_data)
1298 if (
associated(this%solver_data_gas)) &
1299 call this%solver_data_gas%update_aero_rep_data(update_data)
1300 if (
associated(this%solver_data_aero)) &
1301 call this%solver_data_aero%update_aero_rep_data(update_data)
1302 if (
associated(this%solver_data_gas_aero)) &
1303 call this%solver_data_gas_aero%update_aero_rep_data(update_data)
1320 if (
associated(this%solver_data_gas)) &
1321 call this%solver_data_gas%update_rxn_data(update_data)
1322 if (
associated(this%solver_data_aero)) &
1323 call this%solver_data_aero%update_rxn_data(update_data)
1324 if (
associated(this%solver_data_gas_aero)) &
1325 call this%solver_data_gas_aero%update_rxn_data(update_data)
1340 if (
associated(this%solver_data_gas)) &
1341 call this%solver_data_gas%update_sub_model_data(update_data)
1342 if (
associated(this%solver_data_aero)) &
1343 call this%solver_data_aero%update_sub_model_data(update_data)
1344 if (
associated(this%solver_data_gas_aero)) &
1345 call this%solver_data_gas_aero%update_sub_model_data(update_data)
1352 subroutine solve(this, camp_state, time_step, rxn_phase, solver_stats)
1361 type(
camp_state_t),
intent(inout),
target :: camp_state
1363 real(kind=
dp),
intent(in) :: time_step
1367 integer(kind=i_kind),
intent(in),
optional :: rxn_phase
1369 type(
solver_stats_t),
intent(inout),
optional,
target :: solver_stats
1372 integer(kind=i_kind) :: phase
1376 call assert_msg(593328365, this%solver_is_initialized, &
1377 "Trying to solve system with uninitialized solver" )
1380 if (
present(rxn_phase))
then
1387 call camp_state%update_env_state( )
1391 solver => this%solver_data_gas
1393 solver => this%solver_data_aero
1395 solver => this%solver_data_gas_aero
1397 call die_msg(704896254,
"Invalid rxn phase specified for chemistry "// &
1402 call assert_msg(730097030,
associated(solver),
"Invalid solver requested")
1405 if (
present(solver_stats))
then
1406 call solver%solve(camp_state, real(0.0, kind=
dp), time_step, &
1409 call solver%solve(camp_state, real(0.0, kind=
dp), time_step)
1412 end subroutine solve
1422 integer,
intent(in),
optional :: comm
1428 integer(kind=i_kind) :: i_mech, i_phase, i_rep, i_sub_model, l_comm
1431 if (
present(comm))
then
1434 l_comm = mpi_comm_world
1437 call assert_msg(143374295, this%core_is_initialized, &
1438 "Trying to get the buffer size of an uninitialized core.")
1444 do i_mech = 1,
size(this%mechanism)
1447 do i_phase = 1,
size(this%aero_phase)
1450 do i_rep = 1,
size(this%aero_rep)
1451 aero_rep => this%aero_rep(i_rep)%val
1455 do i_sub_model = 1,
size(this%sub_model)
1456 sub_model => this%sub_model(i_sub_model)%val
1481 character,
intent(inout) :: buffer(:)
1483 integer,
intent(inout) :: pos
1485 integer,
intent(in),
optional :: comm
1492 integer(kind=i_kind) :: i_mech, i_phase, i_rep, i_sub_model, &
1493 prev_position, l_comm
1495 if (
present(comm))
then
1498 l_comm = mpi_comm_world
1501 call assert_msg(143374295, this%core_is_initialized, &
1502 "Trying to pack an uninitialized core.")
1509 do i_mech = 1,
size(this%mechanism)
1510 call this%mechanism(i_mech)%val%bin_pack(buffer, pos, l_comm)
1512 do i_phase = 1,
size(this%aero_phase)
1513 call this%aero_phase(i_phase)%val%bin_pack(buffer, pos, l_comm)
1515 do i_rep = 1,
size(this%aero_rep)
1516 aero_rep => this%aero_rep(i_rep)%val
1517 call aero_rep_factory%bin_pack(aero_rep, buffer, pos, l_comm)
1520 do i_sub_model = 1,
size(this%sub_model)
1521 sub_model => this%sub_model(i_sub_model)%val
1522 call sub_model_factory%bin_pack(sub_model, buffer, pos, l_comm)
1533 pos - prev_position <= this%pack_size(l_comm))
1546 character,
intent(inout) :: buffer(:)
1548 integer,
intent(inout) :: pos
1550 integer,
intent(in),
optional :: comm
1555 integer(kind=i_kind) :: i_mech, i_phase, i_rep, i_sub_model, &
1556 prev_position, num_mech, num_phase, num_rep, num_sub_model, &
1559 if (
present(comm))
then
1562 l_comm = mpi_comm_world
1573 allocate(this%mechanism(num_mech))
1574 allocate(this%aero_phase(num_phase))
1575 allocate(this%aero_rep(num_rep))
1576 allocate(this%sub_model(num_sub_model))
1577 do i_mech = 1, num_mech
1579 call this%mechanism(i_mech)%val%bin_unpack(buffer, pos, l_comm)
1581 do i_phase = 1, num_phase
1583 call this%aero_phase(i_phase)%val%bin_unpack(buffer, pos, l_comm)
1585 do i_rep = 1, num_rep
1586 this%aero_rep(i_rep)%val => aero_rep_factory%bin_unpack(buffer, pos, l_comm)
1588 do i_sub_model = 1, num_sub_model
1589 this%sub_model(i_sub_model)%val => &
1590 sub_model_factory%bin_unpack(buffer, pos, l_comm)
1599 this%core_is_initialized = .true.
1601 pos - prev_position <= this%pack_size(l_comm))
1614 integer(kind=i_kind),
intent(in),
optional :: file_unit
1616 logical,
intent(in),
optional :: solver_data_only
1618 integer(kind=i_kind) :: i_gas_spec, i_spec, j_spec, i_phase, i_aero_rep, i_mech
1619 integer(kind=i_kind) :: i_sub_model, i_solver_spec
1620 integer(kind=i_kind) :: f_unit
1621 type(
string_t),
allocatable :: state_names(:), rep_spec_names(:)
1627 if (
present(file_unit)) f_unit = file_unit
1628 if (
present(solver_data_only)) sd_only = solver_data_only
1630 write(f_unit,*)
"*********************"
1631 write(f_unit,*)
"** CAMP core data **"
1632 write(f_unit,*)
"*********************"
1633 if (.not.sd_only )
then
1634 write(f_unit,*)
"Number of grid cells to solve simultaneously: ", &
1636 write(f_unit,*)
"Relative integration tolerance: ", this%rel_tol
1637 call this%chem_spec_data%print(f_unit)
1638 write(f_unit,*)
"*** Aerosol Phases ***"
1639 do i_phase=1,
size(this%aero_phase)
1640 call this%aero_phase(i_phase)%val%print(f_unit)
1642 write(f_unit,*)
"*** Aerosol Representations ***"
1643 do i_aero_rep=1,
size(this%aero_rep)
1644 write(f_unit,*)
"Aerosol representation ", i_aero_rep
1645 call this%aero_rep(i_aero_rep)%val%print(f_unit)
1647 write(f_unit,*)
"*** Sub Models ***"
1648 do i_sub_model=1,
size(this%sub_model)
1649 write(f_unit,*)
"Sub model: ", i_sub_model
1650 call this%sub_model(i_sub_model)%val%print(f_unit)
1652 write(f_unit,*)
"*** Mechanisms ***"
1653 write(f_unit,*)
"Number of mechanisms: ",
size(this%mechanism)
1654 do i_mech=1,
size(this%mechanism)
1655 call this%mechanism(i_mech)%val%print(f_unit)
1657 write(f_unit,*)
"*** State Array ***"
1658 write(f_unit,*)
"Number of species on the state array per grid cell: ", &
1659 this%size_state_per_cell
1660 allocate(state_names(this%size_state_per_cell))
1662 do i_gas_spec = 1, &
1665 state_names(i_spec)%string = &
1666 this%chem_spec_data%gas_state_name(i_gas_spec)
1668 write(f_unit,*)
"Gas-phase species: ", i_spec
1669 do i_aero_rep = 1,
size(this%aero_rep)
1670 rep_spec_names = this%aero_rep(i_aero_rep)%val%unique_names()
1671 call assert(620697091,
allocated(rep_spec_names))
1672 call assert(787495222,
size(rep_spec_names).gt.0)
1673 forall (j_spec=1:
size(rep_spec_names)) &
1674 state_names(i_spec+j_spec)%string = &
1675 rep_spec_names(j_spec)%string
1676 i_spec = i_spec +
size(rep_spec_names)
1677 write(f_unit,*)
"Aerosol rep ", &
1678 this%aero_rep(i_aero_rep)%val%rep_name, &
1679 " species: ",
size(rep_spec_names)
1680 deallocate(rep_spec_names)
1682 do i_spec = 1,
size(state_names)
1683 write(f_unit,*) i_spec-1, state_names(i_spec)%string
1686 write(f_unit,*)
"*** Solver Data ***"
1687 write(f_unit,*)
"Relative tolerance:", this%rel_tol
1688 write(f_unit,*)
" Solver id | Absolute Tolerance "// &
1691 do i_spec = 1,
size(state_names)
1693 write(f_unit,*) i_solver_spec,
"|", this%abs_tol(i_spec),
"| ", &
1694 state_names(i_spec)%string
1695 i_solver_spec = i_solver_spec + 1
1699 deallocate(state_names)
1704 if (
associated(this%solver_data_gas)) &
1705 call this%solver_data_gas%print()
1706 if (
associated(this%solver_data_gas_aero)) &
1707 call this%solver_data_gas_aero%print()
1721 if (
associated(this%mechanism)) &
1722 deallocate(this%mechanism)
1723 if (
associated(this%chem_spec_data)) &
1724 deallocate(this%chem_spec_data)
1725 if (
associated(this%sub_model)) &
1726 deallocate(this%sub_model)
1727 if (
associated(this%aero_rep)) &
1728 deallocate(this%aero_rep)
1729 if (
associated(this%aero_phase)) &
1730 deallocate(this%aero_phase)
1731 if (
allocated(this%abs_tol)) &
1732 deallocate(this%abs_tol)
1733 if (
allocated(this%var_type)) &
1734 deallocate(this%var_type)
1735 if (
associated(this%solver_data_gas)) &
1736 deallocate(this%solver_data_gas)
1737 if (
associated(this%solver_data_aero)) &
1738 deallocate(this%solver_data_aero)
1739 if (
associated(this%solver_data_gas_aero)) &
1740 deallocate(this%solver_data_gas_aero)
1752 integer(kind=i_kind) :: i_core
1754 do i_core = 1,
size(this)
1768 character(len=*),
intent(in) :: phase_name
1772 allocate(new_aero_phase(
size(this%aero_phase)+1))
1774 new_aero_phase(1:
size(this%aero_phase)) = &
1775 this%aero_phase(1:
size(this%aero_phase))
1779 deallocate(this%aero_phase)
1780 this%aero_phase => new_aero_phase
1792 character(len=*),
intent(in) :: rep_name
1798 allocate(new_aero_rep(
size(this%aero_rep)+1))
1800 new_aero_rep(1:
size(this%aero_rep)) = &
1801 this%aero_rep(1:
size(this%aero_rep))
1802 new_aero_rep(
size(new_aero_rep))%val => aero_rep_factory%create(rep_name)
1804 call this%aero_rep(:)%dereference()
1805 deallocate(this%aero_rep)
1806 this%aero_rep => new_aero_rep
1818 character(len=*),
intent(in) :: mech_name
1822 allocate(new_mechanism(
size(this%mechanism)+1))
1824 new_mechanism(1:
size(this%mechanism)) = &
1825 this%mechanism(1:
size(this%mechanism))
1829 call this%mechanism(:)%dereference()
1830 deallocate(this%mechanism)
1831 this%mechanism => new_mechanism
1843 character(len=*),
intent(in) :: sub_model_name
1848 allocate(new_sub_model(
size(this%sub_model)+1))
1850 new_sub_model(1:
size(this%sub_model)) = &
1851 this%sub_model(1:
size(this%sub_model))
1852 new_sub_model(
size(new_sub_model))%val => &
1853 sub_model_factory%create(sub_model_name)
1855 deallocate(this%sub_model)
1856 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.
subroutine finalize_array(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.
subroutine finalize(this)
Finalize the aerosol phase data.
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.