diff --git a/components/eamxx/src/physics/p3/CMakeLists.txt b/components/eamxx/src/physics/p3/CMakeLists.txt index a1dfc946267d..2a630438049d 100644 --- a/components/eamxx/src/physics/p3/CMakeLists.txt +++ b/components/eamxx/src/physics/p3/CMakeLists.txt @@ -1,19 +1,10 @@ set(P3_SRCS - p3_f90.cpp - p3_ic_cases.cpp p3_iso_c.f90 ${SCREAM_BASE_DIR}/../eam/src/physics/p3/scream/micro_p3.F90 eamxx_p3_process_interface.cpp eamxx_p3_run.cpp ) -if (NOT SCREAM_LIB_ONLY) - list(APPEND P3_SRCS - p3_functions_f90.cpp - p3_main_wrap.cpp - ) # Add f90 bridges needed for testing -endif() - # Add ETI source files if not on CUDA/HIP if (NOT EAMXX_ENABLE_GPU OR Kokkos_ENABLE_CUDA_RELOCATABLE_DEVICE_CODE OR Kokkos_ENABLE_HIP_RELOCATABLE_DEVICE_CODE) list(APPEND P3_SRCS @@ -27,6 +18,7 @@ if (NOT EAMXX_ENABLE_GPU OR Kokkos_ENABLE_CUDA_RELOCATABLE_DEVICE_CODE OR Kokkos eti/p3_table_ice.cpp eti/p3_dsd2.cpp eti/p3_find.cpp + eti/p3_init.cpp eti/p3_update_prognostics.cpp eti/p3_get_time_space_phys_variables.cpp eti/p3_autoconversion.cpp @@ -123,11 +115,6 @@ endforeach() add_executable(p3_tables_setup EXCLUDE_FROM_ALL p3_tables_setup.cpp) target_link_libraries(p3_tables_setup p3) -#crusher change -if (Kokkos_ENABLE_HIP) -set_source_files_properties(p3_functions_f90.cpp PROPERTIES COMPILE_FLAGS -O0) -endif() - if (NOT SCREAM_LIB_ONLY) add_subdirectory(tests) endif() diff --git a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp index a2b8ccb2e298..f6771d6bf171 100644 --- a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp +++ b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp @@ -1,9 +1,7 @@ -#include "physics/p3/eamxx_p3_process_interface.hpp" #include "share/property_checks/field_within_interval_check.hpp" #include "share/property_checks/field_lower_bound_check.hpp" -// Needed for p3_init, the only F90 code still used. -#include "physics/p3/p3_functions.hpp" -#include "physics/p3/p3_f90.hpp" +#include "p3_functions.hpp" +#include "eamxx_p3_process_interface.hpp" #include "ekat/ekat_assert.hpp" #include "ekat/util/ekat_units.hpp" @@ -243,8 +241,8 @@ void P3Microphysics::initialize_impl (const RunType /* run_type */) add_postcondition_check(get_field_out("eff_radius_qr"),m_grid,0.0,5.0e3,false); // Initialize p3 - p3::p3_init(/* write_tables = */ false, - this->get_comm().am_i_root()); + P3F::p3_init(/* write_tables = */ false, + this->get_comm().am_i_root()); // Initialize all of the structures that are passed to p3_main in run_impl. // Note: Some variables in the structures are not stored in the field manager. For these diff --git a/components/eamxx/src/physics/p3/eti/p3_init.cpp b/components/eamxx/src/physics/p3/eti/p3_init.cpp new file mode 100644 index 000000000000..b1878af89840 --- /dev/null +++ b/components/eamxx/src/physics/p3/eti/p3_init.cpp @@ -0,0 +1,14 @@ +#include "p3_init_impl.hpp" + +namespace scream { +namespace p3 { + +/* + * Explicit instantiation for doing find functions on Reals using the + * default device. + */ + +template struct Functions; + +} // namespace p3 +} // namespace scream diff --git a/components/eamxx/src/physics/p3/impl/p3_init_impl.hpp b/components/eamxx/src/physics/p3/impl/p3_init_impl.hpp new file mode 100644 index 000000000000..9b4b999bce0f --- /dev/null +++ b/components/eamxx/src/physics/p3/impl/p3_init_impl.hpp @@ -0,0 +1,40 @@ +#ifndef P3_INIT_IMPL_HPP +#define P3_INIT_IMPL_HPP + +#include "p3_functions.hpp" // for ETI only but harmless for GPU + +extern "C" { + void micro_p3_utils_init_c(scream::Real Cpair, scream::Real Rair, scream::Real RH2O, scream::Real RHO_H2O, + scream::Real MWH2O, scream::Real MWdry, scream::Real gravit, scream::Real LatVap, scream::Real LatIce, + scream::Real CpLiq, scream::Real Tmelt, scream::Real Pi, bool masterproc); + void p3_init_c(const char** lookup_file_dir, int* info, const bool& write_tables); +} + +namespace scream { +namespace p3 { + +/* + * Implementation of p3 init. Clients should NOT #include + * this file, #include p3_functions.hpp instead. + */ +template +void Functions +::p3_init (const bool write_tables, const bool masterproc) { + static bool is_init = false; + if (!is_init) { + using c = scream::physics::Constants; + micro_p3_utils_init_c(c::Cpair, c::Rair, c::RH2O, c::RHO_H2O, + c::MWH2O, c::MWdry, c::gravit, c::LatVap, c::LatIce, + c::CpLiq, c::Tmelt, c::Pi, masterproc); + static const char* dir = SCREAM_DATA_DIR "/tables"; + Int info; + p3_init_c(&dir, &info, write_tables); + EKAT_REQUIRE_MSG(info == 0, "p3_init_c returned info " << info); + is_init = true; + } +} + +} // namespace p3 +} // namespace scream + +#endif diff --git a/components/eamxx/src/physics/p3/p3_functions.hpp b/components/eamxx/src/physics/p3/p3_functions.hpp index 4ac88b4afc48..eef5a8ec73ee 100644 --- a/components/eamxx/src/physics/p3/p3_functions.hpp +++ b/components/eamxx/src/physics/p3/p3_functions.hpp @@ -357,6 +357,9 @@ struct Functions static void init_kokkos_ice_lookup_tables( view_ice_table& ice_table_vals, view_collect_table& collect_table_vals); + static void p3_init(const bool write_tables = false, + const bool masterproc = false); + // Map (mu_r, lamr) to Table3 data. KOKKOS_FUNCTION static void lookup(const Spack& mu_r, const Spack& lamr, @@ -1468,5 +1471,6 @@ void init_tables_from_f90_c(Real* vn_table_vals_data, Real* vm_table_vals_data, # include "p3_nr_conservation_impl.hpp" # include "p3_ni_conservation_impl.hpp" # include "p3_prevent_liq_supersaturation_impl.hpp" +# include "p3_init_impl.hpp" #endif // GPU && !KOKKOS_ENABLE_*_RELOCATABLE_DEVICE_CODE #endif // P3_FUNCTIONS_HPP diff --git a/components/eamxx/src/physics/p3/p3_iso_c.f90 b/components/eamxx/src/physics/p3/p3_iso_c.f90 index ea0a18411c10..71c846b71674 100644 --- a/components/eamxx/src/physics/p3/p3_iso_c.f90 +++ b/components/eamxx/src/physics/p3/p3_iso_c.f90 @@ -14,15 +14,6 @@ module p3_iso_c ! contains - subroutine append_precision(string, prefix) - - character(kind=c_char, len=512), intent(out) :: string - character(*), intent(in) :: prefix - real(kind=c_real) :: s - - write (string, '(a,i1,a1)') prefix, sizeof(s), C_NULL_CHAR - end subroutine append_precision - subroutine init_tables_from_f90_c(vn_table_vals_c, vm_table_vals_c, revap_table_vals_c, mu_table_c) bind(C) use micro_p3, only: p3_get_tables @@ -129,59 +120,6 @@ subroutine p3_init_c(lookup_file_dir_c, info, write_tables) bind(c) end subroutine p3_init_c - subroutine p3_main_c(qc,nc,qr,nr,th_atm,qv,dt,qi,qm,ni,bm, & - pres,dz,nc_nuceat_tend,nccn_prescribed,ni_activated,inv_qc_relvar,it,precip_liq_surf,precip_ice_surf,its,ite,kts,kte,diag_eff_radius_qc, & - diag_eff_radius_qi,diag_eff_radius_qr,rho_qi,do_predict_nc,do_prescribed_CCN,dpres,inv_exner,qv2qi_depos_tend, & - precip_liq_flux,precip_ice_flux,cld_frac_r,cld_frac_l,cld_frac_i,liq_ice_exchange, & - vap_liq_exchange, vap_ice_exchange, qv_prev, t_prev, elapsed_s) bind(C) - use micro_p3, only : p3_main - - real(kind=c_real), intent(inout), dimension(its:ite,kts:kte) :: qc, nc, qr, nr, qv, th_atm - real(kind=c_real), intent(inout), dimension(its:ite,kts:kte) :: qi, qm, ni, bm - real(kind=c_real), intent(in), dimension(its:ite,kts:kte) :: pres, dz - real(kind=c_real), intent(in), dimension(its:ite,kts:kte) :: nc_nuceat_tend,nccn_prescribed,ni_activated - real(kind=c_real), intent(in), dimension(its:ite,kts:kte) :: inv_qc_relvar - real(kind=c_real), value, intent(in) :: dt - real(kind=c_real), intent(out), dimension(its:ite) :: precip_liq_surf, precip_ice_surf - real(kind=c_real), intent(out), dimension(its:ite,kts:kte) :: diag_eff_radius_qc - real(kind=c_real), intent(out), dimension(its:ite,kts:kte) :: diag_eff_radius_qi - real(kind=c_real), intent(out), dimension(its:ite,kts:kte) :: diag_eff_radius_qr - real(kind=c_real), intent(out), dimension(its:ite,kts:kte) :: rho_qi - integer(kind=c_int), value, intent(in) :: its,ite, kts,kte, it - logical(kind=c_bool), value, intent(in) :: do_predict_nc,do_prescribed_CCN - - real(kind=c_real), intent(in), dimension(its:ite,kts:kte) :: dpres - real(kind=c_real), intent(in), dimension(its:ite,kts:kte) :: inv_exner - real(kind=c_real), intent(out), dimension(its:ite,kts:kte) :: qv2qi_depos_tend - real(kind=c_real), intent(out), dimension(its:ite,kts:kte+1) :: precip_liq_flux - real(kind=c_real), intent(out), dimension(its:ite,kts:kte+1) :: precip_ice_flux - real(kind=c_real), intent(in), dimension(its:ite,kts:kte) :: cld_frac_i, cld_frac_l, cld_frac_r - real(kind=c_real), intent(out), dimension(its:ite,kts:kte) :: liq_ice_exchange - real(kind=c_real), intent(out), dimension(its:ite,kts:kte) :: vap_liq_exchange - real(kind=c_real), intent(out), dimension(its:ite,kts:kte) :: vap_ice_exchange - real(kind=c_real), intent(in), dimension(its:ite,kts:kte) :: qv_prev - real(kind=c_real), intent(in), dimension(its:ite,kts:kte) :: t_prev - - real(kind=c_real), intent(out) :: elapsed_s - - real(kind=c_real), dimension(its:ite,kts:kte,49) :: p3_tend_out - real(kind=c_real), dimension(its:ite,3) :: col_location - real(kind=c_real), dimension(its:ite,kts:kte) :: mu_c, lamc - real(kind=c_real), dimension(its:ite,kts:kte) :: precip_total_tend - real(kind=c_real), dimension(its:ite,kts:kte) :: nevapr - real(kind=c_real), dimension(its:ite,kts:kte) :: qr_evap_tend - integer :: i - do i = its,ite - col_location(i,:) = real(i) - end do - - call p3_main(qc,nc,qr,nr,th_atm,qv,dt,qi,qm,ni,bm, & - pres,dz,nc_nuceat_tend,nccn_prescribed,ni_activated,inv_qc_relvar,it,precip_liq_surf,precip_ice_surf,its,ite,kts,kte,diag_eff_radius_qc, & - diag_eff_radius_qi,diag_eff_radius_qr, rho_qi,do_predict_nc,do_prescribed_CCN,dpres,inv_exner,qv2qi_depos_tend,precip_total_tend,nevapr, & - qr_evap_tend,precip_liq_flux,precip_ice_flux,cld_frac_r,cld_frac_l,cld_frac_i,p3_tend_out,mu_c,lamc,liq_ice_exchange,& - vap_liq_exchange,vap_ice_exchange,qv_prev,t_prev,col_location,elapsed_s) - end subroutine p3_main_c - subroutine micro_p3_utils_init_c(Cpair, Rair, RH2O, RHO_H2O, & MWH2O, MWdry, gravit, LatVap, LatIce, & CpLiq, Tmelt, Pi, masterproc) bind(C) @@ -217,772 +155,4 @@ subroutine p3_init_a_c(ice_table_vals_c, collect_table_vals_c) bind(C) collect_table_vals_c(:,:,:,:,:) = collect_table_vals(:,:,:,:,:) end subroutine p3_init_a_c - subroutine find_lookuptable_indices_1a_c(dumi,dumjj,dumii,dumzz,dum1,dum4,dum5,dum6, & - qi,ni,qm,rhop) bind(C) - use micro_p3, only: find_lookupTable_indices_1a - use micro_p3_utils, only: densize,rimsize,isize - - ! arguments: - integer(kind=c_int), intent(out) :: dumi,dumjj,dumii,dumzz - real(kind=c_real), intent(out) :: dum1,dum4,dum5,dum6 - real(kind=c_real), value, intent(in) :: qi,ni,qm,rhop - - call find_lookupTable_indices_1a(dumi, dumjj, dumii, dumzz, dum1, dum4, dum5, dum6, & - isize, rimsize, densize, qi, ni, qm, rhop) - end subroutine find_lookuptable_indices_1a_c - - subroutine find_lookuptable_indices_1b_c(dumj,dum3,qr,nr) bind(C) - use micro_p3, only: find_lookupTable_indices_1b - use micro_p3_utils, only: rcollsize - - integer(kind=c_int), intent(out) :: dumj - real(kind=c_real), intent(out) :: dum3 - real(kind=c_real), value, intent(in) :: qr, nr - - call find_lookupTable_indices_1b(dumj, dum3, rcollsize, qr, nr) - end subroutine find_lookupTable_indices_1b_c - - subroutine access_lookup_table_c(dumjj,dumii,dumi,index,dum1,dum4,dum5,proc) bind(C) - use micro_p3, only: access_lookup_table - - integer(kind=c_int), value, intent(in) :: dumjj, dumii, dumi, index - real(kind=c_real), value, intent(in) :: dum1, dum4, dum5 - real(kind=c_real), intent(out) :: proc - - call access_lookup_table(dumjj,dumii,dumi,index,dum1,dum4,dum5,proc) - end subroutine access_lookup_table_c - - subroutine access_lookup_table_coll_c(dumjj,dumii,dumj,dumi,index,dum1,dum3,dum4,dum5,proc) bind(C) - use micro_p3, only: access_lookup_table_coll - - integer(kind=c_int), value, intent(in) :: dumjj,dumii,dumj,dumi,index - real(kind=c_real), value, intent(in) :: dum1,dum3,dum4,dum5 - real(kind=c_real), intent(out) :: proc - - call access_lookup_table_coll(dumjj,dumii,dumj,dumi,index,dum1,dum3,dum4,dum5,proc) - end subroutine access_lookup_table_coll_c - - subroutine back_to_cell_average_c(cld_frac_l,cld_frac_r,cld_frac_i, qc2qr_accret_tend,qr2qv_evap_tend,qc2qr_autoconv_tend,& - nc_accret_tend,nc_selfcollect_tend,nc2nr_autoconv_tend,nr_selfcollect_tend,nr_evap_tend,ncautr,qi2qv_sublim_tend,nr_ice_shed_tend,qc2qi_hetero_freeze_tend,& - qr2qi_collect_tend,qc2qr_ice_shed_tend,qi2qr_melt_tend,qc2qi_collect_tend,qr2qi_immers_freeze_tend,ni2nr_melt_tend,nc_collect_tend,ncshdc,nc2ni_immers_freeze_tend,nr_collect_tend,ni_selfcollect_tend,& - qv2qi_vapdep_tend,nr2ni_immers_freeze_tend,ni_sublim_tend,qv2qi_nucleat_tend,ni_nucleat_tend,qc2qi_berg_tend) bind(C) - - use micro_p3, only: back_to_cell_average - real(kind=c_real), value, intent(in) :: cld_frac_l, cld_frac_r, cld_frac_i - - real(kind=c_real), intent(inout) :: qc2qr_accret_tend, qr2qv_evap_tend, qc2qr_autoconv_tend, nc_accret_tend, nc_selfcollect_tend, nc2nr_autoconv_tend, & - nr_selfcollect_tend, nr_evap_tend, ncautr, qi2qv_sublim_tend, & - nr_ice_shed_tend, qc2qi_hetero_freeze_tend, qr2qi_collect_tend, qc2qr_ice_shed_tend, qi2qr_melt_tend, qc2qi_collect_tend, & - qr2qi_immers_freeze_tend, ni2nr_melt_tend, nc_collect_tend, ncshdc, nc2ni_immers_freeze_tend, nr_collect_tend,& - ni_selfcollect_tend, qv2qi_vapdep_tend, nr2ni_immers_freeze_tend, ni_sublim_tend, qv2qi_nucleat_tend, ni_nucleat_tend, & - qc2qi_berg_tend - - call back_to_cell_average(cld_frac_l, cld_frac_r, cld_frac_i, qc2qr_accret_tend, qr2qv_evap_tend, qc2qr_autoconv_tend,& - nc_accret_tend, nc_selfcollect_tend, nc2nr_autoconv_tend, nr_selfcollect_tend, nr_evap_tend, ncautr, qi2qv_sublim_tend, nr_ice_shed_tend, qc2qi_hetero_freeze_tend,& - qr2qi_collect_tend, qc2qr_ice_shed_tend, qi2qr_melt_tend, qc2qi_collect_tend, qr2qi_immers_freeze_tend, ni2nr_melt_tend, nc_collect_tend, ncshdc, nc2ni_immers_freeze_tend, nr_collect_tend, ni_selfcollect_tend,& - qv2qi_vapdep_tend, nr2ni_immers_freeze_tend, ni_sublim_tend, qv2qi_nucleat_tend, ni_nucleat_tend, qc2qi_berg_tend) - end subroutine back_to_cell_average_c - - subroutine cloud_water_conservation_c(qc,dt,qc2qr_autoconv_tend,qc2qr_accret_tend,qc2qi_collect_tend,qc2qi_hetero_freeze_tend,qc2qr_ice_shed_tend, & - qc2qi_berg_tend,qi2qv_sublim_tend,qv2qi_vapdep_tend) bind(C) - use micro_p3, only: cloud_water_conservation - - real(kind=c_real), value, intent(in) :: qc, dt - real(kind=c_real), intent(inout) :: qc2qr_autoconv_tend, qc2qr_accret_tend, qc2qi_collect_tend, qc2qi_hetero_freeze_tend, qc2qr_ice_shed_tend, qc2qi_berg_tend, qi2qv_sublim_tend, qv2qi_vapdep_tend - - call cloud_water_conservation(qc,dt,qc2qr_autoconv_tend,qc2qr_accret_tend,qc2qi_collect_tend,qc2qi_hetero_freeze_tend,qc2qr_ice_shed_tend,qc2qi_berg_tend,qi2qv_sublim_tend,qv2qi_vapdep_tend) - end subroutine cloud_water_conservation_c - - subroutine rain_water_conservation_c(qr,qc2qr_autoconv_tend,qc2qr_accret_tend,qi2qr_melt_tend,qc2qr_ice_shed_tend,dt, & - qr2qv_evap_tend,qr2qi_collect_tend,qr2qi_immers_freeze_tend) bind(C) - use micro_p3, only: rain_water_conservation - - real(kind=c_real), value, intent(in) :: qr, qc2qr_autoconv_tend, qc2qr_accret_tend, qi2qr_melt_tend, qc2qr_ice_shed_tend, dt - real(kind=c_real), intent(inout) :: qr2qv_evap_tend, qr2qi_collect_tend, qr2qi_immers_freeze_tend - - call rain_water_conservation(qr,qc2qr_autoconv_tend,qc2qr_accret_tend,qi2qr_melt_tend,qc2qr_ice_shed_tend,dt,qr2qv_evap_tend,qr2qi_collect_tend,qr2qi_immers_freeze_tend) - end subroutine rain_water_conservation_c - - subroutine rain_self_collection_c(rho, qr_incld, nr_incld, nr_selfcollect_tend) bind(C) - use micro_p3, only: rain_self_collection - - real(kind=c_real), value, intent(in) :: rho, qr_incld, nr_incld - real(kind=c_real), intent(out) :: nr_selfcollect_tend - - call rain_self_collection(rho, qr_incld, nr_incld, nr_selfcollect_tend) - end subroutine rain_self_collection_c - - subroutine ice_water_conservation_c(qi,qv2qi_vapdep_tend,qv2qi_nucleat_tend,qc2qi_berg_tend,qr2qi_collect_tend,qc2qi_collect_tend,qr2qi_immers_freeze_tend,qc2qi_hetero_freeze_tend,dt, & - qi2qv_sublim_tend,qi2qr_melt_tend) bind(C) - use micro_p3, only: ice_water_conservation - - real(kind=c_real), value, intent(in) :: qi, qv2qi_vapdep_tend, qv2qi_nucleat_tend, qr2qi_collect_tend, qc2qi_collect_tend, qr2qi_immers_freeze_tend, qc2qi_hetero_freeze_tend, qc2qi_berg_tend, dt - real(kind=c_real), intent(inout) :: qi2qv_sublim_tend, qi2qr_melt_tend - - call ice_water_conservation(qi,qv2qi_vapdep_tend,qv2qi_nucleat_tend,qr2qi_collect_tend,qc2qi_collect_tend,qr2qi_immers_freeze_tend,qc2qi_hetero_freeze_tend,qc2qi_berg_tend,dt,qi2qv_sublim_tend,qi2qr_melt_tend) - end subroutine ice_water_conservation_c - - subroutine get_cloud_dsd2_c(qc,nc,mu_c,rho,nu,lamc,cdist,cdist1) bind(C) - use micro_p3, only: get_cloud_dsd2 - use micro_p3_utils, only: dnu - - !arguments: - real(kind=c_real), value, intent(in) :: qc,rho - real(kind=c_real), intent(inout) :: nc - real(kind=c_real), intent(out) :: mu_c,nu,lamc,cdist,cdist1 - - call get_cloud_dsd2(qc,nc,mu_c,rho,nu,dnu,lamc,cdist,cdist1) - end subroutine get_cloud_dsd2_c - - subroutine get_rain_dsd2_c(qr,nr,mu_r,lamr,cdistr,logn0r) bind(C) - use micro_p3, only: get_rain_dsd2 - - !arguments: - real(kind=c_real), value, intent(in) :: qr - real(kind=c_real), intent(inout) :: nr - real(kind=c_real), intent(out) :: lamr,mu_r,cdistr,logn0r - - call get_rain_dsd2(qr,nr,mu_r,lamr,cdistr,logn0r) - end subroutine get_rain_dsd2_c - - subroutine calc_rime_density_c(T_atm,rhofaci,table_val_qi_fallspd,acn,lamc,mu_c,qc_incld,qc2qi_collect_tend, & - vtrmi1,rho_qm_cloud) bind(C) - - use micro_p3, only: calc_rime_density - real(kind=c_real), value, intent(in) :: T_atm, rhofaci, table_val_qi_fallspd, acn, lamc, mu_c, qc_incld, qc2qi_collect_tend - real(kind=c_real), intent(out) :: vtrmi1, rho_qm_cloud - - call calc_rime_density(T_atm, rhofaci, table_val_qi_fallspd, acn, lamc, mu_c, qc_incld, qc2qi_collect_tend, vtrmi1, rho_qm_cloud) - end subroutine calc_rime_density_c - - subroutine cldliq_immersion_freezing_c(T_atm,lamc,mu_c,cdist1,qc_incld,inv_qc_relvar,qc2qi_hetero_freeze_tend,nc2ni_immers_freeze_tend) bind(C) - - use micro_p3, only: cldliq_immersion_freezing - real(kind=c_real), value, intent(in) :: T_atm, lamc, mu_c, cdist1, qc_incld,inv_qc_relvar - real(kind=c_real), intent(out) :: qc2qi_hetero_freeze_tend, nc2ni_immers_freeze_tend - - call cldliq_immersion_freezing(T_atm, lamc, mu_c, cdist1, qc_incld, inv_qc_relvar, qc2qi_hetero_freeze_tend, nc2ni_immers_freeze_tend) - end subroutine cldliq_immersion_freezing_c - - subroutine rain_immersion_freezing_c(T_atm,lamr,mu_r,cdistr,qr_incld,qr2qi_immers_freeze_tend,nr2ni_immers_freeze_tend) bind(C) - - use micro_p3, only: rain_immersion_freezing - real(kind=c_real), value, intent(in) :: T_atm, lamr, mu_r, cdistr, qr_incld - real(kind=c_real), intent(out) :: qr2qi_immers_freeze_tend, nr2ni_immers_freeze_tend - - call rain_immersion_freezing(T_atm, lamr, mu_r, cdistr, qr_incld, qr2qi_immers_freeze_tend, nr2ni_immers_freeze_tend) - end subroutine rain_immersion_freezing_c - - subroutine droplet_self_collection_c(rho,inv_rho,qc_incld,mu_c,nu,nc2nr_autoconv_tend,nc_selfcollect_tend) bind(C) - - use micro_p3, only: droplet_self_collection - real(kind=c_real), value, intent(in) :: rho, inv_rho, qc_incld, mu_c, nu, nc2nr_autoconv_tend - real(kind=c_real), intent(out) :: nc_selfcollect_tend - - call droplet_self_collection(rho, inv_rho, qc_incld, mu_c, nu, nc2nr_autoconv_tend, nc_selfcollect_tend) - end subroutine droplet_self_collection_c - - subroutine cloud_rain_accretion_c(rho,inv_rho,qc_incld,nc_incld,qr_incld,inv_qc_relvar,qc2qr_accret_tend,nc_accret_tend) bind(C) - - use micro_p3, only: cloud_rain_accretion - real(kind=c_real), value, intent(in) :: rho, inv_rho, qc_incld, nc_incld, qr_incld,inv_qc_relvar - real(kind=c_real), intent(out) :: qc2qr_accret_tend, nc_accret_tend - - call cloud_rain_accretion(rho, inv_rho, qc_incld, nc_incld, qr_incld, inv_qc_relvar, qc2qr_accret_tend, nc_accret_tend) - end subroutine cloud_rain_accretion_c - - subroutine cloud_water_autoconversion_c(rho,qc_incld,nc_incld,inv_qc_relvar,qc2qr_autoconv_tend,nc2nr_autoconv_tend,ncautr) bind(C) - - use micro_p3, only: cloud_water_autoconversion - real(kind=c_real), value, intent(in) :: rho, qc_incld, nc_incld,inv_qc_relvar - real(kind=c_real), intent(inout) :: qc2qr_autoconv_tend, nc2nr_autoconv_tend, ncautr - - call cloud_water_autoconversion(rho, qc_incld, nc_incld, inv_qc_relvar, qc2qr_autoconv_tend, nc2nr_autoconv_tend, ncautr) - end subroutine cloud_water_autoconversion_c - - subroutine impose_max_total_ni_c(ni_local, max_total_ni, inv_rho_local) bind(C) - use micro_p3, only: impose_max_total_ni - - real(kind=c_real), intent(inout) :: ni_local - real(kind=c_real), value, intent(in) :: max_total_ni, inv_rho_local - - call impose_max_total_ni(ni_local, max_total_ni, inv_rho_local) - end subroutine impose_max_total_ni_c - - subroutine calc_first_order_upwind_step_c(kts, kte, kdir, kbot, k_qxtop, dt_sub, rho, inv_rho, inv_dz, num_arrays, fluxes, vs, qnx) bind(C) - use micro_p3, only: calc_first_order_upwind_step, realptr - - !arguments: - integer(kind=c_int), value, intent(in) :: kts, kte, kdir, kbot, k_qxtop, num_arrays - real(kind=c_real), value, intent(in) :: dt_sub - real(kind=c_real), dimension(kts:kte), intent(in) :: rho, inv_rho, inv_dz - type(c_ptr), intent(in), dimension(num_arrays) :: fluxes, vs, qnx - - type(realptr), dimension(num_arrays) :: fluxes_f, vs_f, qnx_f - integer :: i - - do i = 1, num_arrays - call c_f_pointer(fluxes(i), fluxes_f(i)%p, [(kte-kts)+1]) - call c_f_pointer(vs(i), vs_f(i)%p, [(kte-kts)+1]) - call c_f_pointer(qnx(i), qnx_f(i)%p , [(kte-kts)+1]) - end do - - call calc_first_order_upwind_step(kts, kte, kdir, kbot, k_qxtop, dt_sub, rho, inv_rho, inv_dz, num_arrays, fluxes_f, vs_f, qnx_f) - - end subroutine calc_first_order_upwind_step_c - - subroutine generalized_sedimentation_c(kts, kte, kdir, k_qxtop, k_qxbot, kbot, Co_max, dt_left, prt_accum, inv_dz, inv_rho, rho, num_arrays, vs, fluxes, qnx) bind(C) - use micro_p3, only: generalized_sedimentation, realptr - - ! arguments - integer(kind=c_int), value, intent(in) :: kts, kte, kdir, k_qxtop, kbot, num_arrays - integer(kind=c_int), intent(inout) :: k_qxbot - real(kind=c_real), value, intent(in) :: Co_max - real(kind=c_real), intent(inout) :: dt_left, prt_accum - real(kind=c_real), dimension(kts:kte), intent(in) :: inv_dz, inv_rho, rho - type(c_ptr), intent(in), dimension(num_arrays) :: vs, fluxes, qnx - - type(realptr), dimension(num_arrays) :: fluxes_f, vs_f, qnx_f - integer :: i - - do i = 1, num_arrays - call c_f_pointer(fluxes(i), fluxes_f(i)%p, [(kte-kts)+1]) - call c_f_pointer(vs(i), vs_f(i)%p, [(kte-kts)+1]) - call c_f_pointer(qnx(i), qnx_f(i)%p , [(kte-kts)+1]) - end do - - call generalized_sedimentation(kts, kte, kdir, k_qxtop, k_qxbot, kbot, Co_max, dt_left, prt_accum, inv_dz, inv_rho, rho, num_arrays, vs_f, fluxes_f, qnx_f) - - end subroutine generalized_sedimentation_c - - subroutine cloud_sedimentation_c(kts,kte,ktop,kbot,kdir, & - qc_incld,rho,inv_rho,cld_frac_l,acn,inv_dz,& - dt,inv_dt,do_predict_nc, & - qc, nc, nc_incld,mu_c,lamc,precip_liq_surf,qc_tend,nc_tend) bind(C) - use micro_p3, only: cloud_sedimentation, dnu - - ! arguments - integer(kind=c_int), value, intent(in) :: kts, kte, ktop, kbot, kdir - - real(kind=c_real), intent(in), dimension(kts:kte) :: rho - real(kind=c_real), intent(in), dimension(kts:kte) :: inv_rho - real(kind=c_real), intent(in), dimension(kts:kte) :: cld_frac_l - real(kind=c_real), intent(in), dimension(kts:kte) :: acn - real(kind=c_real), intent(in), dimension(kts:kte) :: inv_dz - - real(kind=c_real), value, intent(in) :: dt - real(kind=c_real), value, intent(in) :: inv_dt - logical(kind=c_bool), value, intent(in) :: do_predict_nc - - real(kind=c_real), intent(inout), dimension(kts:kte) :: qc - real(kind=c_real), intent(inout), dimension(kts:kte) :: nc - real(kind=c_real), intent(inout), dimension(kts:kte) :: qc_incld - real(kind=c_real), intent(inout), dimension(kts:kte) :: nc_incld - real(kind=c_real), intent(inout), dimension(kts:kte) :: mu_c - real(kind=c_real), intent(inout), dimension(kts:kte) :: lamc - real(kind=c_real), intent(inout) :: precip_liq_surf - real(kind=c_real), intent(inout), dimension(kts:kte) :: qc_tend - real(kind=c_real), intent(inout), dimension(kts:kte) :: nc_tend - - call cloud_sedimentation(kts,kte,ktop,kbot,kdir, & - qc_incld,rho,inv_rho,cld_frac_l,acn,inv_dz,& - dt,inv_dt,dnu,do_predict_nc, & - qc, nc, nc_incld,mu_c,lamc,precip_liq_surf,qc_tend,nc_tend) - - end subroutine cloud_sedimentation_c - - subroutine ice_sedimentation_c(kts,kte,ktop,kbot,kdir, & - rho,inv_rho,rhofaci,cld_frac_i,inv_dz,dt,inv_dt, & - qi,qi_incld,ni,qm,qm_incld,bm,bm_incld,ni_incld,precip_ice_surf,qi_tend,ni_tend) bind(C) - use micro_p3, only: ice_sedimentation - - ! arguments - integer(kind=c_int), value, intent(in) :: kts, kte, ktop, kbot, kdir - - real(kind=c_real), intent(in), dimension(kts:kte) :: rho - real(kind=c_real), intent(in), dimension(kts:kte) :: inv_rho - real(kind=c_real), intent(in), dimension(kts:kte) :: rhofaci - real(kind=c_real), intent(in), dimension(kts:kte) :: cld_frac_i - real(kind=c_real), intent(in), dimension(kts:kte) :: inv_dz - real(kind=c_real), value, intent(in) :: dt, inv_dt - - real(kind=c_real), intent(inout), dimension(kts:kte), target :: qi - real(kind=c_real), intent(inout), dimension(kts:kte) :: qi_incld - real(kind=c_real), intent(inout), dimension(kts:kte), target :: ni - real(kind=c_real), intent(inout), dimension(kts:kte) :: ni_incld - real(kind=c_real), intent(inout), dimension(kts:kte), target :: qm - real(kind=c_real), intent(inout), dimension(kts:kte) :: qm_incld - real(kind=c_real), intent(inout), dimension(kts:kte), target :: bm - real(kind=c_real), intent(inout), dimension(kts:kte) :: bm_incld - - real(kind=c_real), intent(inout) :: precip_ice_surf - real(kind=c_real), intent(inout), dimension(kts:kte) :: qi_tend - real(kind=c_real), intent(inout), dimension(kts:kte) :: ni_tend - - call ice_sedimentation(kts,kte,ktop,kbot,kdir, & - rho,inv_rho,rhofaci,cld_frac_i,inv_dz,dt,inv_dt, & - qi,qi_incld,ni,qm,qm_incld,bm,bm_incld,ni_incld,precip_ice_surf,qi_tend,ni_tend) - - end subroutine ice_sedimentation_c - - subroutine rain_sedimentation_c(kts,kte,ktop,kbot,kdir, & - qr_incld,rho,inv_rho,rhofacr,cld_frac_r,inv_dz,dt,inv_dt, & - qr,nr,nr_incld,mu_r,lamr,precip_liq_surf,precip_liq_flux,qr_tend,nr_tend) bind(C) - use micro_p3, only: rain_sedimentation - - integer(kind=c_int), value, intent(in) :: kts, kte, ktop, kbot, kdir - - real(kind=c_real), intent(in), dimension(kts:kte) :: rho - real(kind=c_real), intent(in), dimension(kts:kte) :: inv_rho - real(kind=c_real), intent(in), dimension(kts:kte) :: rhofacr - real(kind=c_real), intent(in), dimension(kts:kte) :: cld_frac_r - real(kind=c_real), intent(in), dimension(kts:kte) :: inv_dz - real(kind=c_real), value, intent(in) :: dt, inv_dt - - real(kind=c_real), intent(inout), target, dimension(kts:kte) :: qr - real(kind=c_real), intent(inout), target, dimension(kts:kte) :: nr - real(kind=c_real), intent(inout), dimension(kts:kte) :: qr_incld - real(kind=c_real), intent(inout), dimension(kts:kte) :: nr_incld - real(kind=c_real), intent(inout), dimension(kts:kte) :: mu_r - real(kind=c_real), intent(inout), dimension(kts:kte) :: lamr - real(kind=c_real), intent(inout) :: precip_liq_surf - real(kind=c_real), intent(inout), dimension(kts:kte+1) :: precip_liq_flux - real(kind=c_real), intent(inout), dimension(kts:kte) :: qr_tend - real(kind=c_real), intent(inout), dimension(kts:kte) :: nr_tend - - call rain_sedimentation(kts,kte,ktop,kbot,kdir, & - qr_incld,rho,inv_rho,rhofacr,cld_frac_r,inv_dz,dt,inv_dt, & - qr,nr,nr_incld,mu_r,lamr,precip_liq_surf,precip_liq_flux,qr_tend,nr_tend) - - end subroutine rain_sedimentation_c - - subroutine calc_bulk_rho_rime_c(qi_tot, qi_rim, bi_rim, rho_rime) bind(C) - use micro_p3, only: calc_bulkRhoRime - - ! arguments: - real(kind=c_real), value, intent(in) :: qi_tot - real(kind=c_real), intent(inout) :: qi_rim, bi_rim - real(kind=c_real), intent(out) :: rho_rime - - call calc_bulkRhoRime(qi_tot, qi_rim, bi_rim, rho_rime) - end subroutine calc_bulk_rho_rime_c - - subroutine homogeneous_freezing_c(kts,kte,ktop,kbot,kdir,T_atm,inv_exner,latent_heat_fusion, & - qc,nc,qr,nr,qi,ni,qm,bm,th_atm) bind(C) - use micro_p3, only: homogeneous_freezing - - ! arguments: - integer(kind=c_int), value, intent(in) :: kts, kte, ktop, kbot, kdir - real(kind=c_real), intent(in), dimension(kts:kte) :: T_atm - real(kind=c_real), intent(in), dimension(kts:kte) :: inv_exner - real(kind=c_real), intent(in), dimension(kts:kte) :: latent_heat_fusion - - real(kind=c_real), intent(inout), dimension(kts:kte) :: qc - real(kind=c_real), intent(inout), dimension(kts:kte) :: nc - real(kind=c_real), intent(inout), dimension(kts:kte) :: qr - real(kind=c_real), intent(inout), dimension(kts:kte) :: nr - - real(kind=c_real), intent(inout), dimension(kts:kte) :: qi - real(kind=c_real), intent(inout), dimension(kts:kte) :: ni - real(kind=c_real), intent(inout), dimension(kts:kte) :: qm - real(kind=c_real), intent(inout), dimension(kts:kte) :: bm - real(kind=c_real), intent(inout), dimension(kts:kte) :: th_atm - - call homogeneous_freezing(kts,kte,ktop,kbot,kdir,T_atm,inv_exner,latent_heat_fusion, & - qc,nc,qr,nr,qi,ni,qm,bm,th_atm) - end subroutine homogeneous_freezing_c - - subroutine compute_rain_fall_velocity_c(qr_incld, rhofacr, nr_incld, mu_r, lamr, V_qr, V_nr) bind(C) - use micro_p3, only: compute_rain_fall_velocity - - ! arguments: - real(kind=c_real), value, intent(in) :: qr_incld, rhofacr - real(kind=c_real), intent(inout) :: nr_incld - real(kind=c_real), intent(out) :: mu_r, lamr, V_qr, V_nr - - call compute_rain_fall_velocity(qr_incld, rhofacr, nr_incld, mu_r, lamr, V_qr, V_nr) - end subroutine compute_rain_fall_velocity_c - -subroutine update_prognostic_ice_c(qc2qi_hetero_freeze_tend,qc2qi_collect_tend,qc2qr_ice_shed_tend,nc_collect_tend,nc2ni_immers_freeze_tend,ncshdc,qr2qi_collect_tend,nr_collect_tend,qr2qi_immers_freeze_tend,nr2ni_immers_freeze_tend,nr_ice_shed_tend, & - qi2qr_melt_tend,ni2nr_melt_tend,qi2qv_sublim_tend,qv2qi_vapdep_tend,qv2qi_nucleat_tend,ni_nucleat_tend,ni_selfcollect_tend,ni_sublim_tend,qc2qi_berg_tend,inv_exner,latent_heat_sublim,latent_heat_fusion,do_predict_nc,log_wetgrowth, & - dt,nmltratio,rho_qm_cloud,th_atm,qv,qi,ni,qm,bm,qc,nc,qr,nr) bind(C) - use micro_p3, only: update_prognostic_ice - - ! arguments - real(kind=c_real), value, intent(in) :: qc2qi_hetero_freeze_tend, qc2qi_collect_tend, qc2qr_ice_shed_tend, nc_collect_tend, nc2ni_immers_freeze_tend, ncshdc, qr2qi_collect_tend, nr_collect_tend, & - qr2qi_immers_freeze_tend, nr2ni_immers_freeze_tend, nr_ice_shed_tend, qi2qr_melt_tend, ni2nr_melt_tend, qi2qv_sublim_tend, qv2qi_vapdep_tend, qv2qi_nucleat_tend, ni_nucleat_tend, ni_selfcollect_tend, ni_sublim_tend, qc2qi_berg_tend, inv_exner, & - latent_heat_fusion, latent_heat_sublim, dt, nmltratio, rho_qm_cloud - - logical(kind=c_bool), value, intent(in) :: do_predict_nc, log_wetgrowth - - real(kind=c_real), intent(inout) :: th_atm, qv, qc, nc, qr, nr, qi, ni, qm, bm - - call update_prognostic_ice(qc2qi_hetero_freeze_tend,qc2qi_collect_tend,qc2qr_ice_shed_tend,nc_collect_tend,nc2ni_immers_freeze_tend,ncshdc,qr2qi_collect_tend,nr_collect_tend,qr2qi_immers_freeze_tend,nr2ni_immers_freeze_tend,nr_ice_shed_tend, & - qi2qr_melt_tend,ni2nr_melt_tend,qi2qv_sublim_tend,qv2qi_vapdep_tend,qv2qi_nucleat_tend,ni_nucleat_tend,ni_selfcollect_tend,ni_sublim_tend,qc2qi_berg_tend,inv_exner,latent_heat_sublim,latent_heat_fusion,do_predict_nc,log_wetgrowth, & - dt,nmltratio,rho_qm_cloud,th_atm,qv,qi,ni,qm,bm,qc,nc,qr,nr) - - end subroutine update_prognostic_ice_c - - subroutine get_time_space_phys_variables_c(T_atm, pres, rho, latent_heat_vapor, latent_heat_sublim, qv_sat_l, qv_sat_i, mu, dv, sc, dqsdt, dqsidt, & - ab, abi, kap, eii) bind(C) - use micro_p3, only: get_time_space_phys_variables - - !arguments - real(kind=c_real), value, intent(in) :: T_atm, pres, rho, latent_heat_vapor, latent_heat_sublim, qv_sat_l, qv_sat_i - real(kind=c_real), intent(out) :: mu, dv, sc, dqsdt, dqsidt, ab, abi, kap, eii - - call get_time_space_phys_variables(T_atm, pres, rho, latent_heat_vapor, latent_heat_sublim, qv_sat_l, qv_sat_i, mu, dv, sc, dqsdt, dqsidt, & - ab, abi, kap, eii) - end subroutine get_time_space_phys_variables_c - - subroutine ice_cldliq_collection_c(rho, temp, rhofaci, table_val_qc2qi_collect, qi_incld, qc_incld, ni_incld, & - nc_incld, qc2qi_collect_tend, nc_collect_tend, qc2qr_ice_shed_tend, ncshdc) bind(C) - use micro_p3, only: ice_cldliq_collection - - ! arguments: - real(kind=c_real), value, intent(in) :: rho, temp, rhofaci, table_val_qc2qi_collect - real(kind=c_real), value, intent(in) :: qi_incld, qc_incld, ni_incld, nc_incld - real(kind=c_real), intent(out) :: qc2qi_collect_tend, nc_collect_tend, qc2qr_ice_shed_tend, ncshdc - - call ice_cldliq_collection(rho, temp, rhofaci, table_val_qc2qi_collect, qi_incld, qc_incld, ni_incld, & - nc_incld, qc2qi_collect_tend, nc_collect_tend, qc2qr_ice_shed_tend, ncshdc) - end subroutine ice_cldliq_collection_c - - subroutine ice_rain_collection_c(rho, temp, rhofaci, logn0r, table_val_nr_collect, table_val_qr2qi_collect, & - qi_incld, ni_incld, qr_incld, qr2qi_collect_tend, nr_collect_tend) bind(C) - use micro_p3, only: ice_rain_collection - - ! arguments: - real(kind=c_real), value, intent(in) :: rho, temp, rhofaci, logn0r, table_val_nr_collect, table_val_qr2qi_collect - real(kind=c_real), value, intent(in) :: qi_incld, ni_incld, qr_incld - real(kind=c_real), intent(out) :: qr2qi_collect_tend, nr_collect_tend - - call ice_rain_collection(rho, temp, rhofaci, logn0r, table_val_nr_collect, table_val_qr2qi_collect, & - qi_incld, ni_incld, qr_incld, qr2qi_collect_tend, nr_collect_tend) - end subroutine ice_rain_collection_c - - subroutine ice_self_collection_c(rho, rhofaci, table_val_ni_self_collect, eii, qm_incld, & - qi_incld, ni_incld, ni_selfcollect_tend) bind(C) - use micro_p3, only: ice_self_collection - - ! arguments: - real(kind=c_real), value, intent(in) :: rho, rhofaci, table_val_ni_self_collect, eii, qm_incld - real(kind=c_real), value, intent(in) :: qi_incld, ni_incld - real(kind=c_real), intent(out) :: ni_selfcollect_tend - - call ice_self_collection(rho, rhofaci, table_val_ni_self_collect, eii, qm_incld, & - qi_incld, ni_incld, ni_selfcollect_tend) - end subroutine ice_self_collection_c - - subroutine evaporate_rain_c(qr_incld,qc_incld,nr_incld,qi_incld, & - cld_frac_l,cld_frac_r,qv,qv_prev,qv_sat_l,qv_sat_i, & - ab,abi,epsr,epsi_tot,t,t_prev,latent_heat_sublim,dqsdt,dt,& - qr2qv_evap_tend,nr_evap_tend) bind(C) - use micro_p3, only: evaporate_rain - - ! arguments - real(kind=c_real), value, intent(in) :: qr_incld,qc_incld,nr_incld,qi_incld, & - cld_frac_l,cld_frac_r,qv,qv_prev,qv_sat_l,qv_sat_i, & - ab,abi,epsr,epsi_tot,t,t_prev,latent_heat_sublim,dqsdt,dt - - real(kind=c_real), intent(out) :: qr2qv_evap_tend, nr_evap_tend - - call evaporate_rain(qr_incld,qc_incld,nr_incld,qi_incld, & - cld_frac_l,cld_frac_r,qv,qv_prev,qv_sat_l,qv_sat_i, & - ab,abi,epsr,epsi_tot,t,t_prev,latent_heat_sublim,dqsdt,dt,& - qr2qv_evap_tend,nr_evap_tend) - end subroutine evaporate_rain_c - - subroutine update_prognostic_liquid_c(qc2qr_accret_tend, nc_accret_tend, qc2qr_autoconv_tend,nc2nr_autoconv_tend, ncautr, nc_selfcollect_tend, & - qr2qv_evap_tend, nr_evap_tend, nr_selfcollect_tend, do_predict_nc, do_prescribed_CCN, inv_rho, inv_exner, latent_heat_vapor, dt, th_atm, qv, qc, nc, qr, nr) bind(C) - use micro_p3, only: update_prognostic_liquid - - ! arguments - real(kind=c_real), value, intent(in) :: qc2qr_accret_tend, nc_accret_tend, qc2qr_autoconv_tend, nc2nr_autoconv_tend, ncautr, nc_selfcollect_tend, & - qr2qv_evap_tend, nr_evap_tend, nr_selfcollect_tend - - logical(kind=c_bool), value, intent(in) :: do_predict_nc - logical(kind=c_bool), value, intent(in) :: do_prescribed_CCN - - real(kind=c_real), value, intent(in) :: inv_rho, inv_exner, latent_heat_vapor, dt - - real(kind=c_real), intent(inout) :: th_atm, qv, qc, nc, qr, nr - - call update_prognostic_liquid(qc2qr_accret_tend, nc_accret_tend, qc2qr_autoconv_tend,nc2nr_autoconv_tend, ncautr, nc_selfcollect_tend, & - qr2qv_evap_tend, nr_evap_tend, nr_selfcollect_tend, do_predict_nc, do_prescribed_CCN, inv_rho, inv_exner, latent_heat_vapor, dt, th_atm, qv, qc, nc, qr, nr) - - end subroutine update_prognostic_liquid_c - - subroutine ice_deposition_sublimation_c(qi_incld, ni_incld, t_atm, qv_sat_l, qv_sat_i, epsi, abi, qv, inv_dt, qidep, qi2qv_sublim_tend, ni_sublim_tend, qiberg) bind(C) - use micro_p3, only : ice_deposition_sublimation - - real(kind=c_real) , value, intent(in) :: qi_incld, ni_incld, t_atm, qv_sat_l, qv_sat_i, epsi, abi, qv, inv_dt - real(kind=c_real) , intent(out) :: qidep, qi2qv_sublim_tend, ni_sublim_tend, qiberg - - call ice_deposition_sublimation(qi_incld, ni_incld, t_atm, qv_sat_l, qv_sat_i, epsi, abi, qv, inv_dt, qidep, qi2qv_sublim_tend, ni_sublim_tend, qiberg) - end subroutine ice_deposition_sublimation_c - - subroutine ice_relaxation_timescale_c(rho, temp, rhofaci, table_val_qi2qr_melting, table_val_qi2qr_vent_melt, & - dv, mu, sc, qi_incld, ni_incld, & - epsi, epsi_tot) bind(C) - use micro_p3, only: calc_ice_relaxation_timescale - - ! arguments - real(kind=c_real), value, intent(in) :: rho, temp, rhofaci, table_val_qi2qr_melting, table_val_qi2qr_vent_melt, & - dv, mu, sc, qi_incld, ni_incld - real(kind=c_real), intent(out) :: epsi - real(kind=c_real), intent(inout) :: epsi_tot - - call calc_ice_relaxation_timescale(rho, temp, rhofaci, table_val_qi2qr_melting, table_val_qi2qr_vent_melt, & - dv, mu, sc, qi_incld, ni_incld, & - epsi, epsi_tot) - end subroutine ice_relaxation_timescale_c - - subroutine calc_liq_relaxation_timescale_c(rho, f1r, f2r, dv, mu, sc, mu_r, & - lamr, cdistr, cdist, qr_incld, & - qc_incld, epsr, epsc) bind(C) - use micro_p3, only: calc_liq_relaxation_timescale - - ! arguments - real(kind=c_real), value, intent(in) :: rho,f1r,f2r,dv,mu,sc,mu_r,lamr, & - cdistr,cdist,qr_incld,qc_incld - real(kind=c_real), intent(out) :: epsr - real(kind=c_real), intent(out) :: epsc - - call calc_liq_relaxation_timescale(rho,f1r,f2r,dv,mu,sc,mu_r,lamr, & - cdistr,cdist,qr_incld,qc_incld,epsr, & - epsc) - end subroutine calc_liq_relaxation_timescale_c - - subroutine ice_nucleation_c(temp, inv_rho, ni, ni_activated, qv_supersat_i, inv_dt, & - do_predict_nc, do_prescribed_CCN, qv2qi_nucleat_tend, ni_nucleat_tend) bind(C) - use micro_p3, only: ice_nucleation - - ! arguments - real(kind=c_real), value, intent(in) :: temp, inv_rho, ni, ni_activated, qv_supersat_i, inv_dt - logical(c_bool), value, intent(in) :: do_predict_nc - logical(c_bool), value, intent(in) :: do_prescribed_CCN - - real(kind=c_real), intent(inout) :: qv2qi_nucleat_tend, ni_nucleat_tend - - call ice_nucleation(temp, inv_rho, ni, ni_activated, qv_supersat_i, inv_dt, & - do_predict_nc, do_prescribed_CCN, qv2qi_nucleat_tend, ni_nucleat_tend) - end subroutine ice_nucleation_c - - subroutine ice_melting_c(rho,T_atm,pres,rhofaci,table_val_qi2qr_melting,table_val_qi2qr_vent_melt,latent_heat_vapor,latent_heat_fusion, & - dv,sc,mu,kap,qv,qi_incld,ni_incld,qi2qr_melt_tend,ni2nr_melt_tend) bind(C) - use micro_p3, only: ice_melting - - ! arguments: - real(kind=c_real), value, intent(in) :: rho,T_atm,pres,rhofaci,table_val_qi2qr_melting,table_val_qi2qr_vent_melt,latent_heat_vapor,latent_heat_fusion,dv,sc,mu,kap,qv,qi_incld,ni_incld - real(kind=c_real), intent(out) :: qi2qr_melt_tend,ni2nr_melt_tend - - call ice_melting(rho,T_atm,pres,rhofaci,table_val_qi2qr_melting,table_val_qi2qr_vent_melt,latent_heat_vapor,latent_heat_fusion,dv,sc,mu,kap,qv,qi_incld,ni_incld,qi2qr_melt_tend,ni2nr_melt_tend) - - end subroutine ice_melting_c - - subroutine ice_cldliq_wet_growth_c(rho, temp, pres, rhofaci, table_val_qi2qr_melting, & - table_val_qi2qr_vent_melt, latent_heat_vapor, latent_heat_fusion, dv, kap, mu, sc, qv, qc_incld, & - qi_incld, ni_incld, qr_incld, & - log_wetgrowth, qr2qi_collect_tend, qc2qi_collect_tend, qc_growth_rate, nr_ice_shed_tend, qc2qr_ice_shed_tend) bind(C) - use micro_p3, only: ice_cldliq_wet_growth - - ! argmens - real(kind=c_real), value, intent(in) :: rho, temp ,pres, rhofaci, table_val_qi2qr_melting, table_val_qi2qr_vent_melt, latent_heat_vapor, latent_heat_fusion, dv, & - kap, mu, sc, qv, qc_incld, qi_incld, ni_incld,qr_incld - logical(kind=c_bool), intent(inout) :: log_wetgrowth - real(kind=c_real), intent(inout) :: qr2qi_collect_tend, qc2qi_collect_tend, qc_growth_rate, nr_ice_shed_tend, qc2qr_ice_shed_tend - - call ice_cldliq_wet_growth(rho, temp, pres, rhofaci, table_val_qi2qr_melting, & - table_val_qi2qr_vent_melt, latent_heat_vapor, latent_heat_fusion, dv, kap, mu, sc, qv, qc_incld, & - qi_incld, ni_incld, qr_incld, & - log_wetgrowth, qr2qi_collect_tend, qc2qi_collect_tend, qc_growth_rate, nr_ice_shed_tend, qc2qr_ice_shed_tend) - end subroutine ice_cldliq_wet_growth_c - - subroutine get_latent_heat_c(its,ite,kts,kte,v,s,f) bind(C) - use micro_p3, only: get_latent_heat - - ! arguments - integer(kind=c_int), intent(in), value :: its, ite, kts, kte - real(kind=c_real), dimension(its:ite, kts:kte), intent(out) :: v, s, f - - call get_latent_heat(its,ite,kts,kte,v,s,f) - end subroutine get_latent_heat_c - - function subgrid_variance_scaling_c(relvar,expon) result(res) bind(C) - use micro_p3, only: subgrid_variance_scaling - - ! arguments - real(kind=c_real), value, intent(in) :: relvar,expon - real(kind=c_real) :: res - - res = subgrid_variance_scaling(relvar,expon) - return - end function subgrid_variance_scaling_c - - subroutine check_values_c(qv, temp, kts, kte, timestepcount, & - force_abort, source_ind, col_loc) bind(C) - use micro_p3, only: check_values - - ! argmens - real(kind=c_real), intent(in) :: qv(kts:kte), temp(kts:kte), col_loc(3) - integer(kind=c_int), value, intent(in) :: kts, kte, timestepcount, source_ind - logical(kind=c_bool), value, intent(in) :: force_abort - - call check_values(qv,Temp,kts,kte,timestepcount,force_abort,source_ind,col_loc) - end subroutine check_values_c - - subroutine calculate_incloud_mixingratios_c(qc, qr, qi, qm, nc, nr, ni, bm, & - inv_cld_frac_l, inv_cld_frac_i, inv_cld_frac_r, & - qc_incld, qr_incld, qi_incld, qm_incld, & - nc_incld, nr_incld, ni_incld, bm_incld) bind(C) - use micro_p3, only: calculate_incloud_mixingratios - - ! argumens - real(kind=c_real), value, intent(in) :: qc, qr, qi, qm, nc, nr, ni, bm, inv_cld_frac_l, inv_cld_frac_i, inv_cld_frac_r - real(kind=c_real), intent(inout) :: qc_incld, qr_incld, qi_incld, qm_incld, nc_incld, nr_incld, ni_incld, bm_incld - - call calculate_incloud_mixingratios(qc, qr, qi, qm, nc, nr, ni, bm, & - inv_cld_frac_l, inv_cld_frac_i, inv_cld_frac_r, & - qc_incld, qr_incld, qi_incld, qm_incld, & - nc_incld, nr_incld, ni_incld, bm_incld) - end subroutine calculate_incloud_mixingratios_c - - subroutine p3_main_part1_c(kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribed_CCN, dt, & - pres, dpres, dz, nc_nuceat_tend, inv_exner, exner, inv_cld_frac_l, inv_cld_frac_i, inv_cld_frac_r, latent_heat_vapor, latent_heat_sublim, latent_heat_fusion, nccn_prescribed, & - T_atm, rho, inv_rho, qv_sat_l, qv_sat_i, qv_supersat_i, rhofacr, rhofaci, acn, qv, th_atm, qc, nc, qr, nr, & - qi, ni, qm, bm, qc_incld, qr_incld, qi_incld, qm_incld, & - nc_incld, nr_incld, ni_incld, bm_incld, is_nucleat_possible, is_hydromet_present) bind(C) - - use micro_p3, only: p3_main_part1 - - ! arguments - integer(kind=c_int), value, intent(in) :: kts, kte, kbot, ktop, kdir - logical(kind=c_bool), value, intent(in) :: do_predict_nc, do_prescribed_CCN - real(kind=c_real), value, intent(in) :: dt - - real(kind=c_real), intent(in), dimension(kts:kte) :: pres, dpres, dz, nc_nuceat_tend, inv_exner, exner, inv_cld_frac_l, inv_cld_frac_i, & - inv_cld_frac_r, latent_heat_vapor, latent_heat_sublim, latent_heat_fusion, nccn_prescribed - - real(kind=c_real), intent(inout), dimension(kts:kte) :: T_atm, rho, inv_rho, qv_sat_l, qv_sat_i, qv_supersat_i, rhofacr, rhofaci, & - acn, qv, th_atm, qc, nc, qr, nr, qi, ni, qm, bm, qc_incld, qr_incld, qi_incld, & - qm_incld, nc_incld, nr_incld, ni_incld, bm_incld - - logical(kind=c_bool), intent(out) :: is_nucleat_possible, is_hydromet_present - - call p3_main_part1(kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribed_CCN, dt, & - pres, dpres, dz, nc_nuceat_tend, inv_exner, exner, inv_cld_frac_l, inv_cld_frac_i, inv_cld_frac_r, latent_heat_vapor, latent_heat_sublim, latent_heat_fusion, nccn_prescribed, & - T_atm, rho, inv_rho, qv_sat_l, qv_sat_i, qv_supersat_i, rhofacr, rhofaci, acn, qv, th_atm, qc, nc, qr, nr, & - qi, ni, qm, bm, qc_incld, qr_incld, qi_incld, qm_incld, & - nc_incld, nr_incld, ni_incld, bm_incld, is_nucleat_possible, is_hydromet_present) - - end subroutine p3_main_part1_c - - subroutine p3_main_part2_c(kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribed_CCN, dt, inv_dt, & - pres, inv_exner, inv_cld_frac_l, inv_cld_frac_i, inv_cld_frac_r, & - ni_activated, inv_qc_relvar, cld_frac_i, cld_frac_l, cld_frac_r, qv_prev, t_prev, & - T_atm, rho, inv_rho, qv_sat_l, qv_sat_i, qv_supersat_i, rhofaci, acn, qv, th_atm, qc, nc, qr, nr, qi, ni, & - qm, bm, latent_heat_vapor, latent_heat_sublim, latent_heat_fusion, qc_incld, qr_incld, qi_incld, qm_incld, nc_incld, nr_incld, & - ni_incld, bm_incld, mu_c, nu, lamc, cdist, cdist1, cdistr, mu_r, lamr, logn0r, qv2qi_depos_tend, precip_total_tend, & - nevapr, qr_evap_tend, vap_liq_exchange, vap_ice_exchange, liq_ice_exchange, pratot, & - prctot, is_hydromet_present) bind(C) - - use micro_p3, only: p3_main_part2 - - !arguments - integer(kind=c_int), value, intent(in) :: kts, kte, kbot, ktop, kdir - logical(kind=c_bool), value, intent(in) :: do_predict_nc, do_prescribed_CCN - real(kind=c_real), value, intent(in) :: dt, inv_dt - - real(kind=c_real), intent(in), dimension(kts:kte) :: pres, inv_exner, inv_cld_frac_l, inv_cld_frac_i, & - inv_cld_frac_r, ni_activated, inv_qc_relvar, cld_frac_i, cld_frac_l, cld_frac_r, qv_prev, t_prev - - real(kind=c_real), intent(inout), dimension(kts:kte) :: T_atm, rho, inv_rho, qv_sat_l, qv_sat_i, qv_supersat_i, rhofaci, acn, & - qv, th_atm, qc, nc, qr, nr, qi, ni, qm, bm, latent_heat_vapor, latent_heat_sublim, latent_heat_fusion, qc_incld, qr_incld, & - qi_incld, qm_incld, nc_incld, nr_incld, ni_incld, bm_incld, mu_c, nu, lamc, cdist, cdist1, & - cdistr, mu_r, lamr, logn0r, qv2qi_depos_tend, precip_total_tend, nevapr, qr_evap_tend, vap_liq_exchange, & - vap_ice_exchange, liq_ice_exchange, pratot, prctot - - logical(kind=c_bool), intent(out) :: is_hydromet_present - - ! throwaway - real(kind=c_real), dimension(kts:kte,49) :: p3_tend_out - - call p3_main_part2(kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribed_CCN, dt, inv_dt, & - pres, inv_exner, inv_cld_frac_l, inv_cld_frac_i, inv_cld_frac_r, ni_activated, inv_qc_relvar, cld_frac_i, cld_frac_l, cld_frac_r, qv_prev, t_prev, & - T_atm, rho, inv_rho, qv_sat_l, qv_sat_i, qv_supersat_i, rhofaci, acn, qv, th_atm, qc, nc, qr, nr, qi, ni, & - qm, bm, latent_heat_vapor, latent_heat_sublim, latent_heat_fusion, qc_incld, qr_incld, qi_incld, qm_incld, nc_incld, nr_incld, & - ni_incld, bm_incld, mu_c, nu, lamc, cdist, cdist1, cdistr, mu_r, lamr, logn0r, qv2qi_depos_tend, precip_total_tend, & - nevapr, qr_evap_tend, vap_liq_exchange, vap_ice_exchange, liq_ice_exchange, pratot, & - prctot, p3_tend_out, is_hydromet_present) - - end subroutine p3_main_part2_c - - subroutine p3_main_part3_c(kts, kte, kbot, ktop, kdir, & - inv_exner, cld_frac_l, cld_frac_r, cld_frac_i, & - rho, inv_rho, rhofaci, qv, th_atm, qc, nc, qr, nr, qi, ni, qm, bm, latent_heat_vapor, latent_heat_sublim, & - mu_c, nu, lamc, mu_r, lamr, vap_liq_exchange, & - ze_rain, ze_ice, diag_vm_qi, diag_eff_radius_qi, diag_diam_qi, rho_qi, diag_equiv_reflectivity, diag_eff_radius_qc, diag_eff_radius_qr) bind(C) - - use micro_p3, only: p3_main_part3 - - ! args - - integer(kind=c_int), value, intent(in) :: kts, kte, kbot, ktop, kdir - real(kind=c_real), intent(in), dimension(kts:kte) :: inv_exner, cld_frac_l, cld_frac_r, cld_frac_i - real(kind=c_real), intent(inout), dimension(kts:kte) :: rho, inv_rho, rhofaci, & - qv, th_atm, qc, nc, qr, nr, qi, ni, qm, bm, latent_heat_vapor, latent_heat_sublim, & - mu_c, nu, lamc, mu_r, & - lamr, vap_liq_exchange, & - ze_rain, ze_ice, diag_vm_qi, diag_eff_radius_qi, diag_diam_qi, rho_qi, & - diag_equiv_reflectivity, diag_eff_radius_qc, diag_eff_radius_qr - - call p3_main_part3(kts, kte, kbot, ktop, kdir, & - inv_exner, cld_frac_l, cld_frac_r, cld_frac_i, & - rho, inv_rho, rhofaci, qv, th_atm, qc, nc, qr, nr, qi, ni, qm, bm, latent_heat_vapor, latent_heat_sublim, & - mu_c, nu, lamc, mu_r, lamr, vap_liq_exchange, & - ze_rain, ze_ice, diag_vm_qi, diag_eff_radius_qi, diag_diam_qi, rho_qi, diag_equiv_reflectivity, diag_eff_radius_qc, diag_eff_radius_qr) - - end subroutine p3_main_part3_c - - subroutine ice_supersat_conservation_c(qidep, qinuc, cld_frac_i, qv, qv_sat_i, latent_heat_sublim, t_atm, dt, qi2qv_sublim_tend, qr2qv_evap_tend) bind(C) - use micro_p3, only : ice_supersat_conservation - - real(kind=c_real) , intent(inout) :: qidep, qinuc - real(kind=c_real) , value, intent(in) :: cld_frac_i, qv, qv_sat_i, latent_heat_sublim, t_atm, dt, qi2qv_sublim_tend, qr2qv_evap_tend - - call ice_supersat_conservation(qidep, qinuc, cld_frac_i, qv, qv_sat_i, latent_heat_sublim, t_atm, dt, qi2qv_sublim_tend, qr2qv_evap_tend) - end subroutine ice_supersat_conservation_c - subroutine nc_conservation_c(nc, nc_selfcollect_tend, dt, nc_collect_tend, nc2ni_immers_freeze_tend, nc_accret_tend, nc2nr_autoconv_tend) bind(C) - use micro_p3, only : nc_conservation - - real(kind=c_real) , value, intent(in) :: nc, nc_selfcollect_tend, dt - real(kind=c_real) , intent(inout) :: nc_collect_tend, nc2ni_immers_freeze_tend, nc_accret_tend, nc2nr_autoconv_tend - - call nc_conservation(nc, nc_selfcollect_tend, dt, nc_collect_tend, nc2ni_immers_freeze_tend, nc_accret_tend, nc2nr_autoconv_tend) - end subroutine nc_conservation_c - subroutine nr_conservation_c(nr, ni2nr_melt_tend, nr_ice_shed_tend, ncshdc, nc2nr_autoconv_tend, dt, nmltratio, nr_collect_tend, nr2ni_immers_freeze_tend, nr_selfcollect_tend, nr_evap_tend) bind(C) - use micro_p3, only : nr_conservation - - real(kind=c_real) , value, intent(in) :: nr, ni2nr_melt_tend, nr_ice_shed_tend, ncshdc, nc2nr_autoconv_tend, dt, nmltratio - real(kind=c_real) , intent(inout) :: nr_collect_tend, nr2ni_immers_freeze_tend, nr_selfcollect_tend, nr_evap_tend - - call nr_conservation(nr, ni2nr_melt_tend, nr_ice_shed_tend, ncshdc, nc2nr_autoconv_tend, dt, nmltratio, nr_collect_tend, nr2ni_immers_freeze_tend, nr_selfcollect_tend, nr_evap_tend) - end subroutine nr_conservation_c - subroutine ni_conservation_c(ni, ni_nucleat_tend, nr2ni_immers_freeze_tend, nc2ni_immers_freeze_tend, dt, ni2nr_melt_tend, ni_sublim_tend, ni_selfcollect_tend) bind(C) - use micro_p3, only : ni_conservation - - real(kind=c_real) , value, intent(in) :: ni, ni_nucleat_tend, nr2ni_immers_freeze_tend, nc2ni_immers_freeze_tend, dt - real(kind=c_real) , intent(inout) :: ni2nr_melt_tend, ni_sublim_tend, ni_selfcollect_tend - - call ni_conservation(ni, ni_nucleat_tend, nr2ni_immers_freeze_tend, nc2ni_immers_freeze_tend, dt, ni2nr_melt_tend, ni_sublim_tend, ni_selfcollect_tend) - end subroutine ni_conservation_c - subroutine prevent_liq_supersaturation_c(pres, t_atm, qv, latent_heat_vapor, latent_heat_sublim, dt, qidep, qinuc, qi2qv_sublim_tend, qr2qv_evap_tend) bind(C) - use micro_p3, only : prevent_liq_supersaturation - - real(kind=c_real) , value, intent(in) :: pres, t_atm, qv, latent_heat_vapor, latent_heat_sublim, dt, qidep, qinuc - real(kind=c_real) , intent(inout) :: qi2qv_sublim_tend, qr2qv_evap_tend - - call prevent_liq_supersaturation(pres, t_atm, qv, latent_heat_vapor, latent_heat_sublim, dt, qidep, qinuc, qi2qv_sublim_tend, qr2qv_evap_tend) - end subroutine prevent_liq_supersaturation_c end module p3_iso_c diff --git a/components/eamxx/src/physics/p3/p3_main_wrap.cpp b/components/eamxx/src/physics/p3/p3_main_wrap.cpp deleted file mode 100644 index ed46e281a675..000000000000 --- a/components/eamxx/src/physics/p3/p3_main_wrap.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "p3_main_wrap.hpp" -#include "p3_f90.hpp" -#include "p3_functions_f90.hpp" -#include "physics_constants.hpp" -#include "p3_ic_cases.hpp" - -#include "ekat/ekat_assert.hpp" - -using scream::Real; -using scream::Int; -extern "C" { - void p3_main_c(Real* qc, Real* nc, Real* qr, Real* nr, Real* th_atm, - Real* qv, Real dt, Real* qi, Real* qm, - Real* ni, Real* bm, Real* pres, - Real* dz, Real* nc_nuceat_tend, Real* nccn_prescribed, Real* ni_activated, Real* inv_qc_relvar, - Int it, Real* precip_liq_surf, Real* precip_ice_surf, Int its, - Int ite, Int kts, Int kte, Real* diag_eff_radius_qc, Real* diag_eff_radius_qi, Real* diag_eff_radius_qr, - Real* rho_qi, bool do_predict_nc, bool do_prescribed_CCN, Real* dpres, Real* inv_exner, - Real* qv2qi_depos_tend, - Real* precip_liq_flux, Real* precip_ice_flux, // 1 extra column size - Real* cld_frac_r, Real* cld_frac_l, Real* cld_frac_i, - Real* liq_ice_exchange, Real* vap_liq_exchange, - Real* vap_ice_exchange, Real* qv_prev, Real* t_prev, Real* elapsed_s); -} - -namespace scream { -namespace p3 { - -Int p3_main_wrap(const FortranData& d, bool use_fortran) { - EKAT_REQUIRE_MSG(d.dt > 0, "invalid dt"); - if (use_fortran) { - Real elapsed_s; - p3_main_c(d.qc.data(), d.nc.data(), d.qr.data(), d.nr.data(), - d.th_atm.data(), d.qv.data(), d.dt, d.qi.data(), - d.qm.data(), d.ni.data(), d.bm.data(), - d.pres.data(), d.dz.data(), d.nc_nuceat_tend.data(), d.nccn_prescribed.data(), d.ni_activated.data(), d.inv_qc_relvar.data(), - d.it, d.precip_liq_surf.data(), d.precip_ice_surf.data(), 1, d.ncol, 1, d.nlev, - d.diag_eff_radius_qc.data(), d.diag_eff_radius_qi.data(), d.diag_eff_radius_qr.data(), d.rho_qi.data(), - d.do_predict_nc, d.do_prescribed_CCN, d.dpres.data(), d.inv_exner.data(), d.qv2qi_depos_tend.data(), - d.precip_liq_flux.data(), d.precip_ice_flux.data(), d.cld_frac_r.data(), d.cld_frac_l.data(), d.cld_frac_i.data(), - d.liq_ice_exchange.data(), d.vap_liq_exchange.data(),d.vap_ice_exchange.data(),d.qv_prev.data(),d.t_prev.data(), &elapsed_s); - return static_cast(elapsed_s * 1000000); - } - else { - return p3_main_f(d.qc.data(), d.nc.data(), d.qr.data(), d.nr.data(), d.th_atm.data(), - d.qv.data(), d.dt, d.qi.data(), d.qm.data(), d.ni.data(), - d.bm.data(), d.pres.data(), d.dz.data(), d.nc_nuceat_tend.data(), d.nccn_prescribed.data(), - d.ni_activated.data(), d.inv_qc_relvar.data(), d.it, d.precip_liq_surf.data(), - d.precip_ice_surf.data(), 1, d.ncol, 1, d.nlev, d.diag_eff_radius_qc.data(), - d.diag_eff_radius_qi.data(), d.diag_eff_radius_qr.data(), d.rho_qi.data(), d.do_predict_nc, d.do_prescribed_CCN, - d.dpres.data(), d.inv_exner.data(), d.qv2qi_depos_tend.data(), - d.precip_liq_flux.data(), d.precip_ice_flux.data(), - d.cld_frac_r.data(), d.cld_frac_l.data(), d.cld_frac_i.data(), - d.liq_ice_exchange.data(), d.vap_liq_exchange.data(), - d.vap_ice_exchange.data(),d.qv_prev.data(),d.t_prev.data() ); - - } -} - -int test_p3_init () { - p3_init(); - P3GlobalForFortran::deinit(); - return 0; -} - -int test_p3_ic (bool use_fortran) { - const auto d = ic::Factory::create(ic::Factory::mixed); - d->dt = 300.0; - p3_init(); - p3_main_wrap(*d, use_fortran); - P3GlobalForFortran::deinit(); - return 0; -} - -} // namespace p3 -} // namespace scream diff --git a/components/eamxx/src/physics/p3/p3_tables_setup.cpp b/components/eamxx/src/physics/p3/p3_tables_setup.cpp index 8582674d1fe5..ec3f5ccbb433 100644 --- a/components/eamxx/src/physics/p3/p3_tables_setup.cpp +++ b/components/eamxx/src/physics/p3/p3_tables_setup.cpp @@ -1,6 +1,6 @@ // This is a tiny program that calls p3_init() to generate tables used by p3 -#include "physics/p3/p3_f90.hpp" +#include "physics/p3/p3_data.hpp" int main(int /* argc */, char** /* argv */) { scream::p3::p3_init(/* write_tables = */ true); diff --git a/components/eamxx/src/physics/p3/tests/CMakeLists.txt b/components/eamxx/src/physics/p3/tests/CMakeLists.txt index 217c2945e489..129e3c455e26 100644 --- a/components/eamxx/src/physics/p3/tests/CMakeLists.txt +++ b/components/eamxx/src/physics/p3/tests/CMakeLists.txt @@ -1,5 +1,7 @@ include(ScreamUtils) +add_subdirectory(infra) + set(P3_TESTS_SRCS p3_tests.cpp p3_unit_tests.cpp @@ -44,75 +46,76 @@ else () set (FORCE_RUN_DIFF_FAILS "") endif() -# NOTE: tests inside this if statement won't be built in a baselines-only build -if (NOT SCREAM_ONLY_GENERATE_BASELINES) - CreateUnitTest(p3_tests "${P3_TESTS_SRCS}" - LIBS p3 - THREADS 1 ${SCREAM_TEST_MAX_THREADS} ${SCREAM_TEST_THREAD_INC} - LABELS "p3;physics") - - # Make sure that a diff in the two implementation triggers a failed test (in debug only) - CreateUnitTest (p3_tests_fail p3_rain_sed_unit_tests.cpp - LIBS p3 - COMPILER_CXX_DEFS SCREAM_FORCE_RUN_DIFF - THREADS 1 ${SCREAM_TEST_MAX_THREADS} ${SCREAM_TEST_THREAD_INC} - LABELS "p3;physics;fail" - ${FORCE_RUN_DIFF_FAILS}) - - if (NOT SCREAM_P3_SMALL_KERNELS) - CreateUnitTest(p3_sk_tests "${P3_TESTS_SRCS}" - LIBS p3_sk - THREADS 1 ${SCREAM_TEST_MAX_THREADS} ${SCREAM_TEST_THREAD_INC} - LABELS "p3_sk;physics") - - # Make sure that a diff in the two implementation triggers a failed test (in debug only) - CreateUnitTest (p3_sk_tests_fail p3_rain_sed_unit_tests.cpp - LIBS p3_sk - COMPILER_CXX_DEFS SCREAM_FORCE_RUN_DIFF - THREADS 1 ${SCREAM_TEST_MAX_THREADS} ${SCREAM_TEST_THREAD_INC} - LABELS "p3_sk;physics;fail" - ${FORCE_RUN_DIFF_FAILS}) - endif() -endif() - +# All tests should understand the same baseline args if (SCREAM_ENABLE_BASELINE_TESTS) if (SCREAM_ONLY_GENERATE_BASELINES) - set(BASELINE_FILE_ARG "-g -b ${SCREAM_BASELINES_DIR}/data/p3_run_and_cmp.baseline") + set(BASELINE_FILE_ARG "-g -b ${SCREAM_BASELINES_DIR}/data") else() - set(BASELINE_FILE_ARG "-b ${SCREAM_BASELINES_DIR}/data/p3_run_and_cmp.baseline") + set(BASELINE_FILE_ARG "-c -b ${SCREAM_BASELINES_DIR}/data") endif() +else() + set(BASELINE_FILE_ARG "-n") # no baselines +endif() - CreateUnitTestExec(p3_run_and_cmp "p3_run_and_cmp.cpp" - LIBS p3 - EXCLUDE_MAIN_CPP) +CreateUnitTest(p3_tests "${P3_TESTS_SRCS}" + LIBS p3 p3_test_infra + EXE_ARGS "--args ${BASELINE_FILE_ARG}" + THREADS 1 ${SCREAM_TEST_MAX_THREADS} ${SCREAM_TEST_THREAD_INC} + LABELS "p3;physics") - CreateUnitTestFromExec(p3_run_and_cmp_cxx p3_run_and_cmp - THREADS ${SCREAM_TEST_MAX_THREADS} - EXE_ARGS "${BASELINE_FILE_ARG}" - LABELS "p3;physics") +# Make sure that a diff in the two implementation triggers a failed test (in debug only) +# No need to run lots of different thread counts. +if (SCREAM_ENABLE_BASELINE_TESTS) + CreateUnitTest (p3_tests_fail p3_rain_sed_unit_tests.cpp + LIBS p3 p3_test_infra + EXE_ARGS "--args ${BASELINE_FILE_ARG}" + COMPILER_CXX_DEFS SCREAM_FORCE_RUN_DIFF + LABELS "p3;physics;fail" + ${FORCE_RUN_DIFF_FAILS}) +endif() - CreateUnitTestFromExec(p3_run_and_cmp_f90 p3_run_and_cmp - THREADS ${SCREAM_TEST_MAX_THREADS} - EXE_ARGS "-f ${BASELINE_FILE_ARG}" - LABELS "p3;physics") +if (NOT SCREAM_P3_SMALL_KERNELS) + CreateUnitTest(p3_sk_tests "${P3_TESTS_SRCS}" + LIBS p3_sk p3_test_infra + EXE_ARGS "--args ${BASELINE_FILE_ARG}" + THREADS 1 ${SCREAM_TEST_MAX_THREADS} ${SCREAM_TEST_THREAD_INC} + LABELS "p3_sk;physics") - # Make sure that a diff from baselines triggers a failed test (in debug only) - CreateUnitTest(p3_run_and_cmp_cxx_fail "p3_run_and_cmp.cpp" - LIBS p3 + # Make sure that a diff in the two implementation triggers a failed test (in debug only) + # No need to run lots of different thread counts. + if (SCREAM_ENABLE_BASELINE_TESTS) + CreateUnitTest (p3_sk_tests_fail p3_rain_sed_unit_tests.cpp + LIBS p3_sk p3_test_infra + EXE_ARGS "--args ${BASELINE_FILE_ARG}" COMPILER_CXX_DEFS SCREAM_FORCE_RUN_DIFF - THREADS ${SCREAM_TEST_MAX_THREADS} - EXE_ARGS "${BASELINE_FILE_ARG}" - LABELS "p3;physics;fail" - EXCLUDE_MAIN_CPP + LABELS "p3_sk;physics;fail" ${FORCE_RUN_DIFF_FAILS}) - - # By default, baselines should be created using all fortran (ctest -L baseline_gen). If the user wants - # to use CXX to generate their baselines, they should use "ctest -L baseline_gen_cxx". - # Note: the baseline_gen label label is really only used if SCREAM_ONLY_GENERATE_BASELINES=ON, but no harm adding it - if (SCREAM_TEST_MAX_THREADS GREATER 1) - # ECUT only adds _ompX if we have more than one value of X, or if X>1 - set (TEST_SUFFIX _omp${SCREAM_TEST_MAX_THREADS}) endif() - set_tests_properties (p3_run_and_cmp_f90${TEST_SUFFIX} PROPERTIES LABELS "baseline_gen;baseline_cmp") - set_tests_properties (p3_run_and_cmp_cxx${TEST_SUFFIX} PROPERTIES LABELS "baseline_gen;cxx baseline_cmp") endif() + +CreateUnitTest(p3_run_and_cmp "p3_run_and_cmp.cpp" + LIBS p3 p3_test_infra + EXCLUDE_MAIN_CPP + THREADS ${SCREAM_TEST_MAX_THREADS} + EXE_ARGS "${BASELINE_FILE_ARG}" + LABELS "p3;physics") + +# Make sure that a diff from baselines triggers a failed test (in debug only) +if (SCREAM_ENABLE_BASELINE_TESTS) + CreateUnitTest(p3_run_and_cmp_fail "p3_run_and_cmp.cpp" + LIBS p3 p3_test_infra + COMPILER_CXX_DEFS SCREAM_FORCE_RUN_DIFF + THREADS ${SCREAM_TEST_MAX_THREADS} + EXE_ARGS "${BASELINE_FILE_ARG}" + LABELS "p3;physics;fail" + EXCLUDE_MAIN_CPP + ${FORCE_RUN_DIFF_FAILS}) +endif() + +# Note: the baseline_gen label label is really only used if SCREAM_ONLY_GENERATE_BASELINES=ON, but no harm adding it +if (SCREAM_TEST_MAX_THREADS GREATER 1) + # ECUT only adds _ompX if we have more than one value of X, or if X>1 + set (TEST_SUFFIX _omp${SCREAM_TEST_MAX_THREADS}) +endif() + +set_tests_properties (p3_run_and_cmp${TEST_SUFFIX} PROPERTIES LABELS "baseline_gen;cxx baseline_cmp") diff --git a/components/eamxx/src/physics/p3/tests/infra/CMakeLists.txt b/components/eamxx/src/physics/p3/tests/infra/CMakeLists.txt new file mode 100644 index 000000000000..6f7093a33ec7 --- /dev/null +++ b/components/eamxx/src/physics/p3/tests/infra/CMakeLists.txt @@ -0,0 +1,15 @@ +set(INFRA_SRCS + p3_data.cpp + p3_ic_cases.cpp + p3_main_wrap.cpp + p3_test_data.cpp +) + +#crusher change +if (Kokkos_ENABLE_HIP) +set_source_files_properties(p3_test_data.cpp PROPERTIES COMPILE_FLAGS -O0) +endif() + +add_library(p3_test_infra ${INFRA_SRCS}) +target_link_libraries(p3_test_infra p3) +target_include_directories(p3_test_infra PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/components/eamxx/src/physics/p3/p3_f90.cpp b/components/eamxx/src/physics/p3/tests/infra/p3_data.cpp similarity index 75% rename from components/eamxx/src/physics/p3/p3_f90.cpp rename to components/eamxx/src/physics/p3/tests/infra/p3_data.cpp index 38bb84c416ec..24fd6529f22d 100644 --- a/components/eamxx/src/physics/p3/p3_f90.cpp +++ b/components/eamxx/src/physics/p3/tests/infra/p3_data.cpp @@ -1,4 +1,4 @@ -#include "p3_f90.hpp" +#include "p3_data.hpp" #include "physics_constants.hpp" #include "p3_ic_cases.hpp" @@ -6,17 +6,11 @@ using scream::Real; using scream::Int; -extern "C" { - void micro_p3_utils_init_c(Real Cpair, Real Rair, Real RH2O, Real RHO_H2O, - Real MWH2O, Real MWdry, Real gravit, Real LatVap, Real LatIce, - Real CpLiq, Real Tmelt, Real Pi, bool masterproc); - void p3_init_c(const char** lookup_file_dir, int* info, const bool& write_tables); -} namespace scream { namespace p3 { -FortranData::FortranData (Int ncol_, Int nlev_) +P3Data::P3Data (Int ncol_, Int nlev_) : ncol(ncol_), nlev(nlev_) { do_predict_nc = true; @@ -62,11 +56,11 @@ FortranData::FortranData (Int ncol_, Int nlev_) vap_ice_exchange = Array2("sum of vap-ice phase change tendenices", ncol, nlev); } -FortranDataIterator::FortranDataIterator (const FortranData::Ptr& d) { +P3DataIterator::P3DataIterator (const P3Data::Ptr& d) { init(d); } -void FortranDataIterator::init (const FortranData::Ptr& dp) { +void P3DataIterator::init (const P3Data::Ptr& dp) { d_ = dp; #define fdipb(name) \ fields_.push_back({#name, \ @@ -79,7 +73,7 @@ void FortranDataIterator::init (const FortranData::Ptr& dp) { fdipb(nc); fdipb(qr); fdipb(nr); fdipb(qi); fdipb(ni); fdipb(qm); fdipb(bm); fdipb(precip_liq_surf); fdipb(precip_ice_surf); fdipb(diag_eff_radius_qc); fdipb(diag_eff_radius_qi); fdipb(diag_eff_radius_qr); fdipb(rho_qi); - fdipb(dpres); fdipb(inv_exner); fdipb(qv2qi_depos_tend); + fdipb(dpres); fdipb(inv_exner); fdipb(qv2qi_depos_tend); fdipb(precip_liq_flux); fdipb(precip_ice_flux); fdipb(cld_frac_r); fdipb(cld_frac_l); fdipb(cld_frac_i); fdipb(liq_ice_exchange); fdipb(vap_liq_exchange); @@ -87,33 +81,14 @@ void FortranDataIterator::init (const FortranData::Ptr& dp) { #undef fdipb } -const FortranDataIterator::RawArray& -FortranDataIterator::getfield (Int i) const { +const P3DataIterator::RawArray& +P3DataIterator::getfield (Int i) const { EKAT_ASSERT(i >= 0 || i < nfield()); return fields_[i]; } -void micro_p3_utils_init (const bool masterproc) { - using c = scream::physics::Constants; - micro_p3_utils_init_c(c::Cpair, c::Rair, c::RH2O, c::RHO_H2O, - c::MWH2O, c::MWdry, c::gravit, c::LatVap, c::LatIce, - c::CpLiq, c::Tmelt, c::Pi, masterproc); -} - -void p3_init (const bool write_tables, const bool masterproc) { - static bool is_init = false; - if (!is_init) { - micro_p3_utils_init(masterproc); - static const char* dir = SCREAM_DATA_DIR "/tables"; - Int info; - p3_init_c(&dir, &info, write_tables); - EKAT_REQUIRE_MSG(info == 0, "p3_init_c returned info " << info); - is_init = true; - } -} - -int test_FortranData () { - FortranData d(11, 72); +int test_P3Data () { + P3Data d(11, 72); return 0; } diff --git a/components/eamxx/src/physics/p3/p3_f90.hpp b/components/eamxx/src/physics/p3/tests/infra/p3_data.hpp similarity index 68% rename from components/eamxx/src/physics/p3/p3_f90.hpp rename to components/eamxx/src/physics/p3/tests/infra/p3_data.hpp index d07524d9c7a2..df5b25e311ae 100644 --- a/components/eamxx/src/physics/p3/p3_f90.hpp +++ b/components/eamxx/src/physics/p3/tests/infra/p3_data.hpp @@ -1,5 +1,5 @@ -#ifndef SCREAM_P3_F90_HPP -#define SCREAM_P3_F90_HPP +#ifndef SCREAM_P3_DATA_HPP +#define SCREAM_P3_DATA_HPP #include "share/scream_types.hpp" @@ -9,9 +9,9 @@ namespace scream { namespace p3 { -// Data format we can use to communicate with Fortran version. -struct FortranData { - typedef std::shared_ptr Ptr; +// Data format we can use to store (and read/write) data for a full P3 run. +struct P3Data { + typedef std::shared_ptr Ptr; using KT = KokkosTypes; using Scalar = Real; @@ -36,41 +36,38 @@ struct FortranData { Array3 p3_tend_out; Array2 liq_ice_exchange,vap_liq_exchange,vap_ice_exchange; - FortranData(Int ncol, Int nlev); + P3Data(Int ncol, Int nlev); }; -// Iterate over a FortranData's arrays. For examples, see Baseline::write, read. -struct FortranDataIterator { +// Iterate over a P3Data's arrays. For examples, see Baseline::write, read. +struct P3DataIterator { struct RawArray { std::string name; Int dim; Int extent[3]; - FortranData::Scalar* data; - FortranData::Array1::size_type size; + P3Data::Scalar* data; + P3Data::Array1::size_type size; }; - explicit FortranDataIterator(const FortranData::Ptr& d); + explicit P3DataIterator(const P3Data::Ptr& d); Int nfield () const { return fields_.size(); } const RawArray& getfield(Int i) const; private: - FortranData::Ptr d_; + P3Data::Ptr d_; std::vector fields_; - void init(const FortranData::Ptr& d); + void init(const P3Data::Ptr& d); }; -void p3_init(const bool write_tables = false, - const bool masterproc = false); - // We will likely want to remove these checks in the future, as we're not tied // to the exact implementation or arithmetic in P3. For now, these checks are // here to establish that the initial regression-testing code gives results that // match the python f2py tester, without needing a data file. -Int check_against_python(const FortranData& d); +Int check_against_python(const P3Data& d); -int test_FortranData(); +int test_P3Data(); } // namespace p3 } // namespace scream diff --git a/components/eamxx/src/physics/p3/p3_ic_cases.cpp b/components/eamxx/src/physics/p3/tests/infra/p3_ic_cases.cpp similarity index 95% rename from components/eamxx/src/physics/p3/p3_ic_cases.cpp rename to components/eamxx/src/physics/p3/tests/infra/p3_ic_cases.cpp index 1560dc0afb28..52b70de6025b 100644 --- a/components/eamxx/src/physics/p3/p3_ic_cases.cpp +++ b/components/eamxx/src/physics/p3/tests/infra/p3_ic_cases.cpp @@ -8,12 +8,12 @@ namespace p3 { namespace ic { // From mixed_case_data.py in scream-docs at commit 4bbea4. -FortranData::Ptr make_mixed (const Int ncol, const Int nlev) { +P3Data::Ptr make_mixed (const Int ncol, const Int nlev) { using consts = scream::physics::Constants; const Int nk = nlev; Int k; - const auto dp = std::make_shared(ncol, nk); + const auto dp = std::make_shared(ncol, nk); auto& d = *dp; for (Int i = 0; i < ncol; ++i) { @@ -66,7 +66,7 @@ FortranData::Ptr make_mixed (const Int ncol, const Int nlev) { // To get potential temperature, start by making absolute temperature vary // between 150K at top of atmos and 300k at surface, then convert to potential // temp. - FortranData::Array1 T_atm("T", nk); + P3Data::Array1 T_atm("T", nk); for (k = 0; k < nk; ++k) { T_atm(k) = 150 + 150/double(nk)*k; if (i > 0) T_atm(k) += ((i % 3) - 0.5)/double(nk)*k; @@ -119,7 +119,7 @@ FortranData::Ptr make_mixed (const Int ncol, const Int nlev) { return dp; } -FortranData::Ptr Factory::create (IC ic, Int ncol, Int nlev) { +P3Data::Ptr Factory::create (IC ic, Int ncol, Int nlev) { switch (ic) { case mixed: return make_mixed(ncol, nlev); default: diff --git a/components/eamxx/src/physics/p3/p3_ic_cases.hpp b/components/eamxx/src/physics/p3/tests/infra/p3_ic_cases.hpp similarity index 64% rename from components/eamxx/src/physics/p3/p3_ic_cases.hpp rename to components/eamxx/src/physics/p3/tests/infra/p3_ic_cases.hpp index a8c461b06daa..bbf6f133e516 100644 --- a/components/eamxx/src/physics/p3/p3_ic_cases.hpp +++ b/components/eamxx/src/physics/p3/tests/infra/p3_ic_cases.hpp @@ -1,18 +1,18 @@ #ifndef INCLUDE_SCREAM_P3_IC_CASES_HPP #define INCLUDE_SCREAM_P3_IC_CASES_HPP -#include "p3_f90.hpp" +#include "p3_data.hpp" namespace scream { namespace p3 { namespace ic { -FortranData::Ptr make_mixed(Int ncol); +P3Data::Ptr make_mixed(Int ncol); struct Factory { enum IC { mixed }; - static FortranData::Ptr create(IC ic, Int ncol = 1, Int nlev = 72); + static P3Data::Ptr create(IC ic, Int ncol = 1, Int nlev = 72); }; } // namespace ic diff --git a/components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.cpp b/components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.cpp new file mode 100644 index 000000000000..2b758a513ec5 --- /dev/null +++ b/components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.cpp @@ -0,0 +1,51 @@ +#include "p3_main_wrap.hpp" +#include "p3_data.hpp" +#include "p3_test_data.hpp" +#include "physics_constants.hpp" +#include "p3_ic_cases.hpp" + +#include "ekat/ekat_assert.hpp" + +using scream::Real; +using scream::Int; + +namespace scream { +namespace p3 { + +Int p3_main_wrap(const P3Data& d) { + EKAT_REQUIRE_MSG(d.dt > 0, "invalid dt"); + return p3_main_host(d.qc.data(), d.nc.data(), d.qr.data(), d.nr.data(), d.th_atm.data(), + d.qv.data(), d.dt, d.qi.data(), d.qm.data(), d.ni.data(), + d.bm.data(), d.pres.data(), d.dz.data(), d.nc_nuceat_tend.data(), d.nccn_prescribed.data(), + d.ni_activated.data(), d.inv_qc_relvar.data(), d.it, d.precip_liq_surf.data(), + d.precip_ice_surf.data(), 1, d.ncol, 1, d.nlev, d.diag_eff_radius_qc.data(), + d.diag_eff_radius_qi.data(), d.diag_eff_radius_qr.data(), d.rho_qi.data(), d.do_predict_nc, d.do_prescribed_CCN, + d.dpres.data(), d.inv_exner.data(), d.qv2qi_depos_tend.data(), + d.precip_liq_flux.data(), d.precip_ice_flux.data(), + d.cld_frac_r.data(), d.cld_frac_l.data(), d.cld_frac_i.data(), + d.liq_ice_exchange.data(), d.vap_liq_exchange.data(), + d.vap_ice_exchange.data(),d.qv_prev.data(),d.t_prev.data() ); +} + +int test_p3_init () { + using P3F = Functions; + + P3F::p3_init(); + P3GlobalForFortran::deinit(); + return 0; +} + +int test_p3_ic () { + using P3F = Functions; + + const auto d = ic::Factory::create(ic::Factory::mixed); + + d->dt = 300.0; + P3F::p3_init(); + p3_main_wrap(*d); + P3GlobalForFortran::deinit(); + return 0; +} + +} // namespace p3 +} // namespace scream diff --git a/components/eamxx/src/physics/p3/p3_main_wrap.hpp b/components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.hpp similarity index 71% rename from components/eamxx/src/physics/p3/p3_main_wrap.hpp rename to components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.hpp index 7c980fa8a5bb..c55007427cdb 100644 --- a/components/eamxx/src/physics/p3/p3_main_wrap.hpp +++ b/components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.hpp @@ -8,15 +8,14 @@ namespace scream { namespace p3 { -struct FortranData; +struct P3Data; // Returns number of microseconds of p3_main execution -Int p3_main_wrap(const FortranData& d, bool use_fortran=false); +Int p3_main_wrap(const P3Data& d); int test_p3_init(); -int test_p3_ic(bool use_fortran); - +int test_p3_ic(); } // namespace p3 } // namespace scream diff --git a/components/eamxx/src/physics/p3/p3_functions_f90.cpp b/components/eamxx/src/physics/p3/tests/infra/p3_test_data.cpp similarity index 64% rename from components/eamxx/src/physics/p3/p3_functions_f90.cpp rename to components/eamxx/src/physics/p3/tests/infra/p3_test_data.cpp index 7ce3f8aaa321..23a9998f43c6 100644 --- a/components/eamxx/src/physics/p3/p3_functions_f90.cpp +++ b/components/eamxx/src/physics/p3/tests/infra/p3_test_data.cpp @@ -1,6 +1,6 @@ -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "ekat/kokkos/ekat_kokkos_types.hpp" -#include "p3_f90.hpp" +#include "p3_data.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "ekat/ekat_pack_kokkos.hpp" @@ -11,275 +11,22 @@ using scream::Real; using scream::Int; -// -// A C++ interface to micro_p3 fortran calls and vice versa -// extern "C" { void p3_init_a_c(Real* ice_table_vals, Real* collect_table_vals); -void find_lookuptable_indices_1a_c(Int* dumi, Int* dumjj, Int* dumii, Int* dumzz, - Real* dum1, Real* dum4, Real* dum5, Real* dum6, - Real qi, Real ni, Real qm, Real rhop); - -void find_lookuptable_indices_1b_c(Int* dumj, Real* dum3, Real qr, Real nr); - -void access_lookup_table_c(Int dumjj, Int dumii, Int dumi, Int index, - Real dum1, Real dum4, Real dum5, Real* proc); - -void access_lookup_table_coll_c(Int dumjj, Int dumii, Int dumj, Int dumi, Int index, - Real dum1, Real dum3, Real dum4, Real dum5, Real* proc); - -void back_to_cell_average_c(Real cld_frac_l_, Real cld_frac_r_, Real cld_frac_i_, - Real* qc2qr_accret_tend_, Real* qr2qv_evap_tend_, Real* qc2qr_autoconv_tend_, - Real* nc_accret_tend_, Real* nc_selfcollect_tend_, Real* nc2nr_autoconv_tend_, - Real* nr_selfcollect_tend_, Real* nr_evap_tend_, Real* ncautr_, - Real* qi2qv_sublim_tend_, - Real* nr_ice_shed_tend_, Real* qc2qi_hetero_freeze_tend_, Real* qr2qi_collect_tend_, - Real* qc2qr_ice_shed_tend_, Real* qi2qr_melt_tend_, Real* qc2qi_collect_tend_, - Real* qr2qi_immers_freeze_tend_, Real* ni2nr_melt_tend_, Real* nc_collect_tend_, - Real* ncshdc_, Real* nc2ni_immers_freeze_tend_, Real* nr_collect_tend_, - Real* ni_selfcollect_tend_, Real* qv2qi_vapdep_tend_, Real* nr2ni_immers_freeze_tend_, - Real* ni_sublim_tend_, Real* qv2qi_nucleat_tend_, Real* ni_nucleat_tend_, - Real* qc2qi_berg_tend_); - -void cloud_water_conservation_c(Real qc, Real dt, Real* qc2qr_autoconv_tend, Real* qc2qr_accret_tend, Real* qc2qi_collect_tend, - Real* qc2qi_hetero_freeze_tend, Real* qc2qr_ice_shed_tend, Real* qc2qi_berg_tend, Real* qi2qv_sublim_tend, Real* qv2qi_vapdep_tend); - -void rain_water_conservation_c(Real qr, Real qc2qr_autoconv_tend, Real qc2qr_accret_tend, Real qi2qr_melt_tend, Real qc2qr_ice_shed_tend, - Real dt, Real* qr2qv_evap_tend, Real* qr2qi_collect_tend, Real* qr2qi_immers_freeze_tend); - -void ice_water_conservation_c(Real qi, Real qv2qi_vapdep_tend, Real qv2qi_nucleat_tend, Real qc2qi_berg_tend, Real qr2qi_collect_tend, Real qc2qi_collect_tend, - Real qr2qi_immers_freeze_tend, Real qc2qi_hetero_freeze_tend, Real dt, Real* qi2qv_sublim_tend, Real* qi2qr_melt_tend); - -void get_cloud_dsd2_c(Real qc, Real* nc, Real* mu_c, Real rho, Real* nu, Real* lamc, - Real* cdist, Real* cdist1); - -void get_rain_dsd2_c(Real qr, Real* nr, Real* mu_r, Real* lamr, Real* cdistr, Real* logn0r); - -void calc_rime_density_c(Real T_atm, Real rhofaci, Real table_val_qi_fallspd, Real acn, - Real lamc, Real mu_c, Real qc_incld, Real qc2qi_collect_tend, - Real* vtrmi1, Real* rho_qm_cloud); - -void cldliq_immersion_freezing_c(Real T_atm, Real lamc, Real mu_c, Real cdist1, - Real qc_incld, Real inv_qc_relvar, Real* qc2qi_hetero_freeze_tend, Real* nc2ni_immers_freeze_tend); - -void rain_immersion_freezing_c(Real T_atm, Real lamr, Real mu_r, Real cdistr, - Real qr_incld, Real* qr2qi_immers_freeze_tend, Real* nr2ni_immers_freeze_tend); - -void droplet_self_collection_c(Real rho, Real inv_rho, Real qc_incld, Real mu_c, - Real nu, Real nc2nr_autoconv_tend, Real* nc_accret_tend); - -void cloud_rain_accretion_c(Real rho, Real inv_rho, Real qc_incld, Real nc_incld, - Real qr_incld, Real inv_qc_relvar, Real* qc2qr_accret_tend, Real* nc_accret_tend); - -void cloud_water_autoconversion_c(Real rho, Real qc_incld, Real nc_incld, Real inv_qc_relvar, Real* qc2qr_autoconv_tend, Real* nc2nr_autoconv_tend, Real* ncautr); - -void rain_self_collection_c(Real rho, Real qr_incld, Real nr_incld, Real* nr_selfcollect_tend); - -void impose_max_total_ni_c(Real* ni_local, Real max_total_ni, Real inv_rho_local); - -void ice_melting_c(Real rho,Real T_atm,Real pres,Real rhofaci,Real table_val_qi2qr_melting,Real table_val_qi2qr_vent_melt, - Real latent_heat_vapor,Real latent_heat_fusion,Real dv,Real sc,Real mu,Real kap,Real qv,Real qi_incld, - Real ni_incld,Real* qi2qr_melt_tend,Real* ni2nr_melt_tend); - -void calc_first_order_upwind_step_c(Int kts, Int kte, Int kdir, Int kbot, Int k_qxtop, Real dt_sub, Real* rho, - Real* inv_rho, Real* inv_dz, Int num_arrays, Real** fluxes, Real** vs, Real** qnx); - -void generalized_sedimentation_c(Int kts, Int kte, Int kdir, Int k_qxtop, Int* k_qxbot, Int kbot, Real Co_max, - Real* dt_left, Real* prt_accum, Real* inv_dz, Real* inv_rho, Real* rho, - Int num_arrays, Real** vs, Real** fluxes, Real** qnx); -void cloud_sedimentation_c( - Int kts, Int kte, Int ktop, Int kbot, Int kdir, - Real* qc_incld, Real* rho, Real* inv_rho, Real* cld_frac_l, Real* acn, Real* inv_dz, - Real dt, Real inv_dt, bool do_predict_nc, - Real* qc, Real* nc, Real* nc_incld, Real* mu_c, Real* lamc, Real* precip_liq_surf, Real* qc_tend, Real* nc_tend); - -void ice_sedimentation_c( - Int kts, Int kte, Int ktop, Int kbot, Int kdir, - Real* rho, Real* inv_rho, Real* rhofaci, Real* cld_frac_i, Real* inv_dz, - Real dt, Real inv_dt, - Real* qi, Real* qi_incld, Real* ni, Real* qm, Real* qm_incld, Real* bm, Real* bm_incld, - Real* ni_incld, Real* precip_ice_surf, Real* qi_tend, Real* ni_tend); - -void rain_sedimentation_c( - Int kts, Int kte, Int ktop, Int kbot, Int kdir, - Real* qr_incld, Real* rho, Real* inv_rho, Real* rhofacr, Real* cld_frac_r, Real* inv_dz, - Real dt, Real inv_dt, - Real* qr, Real* nr, Real* nr_incld, Real* mu_r, Real* lamr, Real* precip_liq_surf, Real* precip_liq_flux, Real* qr_tend, Real* nr_tend); - -void calc_bulk_rho_rime_c(Real qi_tot, Real* qi_rim, Real* bi_rim, Real* rho_rime); - -void homogeneous_freezing_c( - Int kts, Int kte, Int ktop, Int kbot, Int kdir, - Real* T_atm, Real* inv_exner, Real* latent_heat_fusion, - Real* qc, Real* nc, Real* qr, Real* nr, Real* qi, Real* ni, Real* qm, Real* bm, Real* th_atm); - -void get_time_space_phys_variables_c(Real T_atm, Real pres, Real rho, Real latent_heat_vapor, Real latent_heat_sublim, Real qv_sat_l, Real qv_sat_i, - Real* mu, Real* dv, Real* sc, Real* dqsdt, Real* dqsidt, Real* ab, Real* abi, Real* kap, Real* eii); - -void update_prognostic_ice_c( - Real qc2qi_hetero_freeze_tend, Real qc2qi_collect_tend, Real qc2qr_ice_shed_tend, Real nc_collect_tend, Real nc2ni_immers_freeze_tend, Real ncshdc, - Real qr2qi_collect_tend, Real nr_collect_tend, Real qr2qi_immers_freeze_tend, Real nr2ni_immers_freeze_tend, Real nr_ice_shed_tend, - Real qi2qr_melt_tend, Real ni2nr_melt_tend, Real qi2qv_sublim_tend, Real qv2qi_vapdep_tend, Real qv2qi_nucleat_tend, Real ni_nucleat_tend, - Real ni_selfcollect_tend, Real ni_sublim_tend, Real qc2qi_berg_tend, Real inv_exner, Real latent_heat_sublim, Real latent_heat_fusion, - bool do_predict_nc, bool log_wetgrowth, Real dt, Real nmltratio, - Real rho_qm_cloud, Real* th_atm, Real* qv, Real* qi, Real* ni, Real* qm, - Real* bm, Real* qc, Real* nc, Real* qr, Real* nr); - -void evaporate_rain_c( Real qr_incld, Real qc_incld, Real nr_incld, Real qi_incld, - Real cld_frac_l, Real cld_frac_r, Real qv, Real qv_prev, - Real qv_sat_l, Real qv_sat_i, Real ab, Real abi, - Real epsr, Real epsi_tot, Real t, Real t_prev, - Real latent_heat_sublim, Real dqsdt, Real dt, - Real* qr2qv_evap_tend, Real* nr_evap_tend); - -void update_prognostic_liquid_c( - Real qc2qr_accret_tend, Real nc_accret_tend, Real qc2qr_autoconv_tend, Real nc2nr_autoconv_tend, Real ncautr, - Real nc_selfcollect_tend, Real qr2qv_evap_tend, Real nr_evap_tend, Real nr_selfcollect_tend , bool do_predict_nc, bool do_prescribed_CCN, - Real inv_rho, Real inv_exner, Real latent_heat_vapor, Real dt, Real* th_atm, Real* qv, - Real* qc, Real* nc, Real* qr, Real* nr); - -void ice_deposition_sublimation_c(Real qi_incld, Real ni_incld, Real t_atm, Real qv_sat_l, Real qv_sat_i, Real epsi, Real abi, Real qv, Real inv_dt, Real* qidep, Real* qi2qv_sublim_tend, Real* ni_sublim_tend, Real* qiberg); - -void compute_rain_fall_velocity_c(Real qr_incld, Real rhofacr, - Real* nr_incld, Real* mu_r, Real* lamr, Real* V_qr, Real* V_nr); - -void ice_cldliq_collection_c(Real rho, Real temp, Real rhofaci, Real table_val_qc2qi_collect, - Real qi_incld,Real qc_incld, Real ni_incld, Real nc_incld, - Real* qc2qi_collect_tend, Real* nc_collect_tend, Real* qc2qr_ice_shed_tend, Real* ncshdc); - -void ice_rain_collection_c(Real rho, Real temp, Real rhofaci, Real logn0r, Real table_val_nr_collect, Real table_val_qr2qi_collect, - Real qi_incld, Real ni_incld, Real qr_incld, Real* qr2qi_collect_tend, Real* nr_collect_tend); - - -void ice_self_collection_c(Real rho, Real rhofaci, Real table_val_ni_self_collect, Real eii, - Real qm_incld, Real qi_incld, Real ni_incld, Real* ni_selfcollect_tend); - -void ice_relaxation_timescale_c(Real rho, Real temp, Real rhofaci, Real table_val_qi2qr_melting, Real table_val_qi2qr_vent_melt, - Real dv, Real mu, Real sc, Real qi_incld, Real ni_incld, - Real* epsi, Real* epsi_tot); - -void calc_liq_relaxation_timescale_c(Real rho, Real f1r, Real f2r, Real dv, - Real mu, Real sc, Real mu_r, Real lamr, - Real cdistr, Real cdist, Real qr_incld, - Real qc_incld, Real* epsr, Real* epsc); - -void ice_nucleation_c(Real temp, Real inv_rho, Real ni, Real ni_activated, - Real qv_supersat_i, Real inv_dt, bool do_predict_nc, bool do_prescribed_CCN, - Real* qv2qi_nucleat_tend, Real* ni_nucleat_tend); - -void ice_cldliq_wet_growth_c(Real rho, Real temp, Real pres, Real rhofaci, Real table_val_qi2qr_melting, - Real table_val_qi2qr_vent_melt, Real latent_heat_vapor, Real latent_heat_fusion, Real dv, - Real kap, Real mu, Real sc, Real qv, Real qc_incld, - Real qi_incld, Real ni_incld, Real qr_incld, bool* log_wetgrowth, - Real* qr2qi_collect_tend, Real* qc2qi_collect_tend, Real* qc_growth_rate, Real* nr_ice_shed_tend, Real* qc2qr_ice_shed_tend); - -void get_latent_heat_c(Int its, Int ite, Int kts, Int kte, Real* s, Real* v, Real* f); - -Real subgrid_variance_scaling_c(Real relvar, Real expon); - -void check_values_c(Real* qv, Real* temp, Int kts, Int kte, Int timestepcount, - Int force_abort, Int source_ind, Real* col_loc); - -void calculate_incloud_mixingratios_c(Real qc, Real qr, Real qi, Real qm, Real nc, Real nr, Real ni, Real bm, - Real inv_cld_frac_l, Real inv_cld_frac_i, Real inv_cld_frac_r, - Real* qc_incld, Real* qr_incld, Real* qi_incld, Real* qm_incld, - Real* nc_incld, Real* nr_incld, Real* ni_incld, Real* bm_incld); - -void p3_main_part1_c( - Int kts, Int kte, Int kbot, Int ktop, Int kdir, - bool do_predict_nc, bool do_prescribed_CCN, - Real dt, - Real* pres, Real* dpres, Real* dz, Real* nc_nuceat_tend, Real* nccn_prescribed, Real* inv_exner, Real* exner, Real* inv_cld_frac_l, Real* inv_cld_frac_i, - Real* inv_cld_frac_r, Real* latent_heat_vapor, Real* latent_heat_sublim, Real* latent_heat_fusion, - Real* T_atm, Real* rho, Real* inv_rho, Real* qv_sat_l, Real* qv_sat_i, Real* qv_supersat_i, Real* rhofacr, Real* rhofaci, - Real* acn, Real* qv, Real* th_atm, Real* qc, Real* nc, Real* qr, Real* nr, Real* qi, Real* ni, Real* qm, Real* bm, Real* qc_incld, Real* qr_incld, Real* qi_incld, - Real* qm_incld, Real* nc_incld, Real* nr_incld, Real* ni_incld, Real* bm_incld, - bool* is_nucleat_possible, bool* is_hydromet_present); - -void p3_main_part2_c( - Int kts, Int kte, Int kbot, Int ktop, Int kdir, bool do_predict_nc, bool do_prescribed_CCN, Real dt, Real inv_dt, - Real* pres, Real* inv_exner, Real* inv_cld_frac_l, Real* inv_cld_frac_i, - Real* inv_cld_frac_r, Real* ni_activated, Real* inv_qc_relvar, Real* cld_frac_i, Real* cld_frac_l, Real* cld_frac_r, Real* qv_prev, Real* t_prev, - Real* T_atm, Real* rho, Real* inv_rho, Real* qv_sat_l, Real* qv_sat_i, Real* qv_supersat_i, Real* rhofaci, Real* acn, - Real* qv, Real* th_atm, Real* qc, Real* nc, Real* qr, Real* nr, Real* qi, Real* ni, - Real* qm, Real* bm, Real* latent_heat_vapor, Real* latent_heat_sublim, Real* latent_heat_fusion, Real* qc_incld, - Real* qr_incld, Real* qi_incld, Real* qm_incld, Real* nc_incld, Real* nr_incld, - Real* ni_incld, Real* bm_incld, Real* mu_c, Real* nu, Real* lamc, Real* cdist, Real* cdist1, - Real* cdistr, Real* mu_r, Real* lamr, Real* logn0r, Real* qv2qi_depos_tend, Real* precip_total_tend, - Real* nevapr, Real* qr_evap_tend, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* liq_ice_exchange, Real* pratot, - Real* prctot, bool* is_hydromet_present); - -void p3_main_part3_c( - Int kts, Int kte, Int kbot, Int ktop, Int kdir, - Real* inv_exner, Real* cld_frac_l, Real* cld_frac_r, Real* cld_frac_i, - Real* rho, Real* inv_rho, Real* rhofaci, Real* qv, Real* th_atm, Real* qc, Real* nc, Real* qr, Real* nr, - Real* qi, Real* ni, Real* qm, Real* bm, Real* latent_heat_vapor, Real* latent_heat_sublim, - Real* mu_c, Real* nu, Real* lamc, Real* mu_r, Real* lamr, Real* vap_liq_exchange, - Real* ze_rain, Real* ze_ice, Real* diag_vm_qi, Real* diag_eff_radius_qi, Real* diag_diam_qi, Real* rho_qi, Real* diag_equiv_reflectivity, Real* diag_eff_radius_qc, Real* diag_eff_radius_qr); - -void p3_main_c( - Real* qc, Real* nc, Real* qr, Real* nr, Real* th_atm, Real* qv, Real dt, - Real* qi, Real* qm, Real* ni, Real* bm, Real* pres, Real* dz, - Real* nc_nuceat_tend, Real* nccn_prescribed, Real* ni_activated, Real* inv_qc_relvar, Int it, Real* precip_liq_surf, - Real* precip_ice_surf, Int its, Int ite, Int kts, Int kte, Real* diag_eff_radius_qc, - Real* diag_eff_radius_qi, Real* diag_eff_radius_qr, Real* rho_qi, bool do_predict_nc, bool do_prescribed, Real* dpres, Real* inv_exner, - Real* qv2qi_depos_tend, Real* precip_liq_flux, Real* precip_ice_flux, Real* cld_frac_r, Real* cld_frac_l, Real* cld_frac_i, - Real* liq_ice_exchange, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* qv_prev, Real* t_prev, Real* elapsed_s); - -void ice_supersat_conservation_c(Real* qidep, Real* qinuc, Real cld_frac_i, Real qv, Real qv_sat_i, Real latent_heat_sublim, Real t_atm, Real dt, Real qi2qv_sublim_tend, Real qr2qv_evap_tend); -void nc_conservation_c(Real nc, Real nc_selfcollect_tend, Real dt, Real* nc_collect_tend, Real* nc2ni_immers_freeze_tend, Real* nc_accret_tend, Real* nc2nr_autoconv_tend); -void nr_conservation_c(Real nr, Real ni2nr_melt_tend, Real nr_ice_shed_tend, Real ncshdc, Real nc2nr_autoconv_tend, Real dt, Real nmltratio, Real* nr_collect_tend, Real* nr2ni_immers_freeze_tend, Real* nr_selfcollect_tend, Real* nr_evap_tend); -void ni_conservation_c(Real ni, Real ni_nucleat_tend, Real nr2ni_immers_freeze_tend, Real nc2ni_immers_freeze_tend, Real dt, Real* ni2nr_melt_tend, Real* ni_sublim_tend, Real* ni_selfcollect_tend); -void prevent_liq_supersaturation_c(Real pres, Real t_atm, Real qv, Real latent_heat_vapor, Real latent_heat_sublim, Real dt, Real qidep, Real qinuc, Real* qi2qv_sublim_tend, Real* qr2qv_evap_tend); } // extern "C" : end _c decls namespace scream { namespace p3 { -// -// In all C++ -> Fortran bridge functions you should see p3_init(). P3 needs -// to be initialized since most of its function depend on global tables to be -// populated. The 'true' argument is to set p3 to use its fortran implementations -// instead of calling back to C++. We want this behavior since it doesn't make much -// sense for C++ to bridge over to fortran only to have fortran bridge back to C++. -// If the client wanted the C++ implementation, they should just call it directly. -// - -void p3_init_a(P3InitAFortranData& d) -{ - p3_init(); // need to initialize p3 first so that tables are loaded - p3_init_a_c(d.ice_table_vals.data(), d.collect_table_vals.data()); -} - -void find_lookuptable_indices_1a(LookupIceData& d) -{ - p3_init(); // need to initialize p3 first so that tables are loaded - find_lookuptable_indices_1a_c(&d.dumi, &d.dumjj, &d.dumii, &d.dumzz, - &d.dum1, &d.dum4, &d.dum5, &d.dum6, - d.qi, d.ni, d.qm, d.rhop); -} - -void find_lookuptable_indices_1b(LookupIceDataB& d) -{ - p3_init(); - find_lookuptable_indices_1b_c(&d.dumj, &d.dum3, d.qr, d.nr); -} - -void access_lookup_table(AccessLookupTableData& d) +void p3_init_a(P3InitAP3Data& d) { - p3_init(); // need to initialize p3 first so that tables are loaded - access_lookup_table_c(d.lid.dumjj, d.lid.dumii, d.lid.dumi, d.index, - d.lid.dum1, d.lid.dum4, d.lid.dum5, &d.proc); -} + using P3F = Functions; -void access_lookup_table_coll(AccessLookupTableCollData& d) -{ - p3_init(); // need to initialize p3 first so that tables are loaded - access_lookup_table_coll_c(d.lid.dumjj, d.lid.dumii, d.lidb.dumj, d.lid.dumi, d.index, - d.lid.dum1, d.lidb.dum3, d.lid.dum4, d.lid.dum5, &d.proc); + P3F::p3_init(); // need to initialize p3 first so that tables are loaded + p3_init_a_c(d.ice_table_vals.data(), d.collect_table_vals.data()); } void BackToCellAverageData::randomize(std::mt19937_64& engine) @@ -322,155 +69,6 @@ void BackToCellAverageData::randomize(std::mt19937_64& engine) qc2qi_berg_tend = data_dist(engine); } -void back_to_cell_average(BackToCellAverageData& d) -{ - p3_init(); - back_to_cell_average_c(d.cld_frac_l, d.cld_frac_r, d.cld_frac_i, &d.qc2qr_accret_tend, &d.qr2qv_evap_tend, - &d.qc2qr_autoconv_tend, &d.nc_accret_tend, &d.nc_selfcollect_tend, &d.nc2nr_autoconv_tend, &d.nr_selfcollect_tend, &d.nr_evap_tend, &d.ncautr, - &d.qi2qv_sublim_tend, &d.nr_ice_shed_tend, &d.qc2qi_hetero_freeze_tend, &d.qr2qi_collect_tend, &d.qc2qr_ice_shed_tend, - &d.qi2qr_melt_tend, &d.qc2qi_collect_tend, &d.qr2qi_immers_freeze_tend, &d.ni2nr_melt_tend, &d.nc_collect_tend, &d.ncshdc, &d.nc2ni_immers_freeze_tend, - &d.nr_collect_tend, &d.ni_selfcollect_tend, &d.qv2qi_vapdep_tend, &d.nr2ni_immers_freeze_tend, &d.ni_sublim_tend, &d.qv2qi_nucleat_tend, &d.ni_nucleat_tend, - &d.qc2qi_berg_tend); -} - -void calc_rime_density(CalcRimeDensityData& d) -{ - p3_init(); - calc_rime_density_c(d.T_atm, d.rhofaci, d.table_val_qi_fallspd, d.acn, d.lamc, d.mu_c, - d.qc_incld, d.qc2qi_collect_tend, &d.vtrmi1, &d.rho_qm_cloud); -} - -void cldliq_immersion_freezing(CldliqImmersionFreezingData& d) -{ - p3_init(); - cldliq_immersion_freezing_c(d.T_atm, d.lamc, d.mu_c, d.cdist1, d.qc_incld, d.inv_qc_relvar, - &d.qc2qi_hetero_freeze_tend, &d.nc2ni_immers_freeze_tend); -} - -LatentHeatData::LatentHeatData(Int kts_, Int kte_, Int its_, Int ite_) : - PhysicsTestData( { {(ite_ - its_) + 1, (kte_ - kts_) + 1} }, - { {&v, &s, &f} }), - its(its_), ite(ite_), kts(kts_), kte(kte_) -{} - -void get_latent_heat(LatentHeatData& d) -{ - p3_init(); - d.transpose(); - get_latent_heat_c(d.its, d.ite, d.kts, d.kte, d.v, d.s, d.f); - d.transpose(); -} - -void droplet_self_collection(DropletSelfCollectionData& d) -{ - p3_init(); - droplet_self_collection_c(d.rho, d.inv_rho, d.qc_incld, d.mu_c, d.nu, d.nc2nr_autoconv_tend, - &d.nc_selfcollect_tend); -} - -void rain_immersion_freezing(RainImmersionFreezingData& d) -{ - p3_init(); - rain_immersion_freezing_c(d.T_atm, d.lamr, d.mu_r, d.cdistr, d.qr_incld, - &d.qr2qi_immers_freeze_tend, &d.nr2ni_immers_freeze_tend); -} - -void cloud_rain_accretion(CloudRainAccretionData& d) -{ - p3_init(); - cloud_rain_accretion_c(d.rho, d.inv_rho, d.qc_incld, d.nc_incld, d.qr_incld, d.inv_qc_relvar, - &d.qc2qr_accret_tend, &d.nc_accret_tend); -} - -void cloud_water_conservation(CloudWaterConservationData& d){ - p3_init(); - cloud_water_conservation_c(d.qc, d.dt, &d.qc2qr_autoconv_tend, &d.qc2qr_accret_tend, &d.qc2qi_collect_tend, &d.qc2qi_hetero_freeze_tend, - &d.qc2qr_ice_shed_tend, &d.qc2qi_berg_tend, &d.qi2qv_sublim_tend, &d.qv2qi_vapdep_tend); -} - -void rain_water_conservation(RainWaterConservationData& d){ - p3_init(); - rain_water_conservation_c(d.qr, d.qc2qr_autoconv_tend, d.qc2qr_accret_tend, d.qi2qr_melt_tend, d.qc2qr_ice_shed_tend, - d.dt, &d.qr2qv_evap_tend, &d.qr2qi_collect_tend, &d.qr2qi_immers_freeze_tend); -} - -void ice_water_conservation(IceWaterConservationData& d){ - p3_init(); - ice_water_conservation_c(d.qi, d.qv2qi_vapdep_tend, d.qv2qi_nucleat_tend, d.qc2qi_berg_tend, d.qr2qi_collect_tend, d.qc2qi_collect_tend, d.qr2qi_immers_freeze_tend, - d.qc2qi_hetero_freeze_tend, d.dt, &d.qi2qv_sublim_tend, &d.qi2qr_melt_tend); -} - -void cloud_water_autoconversion(CloudWaterAutoconversionData& d){ - p3_init(); - cloud_water_autoconversion_c(d.rho, d.qc_incld, d.nc_incld, d.inv_qc_relvar, - &d.qc2qr_autoconv_tend, &d.nc2nr_autoconv_tend, &d.ncautr); -} - -void rain_self_collection(RainSelfCollectionData& d){ - p3_init(); - rain_self_collection_c(d.rho, d.qr_incld, d.nr_incld, &d.nr_selfcollect_tend); -} - -void impose_max_total_ni(ImposeMaxTotalNiData& d){ - p3_init(); - impose_max_total_ni_c(&d.ni_local, d.max_total_ni, d.inv_rho_local); -} - -void get_cloud_dsd2(GetCloudDsd2Data& d) -{ - p3_init(); - Real nc_in = d.nc_in; - get_cloud_dsd2_c(d.qc, &nc_in, &d.mu_c, d.rho, &d.nu, &d.lamc, &d.cdist, &d.cdist1); - d.nc_out = nc_in; -} - -void get_rain_dsd2(GetRainDsd2Data& d) -{ - p3_init(); - Real nr_in = d.nr_in; - get_rain_dsd2_c(d.qr, &nr_in, &d.mu_r, &d.lamr, &d.cdistr, &d.logn0r); - d.nr_out = nr_in; -} - -void ice_cldliq_collection(IceCldliqCollectionData& d) -{ - p3_init(); - ice_cldliq_collection_c(d.rho, d.temp, d.rhofaci, d.table_val_qc2qi_collect, - d.qi_incld, d.qc_incld, d.ni_incld, d.nc_incld, - &d.qc2qi_collect_tend, &d.nc_collect_tend, &d.qc2qr_ice_shed_tend, &d.ncshdc); -} - -void ice_rain_collection(IceRainCollectionData& d) -{ - p3_init(); - ice_rain_collection_c(d.rho, d.temp, d.rhofaci, d.logn0r, d.table_val_nr_collect, d.table_val_qr2qi_collect, - d.qi_incld, d.ni_incld, d.qr_incld, - &d.qr2qi_collect_tend, &d.nr_collect_tend); -} - -void ice_self_collection(IceSelfCollectionData& d) -{ - p3_init(); - ice_self_collection_c(d.rho, d.rhofaci, d.table_val_ni_self_collect, d.eii, d.qm_incld, - d.qi_incld, d.ni_incld, - &d.ni_selfcollect_tend); -} - -void get_time_space_phys_variables(GetTimeSpacePhysVarsData& d) -{ - p3_init(); - get_time_space_phys_variables_c(d.T_atm, d.pres, d.rho, d.latent_heat_vapor, d.latent_heat_sublim, d.qv_sat_l, d.qv_sat_i, &d.mu, &d.dv, - &d.sc, &d.dqsdt, &d.dqsidt, &d.ab, &d.abi, &d.kap, &d.eii); -} - -void ice_relaxation_timescale(IceRelaxationData& d) -{ - p3_init(); - ice_relaxation_timescale_c(d.rho, d.temp, d.rhofaci, d.table_val_qi2qr_melting, d.table_val_qi2qr_vent_melt, - d.dv, d.mu, d.sc, d.qi_incld, d.ni_incld, - &d.epsi, &d.epsi_tot); -} - void CalcLiqRelaxationData::randomize(std::mt19937_64& engine) { // Populate the struct's input fields with numbers between 0 and 1. @@ -489,31 +87,6 @@ void CalcLiqRelaxationData::randomize(std::mt19937_64& engine) qc_incld = data_dist(engine); } -void calc_liq_relaxation_timescale(CalcLiqRelaxationData& d) -{ - p3_init(); - calc_liq_relaxation_timescale_c(d.rho, d.f1r, d.f2r, d.dv, d.mu, d.sc, d.mu_r, - d.lamr, d.cdistr, d.cdist, d.qr_incld, d.qc_incld, &d.epsr, &d.epsc); -} - -void ice_nucleation(IceNucleationData& d) -{ - p3_init(); - ice_nucleation_c(d.temp, d.inv_rho, d.ni, d.ni_activated, - d.qv_supersat_i, d.inv_dt, d.do_predict_nc, d.do_prescribed_CCN, &d.qv2qi_nucleat_tend, &d.ni_nucleat_tend); -} - -void ice_cldliq_wet_growth(IceWetGrowthData& d) -{ - p3_init(); - - ice_cldliq_wet_growth_c(d.rho, d.temp, d.pres, d.rhofaci, d.table_val_qi2qr_melting, - d.table_val_qi2qr_vent_melt, d.latent_heat_vapor, d.latent_heat_fusion, d.dv, - d.kap, d.mu, d.sc, d.qv, d.qc_incld, - d.qi_incld, d.ni_incld, d.qr_incld, &d.log_wetgrowth, - &d.qr2qi_collect_tend, &d.qc2qi_collect_tend, &d.qc_growth_rate, &d.nr_ice_shed_tend, &d.qc2qr_ice_shed_tend); -} - CheckValuesData::CheckValuesData( Int kts_, Int kte_, Int timestepcount_, Int source_ind_, bool force_abort_) : PhysicsTestData( { {(kte_-kts_)+1} }, @@ -523,57 +96,6 @@ CheckValuesData::CheckValuesData( EKAT_REQUIRE_MSG(nk() >= 3 || (kte == 1 && kts == 1), "nk too small to use for col_loc"); } -void check_values(CheckValuesData& d) -{ - p3_init(); - check_values_c(d.qv, d.temp, d.kts, d.kte, d.timestepcount, - d.force_abort, d.source_ind, d.col_loc); -} - -void calculate_incloud_mixingratios(IncloudMixingData& d) -{ - p3_init(); - - calculate_incloud_mixingratios_c(d.qc, d.qr, d.qi, d.qm, d.nc, d.nr, d.ni, d.bm, d.inv_cld_frac_l, d.inv_cld_frac_i, d.inv_cld_frac_r, - &d.qc_incld, &d.qr_incld, &d.qi_incld, &d.qm_incld, - &d.nc_incld, &d.nr_incld, &d.ni_incld, &d.bm_incld); - -} - -void update_prognostic_ice(P3UpdatePrognosticIceData& d){ - p3_init(); - update_prognostic_ice_c(d.qc2qi_hetero_freeze_tend, d.qc2qi_collect_tend, d.qc2qr_ice_shed_tend, d.nc_collect_tend, d.nc2ni_immers_freeze_tend, d.ncshdc, - d.qr2qi_collect_tend, d.nr_collect_tend, d.qr2qi_immers_freeze_tend, d.nr2ni_immers_freeze_tend, d.nr_ice_shed_tend, - d.qi2qr_melt_tend, d.ni2nr_melt_tend, d.qi2qv_sublim_tend, d.qv2qi_vapdep_tend, d.qv2qi_nucleat_tend, d.ni_nucleat_tend, - d.ni_selfcollect_tend, d.ni_sublim_tend, d.qc2qi_berg_tend, d.inv_exner, d.latent_heat_sublim, d.latent_heat_fusion, - d.do_predict_nc, d.log_wetgrowth, d.dt, d.nmltratio, - d.rho_qm_cloud, &d.th_atm, &d.qv, &d.qi, &d.ni, &d.qm, - &d.bm, &d.qc, &d.nc, &d.qr, &d.nr); -} - -void evaporate_rain(EvapRainData& d) -{ - p3_init(); - evaporate_rain_c(d.qr_incld,d.qc_incld,d.nr_incld,d.qi_incld, - d.cld_frac_l,d.cld_frac_r,d.qv,d.qv_prev,d.qv_sat_l,d.qv_sat_i, - d.ab,d.abi,d.epsr,d.epsi_tot,d.t,d.t_prev,d.latent_heat_sublim,d.dqsdt,d.dt, - &d.qr2qv_evap_tend,&d.nr_evap_tend); -} - -void update_prognostic_liquid(P3UpdatePrognosticLiqData& d){ - p3_init(); - update_prognostic_liquid_c(d.qc2qr_accret_tend, d.nc_accret_tend, d.qc2qr_autoconv_tend, d.nc2nr_autoconv_tend, d.ncautr, - d.nc_selfcollect_tend, d. qr2qv_evap_tend, d.nr_evap_tend, d.nr_selfcollect_tend , d.do_predict_nc, d.do_prescribed_CCN, - d.inv_rho, d.inv_exner, d.latent_heat_vapor, d.dt, &d.th_atm, &d.qv, - &d.qc, &d.nc, &d.qr, &d.nr); -} - -void ice_deposition_sublimation(IceDepositionSublimationData& d) -{ - p3_init(); - ice_deposition_sublimation_c(d.qi_incld, d.ni_incld, d.T_atm, d.qv_sat_l, d.qv_sat_i, d.epsi, d.abi, d.qv, d.inv_dt, &d.qv2qi_vapdep_tend, &d.qi2qv_sublim_tend, &d.ni_sublim_tend, &d.qc2qi_berg_tend); -} - CalcUpwindData::CalcUpwindData( Int kts_, Int kte_, Int kdir_, Int kbot_, Int k_qxtop_, Int num_arrays_, Real dt_sub_) : PhysicsTestData({ {(kte_ - kts_)+1, num_arrays_}, {(kte_ - kts_)+1} }, @@ -594,15 +116,6 @@ void CalcUpwindData::convert_to_ptr_arr(std::vector& mem_space, Real**& f qnx_ = mem_space.data() + num_arrays*2; } -void calc_first_order_upwind_step(CalcUpwindData& d) -{ - p3_init(); - std::vector tmp; - Real** fluxes, **vs, **qnx; - d.convert_to_ptr_arr(tmp, fluxes, vs, qnx); - calc_first_order_upwind_step_c(d.kts, d.kte, d.kdir, d.kbot, d.k_qxtop, d.dt_sub, d.rho, d.inv_rho, d.inv_dz, d.num_arrays, fluxes, vs, qnx); -} - GenSedData::GenSedData( Int kts_, Int kte_, Int kdir_, Int k_qxtop_, Int k_qxbot_, Int kbot_, Real Co_max_, Real dt_left_, Real prt_accum_, Int num_arrays_) : @@ -610,17 +123,6 @@ GenSedData::GenSedData( Co_max(Co_max_), k_qxbot(k_qxbot_), dt_left(dt_left_), prt_accum(prt_accum_) { } -void generalized_sedimentation(GenSedData& d) -{ - p3_init(); - std::vector tmp; - Real** fluxes, **vs, **qnx; - d.convert_to_ptr_arr(tmp, fluxes, vs, qnx); - generalized_sedimentation_c(d.kts, d.kte, d.kdir, d.k_qxtop, &d.k_qxbot, d.kbot, d.Co_max, - &d.dt_left, &d.prt_accum, d.inv_dz, d.inv_rho, d.rho, - d.num_arrays, fluxes, vs, qnx); -} - CloudSedData::CloudSedData( Int kts_, Int kte_, Int ktop_, Int kbot_, Int kdir_, Real dt_, Real inv_dt_, bool do_predict_nc_, Real precip_liq_surf_) : @@ -630,15 +132,6 @@ CloudSedData::CloudSedData( dt(dt_), inv_dt(inv_dt_), do_predict_nc(do_predict_nc_), precip_liq_surf(precip_liq_surf_) {} -void cloud_sedimentation(CloudSedData& d) -{ - p3_init(); - cloud_sedimentation_c(d.kts, d.kte, d.ktop, d.kbot, d.kdir, - d.qc_incld, d.rho, d.inv_rho, d.cld_frac_l, d.acn, d.inv_dz, - d.dt, d.inv_dt, d.do_predict_nc, - d.qc, d.nc, d.nc_incld, d.mu_c, d.lamc, &d.precip_liq_surf, d.qc_tend, d.nc_tend); -} - IceSedData::IceSedData( Int kts_, Int kte_, Int ktop_, Int kbot_, Int kdir_, Real dt_, Real inv_dt_, Real precip_ice_surf_) : @@ -648,15 +141,6 @@ IceSedData::IceSedData( dt(dt_), inv_dt(inv_dt_), precip_ice_surf(precip_ice_surf_) {} -void ice_sedimentation(IceSedData& d) -{ - p3_init(); - ice_sedimentation_c(d.kts, d.kte, d.ktop, d.kbot, d.kdir, - d.rho, d.inv_rho, d.rhofaci, d.cld_frac_i, d.inv_dz, d.dt, d.inv_dt, - d.qi, d.qi_incld, d.ni, d.qm, d.qm_incld, d.bm, d.bm_incld, d.ni_incld, - &d.precip_ice_surf, d.qi_tend, d.ni_tend); -} - RainSedData::RainSedData( Int kts_, Int kte_, Int ktop_, Int kbot_, Int kdir_, Real dt_, Real inv_dt_, Real precip_liq_surf_) : @@ -666,21 +150,6 @@ RainSedData::RainSedData( dt(dt_), inv_dt(inv_dt_), precip_liq_surf(precip_liq_surf_) {} -void rain_sedimentation(RainSedData& d) -{ - p3_init(); - rain_sedimentation_c(d.kts, d.kte, d.ktop, d.kbot, d.kdir, - d.qr_incld, d.rho, d.inv_rho, d.rhofacr, d.cld_frac_r, d.inv_dz, - d.dt, d.inv_dt, - d.qr, d.nr, d.nr_incld, d.mu_r, d.lamr, &d.precip_liq_surf, d.precip_liq_flux, d.qr_tend, d.nr_tend); -} - -void calc_bulk_rho_rime(CalcBulkRhoRimeData& d) -{ - p3_init(); - calc_bulk_rho_rime_c(d.qi_tot, &d.qi_rim, &d.bi_rim, &d.rho_rime); -} - HomogeneousFreezingData::HomogeneousFreezingData( Int kts_, Int kte_, Int ktop_, Int kbot_, Int kdir_) : PhysicsTestData( { {(kte_ - kts_) + 1} }, @@ -688,36 +157,9 @@ HomogeneousFreezingData::HomogeneousFreezingData( kts(kts_), kte(kte_), ktop(ktop_), kbot(kbot_), kdir(kdir_) {} -void homogeneous_freezing(HomogeneousFreezingData& d) -{ - p3_init(); - homogeneous_freezing_c(d.kts, d.kte, d.ktop, d.kbot, d.kdir, - d.T_atm, d.inv_exner, d.latent_heat_fusion, - d.qc, d.nc, d.qr, d.nr, d.qi, d.ni, d.qm, d.bm, d.th_atm); -} - -void ice_melting(IceMeltingData& d){ - p3_init(); - ice_melting_c(d.rho,d.T_atm,d.pres,d.rhofaci,d.table_val_qi2qr_melting,d.table_val_qi2qr_vent_melt, - d.latent_heat_vapor,d.latent_heat_fusion,d.dv,d.sc,d.mu,d.kap, - d.qv,d.qi_incld,d.ni_incld,&d.qi2qr_melt_tend,&d.ni2nr_melt_tend); -} - -Real subgrid_variance_scaling(SubgridVarianceScalingData& d){ - p3_init(); - return subgrid_variance_scaling_c(d.relvar,d.expon); -} - -void compute_rain_fall_velocity(ComputeRainFallVelocityData& d) -{ - p3_init(); - compute_rain_fall_velocity_c(d.qr_incld, d.rhofacr, - &d.nr_incld, &d.mu_r, &d.lamr, &d.V_qr, &d.V_nr); -} - P3MainPart1Data::P3MainPart1Data( Int kts_, Int kte_, Int kbot_, Int ktop_, Int kdir_, - bool do_predict_nc_, bool do_prescribed_CCN_, Real dt_) : + bool do_predict_nc_, bool do_prescribed_CCN_, Real dt_, bool, bool) : PhysicsTestData( { {(kte_ - kts_) + 1} }, { { &pres, &dpres, &dz, &nc_nuceat_tend, &inv_exner, &exner, &inv_cld_frac_l, &inv_cld_frac_i, &inv_cld_frac_r, &latent_heat_vapor, &latent_heat_sublim, &latent_heat_fusion, &nccn_prescribed, &T_atm, &rho, &inv_rho, &qv_sat_l, &qv_sat_i, &qv_supersat_i, &rhofacr, &rhofaci, @@ -727,26 +169,11 @@ P3MainPart1Data::P3MainPart1Data( do_predict_nc(do_predict_nc_), do_prescribed_CCN(do_prescribed_CCN_), dt(dt_) {} -void p3_main_part1(P3MainPart1Data& d) -{ - p3_init(); - p3_main_part1_c( - d.kts, d.kte, d.kbot, d.ktop, d.kdir, - d.do_predict_nc, d.do_prescribed_CCN, - d.dt, - d.pres, d.dpres, d.dz, d.nc_nuceat_tend, d.nccn_prescribed, d.inv_exner, d.exner, d.inv_cld_frac_l, d.inv_cld_frac_i, d.inv_cld_frac_r, d.latent_heat_vapor, - d.latent_heat_sublim, d.latent_heat_fusion, - d.T_atm, d.rho, d.inv_rho, d.qv_sat_l, d.qv_sat_i, d.qv_supersat_i, d.rhofacr, d.rhofaci, - d.acn, d.qv, d.th_atm, d.qc, d.nc, d.qr, d.nr, d.qi, d.ni, d.qm, d.bm, d.qc_incld, d.qr_incld, d.qi_incld, - d.qm_incld, d.nc_incld, d.nr_incld, d.ni_incld, d.bm_incld, - &d.is_nucleat_possible, &d.is_hydromet_present); -} - /////////////////////////////////////////////////////////////////////////////// P3MainPart2Data::P3MainPart2Data( Int kts_, Int kte_, Int kbot_, Int ktop_, Int kdir_, - bool do_predict_nc_, bool do_prescribed_CCN_, Real dt_) : + bool do_predict_nc_, bool do_prescribed_CCN_, Real dt_, Real, bool) : PhysicsTestData( { {(kte_ - kts_) + 1} }, { { &pres, &dpres, &dz, &nc_nuceat_tend, &inv_exner, &exner, &inv_cld_frac_l, &inv_cld_frac_i, &inv_cld_frac_r, &ni_activated, &inv_qc_relvar, &cld_frac_i, &cld_frac_l, &cld_frac_r, &qv_prev, &t_prev, &T_atm, &rho, &inv_rho, &qv_sat_l, &qv_sat_i, &qv_supersat_i, &rhofacr, &rhofaci, &acn, @@ -758,20 +185,6 @@ P3MainPart2Data::P3MainPart2Data( do_predict_nc(do_predict_nc_), do_prescribed_CCN(do_prescribed_CCN_), dt(dt_), inv_dt(1 / dt) {} -void p3_main_part2(P3MainPart2Data& d) -{ - p3_init(); - p3_main_part2_c( - d.kts, d.kte, d.kbot, d.ktop, d.kdir, d.do_predict_nc, d.do_prescribed_CCN, d.dt, d.inv_dt, - d.pres, d.inv_exner, d.inv_cld_frac_l, d.inv_cld_frac_i, d.inv_cld_frac_r, d.ni_activated, d.inv_qc_relvar, - d.cld_frac_i, d.cld_frac_l, d.cld_frac_r, d.qv_prev, d.t_prev, - d.T_atm, d.rho, d.inv_rho, d.qv_sat_l, d.qv_sat_i, d.qv_supersat_i, d.rhofaci, d.acn, d.qv, d.th_atm, d.qc, d.nc, d.qr, d.nr, d.qi, d.ni, - d.qm, d.bm, d.latent_heat_vapor, d.latent_heat_sublim, d.latent_heat_fusion, d.qc_incld, d.qr_incld, d.qi_incld, d.qm_incld, d.nc_incld, d.nr_incld, - d.ni_incld, d.bm_incld, d.mu_c, d.nu, d.lamc, d.cdist, d.cdist1, d.cdistr, d.mu_r, d.lamr, d.logn0r, d.qv2qi_depos_tend, d.precip_total_tend, - d.nevapr, d.qr_evap_tend, d.vap_liq_exchange, d.vap_ice_exchange, d.liq_ice_exchange, d.pratot, - d.prctot, &d.is_hydromet_present); -} - /////////////////////////////////////////////////////////////////////////////// P3MainPart3Data::P3MainPart3Data( @@ -787,21 +200,10 @@ P3MainPart3Data::P3MainPart3Data( kts(kts_), kte(kte_), kbot(kbot_), ktop(ktop_), kdir(kdir_) {} -void p3_main_part3(P3MainPart3Data& d) -{ - p3_init(); - p3_main_part3_c( - d.kts, d.kte, d.kbot, d.ktop, d.kdir, - d.inv_exner, d.cld_frac_l, d.cld_frac_r, d.cld_frac_i, - d.rho, d.inv_rho, d.rhofaci, d.qv, d.th_atm, d.qc, d.nc, d.qr, d.nr, d.qi, d.ni, d.qm, d.bm, d.latent_heat_vapor, d.latent_heat_sublim, - d.mu_c, d.nu, d.lamc, d.mu_r, d.lamr, d.vap_liq_exchange, - d. ze_rain, d.ze_ice, d.diag_vm_qi, d.diag_eff_radius_qi, d.diag_diam_qi, d.rho_qi, d.diag_equiv_reflectivity, d.diag_eff_radius_qc, d.diag_eff_radius_qr); -} - /////////////////////////////////////////////////////////////////////////////// P3MainData::P3MainData( - Int its_, Int ite_, Int kts_, Int kte_, Int it_, Real dt_, bool do_predict_nc_, bool do_prescribed_CCN_) : + Int its_, Int ite_, Int kts_, Int kte_, Int it_, Real dt_, bool do_predict_nc_, bool do_prescribed_CCN_, Real) : PhysicsTestData( { {(ite_ - its_) + 1, (kte_ - kts_) + 1}, {(ite_ - its_) + 1, (kte_ - kts_) + 2} }, { { &pres, &dz, &nc_nuceat_tend, &nccn_prescribed, &ni_activated, &dpres, &inv_exner, &cld_frac_i, &cld_frac_l, &cld_frac_r, &inv_qc_relvar, &qc, &nc, &qr, &nr, &qi, &qm, &ni, &bm, &qv, &th_atm, &qv_prev, &t_prev, @@ -812,51 +214,6 @@ P3MainData::P3MainData( its(its_), ite(ite_), kts(kts_), kte(kte_), it(it_), dt(dt_), do_predict_nc(do_predict_nc_), do_prescribed_CCN(do_prescribed_CCN_) {} -//This is the variable ordering from micro_p3.F90 -void p3_main(P3MainData& d) -{ - p3_init(); - d.transpose(); - p3_main_c( - d.qc, d.nc, d.qr, d.nr, d.th_atm, d.qv, d.dt, d.qi, d.qm, d.ni, - d.bm, d.pres, d.dz, d.nc_nuceat_tend, d.nccn_prescribed, d.ni_activated, d.inv_qc_relvar, d.it, d.precip_liq_surf, - d.precip_ice_surf, d.its, d.ite, d.kts, d.kte, d.diag_eff_radius_qc, d.diag_eff_radius_qi, d.diag_eff_radius_qr, - d.rho_qi, d.do_predict_nc, d.do_prescribed_CCN, d.dpres, d.inv_exner, d.qv2qi_depos_tend, - d.precip_liq_flux, d.precip_ice_flux, d.cld_frac_r, d.cld_frac_l, d.cld_frac_i, - d.liq_ice_exchange, d.vap_liq_exchange, d.vap_ice_exchange, d.qv_prev, d.t_prev, &d.elapsed_s); - d.transpose(); -} - -void ice_supersat_conservation(IceSupersatConservationData& d) -{ - p3_init(); - ice_supersat_conservation_c(&d.qidep, &d.qinuc, d.cld_frac_i, d.qv, d.qv_sat_i, d.latent_heat_sublim, d.t_atm, d.dt, d.qi2qv_sublim_tend, d.qr2qv_evap_tend); -} - -void nc_conservation(NcConservationData& d) -{ - p3_init(); - nc_conservation_c(d.nc, d.nc_selfcollect_tend, d.dt, &d.nc_collect_tend, &d.nc2ni_immers_freeze_tend, &d.nc_accret_tend, &d.nc2nr_autoconv_tend); -} - -void nr_conservation(NrConservationData& d) -{ - p3_init(); - nr_conservation_c(d.nr, d.ni2nr_melt_tend, d.nr_ice_shed_tend, d.ncshdc, d.nc2nr_autoconv_tend, d.dt, d.nmltratio, &d.nr_collect_tend, &d.nr2ni_immers_freeze_tend, &d.nr_selfcollect_tend, &d.nr_evap_tend); -} - -void ni_conservation(NiConservationData& d) -{ - p3_init(); - ni_conservation_c(d.ni, d.ni_nucleat_tend, d.nr2ni_immers_freeze_tend, d.nc2ni_immers_freeze_tend, d.dt, &d.ni2nr_melt_tend, &d.ni_sublim_tend, &d.ni_selfcollect_tend); -} - -void prevent_liq_supersaturation(PreventLiqSupersaturationData& d) -{ - p3_init(); - prevent_liq_supersaturation_c(d.pres, d.t_atm, d.qv, d.latent_heat_vapor, d.latent_heat_sublim, d.dt, d.qidep, d.qinuc, &d.qi2qv_sublim_tend, &d.qr2qv_evap_tend); -} - void IceSupersatConservationData::randomize(std::mt19937_64& engine) { std::uniform_real_distribution data_dist(0.0, 1.0); @@ -970,8 +327,6 @@ void PreventLiqSupersaturationData::randomize(std::mt19937_64& engine) */ } -// end _c impls - /////////////////////////////////////////////////////////////////////////////// std::shared_ptr P3GlobalForFortran::s_views; @@ -993,7 +348,7 @@ void P3GlobalForFortran::deinit() } // -// _f function definitions +// _host function definitions // template @@ -1006,7 +361,7 @@ std::vector ptr_to_arr(T** data, int n) } template -void calc_first_order_upwind_step_f_impl( +void calc_first_order_upwind_step_host_impl( Int kts, Int kte, Int kdir, Int kbot, Int k_qxtop, Real dt_sub, Real* rho, Real* inv_rho, Real* inv_dz, Real** fluxes, Real** vs, Real** qnx) @@ -1070,7 +425,7 @@ void calc_first_order_upwind_step_f_impl( } template -void generalized_sedimentation_f_impl( +void generalized_sedimentation_host_impl( Int kts, Int kte, Int kdir, Int k_qxtop, Int* k_qxbot, Int kbot, Real Co_max, Real* dt_left, Real* prt_accum, Real* inv_dz, Real* inv_rho, Real* rho, Real** vs, Real** fluxes, Real** qnx) @@ -1159,40 +514,40 @@ void generalized_sedimentation_f_impl( *k_qxbot = scalars[2] + 1; } -void calc_first_order_upwind_step_f( +void calc_first_order_upwind_step_host( Int kts, Int kte, Int kdir, Int kbot, Int k_qxtop, Real dt_sub, Real* rho, Real* inv_rho, Real* inv_dz, Int num_arrays, Real** fluxes, Real** vs, Real** qnx) { if (num_arrays == 1) { - calc_first_order_upwind_step_f_impl<1>(kts, kte, kdir, kbot, k_qxtop, dt_sub, rho, inv_rho, inv_dz, fluxes, vs, qnx); + calc_first_order_upwind_step_host_impl<1>(kts, kte, kdir, kbot, k_qxtop, dt_sub, rho, inv_rho, inv_dz, fluxes, vs, qnx); } else if (num_arrays == 2) { - calc_first_order_upwind_step_f_impl<2>(kts, kte, kdir, kbot, k_qxtop, dt_sub, rho, inv_rho, inv_dz, fluxes, vs, qnx); + calc_first_order_upwind_step_host_impl<2>(kts, kte, kdir, kbot, k_qxtop, dt_sub, rho, inv_rho, inv_dz, fluxes, vs, qnx); } else if (num_arrays == 4) { - calc_first_order_upwind_step_f_impl<4>(kts, kte, kdir, kbot, k_qxtop, dt_sub, rho, inv_rho, inv_dz, fluxes, vs, qnx); + calc_first_order_upwind_step_host_impl<4>(kts, kte, kdir, kbot, k_qxtop, dt_sub, rho, inv_rho, inv_dz, fluxes, vs, qnx); } else { EKAT_REQUIRE_MSG(false, "Unsupported num arrays in bridge calc_first_order_upwind_step_f: " << num_arrays); } } -void generalized_sedimentation_f( +void generalized_sedimentation_host( Int kts, Int kte, Int kdir, Int k_qxtop, Int* k_qxbot, Int kbot, Real Co_max, Real* dt_left, Real* prt_accum, Real* inv_dz, Real* inv_rho, Real* rho, Int num_arrays, Real** vs, Real** fluxes, Real** qnx) { if (num_arrays == 1) { - generalized_sedimentation_f_impl<1>(kts, kte, kdir, k_qxtop, k_qxbot, kbot, Co_max, dt_left, prt_accum, + generalized_sedimentation_host_impl<1>(kts, kte, kdir, k_qxtop, k_qxbot, kbot, Co_max, dt_left, prt_accum, inv_dz, inv_rho, rho, vs, fluxes, qnx); } else if (num_arrays == 2) { - generalized_sedimentation_f_impl<2>(kts, kte, kdir, k_qxtop, k_qxbot, kbot, Co_max, dt_left, prt_accum, + generalized_sedimentation_host_impl<2>(kts, kte, kdir, k_qxtop, k_qxbot, kbot, Co_max, dt_left, prt_accum, inv_dz, inv_rho, rho, vs, fluxes, qnx); } else if (num_arrays == 4) { - generalized_sedimentation_f_impl<4>(kts, kte, kdir, k_qxtop, k_qxbot, kbot, Co_max, dt_left, prt_accum, + generalized_sedimentation_host_impl<4>(kts, kte, kdir, k_qxtop, k_qxbot, kbot, Co_max, dt_left, prt_accum, inv_dz, inv_rho, rho, vs, fluxes, qnx); } else { @@ -1200,7 +555,7 @@ void generalized_sedimentation_f( } } -void cloud_sedimentation_f( +void cloud_sedimentation_host( Int kts, Int kte, Int ktop, Int kbot, Int kdir, Real* qc_incld, Real* rho, Real* inv_rho, Real* cld_frac_l, Real* acn, Real* inv_dz, Real dt, Real inv_dt, bool do_predict_nc, @@ -1267,7 +622,7 @@ void cloud_sedimentation_f( ekat::device_to_host({qc, nc, nc_incld, mu_c, lamc, qc_tend, nc_tend}, nk, inout_views); } -void ice_sedimentation_f( +void ice_sedimentation_host( Int kts, Int kte, Int ktop, Int kbot, Int kdir, Real* rho, Real* inv_rho, Real* rhofaci, Real* cld_frac_i, Real* inv_dz, Real dt, Real inv_dt, @@ -1340,7 +695,7 @@ void ice_sedimentation_f( ekat::device_to_host({qi, qi_incld, ni, ni_incld, qm, qm_incld, bm, bm_incld, qi_tend, ni_tend}, nk, inout_views); } -void rain_sedimentation_f( +void rain_sedimentation_host( Int kts, Int kte, Int ktop, Int kbot, Int kdir, Real* qr_incld, Real* rho, Real* inv_rho, Real* rhofacr, Real* cld_frac_r, Real* inv_dz, Real dt, Real inv_dt, @@ -1415,7 +770,7 @@ void rain_sedimentation_f( ekat::device_to_host({qr, nr, nr_incld, mu_r, lamr, qr_tend, nr_tend, precip_liq_flux}, sizes_out, inout_views); } -void homogeneous_freezing_f( +void homogeneous_freezing_host( Int kts, Int kte, Int ktop, Int kbot, Int kdir, Real* T_atm, Real* inv_exner, Real* qc, Real* nc, Real* qr, Real* nr, Real* qi, Real* ni, Real* qm, Real* bm, Real* th_atm) @@ -1476,7 +831,7 @@ void homogeneous_freezing_f( ekat::device_to_host({qc, nc, qr, nr, qi, ni, qm, bm, th_atm}, nk, inout_views); } -void check_values_f(Real* qv, Real* temp, Int kstart, Int kend, +void check_values_host(Real* qv, Real* temp, Int kstart, Int kend, Int timestepcount, bool force_abort, Int source_ind, Real* col_loc) { using P3F = Functions; @@ -1509,7 +864,7 @@ void check_values_f(Real* qv, Real* temp, Int kstart, Int kend, }); } -void p3_main_part1_f( +void p3_main_part1_host( Int kts, Int kte, Int kbot, Int ktop, Int kdir, bool do_predict_nc, bool do_prescribed_CCN, Real dt, @@ -1621,7 +976,7 @@ void p3_main_part1_f( *is_hydromet_present = bools_h(1); } -void p3_main_part2_f( +void p3_main_part2_host( Int kts, Int kte, Int kbot, Int ktop, Int kdir, bool do_predict_nc, bool do_prescribed_CCN, Real dt, Real inv_dt, Real* pres, Real* dpres, Real* dz, Real* nc_nuceat_tend, Real* inv_exner, Real* exner, Real* inv_cld_frac_l, Real* inv_cld_frac_i, Real* inv_cld_frac_r, Real* ni_activated, Real* inv_qc_relvar, Real* cld_frac_i, Real* cld_frac_l, Real* cld_frac_r, Real* qv_prev, Real* t_prev, @@ -1777,7 +1132,7 @@ void p3_main_part2_f( *is_hydromet_present = bools_h(0); } -void p3_main_part3_f( +void p3_main_part3_host( Int kts, Int kte, Int kbot, Int ktop, Int kdir, Real* inv_exner, Real* cld_frac_l, Real* cld_frac_r, Real* cld_frac_i, Real* rho, Real* inv_rho, Real* rhofaci, Real* qv, Real* th_atm, Real* qc, @@ -1885,7 +1240,7 @@ void p3_main_part3_f( nk, inout_views); } -Int p3_main_f( +Int p3_main_host( Real* qc, Real* nc, Real* qr, Real* nr, Real* th_atm, Real* qv, Real dt, Real* qi, Real* qm, Real* ni, Real* bm, Real* pres, Real* dz, Real* nc_nuceat_tend, Real* nccn_prescribed, Real* ni_activated, Real* inv_qc_relvar, Int it, Real* precip_liq_surf, diff --git a/components/eamxx/src/physics/p3/p3_functions_f90.hpp b/components/eamxx/src/physics/p3/tests/infra/p3_test_data.hpp similarity index 83% rename from components/eamxx/src/physics/p3/p3_functions_f90.hpp rename to components/eamxx/src/physics/p3/tests/infra/p3_test_data.hpp index 89e6ac569085..a1bbe864f4cc 100644 --- a/components/eamxx/src/physics/p3/p3_functions_f90.hpp +++ b/components/eamxx/src/physics/p3/tests/infra/p3_test_data.hpp @@ -4,23 +4,40 @@ #include "physics/p3/p3_functions.hpp" #include "physics/share/physics_test_data.hpp" #include "share/scream_types.hpp" +#include "ekat/util/ekat_file_utils.hpp" #include #include #include // for shared_ptr -// -// Bridge functions to call fortran version of p3 functions from C++ -// - namespace scream { namespace p3 { -// +/////////////////////////////////////////////////////////////////////////////// + +struct P3InitAP3Data +{ + // Must use Host as device, f90 code might not be able to use Device memory + using P3F = Functions; + using P3C = typename P3F::P3C; + + using view_ice_table = typename P3F::KT::template lview; + using view_collect_table = typename P3F::KT::template lview; + + // Need to be LayoutLeft to be fortran compatible + view_ice_table ice_table_vals; + view_collect_table collect_table_vals; + + P3InitAP3Data() : + ice_table_vals("P3InitAP3Data::ice_table_vals"), + collect_table_vals("P3InitAP3Data::collect_table_vals") + {} +}; + +/////////////////////////////////////////////////////////////////////////////// + // Singleton for holding the same global data that are maintained in -// micro_p3, but for use in C++. This data is necessary to complete -// the "bridge" when calling C++ from micro_p3. -// +// micro_p3, but for use in C++. struct P3GlobalForFortran { using P3F = Functions; @@ -63,26 +80,10 @@ struct P3GlobalForFortran /////////////////////////////////////////////////////////////////////////////// -struct P3InitAFortranData -{ - // Must use Host as device, f90 code might not be able to use Device memory - using P3F = Functions; - using P3C = typename P3F::P3C; - - using view_ice_table = typename P3F::KT::template lview; - using view_collect_table = typename P3F::KT::template lview; - - // Need to be LayoutLeft to be fortran compatible - view_ice_table ice_table_vals; - view_collect_table collect_table_vals; - - P3InitAFortranData() : - ice_table_vals("P3InitAFortranData::ice_table_vals"), - collect_table_vals("P3InitAFortranData::collect_table_vals") - {} -}; - -/////////////////////////////////////////////////////////////////////////////// +/** + * Structs for holding data related to specific P3 calls; these are used for + * the BFB unit tests. + */ struct LookupIceData { @@ -92,6 +93,8 @@ struct LookupIceData // Outputs Int dumi, dumjj, dumii, dumzz; Real dum1, dum4, dum5, dum6; + + PTD_RW_SCALARS_ONLY(8, dumi, dumjj, dumii, dumzz, dum1, dum4, dum5, dum6); }; /////////////////////////////////////////////////////////////////////////////// @@ -104,6 +107,8 @@ struct LookupIceDataB // Outputs Int dumj; Real dum3; + + PTD_RW_SCALARS_ONLY(2, dumj, dum3); }; /////////////////////////////////////////////////////////////////////////////// @@ -116,6 +121,8 @@ struct AccessLookupTableData // Outputs Real proc; + + PTD_RW_SCALARS_ONLY(1, proc); }; /////////////////////////////////////////////////////////////////////////////// @@ -129,6 +136,8 @@ struct AccessLookupTableCollData // Outputs Real proc; + + PTD_RW_SCALARS_ONLY(1, proc); }; /////////////////////////////////////////////////////////////////////////////// @@ -146,6 +155,11 @@ struct BackToCellAverageData // This populates all fields with test data within [0,1]. void randomize(std::mt19937_64& engine); + + PTD_RW_SCALARS_ONLY(31, qc2qr_accret_tend, qr2qv_evap_tend, qc2qr_autoconv_tend, nc_accret_tend, nc_selfcollect_tend, nc2nr_autoconv_tend, nr_selfcollect_tend, nr_evap_tend, ncautr, qcnuc, + nc_nuceat_tend, qi2qv_sublim_tend, nr_ice_shed_tend, qc2qi_hetero_freeze_tend, qr2qi_collect_tend, qc2qr_ice_shed_tend, qi2qr_melt_tend, qc2qi_collect_tend, qr2qi_immers_freeze_tend, ni2nr_melt_tend, + nc_collect_tend, ncshdc, nc2ni_immers_freeze_tend, nr_collect_tend, ni_selfcollect_tend, qv2qi_vapdep_tend, nr2ni_immers_freeze_tend, ni_sublim_tend, qv2qi_nucleat_tend, ni_nucleat_tend, + qc2qi_berg_tend); }; /////////////////////////////////////////////////////////////////////////////// @@ -157,6 +171,8 @@ struct CloudWaterConservationData //output Real qc2qr_autoconv_tend, qc2qr_accret_tend, qc2qi_collect_tend, qc2qi_hetero_freeze_tend, qc2qr_ice_shed_tend, qc2qi_berg_tend, qi2qv_sublim_tend, qv2qi_vapdep_tend; + + PTD_RW_SCALARS_ONLY(8, qc2qr_autoconv_tend, qc2qr_accret_tend, qc2qi_collect_tend, qc2qi_hetero_freeze_tend, qc2qr_ice_shed_tend, qc2qi_berg_tend, qi2qv_sublim_tend, qv2qi_vapdep_tend); }; struct RainWaterConservationData @@ -166,6 +182,8 @@ struct RainWaterConservationData //output Real qr2qv_evap_tend, qr2qi_collect_tend, qr2qi_immers_freeze_tend; + + PTD_RW_SCALARS_ONLY(3, qr2qv_evap_tend, qr2qi_collect_tend, qr2qi_immers_freeze_tend); }; struct IceWaterConservationData @@ -175,6 +193,8 @@ struct IceWaterConservationData //output Real qi2qv_sublim_tend, qi2qr_melt_tend; + + PTD_RW_SCALARS_ONLY(2, qi2qv_sublim_tend, qi2qr_melt_tend); }; /////////////////////////////////////////////////////////////////////////////// @@ -186,6 +206,8 @@ struct CalcRimeDensityData // output Real vtrmi1, rho_qm_cloud; + + PTD_RW_SCALARS_ONLY(2, vtrmi1, rho_qm_cloud); }; /////////////////////////////////////////////////////////////////////////////// @@ -197,6 +219,8 @@ struct CldliqImmersionFreezingData // output Real qc2qi_hetero_freeze_tend, nc2ni_immers_freeze_tend; + + PTD_RW_SCALARS_ONLY(2, qc2qi_hetero_freeze_tend, nc2ni_immers_freeze_tend); }; /////////////////////////////////////////////////////////////////////////////// @@ -208,6 +232,8 @@ struct RainImmersionFreezingData // output Real qr2qi_immers_freeze_tend, nr2ni_immers_freeze_tend; + + PTD_RW_SCALARS_ONLY(2, qr2qi_immers_freeze_tend, nr2ni_immers_freeze_tend); }; /////////////////////////////////////////////////////////////////////////////// @@ -219,6 +245,8 @@ struct DropletSelfCollectionData // output Real nc_selfcollect_tend; + + PTD_RW_SCALARS_ONLY(1, nc_selfcollect_tend); }; /////////////////////////////////////////////////////////////////////////////// @@ -230,6 +258,8 @@ struct CloudRainAccretionData // output Real qc2qr_accret_tend, nc_accret_tend; + + PTD_RW_SCALARS_ONLY(2, qc2qr_accret_tend, nc_accret_tend); }; /////////////////////////////////////////////////////////////////////////////// @@ -237,15 +267,12 @@ struct CloudRainAccretionData struct CloudWaterAutoconversionData { // inputs - Real rho; - Real qc_incld; - Real nc_incld; - Real inv_qc_relvar; + Real rho, qc_incld, nc_incld, inv_qc_relvar; // output - Real qc2qr_autoconv_tend; - Real nc2nr_autoconv_tend; - Real ncautr; + Real qc2qr_autoconv_tend, nc2nr_autoconv_tend, ncautr; + + PTD_RW_SCALARS_ONLY(3, qc2qr_autoconv_tend, nc2nr_autoconv_tend, ncautr); }; /////////////////////////////////////////////////////////////////////////////// @@ -257,6 +284,8 @@ struct RainSelfCollectionData //output Real nr_selfcollect_tend; + + PTD_RW_SCALARS_ONLY(1, nr_selfcollect_tend); }; /////////////////////////////////////////////////////////////////////////////// @@ -267,6 +296,8 @@ struct ImposeMaxTotalNiData{ //input Real max_total_ni, inv_rho_local; + + PTD_RW_SCALARS_ONLY(2, ni_local, inv_rho_local); }; /////////////////////////////////////////////////////////////////////////////// @@ -278,6 +309,8 @@ struct IceMeltingData // output Real qi2qr_melt_tend,ni2nr_melt_tend; + + PTD_RW_SCALARS_ONLY(2, qi2qr_melt_tend, ni2nr_melt_tend); }; /////////////////////////////////////////////////////////////////////////////// @@ -298,6 +331,8 @@ struct GetCloudDsd2Data // Outputs Real nc_out, mu_c, nu, lamc, cdist, cdist1; + + PTD_RW_SCALARS_ONLY(6, nc_out, mu_c, nu, lamc, cdist, cdist1) }; ////////////////////////////////////////////////////////////////////////// @@ -309,6 +344,8 @@ struct GetRainDsd2Data // Outputs Real nr_out, lamr, mu_r, cdistr, logn0r; + + PTD_RW_SCALARS_ONLY(5, nr_out, lamr, mu_r, cdistr, logn0r); }; /////////////////////////////////////////////////////////////////////////////// @@ -352,6 +389,8 @@ struct GenSedData : public CalcUpwindData PTD_DATA_COPY_CTOR(GenSedData, 10); PTD_ASSIGN_OP(GenSedData, 11, kts, kte, kdir, kbot, k_qxtop, num_arrays, dt_sub, Co_max, k_qxbot, dt_left, prt_accum); + PTD_RW(); + PTD_RW_SCALARS(11, kts, kte, kdir, kbot, k_qxtop, num_arrays, dt_sub, Co_max, k_qxbot, dt_left, prt_accum); }; /////////////////////////////////////////////////////////////////////////////// @@ -437,6 +476,8 @@ struct CalcBulkRhoRimeData // Outputs Real rho_rime; + + PTD_RW_SCALARS_ONLY(3, qi_rim, bi_rim, rho_rime); }; /////////////////////////////////////////////////////////////////////////////// @@ -471,6 +512,8 @@ struct ComputeRainFallVelocityData // Outputs Real mu_r, lamr, V_qr, V_nr; + + PTD_RW_SCALARS_ONLY(5, nr_incld, mu_r, lamr, V_qr, V_nr); }; /////////////////////////////////////////////////////////////////////////////// @@ -482,6 +525,8 @@ struct GetTimeSpacePhysVarsData //Outs Real mu, dv, sc, dqsdt, dqsidt, ab, abi, kap, eii; + + PTD_RW_SCALARS_ONLY(9, mu, dv, sc, dqsdt, dqsidt, ab, abi, kap, eii); }; /////////////////////////////////////////////////////////////////////////////// @@ -496,6 +541,8 @@ struct P3UpdatePrognosticIceData // In/outs Real th_atm, qv, qi, ni, qm, bm, qc, nc, qr, nr; + + PTD_RW_SCALARS_ONLY(10, th_atm, qv, qi, ni, qm, bm, qc, nc, qr, nr); }; /////////////////////////////////////////////////////////////////////////////// @@ -508,6 +555,8 @@ struct EvapRainData //Outs Real qr2qv_evap_tend, nr_evap_tend; + + PTD_RW_SCALARS_ONLY(2, qr2qv_evap_tend, nr_evap_tend); }; /////////////////////////////////////////////////////////////////////////////// @@ -523,6 +572,8 @@ struct P3UpdatePrognosticLiqData // In/outs Real th_atm, qv, qc, nc, qr, nr; + + PTD_RW_SCALARS_ONLY(6, th_atm, qv, qc, nc, qr, nr); }; /////////////////////////////////////////////////////////////////////////////// @@ -538,6 +589,7 @@ struct IceDepositionSublimationData // This populates all input fields with test data within [0,1]. void randomize(std::mt19937_64& engine); + PTD_RW_SCALARS_ONLY(4, qv2qi_vapdep_tend, qi2qv_sublim_tend, ni_sublim_tend, qc2qi_berg_tend); }; struct IceCldliqCollectionData @@ -549,6 +601,7 @@ struct IceCldliqCollectionData // Outputs Real qc2qi_collect_tend, nc_collect_tend, qc2qr_ice_shed_tend, ncshdc; + PTD_RW_SCALARS_ONLY(4, qc2qi_collect_tend, nc_collect_tend, qc2qr_ice_shed_tend, ncshdc); }; struct IceRainCollectionData @@ -560,6 +613,7 @@ struct IceRainCollectionData // Outputs Real qr2qi_collect_tend, nr_collect_tend; + PTD_RW_SCALARS_ONLY(2, qr2qi_collect_tend, nr_collect_tend); }; struct IceSelfCollectionData @@ -571,6 +625,7 @@ struct IceSelfCollectionData // Outputs Real ni_selfcollect_tend; + PTD_RW_SCALARS_ONLY(1, ni_selfcollect_tend); }; struct IceRelaxationData @@ -580,6 +635,8 @@ struct IceRelaxationData // Outputs Real epsi, epsi_tot; + + PTD_RW_SCALARS_ONLY(2, epsi, epsi_tot); }; struct CalcLiqRelaxationData @@ -592,6 +649,8 @@ struct CalcLiqRelaxationData // This populates all input fields with test data within [0,1]. void randomize(std::mt19937_64& engine); + + PTD_RW_SCALARS_ONLY(2, epsr, epsc); }; struct IceNucleationData @@ -603,6 +662,8 @@ struct IceNucleationData // Outputs Real qv2qi_nucleat_tend, ni_nucleat_tend; + + PTD_RW_SCALARS_ONLY(2, qv2qi_nucleat_tend, ni_nucleat_tend); }; struct IceWetGrowthData @@ -615,21 +676,8 @@ struct IceWetGrowthData bool log_wetgrowth; Real qr2qi_collect_tend, qc2qi_collect_tend, qc_growth_rate, nr_ice_shed_tend, qc2qr_ice_shed_tend; -}; - -struct LatentHeatData : public PhysicsTestData -{ - static constexpr size_t NUM_ARRAYS = 3; - - // Inputs - Int its, ite, kts, kte; - - // Outputs - Real* v, *s, *f; - LatentHeatData(Int its_, Int ite_, Int kts_, Int kte_); - - PTD_STD_DEF(LatentHeatData, 4, its, ite, kts, kte); + PTD_RW_SCALARS_ONLY(6, log_wetgrowth, qr2qi_collect_tend, qc2qi_collect_tend, qc_growth_rate, nr_ice_shed_tend, qc2qr_ice_shed_tend); }; struct CheckValuesData : public PhysicsTestData @@ -659,6 +707,8 @@ struct IncloudMixingData // Outputs Real qc_incld, qr_incld, qi_incld, qm_incld, nc_incld, nr_incld, ni_incld, bm_incld; + + PTD_RW_SCALARS_ONLY(8, qc_incld, qr_incld, qi_incld, qm_incld, nc_incld, nr_incld, ni_incld, bm_incld); }; /////////////////////////////////////////////////////////////////////////////// @@ -683,9 +733,9 @@ struct P3MainPart1Data : public PhysicsTestData bool is_nucleat_possible, is_hydromet_present; P3MainPart1Data(Int kts_, Int kte_, Int kbot_, Int ktop_, Int kdir_, - bool do_predict_nc_, bool do_prescribed_CCN_, Real dt_); + bool do_predict_nc_, bool do_prescribed_CCN_, Real dt_, bool=false, bool=false); - PTD_STD_DEF(P3MainPart1Data, 8, kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribed_CCN, dt); + PTD_STD_DEF(P3MainPart1Data, 10, kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribed_CCN, dt, is_nucleat_possible, is_hydromet_present); Int nk() const { return (kte - kts) + 1; } }; @@ -712,10 +762,9 @@ struct P3MainPart2Data : public PhysicsTestData bool is_hydromet_present; P3MainPart2Data(Int kts_, Int kte_, Int kbot_, Int ktop_, Int kdir_, - bool do_predict_nc_, bool do_prescribed_CCN, Real dt_); + bool do_predict_nc_, bool do_prescribed_CCN, Real dt_, Real=0., bool=false); - PTD_DATA_COPY_CTOR(P3MainPart2Data, 8); - PTD_ASSIGN_OP(P3MainPart2Data, 10, kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribed_CCN, dt, inv_dt, is_hydromet_present); + PTD_STD_DEF(P3MainPart2Data, 10, kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribed_CCN, dt, inv_dt, is_hydromet_present); Int nk() const { return (kte - kts) + 1; } }; @@ -767,9 +816,9 @@ struct P3MainData : public PhysicsTestData *precip_liq_flux, *precip_ice_flux, *precip_liq_surf, *precip_ice_surf; Real elapsed_s; - P3MainData(Int its_, Int ite_, Int kts_, Int kte_, Int it_, Real dt_, bool do_predict_nc_, bool do_prescribed_CCN_); + P3MainData(Int its_, Int ite_, Int kts_, Int kte_, Int it_, Real dt_, bool do_predict_nc_, bool do_prescribed_CCN_, Real=0.); - PTD_STD_DEF(P3MainData, 8, its, ite, kts, kte, it, dt, do_predict_nc, do_prescribed_CCN); + PTD_STD_DEF(P3MainData, 9, its, ite, kts, kte, it, dt, do_predict_nc, do_prescribed_CCN, elapsed_s); }; struct IceSupersatConservationData { @@ -780,6 +829,8 @@ struct IceSupersatConservationData { Real qidep, qinuc; void randomize(std::mt19937_64& engine); + + PTD_RW_SCALARS_ONLY(2, qidep, qinuc); }; struct NcConservationData { @@ -790,6 +841,8 @@ struct NcConservationData { Real nc_collect_tend, nc2ni_immers_freeze_tend, nc_accret_tend, nc2nr_autoconv_tend; void randomize(std::mt19937_64& engine); + + PTD_RW_SCALARS_ONLY(4, nc_collect_tend, nc2ni_immers_freeze_tend, nc_accret_tend, nc2nr_autoconv_tend); }; struct NrConservationData { @@ -800,6 +853,8 @@ struct NrConservationData { Real nr_collect_tend, nr2ni_immers_freeze_tend, nr_selfcollect_tend, nr_evap_tend; void randomize(std::mt19937_64& engine); + + PTD_RW_SCALARS_ONLY(4, nr_collect_tend, nr2ni_immers_freeze_tend, nr_selfcollect_tend, nr_evap_tend); }; struct NiConservationData { @@ -810,6 +865,8 @@ struct NiConservationData { Real ni2nr_melt_tend, ni_sublim_tend, ni_selfcollect_tend; void randomize(std::mt19937_64& engine); + + PTD_RW_SCALARS_ONLY(3, ni2nr_melt_tend, ni_sublim_tend, ni_selfcollect_tend); }; struct PreventLiqSupersaturationData { @@ -821,101 +878,54 @@ struct PreventLiqSupersaturationData { // This populates all fields with test data within [0,1]. void randomize(std::mt19937_64& engine); + + PTD_RW_SCALARS_ONLY(2, qi2qv_sublim_tend, qr2qv_evap_tend); }; -// Glue functions to call fortran from from C++ with the Data struct -void p3_init_a(P3InitAFortranData& d); -void find_lookuptable_indices_1a(LookupIceData& d); -void find_lookuptable_indices_1b(LookupIceDataB& d); -void access_lookup_table(AccessLookupTableData& d); -void access_lookup_table_coll(AccessLookupTableCollData& d); -void back_to_cell_average(BackToCellAverageData& d); -void cloud_water_conservation(CloudWaterConservationData& d); -void rain_water_conservation(RainWaterConservationData& d); -void ice_water_conservation(IceWaterConservationData& d); -void calc_rime_density(CalcRimeDensityData& d); -void cldliq_immersion_freezing(CldliqImmersionFreezingData& d); -void rain_immersion_freezing(RainImmersionFreezingData& d); -void droplet_self_collection(DropletSelfCollectionData& d); -void cloud_rain_accretion(CloudRainAccretionData& d); -void cloud_water_autoconversion(CloudWaterAutoconversionData& d); -void rain_self_collection(RainSelfCollectionData& d); -void impose_max_total_ni(ImposeMaxTotalNiData& d); -void ice_melting(IceMeltingData& d); -Real subgrid_variance_scaling(SubgridVarianceScalingData& d); -void get_cloud_dsd2(GetCloudDsd2Data& d); -void get_rain_dsd2(GetRainDsd2Data& d); -void calc_first_order_upwind_step(CalcUpwindData& d); -void generalized_sedimentation(GenSedData& d); -void cloud_sedimentation(CloudSedData& d); -void ice_sedimentation(IceSedData& d); -void rain_sedimentation(RainSedData& d); -void calc_bulk_rho_rime(CalcBulkRhoRimeData& d); -void homogeneous_freezing(HomogeneousFreezingData& d); -void compute_rain_fall_velocity(ComputeRainFallVelocityData& d); -void get_time_space_phys_variables(GetTimeSpacePhysVarsData& d); -void update_prognostic_ice(P3UpdatePrognosticIceData& d); -void evaporate_rain(EvapRainData& d); -void update_prognostic_liquid(P3UpdatePrognosticLiqData& d); -void ice_deposition_sublimation(IceDepositionSublimationData& d); -void ice_cldliq_collection(IceCldliqCollectionData& d); -void ice_rain_collection(IceRainCollectionData& d); -void ice_self_collection(IceSelfCollectionData& d); -void ice_relaxation_timescale(IceRelaxationData& d); -void calc_liq_relaxation_timescale(CalcLiqRelaxationData& d); -void ice_nucleation(IceNucleationData& d); -void ice_cldliq_wet_growth(IceWetGrowthData& d); -void get_latent_heat(LatentHeatData& d); -void check_values(CheckValuesData& d); -void calculate_incloud_mixingratios(IncloudMixingData& d); -void p3_main_part1(P3MainPart1Data& d); -void p3_main_part2(P3MainPart2Data& d); -void p3_main_part3(P3MainPart3Data& d); -void p3_main(P3MainData& d); - -void ice_supersat_conservation(IceSupersatConservationData& d); -void nc_conservation(NcConservationData& d); -void nr_conservation(NrConservationData& d); -void ni_conservation(NiConservationData& d); -void prevent_liq_supersaturation(PreventLiqSupersaturationData& d); -extern "C" { // _f function decls - -void calc_first_order_upwind_step_f( +void p3_init_a(P3InitAP3Data& d); + +/** + * Convenience functions for calling p3 routines from the host with scalar data. + * These function will pack your data, sync it to device, call the p3 function, + * then sync back to host and unpack. These are used by the BFB unit tests. + */ + +void calc_first_order_upwind_step_host( Int kts, Int kte, Int kdir, Int kbot, Int k_qxtop, Real dt_sub, Real* rho, Real* inv_rho, Real* inv_dz, Int num_arrays, Real** fluxes, Real** vs, Real** qnx); -void generalized_sedimentation_f(Int kts, Int kte, Int kdir, Int k_qxtop, Int *k_qxbot, Int kbot, Real Co_max, +void generalized_sedimentation_host(Int kts, Int kte, Int kdir, Int k_qxtop, Int *k_qxbot, Int kbot, Real Co_max, Real* dt_left, Real* prt_accum, Real* inv_dz, Real* inv_rho, Real* rho, Int num_arrays, Real** vs, Real** fluxes, Real** qnx); -void cloud_sedimentation_f( +void cloud_sedimentation_host( Int kts, Int kte, Int ktop, Int kbot, Int kdir, Real* qc_incld, Real* rho, Real* inv_rho, Real* cld_frac_l, Real* acn, Real* inv_dz, Real dt, Real inv_dt, bool do_predict_nc, Real* qc, Real* nc, Real* nc_incld, Real* mu_c, Real* lamc, Real* precip_liq_surf, Real* qc_tend, Real* nc_tend); -void ice_sedimentation_f( +void ice_sedimentation_host( Int kts, Int kte, Int ktop, Int kbot, Int kdir, Real* rho, Real* inv_rho, Real* rhofaci, Real* cld_frac_i, Real* inv_dz, Real dt, Real inv_dt, Real* qi, Real* qi_incld, Real* ni, Real* qm, Real* qm_incld, Real* bm, Real* bm_incld, Real* ni_incld, Real* precip_ice_surf, Real* qi_tend, Real* ni_tend); -void rain_sedimentation_f( +void rain_sedimentation_host( Int kts, Int kte, Int ktop, Int kbot, Int kdir, Real* qr_incld, Real* rho, Real* inv_rho, Real* rhofacr, Real* cld_frac_r, Real* inv_dz, Real dt, Real inv_dt, Real* qr, Real* nr, Real* nr_incld, Real* mu_r, Real* lamr, Real* precip_liq_surf, Real* precip_liq_flux, Real* qr_tend, Real* nr_tend); -void homogeneous_freezing_f( +void homogeneous_freezing_host( Int kts, Int kte, Int ktop, Int kbot, Int kdir, Real* T_atm, Real* inv_exner, Real* qc, Real* nc, Real* qr, Real* nr, Real* qi, Real* ni, Real* qm, Real* bm, Real* th_atm); -void check_values_f(Real* Qv, Real* temp, Int kstart, Int kend, - Int timestepcount, bool force_abort, Int source_ind, Real* col_loc); +void check_values_host(Real* Qv, Real* temp, Int kstart, Int kend, + Int timestepcount, bool force_abort, Int source_ind, Real* col_loc); -void p3_main_part1_f( +void p3_main_part1_host( Int kts, Int kte, Int kbot, Int ktop, Int kdir, bool do_predict_nc, bool do_prescribed_CCN, Real dt, @@ -926,7 +936,7 @@ void p3_main_part1_f( Real* qm_incld, Real* nc_incld, Real* nr_incld, Real* ni_incld, Real* bm_incld, bool* is_nucleat_possible, bool* is_hydromet_present); -void p3_main_part2_f( +void p3_main_part2_host( Int kts, Int kte, Int kbot, Int ktop, Int kdir, bool do_predict_nc, bool do_prescribed_CCN, Real dt, Real inv_dt, Real* pres, Real* dpres, Real* dz, Real* nc_nuceat_tend, Real* inv_exner, Real* exner, Real* inv_cld_frac_l, Real* inv_cld_frac_i, Real* inv_cld_frac_r, Real* ni_activated, Real* inv_qc_relvar, Real* cld_frac_i, Real* cld_frac_l, Real* cld_frac_r, Real* qv_prev, Real* t_prev, Real* T_atm, Real* rho, Real* inv_rho, Real* qv_sat_l, Real* qv_sat_i, Real* qv_supersat_i, Real* rhofacr, Real* rhofaci, Real* acn, Real* qv, Real* th_atm, Real* qc, Real* nc, Real* qr, Real* nr, Real* qi, Real* ni, @@ -935,14 +945,14 @@ void p3_main_part2_f( Real* nevapr, Real* qr_evap_tend, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* liq_ice_exchange, Real* pratot, Real* prctot, bool* is_hydromet_present); -void p3_main_part3_f( +void p3_main_part3_host( Int kts, Int kte, Int kbot, Int ktop, Int kdir, Real* inv_exner, Real* cld_frac_l, Real* cld_frac_r, Real* cld_frac_i, Real* rho, Real* inv_rho, Real* rhofaci, Real* qv, Real* th_atm, Real* qc, Real* nc, Real* qr, Real* nr, Real* qi, Real* ni, Real* qm, Real* bm, Real* mu_c, Real* nu, Real* lamc, Real* mu_r, Real* lamr, Real* vap_liq_exchange, Real* ze_rain, Real* ze_ice, Real* diag_vm_qi, Real* diag_eff_radius_qi, Real* diag_diam_qi, Real* rho_qi, Real* diag_equiv_reflectivity, Real* diag_eff_radius_qc, Real* diag_eff_radius_qr); -Int p3_main_f( +Int p3_main_host( Real* qc, Real* nc, Real* qr, Real* nr, Real* th_atm, Real* qv, Real dt, Real* qi, Real* qm, Real* ni, Real* bm, Real* pres, Real* dz, Real* nc_nuceat_tend, Real* nccn_prescribed, Real* ni_activated, Real* inv_qc_relvar, Int it, Real* precip_liq_surf, @@ -951,8 +961,6 @@ Int p3_main_f( Real* qv2qi_depos_tend, Real* precip_liq_flux, Real* precip_ice_flux, Real* cld_frac_r, Real* cld_frac_l, Real* cld_frac_i, Real* liq_ice_exchange, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* qv_prev, Real* t_prev); -} // end _f function decls - } // namespace p3 } // namespace scream diff --git a/components/eamxx/src/physics/p3/tests/p3_unit_tests_common.hpp b/components/eamxx/src/physics/p3/tests/infra/p3_unit_tests_common.hpp similarity index 63% rename from components/eamxx/src/physics/p3/tests/p3_unit_tests_common.hpp rename to components/eamxx/src/physics/p3/tests/infra/p3_unit_tests_common.hpp index 68f4491f789d..9dd7dee95b31 100644 --- a/components/eamxx/src/physics/p3/tests/p3_unit_tests_common.hpp +++ b/components/eamxx/src/physics/p3/tests/infra/p3_unit_tests_common.hpp @@ -2,7 +2,14 @@ #define P3_UNIT_TESTS_COMMON_HPP #include "share/scream_types.hpp" +#include "share/util/scream_setup_random_test.hpp" #include "p3_functions.hpp" +#include "p3_data.hpp" +#include "ekat/util/ekat_test_utils.hpp" +#include "p3_test_data.hpp" + +#include +#include namespace scream { namespace p3 { @@ -20,6 +27,12 @@ namespace unit_test { struct UnitWrap { + enum BASELINE_ACTION { + NONE, + COMPARE, + GENERATE + }; + template struct UnitTest : public KokkosTypes { @@ -58,6 +71,69 @@ struct UnitWrap { static constexpr Int max_pack_size = 16; static constexpr Int num_test_itrs = max_pack_size / Spack::n; + struct Base { + std::string m_baseline_path; + std::string m_test_name; + BASELINE_ACTION m_baseline_action; + ekat::FILEPtr m_fid; + + Base() : + m_baseline_path(""), + m_test_name(Catch::getResultCapture().getCurrentTestName()), + m_baseline_action(NONE), + m_fid() + { + Functions::p3_init(); // many tests will need fortran table data + auto& ts = ekat::TestSession::get(); + if (ts.flags["c"]) { + m_baseline_action = COMPARE; + } + else if (ts.flags["g"]) { + m_baseline_action = GENERATE; + } + else if (ts.flags["n"]) { + m_baseline_action = NONE; + } + m_baseline_path = ts.params["b"]; + + EKAT_REQUIRE_MSG( !(m_baseline_action != NONE && m_baseline_path == ""), + "P3 unit test flags problem: baseline actions were requested but no baseline path was provided"); + + std::string baseline_name = m_baseline_path + "/" + m_test_name; + if (m_baseline_action == COMPARE) { + m_fid = ekat::FILEPtr(fopen(baseline_name.c_str(), "r")); + } + else if (m_baseline_action == GENERATE) { + m_fid = ekat::FILEPtr(fopen(baseline_name.c_str(), "w")); + } + } + + ~Base() + { + scream::p3::P3GlobalForFortran::deinit(); + } + + std::mt19937_64 get_engine() + { + if (m_baseline_action != COMPARE) { + // We can use any seed + int seed; + auto engine = setup_random_test(nullptr, &seed); + if (m_baseline_action == GENERATE) { + // Write the seed + ekat::write(&seed, 1, m_fid); + } + return engine; + } + else { + // Read the seed + int seed; + ekat::read(&seed, 1, m_fid); + return setup_random_test(seed); + } + } + }; + // Put struct decls here struct TestTableIce; struct TestTable3; @@ -102,7 +178,6 @@ struct UnitWrap { struct TestIceDepositionSublimation; struct TestPreventLiqSupersaturation; }; - }; } // namespace unit_test diff --git a/components/eamxx/src/physics/p3/tests/p3_autoconversion_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_autoconversion_unit_tests.cpp index 78f673121dd6..be08e5b0d4f3 100644 --- a/components/eamxx/src/physics/p3/tests/p3_autoconversion_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_autoconversion_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,10 +19,10 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestP3CloudWaterAutoconversion +struct UnitWrap::UnitTest::TestP3CloudWaterAutoconversion : public UnitWrap::UnitTest::Base { -static void cloud_water_autoconversion_unit_bfb_tests(){ +void cloud_water_autoconversion_unit_bfb_tests() { CloudWaterAutoconversionData cwadc[max_pack_size] = { // rho, qc_incld, nc_incld, inv_qc_relvar @@ -59,12 +59,14 @@ static void cloud_water_autoconversion_unit_bfb_tests(){ std::copy(&cwadc[0], &cwadc[0] + max_pack_size, cwadc_host.data()); Kokkos::deep_copy(cwadc_device, cwadc_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - cloud_water_autoconversion(cwadc[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + cwadc[i].read(Base::m_fid); + } } - // Run the lookup from a kernel and copy results back to host + // Run the lookup from a kernel and copy results back to host Kokkos::parallel_for(num_test_itrs, KOKKOS_LAMBDA(const Int& i) { const Int offset = i * Spack::n; @@ -101,7 +103,7 @@ static void cloud_water_autoconversion_unit_bfb_tests(){ Kokkos::deep_copy(cwadc_host, cwadc_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(cwadc[s].rho == cwadc_host(s).rho); REQUIRE(cwadc[s].qc_incld == cwadc_host(s).qc_incld); @@ -112,13 +114,18 @@ static void cloud_water_autoconversion_unit_bfb_tests(){ REQUIRE(cwadc[s].ncautr == cwadc_host(s).ncautr); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cwadc_host(s).write(Base::m_fid); + } + } } - static void run_bfb(){ + void run_bfb() { cloud_water_autoconversion_unit_bfb_tests(); } - KOKKOS_FUNCTION static void autoconversion_is_positive(const Int &i, Int &errors){ + KOKKOS_FUNCTION static void autoconversion_is_positive(const Int &i, Int &errors){ const Spack rho(1.0), inv_qc_relvar(1.0); Spack qc_incld, nc_incld(1e7), qc2qr_autoconv_tend(0.0), nc2nr_autoconv_tend(0.0), ncautr(0.0); @@ -134,7 +141,7 @@ static void cloud_water_autoconversion_unit_bfb_tests(){ } } - static void run_physics(){ + void run_physics(){ int nerr = 0; @@ -153,12 +160,14 @@ static void cloud_water_autoconversion_unit_bfb_tests(){ } // namespace p3 } // namespace scream -namespace{ +namespace { TEST_CASE("p3_cloud_water_autoconversion_test", "[p3_cloud_water_autoconversion_test]"){ - scream::p3::unit_test::UnitWrap::UnitTest::TestP3CloudWaterAutoconversion::run_physics(); - scream::p3::unit_test::UnitWrap::UnitTest::TestP3CloudWaterAutoconversion::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestP3CloudWaterAutoconversion; + + T t; + t.run_physics(); + t.run_bfb(); } } // namespace - diff --git a/components/eamxx/src/physics/p3/tests/p3_back_to_cell_average_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_back_to_cell_average_unit_tests.cpp index 0377b990d786..b108ce329d3e 100644 --- a/components/eamxx/src/physics/p3/tests/p3_back_to_cell_average_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_back_to_cell_average_unit_tests.cpp @@ -4,8 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,45 +18,49 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestBackToCellAverage { +struct UnitWrap::UnitTest::TestBackToCellAverage : public UnitWrap::UnitTest::Base { -static void run_phys() +void run_phys() { // TODO } -static void run_bfb() +void run_bfb() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); // Generate n test structs, each populated with random data (values within // [0,1]) by the default constructor. - BackToCellAverageData back_to_cell_average_data[Spack::n]; - for (Int i = 0; i < Spack::n; ++i) { - back_to_cell_average_data[i].randomize(engine); + BackToCellAverageData back_to_cell_average_data[max_pack_size]; + for (auto& item : back_to_cell_average_data) { + item.randomize(engine); } // Sync to device. - view_1d device_data("back_to_cell_average", Spack::n); + view_1d device_data("back_to_cell_average", max_pack_size); const auto host_data = Kokkos::create_mirror_view(device_data); - std::copy(&back_to_cell_average_data[0], &back_to_cell_average_data[0] + Spack::n, + std::copy(&back_to_cell_average_data[0], &back_to_cell_average_data[0] + max_pack_size, host_data.data()); Kokkos::deep_copy(device_data, host_data); - // Run the Fortran subroutine. - for (Int i = 0; i < Spack::n; ++i) { - back_to_cell_average(back_to_cell_average_data[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + back_to_cell_average_data[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host - Kokkos::parallel_for(1, KOKKOS_LAMBDA(const Int&) { + Kokkos::parallel_for(num_test_itrs, KOKKOS_LAMBDA(const Int& i) { + const Int offset = i * Spack::n; + // Init pack inputs Spack cld_frac_l, cld_frac_r, cld_frac_i, qc2qr_accret_tend, qr2qv_evap_tend, qc2qr_autoconv_tend, nc_accret_tend, nc_selfcollect_tend, nc2nr_autoconv_tend, nr_selfcollect_tend, nr_evap_tend, ncautr, qi2qv_sublim_tend, nr_ice_shed_tend, qc2qi_hetero_freeze_tend, qr2qi_collect_tend, qc2qr_ice_shed_tend, qi2qr_melt_tend, qc2qi_collect_tend, qr2qi_immers_freeze_tend, ni2nr_melt_tend, nc_collect_tend, ncshdc, nc2ni_immers_freeze_tend, nr_collect_tend, ni_selfcollect_tend, qv2qi_vapdep_tend, nr2ni_immers_freeze_tend, ni_sublim_tend, qv2qi_nucleat_tend, ni_nucleat_tend, qc2qi_berg_tend; - for (Int s = 0; s < Spack::n; ++s) { + for (Int s = 0, vs = offset; s < Spack::n; ++s, ++vs) { cld_frac_l[s] = device_data[s].cld_frac_l; cld_frac_r[s] = device_data[s].cld_frac_r; cld_frac_i[s] = device_data[s].cld_frac_i; @@ -99,7 +102,7 @@ static void run_bfb() nr_collect_tend, ni_selfcollect_tend, qv2qi_vapdep_tend, nr2ni_immers_freeze_tend, ni_sublim_tend, qv2qi_nucleat_tend, ni_nucleat_tend, qc2qi_berg_tend); // Copy results back into views - for (Int s = 0; s < Spack::n; ++s) { + for (Int s = 0, vs = offset; s < Spack::n; ++s, ++vs) { device_data(s).qc2qr_accret_tend = qc2qr_accret_tend[s]; device_data(s).qr2qv_evap_tend = qr2qv_evap_tend[s]; device_data(s).qc2qr_autoconv_tend = qc2qr_autoconv_tend[s]; @@ -136,8 +139,8 @@ static void run_bfb() Kokkos::deep_copy(host_data, device_data); // Validate results. - if (SCREAM_BFB_TESTING) { - for (Int s = 0; s < Spack::n; ++s) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { + for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(back_to_cell_average_data[s].qc2qr_accret_tend == host_data[s].qc2qr_accret_tend); REQUIRE(back_to_cell_average_data[s].qr2qv_evap_tend == host_data[s].qr2qv_evap_tend); REQUIRE(back_to_cell_average_data[s].qc2qr_autoconv_tend == host_data[s].qc2qr_autoconv_tend); @@ -169,6 +172,11 @@ static void run_bfb() REQUIRE(back_to_cell_average_data[s].qc2qi_berg_tend == host_data[s].qc2qi_berg_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + host_data(s).write(Base::m_fid); + } + } } }; @@ -181,12 +189,11 @@ namespace { TEST_CASE("p3_back_to_cell_average", "[p3_functions]") { - using TRIF = scream::p3::unit_test::UnitWrap::UnitTest::TestBackToCellAverage; - - TRIF::run_phys(); - TRIF::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestBackToCellAverage; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_calc_liq_relaxation_timescale_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_calc_liq_relaxation_timescale_unit_tests.cpp index 97193fd06d31..2752746b7925 100644 --- a/components/eamxx/src/physics/p3/tests/p3_calc_liq_relaxation_timescale_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_calc_liq_relaxation_timescale_unit_tests.cpp @@ -4,8 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -20,16 +19,16 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestCalcLiqRelaxationTimescale { +struct UnitWrap::UnitTest::TestCalcLiqRelaxationTimescale : public UnitWrap::UnitTest::Base { - static void run_phys() + void run_phys() { // TODO } - static void run_bfb() + void run_bfb() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); // Read in tables view_2d_table vn_table_vals, vm_table_vals, revap_table_vals; @@ -54,9 +53,11 @@ struct UnitWrap::UnitTest::TestCalcLiqRelaxationTimescale { self[i].f2r = C::f2r; } - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - calc_liq_relaxation_timescale(self[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + self[i].read(Base::m_fid); + } } // Sync to device @@ -97,12 +98,17 @@ struct UnitWrap::UnitTest::TestCalcLiqRelaxationTimescale { Kokkos::deep_copy(self_host, self_device); - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(self[s].epsr == self_host(s).epsr); REQUIRE(self[s].epsc == self_host(s).epsc); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + self_host(s).write(Base::m_fid); + } + } } }; @@ -115,10 +121,11 @@ namespace { TEST_CASE("p3_calc_liq_relaxation_timescale", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestCalcLiqRelaxationTimescale; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestCalcLiqRelaxationTimescale; - TD::run_phys(); - TD::run_bfb(); + T t; + t.run_phys(); + t.run_bfb(); } } diff --git a/components/eamxx/src/physics/p3/tests/p3_calc_rime_density_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_calc_rime_density_unit_tests.cpp index 5d70c7302ae1..9b7722895faf 100644 --- a/components/eamxx/src/physics/p3/tests/p3_calc_rime_density_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_calc_rime_density_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -18,14 +18,14 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestCalcRimeDensity { +struct UnitWrap::UnitTest::TestCalcRimeDensity : public UnitWrap::UnitTest::Base { -static void run_phys() +void run_phys() { // TODO } -static void run_bfb() +void run_bfb() { // This is the threshold for whether the qc cloud mixing ratio is large // enough to affect the rime density. @@ -87,9 +87,11 @@ static void run_bfb() host_data.data()); Kokkos::deep_copy(device_data, host_data); - // Run the Fortran subroutine. - for (Int i = 0; i < max_pack_size; ++i) { - calc_rime_density(calc_rime_density_data[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + calc_rime_density_data[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -126,12 +128,17 @@ static void run_bfb() Kokkos::deep_copy(host_data, device_data); // Validate results. - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(calc_rime_density_data[s].vtrmi1 == host_data[s].vtrmi1); REQUIRE(calc_rime_density_data[s].rho_qm_cloud == host_data[s].rho_qm_cloud); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + host_data(s).write(Base::m_fid); + } + } } }; @@ -144,12 +151,11 @@ namespace { TEST_CASE("p3_calc_rime_density", "[p3_functions]") { - using TRIF = scream::p3::unit_test::UnitWrap::UnitTest::TestCalcRimeDensity; - - TRIF::run_phys(); - TRIF::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestCalcRimeDensity; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_check_values_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_check_values_unit_tests.cpp index f2f4a7f44047..90c8d28be932 100644 --- a/components/eamxx/src/physics/p3/tests/p3_check_values_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_check_values_unit_tests.cpp @@ -4,9 +4,8 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "p3_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" +#include "p3_data.hpp" #include "p3_unit_tests_common.hpp" @@ -20,13 +19,14 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestCheckValues { +struct UnitWrap::UnitTest::TestCheckValues : public UnitWrap::UnitTest::Base { -static void run_check_values_bfb() +void run_check_values_bfb() { + // This is not really a bfb test since no results are being checked. auto engine = setup_random_test(); - CheckValuesData cvd_fortran[] = { + CheckValuesData cvd_cxx[] = { // kts_, kte_, timestepcount_, source_ind_, force_abort_ CheckValuesData(1, 72, 2, 100, false), CheckValuesData(1, 72, 3, 100, false), @@ -34,33 +34,17 @@ static void run_check_values_bfb() CheckValuesData(1, 72, 5, 100, false), }; - static constexpr Int num_runs = sizeof(cvd_fortran) / sizeof(CheckValuesData); - - for (auto& d : cvd_fortran) { + for (auto& d : cvd_cxx) { d.randomize(engine, { {d.qv, {-4.056E-01, 1.153E+00}}, {d.temp, {1.000E+02, 5.000E+02}} }); } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that - // inout data is in original state - CheckValuesData cvd_cxx[num_runs] = { - CheckValuesData(cvd_fortran[0]), - CheckValuesData(cvd_fortran[1]), - CheckValuesData(cvd_fortran[2]), - CheckValuesData(cvd_fortran[3]), - }; - - // Get data from fortran - for (auto& d : cvd_fortran) { - check_values(d); - } - // Get data from cxx for (auto& d : cvd_cxx) { - check_values_f(d.qv, d.temp, d.kts, d.kte, d.timestepcount, d.force_abort, d.source_ind, d.col_loc); + check_values_host(d.qv, d.temp, d.kts, d.kte, d.timestepcount, d.force_abort, d.source_ind, d.col_loc); } } -static void run_check_values_phys() +void run_check_values_phys() { // TODO } @@ -75,14 +59,11 @@ namespace { TEST_CASE("p3_check_values", "[p3_functions]") { - using TRS = scream::p3::unit_test::UnitWrap::UnitTest::TestCheckValues; - - scream::p3::p3_init(); // need fortran table data - - TRS::run_check_values_phys(); - TRS::run_check_values_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestCheckValues; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_check_values_phys(); + t.run_check_values_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_cldliq_imm_freezing_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_cldliq_imm_freezing_unit_tests.cpp index eeccb70fd58a..bbaa95e87a03 100644 --- a/components/eamxx/src/physics/p3/tests/p3_cldliq_imm_freezing_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_cldliq_imm_freezing_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -18,14 +18,14 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestCldliqImmersionFreezing { +struct UnitWrap::UnitTest::TestCldliqImmersionFreezing : public UnitWrap::UnitTest::Base { -static void run_phys() +void run_phys() { // TODO } -static void run_bfb() +void run_bfb() { // This is the threshold for whether the qc and qr cloud mixing ratios are // large enough to affect the warm-phase process rates qc2qr_accret_tend and nc_accret_tend. @@ -70,9 +70,11 @@ static void run_bfb() host_data.data()); Kokkos::deep_copy(device_data, host_data); - // Run the Fortran subroutine. - for (Int i = 0; i < max_pack_size; ++i) { - cldliq_immersion_freezing(cldliq_imm_freezing_data[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + cldliq_imm_freezing_data[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -109,12 +111,17 @@ static void run_bfb() Kokkos::deep_copy(host_data, device_data); // Validate results. - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(cldliq_imm_freezing_data[s].qc2qi_hetero_freeze_tend == host_data[s].qc2qi_hetero_freeze_tend); REQUIRE(cldliq_imm_freezing_data[s].nc2ni_immers_freeze_tend == host_data[s].nc2ni_immers_freeze_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + host_data(s).write(Base::m_fid); + } + } } }; @@ -127,12 +134,11 @@ namespace { TEST_CASE("p3_cldliq_immersion_freezing", "[p3_functions]") { - using TRIF = scream::p3::unit_test::UnitWrap::UnitTest::TestCldliqImmersionFreezing; - - TRIF::run_phys(); - TRIF::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestCldliqImmersionFreezing; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_cloud_rain_acc_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_cloud_rain_acc_unit_tests.cpp index 472f9de1987a..271f7e27bd61 100644 --- a/components/eamxx/src/physics/p3/tests/p3_cloud_rain_acc_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_cloud_rain_acc_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -18,14 +18,14 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestCloudRainAccretion { +struct UnitWrap::UnitTest::TestCloudRainAccretion : public UnitWrap::UnitTest::Base { -static void run_phys() +void run_phys() { // TODO } -static void run_bfb() +void run_bfb() { // This is the threshold for whether the qc and qr cloud mixing ratios are // large enough to affect the warm-phase process rates qc2qr_accret_tend and nc_accret_tend. @@ -73,9 +73,11 @@ static void run_bfb() host_data.data()); Kokkos::deep_copy(device_data, host_data); - // Run the Fortran subroutine. - for (Int i = 0; i < max_pack_size; ++i) { - cloud_rain_accretion(cloud_rain_acc_data[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + cloud_rain_acc_data[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -112,12 +114,17 @@ static void run_bfb() Kokkos::deep_copy(host_data, device_data); // Validate results. - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(cloud_rain_acc_data[s].qc2qr_accret_tend == host_data[s].qc2qr_accret_tend); REQUIRE(cloud_rain_acc_data[s].nc_accret_tend == host_data[s].nc_accret_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + host_data(s).write(Base::m_fid); + } + } } }; @@ -130,12 +137,11 @@ namespace { TEST_CASE("p3_cloud_rain_accretion", "[p3_functions]") { - using TCRA = scream::p3::unit_test::UnitWrap::UnitTest::TestCloudRainAccretion; - - TCRA::run_phys(); - TCRA::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestCloudRainAccretion; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_cloud_sed_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_cloud_sed_unit_tests.cpp index 19fe5b3279e7..b29bf11faa1c 100644 --- a/components/eamxx/src/physics/p3/tests/p3_cloud_sed_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_cloud_sed_unit_tests.cpp @@ -4,8 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,18 +18,18 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestCloudSed { +struct UnitWrap::UnitTest::TestCloudSed : public UnitWrap::UnitTest::Base { -static void run_phys() +void run_phys() { // TODO } -static void run_bfb() +void run_bfb() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); - CloudSedData csds_fortran[] = { + CloudSedData csds_baseline[] = { // kts, kte, ktop, kbot, kdir, dt, inv_dt, do_predict_nc, precip_liq_surf, CloudSedData(1, 72, 27, 72, -1, 1.800E+03, 5.556E-04, false, 0.0), CloudSedData(1, 72, 72, 27, 1, 1.800E+03, 5.556E-04, false, 0.0), @@ -39,51 +38,58 @@ static void run_bfb() CloudSedData(1, 72, 27, 27, -1, 1.800E+03, 5.556E-04, true, 0.0), }; - static constexpr Int num_runs = sizeof(csds_fortran) / sizeof(CloudSedData); + static constexpr Int num_runs = sizeof(csds_baseline) / sizeof(CloudSedData); // Set up random input data - for (auto& d : csds_fortran) { + for (auto& d : csds_baseline) { d.randomize(engine, { {d.qc_incld, {C::QSMALL/2, C::QSMALL*2}} }); } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state CloudSedData csds_cxx[num_runs] = { - CloudSedData(csds_fortran[0]), - CloudSedData(csds_fortran[1]), - CloudSedData(csds_fortran[2]), - CloudSedData(csds_fortran[3]), - CloudSedData(csds_fortran[4]), + CloudSedData(csds_baseline[0]), + CloudSedData(csds_baseline[1]), + CloudSedData(csds_baseline[2]), + CloudSedData(csds_baseline[3]), + CloudSedData(csds_baseline[4]), }; - // Get data from fortran - for (auto& d : csds_fortran) { - cloud_sedimentation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (auto& d : csds_baseline) { + d.read(Base::m_fid); + } } // Get data from cxx for (auto& d : csds_cxx) { - cloud_sedimentation_f(d.kts, d.kte, d.ktop, d.kbot, d.kdir, + cloud_sedimentation_host(d.kts, d.kte, d.ktop, d.kbot, d.kdir, d.qc_incld, d.rho, d.inv_rho, d.cld_frac_l, d.acn, d.inv_dz, d.dt, d.inv_dt, d.do_predict_nc, d.qc, d.nc, d.nc_incld, d.mu_c, d.lamc, &d.precip_liq_surf, d.qc_tend, d.nc_tend); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { // Due to pack issues, we must restrict checks to the active k space - Int start = std::min(csds_fortran[i].kbot, csds_fortran[i].ktop) - 1; // 0-based indx - Int end = std::max(csds_fortran[i].kbot, csds_fortran[i].ktop); // 0-based indx + Int start = std::min(csds_baseline[i].kbot, csds_baseline[i].ktop) - 1; // 0-based indx + Int end = std::max(csds_baseline[i].kbot, csds_baseline[i].ktop); // 0-based indx for (Int k = start; k < end; ++k) { - REQUIRE(csds_fortran[i].qc[k] == csds_cxx[i].qc[k]); - REQUIRE(csds_fortran[i].nc[k] == csds_cxx[i].nc[k]); - REQUIRE(csds_fortran[i].nc_incld[k] == csds_cxx[i].nc_incld[k]); - REQUIRE(csds_fortran[i].mu_c[k] == csds_cxx[i].mu_c[k]); - REQUIRE(csds_fortran[i].lamc[k] == csds_cxx[i].lamc[k]); - REQUIRE(csds_fortran[i].qc_tend[k] == csds_cxx[i].qc_tend[k]); - REQUIRE(csds_fortran[i].nc_tend[k] == csds_cxx[i].nc_tend[k]); + REQUIRE(csds_baseline[i].qc[k] == csds_cxx[i].qc[k]); + REQUIRE(csds_baseline[i].nc[k] == csds_cxx[i].nc[k]); + REQUIRE(csds_baseline[i].nc_incld[k] == csds_cxx[i].nc_incld[k]); + REQUIRE(csds_baseline[i].mu_c[k] == csds_cxx[i].mu_c[k]); + REQUIRE(csds_baseline[i].lamc[k] == csds_cxx[i].lamc[k]); + REQUIRE(csds_baseline[i].qc_tend[k] == csds_cxx[i].qc_tend[k]); + REQUIRE(csds_baseline[i].nc_tend[k] == csds_cxx[i].nc_tend[k]); } - REQUIRE(csds_fortran[i].precip_liq_surf == csds_cxx[i].precip_liq_surf); + REQUIRE(csds_baseline[i].precip_liq_surf == csds_cxx[i].precip_liq_surf); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + csds_cxx[i].write(Base::m_fid); } } } @@ -98,12 +104,11 @@ namespace { TEST_CASE("p3_cloud_sed", "[p3_functions]") { - using TCS = scream::p3::unit_test::UnitWrap::UnitTest::TestCloudSed; - - TCS::run_phys(); - TCS::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestCloudSed; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_droplet_self_coll_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_droplet_self_coll_unit_tests.cpp index b81505816eac..f183bba65da6 100644 --- a/components/eamxx/src/physics/p3/tests/p3_droplet_self_coll_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_droplet_self_coll_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -18,14 +18,14 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestDropletSelfCollection { +struct UnitWrap::UnitTest::TestDropletSelfCollection : public UnitWrap::UnitTest::Base { -static void run_phys() +void run_phys() { // TODO } -static void run_bfb() +void run_bfb() { // This is the threshold for whether the qc and qr cloud mixing ratios are // large enough to affect the warm-phase process rates qc2qr_accret_tend and nc_accret_tend. @@ -72,9 +72,11 @@ static void run_bfb() host_data.data()); Kokkos::deep_copy(device_data, host_data); - // Run the Fortran subroutine. - for (Int i = 0; i < max_pack_size; ++i) { - droplet_self_collection(droplet_self_coll_data[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + droplet_self_coll_data[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -107,11 +109,17 @@ static void run_bfb() Kokkos::deep_copy(host_data, device_data); // Validate results. - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(droplet_self_coll_data[s].nc_selfcollect_tend == host_data[s].nc_selfcollect_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + host_data(s).write(Base::m_fid); + } + } + } }; @@ -124,12 +132,11 @@ namespace { TEST_CASE("p3_droplet_self_collection", "[p3_functions]") { - using TCRA = scream::p3::unit_test::UnitWrap::UnitTest::TestDropletSelfCollection; - - TCRA::run_phys(); - TCRA::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestDropletSelfCollection; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_dsd2_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_dsd2_unit_tests.cpp index 50894b03855f..268607645f04 100644 --- a/components/eamxx/src/physics/p3/tests/p3_dsd2_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_dsd2_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -22,9 +22,9 @@ namespace unit_test { */ template -struct UnitWrap::UnitTest::TestDsd2 { +struct UnitWrap::UnitTest::TestDsd2 : public UnitWrap::UnitTest::Base { - static void run_cloud_bfb() + void run_cloud_bfb() { // Read in tables view_2d_table vn_table_vals; view_2d_table vm_table_vals; view_2d_table revap_table_vals; @@ -60,9 +60,11 @@ struct UnitWrap::UnitTest::TestDsd2 { std::copy(&gcdd[0], &gcdd[0] + max_pack_size, gcdd_host.data()); Kokkos::deep_copy(gcdd_device, gcdd_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - get_cloud_dsd2(gcdd[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + gcdd[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -95,7 +97,7 @@ struct UnitWrap::UnitTest::TestDsd2 { Kokkos::deep_copy(gcdd_host, gcdd_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(gcdd[s].nc_out == gcdd_host(s).nc_out); REQUIRE(gcdd[s].mu_c == gcdd_host(s).mu_c); @@ -105,14 +107,19 @@ struct UnitWrap::UnitTest::TestDsd2 { REQUIRE(gcdd[s].cdist1 == gcdd_host(s).cdist1); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + gcdd_host(s).write(Base::m_fid); + } + } } - static void run_cloud_phys() + void run_cloud_phys() { // TODO } - static void run_rain_bfb() + void run_rain_bfb() { using KTH = KokkosTypes; @@ -144,9 +151,11 @@ struct UnitWrap::UnitTest::TestDsd2 { std::copy(&grdd[0], &grdd[0] + max_pack_size, grdd_host.data()); Kokkos::deep_copy(grdd_device, grdd_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - get_rain_dsd2(grdd[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + grdd[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -179,7 +188,7 @@ struct UnitWrap::UnitTest::TestDsd2 { Kokkos::deep_copy(grdd_host, grdd_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(grdd[s].nr_out == grdd_host(s).nr_out); REQUIRE(grdd[s].mu_r == grdd_host(s).mu_r); @@ -188,9 +197,14 @@ struct UnitWrap::UnitTest::TestDsd2 { REQUIRE(grdd[s].logn0r == grdd_host(s).logn0r); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + grdd_host(s).write(Base::m_fid); + } + } } - static void run_rain_phys() + void run_rain_phys() { // TODO } @@ -204,18 +218,20 @@ namespace { TEST_CASE("p3_cloud_dsd2", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestDsd2; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestDsd2; - TD::run_cloud_phys(); - TD::run_cloud_bfb(); + T t; + t.run_cloud_phys(); + t.run_cloud_bfb(); } TEST_CASE("p3_rain_dsd2", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestDsd2; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestDsd2; - TD::run_rain_phys(); - TD::run_rain_bfb(); + T t; + t.run_rain_phys(); + t.run_rain_bfb(); } } diff --git a/components/eamxx/src/physics/p3/tests/p3_evaporate_rain_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_evaporate_rain_unit_tests.cpp index f8398135a19e..a84b1e0448ad 100644 --- a/components/eamxx/src/physics/p3/tests/p3_evaporate_rain_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_evaporate_rain_unit_tests.cpp @@ -4,25 +4,18 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" -//#include -//#include -//#include -//#include -//#include // std::setprecision - namespace scream { namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestEvapSublPrecip -{ +struct UnitWrap::UnitTest::TestEvapSublPrecip : public UnitWrap::UnitTest::Base { - static void run_property(){ + void run_property() { //TEST WEIGHTING TIMESCALE //======================== @@ -133,13 +126,13 @@ struct UnitWrap::UnitTest::TestEvapSublPrecip REQUIRE( qrtend[0] <= qr_incld[0]/dt); REQUIRE( nrtend[0] <= nr_incld[0]/dt); //keep end-of-step nr positive. Should always be true. - }; //end run_property + } //end run_property - static void run_bfb(){ + void run_bfb() { constexpr Scalar latvap = C::LatVap; constexpr Scalar latice = C::LatIce; - //fortran generated data is input to the following + //baseline generated data is input to the following //This subroutine has 20 args, only 18 are supplied here for invoking it as last 2 are intent-outs //note that dt is the same val for each row - this is needed since dt is a scalar and all rows are executed simultaneously on CPU in C++. //row1: above freezing, should trigger @@ -180,9 +173,11 @@ struct UnitWrap::UnitTest::TestEvapSublPrecip std::copy(&espd[0], &espd[0] + max_pack_size, espd_host.data()); Kokkos::deep_copy(espd_device, espd_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - evaporate_rain(espd[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + espd[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -248,12 +243,17 @@ struct UnitWrap::UnitTest::TestEvapSublPrecip Kokkos::deep_copy(espd_host, espd_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(espd[s].qr2qv_evap_tend == espd_host(s).qr2qv_evap_tend); REQUIRE(espd[s].nr_evap_tend == espd_host(s).nr_evap_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + espd_host(s).write(Base::m_fid); + } + } } // end run_bfb @@ -267,14 +267,18 @@ namespace { TEST_CASE("p3_evaporate_rain_property", "p3_unit_tests") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestEvapSublPrecip; - TestStruct::run_property(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestEvapSublPrecip; + + T t; + t.run_property(); } TEST_CASE("p3_evaporate_rain_test", "p3_unit_tests") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestEvapSublPrecip; - TestStruct::run_bfb(); -} + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestEvapSublPrecip; + + T t; + t.run_bfb(); + } }// end anonymous namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_find_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_find_unit_tests.cpp index 4ba2dc6760e7..6e8e09226b7f 100644 --- a/components/eamxx/src/physics/p3/tests/p3_find_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_find_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -22,9 +22,9 @@ namespace unit_test { // template -struct UnitWrap::UnitTest::TestFind { +struct UnitWrap::UnitTest::TestFind : public UnitWrap::UnitTest::Base { -static void run() +void run() { const int max_threads = #ifdef KOKKOS_ENABLE_OPENMP @@ -112,7 +112,10 @@ namespace { TEST_CASE("p3_find", "[p3_functions]") { - scream::p3::unit_test::UnitWrap::UnitTest::TestFind::run(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestFind; + + T t; + t.run(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_get_latent_heat_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_get_latent_heat_unit_tests.cpp deleted file mode 100644 index 5d7b4de4ea7e..000000000000 --- a/components/eamxx/src/physics/p3/tests/p3_get_latent_heat_unit_tests.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "catch2/catch.hpp" - -#include "share/scream_types.hpp" -#include "ekat/ekat_pack.hpp" -#include "ekat/kokkos/ekat_kokkos_utils.hpp" -#include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "p3_f90.hpp" - -#include "p3_unit_tests_common.hpp" - -#include -#include -#include -#include -#include // std::setprecision - -namespace scream { -namespace p3 { -namespace unit_test { - -template -struct UnitWrap::UnitTest::TestLatentHeat { - - static void run_latent_heat_bfb() - { - constexpr Scalar latvap = C::LatVap; - constexpr Scalar latice = C::LatIce; - - LatentHeatData latent_fortran[] = { - // its, ite, kts, kte - LatentHeatData(1, 7, 1, 10), - }; - - static constexpr Int num_runs = sizeof(latent_fortran) / sizeof(LatentHeatData); - - LatentHeatData latent_cxx[num_runs] = { - LatentHeatData(latent_fortran[0]), - LatentHeatData(latent_fortran[1]), - LatentHeatData(latent_fortran[2]), - LatentHeatData(latent_fortran[3]), - }; - - for (Int i = 0; i < num_runs; ++i) { - LatentHeatData& h = latent_fortran[i]; - get_latent_heat(h); - - if (SCREAM_BFB_TESTING) { - for (Int j = 0; j < h.total(h.v); ++j) { - REQUIRE(h.v[j] == latvap); - REQUIRE(h.s[j] == (latvap+latice)); - REQUIRE(h.f[j] == latice); - } - } - } - } - - static void run_latent_heat_phys() - { - // TODO - } -}; - -} -} -} - -namespace { - -TEST_CASE("p3_latent_heat", "[p3_functions]") -{ - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestLatentHeat; - - TD::run_latent_heat_phys(); - TD::run_latent_heat_bfb(); -} - -} diff --git a/components/eamxx/src/physics/p3/tests/p3_ice_cldliq_wet_growth_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ice_cldliq_wet_growth_unit_tests.cpp index caf6638d5cd5..cca204b9b3a3 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ice_cldliq_wet_growth_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ice_cldliq_wet_growth_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,9 +19,9 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestIceCldliqWetGrowth { +struct UnitWrap::UnitTest::TestIceCldliqWetGrowth : public UnitWrap::UnitTest::Base { - static void run_ice_cldliq_wet_growth_bfb() + void run_ice_cldliq_wet_growth_bfb() { using KTH = KokkosTypes; @@ -57,9 +57,11 @@ struct UnitWrap::UnitTest::TestIceCldliqWetGrowth { std::copy(&self[0], &self[0] + max_pack_size, self_host.data()); Kokkos::deep_copy(self_device, self_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - ice_cldliq_wet_growth(self[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + self[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -114,7 +116,7 @@ struct UnitWrap::UnitTest::TestIceCldliqWetGrowth { Kokkos::deep_copy(self_host, self_device); - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(static_cast(self[s].log_wetgrowth) == static_cast(self_host(s).log_wetgrowth)); @@ -125,9 +127,14 @@ struct UnitWrap::UnitTest::TestIceCldliqWetGrowth { REQUIRE(self[s].qc2qr_ice_shed_tend == self_host(s).qc2qr_ice_shed_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + self_host(s).write(Base::m_fid); + } + } } - static void run_ice_cldliq_wet_growth_phys() + void run_ice_cldliq_wet_growth_phys() { // TODO } @@ -141,10 +148,11 @@ namespace { TEST_CASE("p3_ice_cldliq_wet_growth", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestIceCldliqWetGrowth; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceCldliqWetGrowth; - TD::run_ice_cldliq_wet_growth_phys(); - TD::run_ice_cldliq_wet_growth_bfb(); + T t; + t.run_ice_cldliq_wet_growth_phys(); + t.run_ice_cldliq_wet_growth_bfb(); } } diff --git a/components/eamxx/src/physics/p3/tests/p3_ice_collection_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ice_collection_unit_tests.cpp index 8fa1649b1213..2561114b519c 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ice_collection_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ice_collection_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -22,9 +22,9 @@ namespace unit_test { * Unit-tests for p3 ice collection functions. */ template -struct UnitWrap::UnitTest::TestIceCollection { +struct UnitWrap::UnitTest::TestIceCollection : public UnitWrap::UnitTest::Base { - static void run_ice_cldliq_bfb() + void run_ice_cldliq_bfb() { // Read in tables view_2d_table vn_table_vals; @@ -63,9 +63,11 @@ struct UnitWrap::UnitTest::TestIceCollection { std::copy(&cldliq[0], &cldliq[0] + max_pack_size, cldliq_host.data()); Kokkos::deep_copy(cldliq_device, cldliq_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - ice_cldliq_collection(cldliq[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + cldliq[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -109,7 +111,7 @@ struct UnitWrap::UnitTest::TestIceCollection { Kokkos::deep_copy(cldliq_host, cldliq_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(cldliq[s].qc2qi_collect_tend == cldliq_host(s).qc2qi_collect_tend); REQUIRE(cldliq[s].nc_collect_tend == cldliq_host(s).nc_collect_tend); @@ -117,14 +119,19 @@ struct UnitWrap::UnitTest::TestIceCollection { REQUIRE(cldliq[s].ncshdc == cldliq_host(s).ncshdc); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cldliq_host(s).write(Base::m_fid); + } + } } - static void run_ice_cldliq_phys() + void run_ice_cldliq_phys() { // TODO } - static void run_ice_rain_bfb() + void run_ice_rain_bfb() { using KTH = KokkosTypes; @@ -157,9 +164,11 @@ struct UnitWrap::UnitTest::TestIceCollection { std::copy(&rain[0], &rain[0] + max_pack_size, rain_host.data()); Kokkos::deep_copy(rain_device, rain_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - ice_rain_collection(rain[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + rain[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -198,20 +207,25 @@ struct UnitWrap::UnitTest::TestIceCollection { Kokkos::deep_copy(rain_host, rain_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(rain[s].qr2qi_collect_tend == rain_host(s).qr2qi_collect_tend); REQUIRE(rain[s].nr_collect_tend == rain_host(s).nr_collect_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + rain_host(s).write(Base::m_fid); + } + } } - static void run_ice_rain_phys() + void run_ice_rain_phys() { // TODO } - static void run_ice_self_bfb() + void run_ice_self_bfb() { using KTH = KokkosTypes; @@ -244,9 +258,11 @@ struct UnitWrap::UnitTest::TestIceCollection { std::copy(&self[0], &self[0] + max_pack_size, self_host.data()); Kokkos::deep_copy(self_device, self_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - ice_self_collection(self[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + self[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -276,15 +292,19 @@ struct UnitWrap::UnitTest::TestIceCollection { Kokkos::deep_copy(self_host, self_device); - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(self[s].ni_selfcollect_tend == self_host(s).ni_selfcollect_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + self_host(s).write(Base::m_fid); + } + } } - - static void run_ice_self_phys() + void run_ice_self_phys() { // TODO } @@ -298,24 +318,29 @@ namespace { TEST_CASE("p3_ice_cldliq", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestIceCollection; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceCollection; - TD::run_ice_cldliq_phys(); - TD::run_ice_cldliq_bfb(); + T t; + t.run_ice_cldliq_phys(); + t.run_ice_cldliq_bfb(); } TEST_CASE("p3_ice_rain", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestIceCollection; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceCollection; - TD::run_ice_rain_phys(); - TD::run_ice_rain_bfb(); + T t; + t.run_ice_rain_phys(); + t.run_ice_rain_bfb(); } TEST_CASE("p3_ice_self", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestIceCollection; - TD::run_ice_self_phys(); - TD::run_ice_self_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceCollection; + + T t; + t.run_ice_self_phys(); + t.run_ice_self_bfb(); } + } diff --git a/components/eamxx/src/physics/p3/tests/p3_ice_deposition_sublimation_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ice_deposition_sublimation_tests.cpp index bc1921441bb3..9b261409ad09 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ice_deposition_sublimation_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ice_deposition_sublimation_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "physics/share/physics_constants.hpp" #include "p3_unit_tests_common.hpp" @@ -13,9 +13,9 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestIceDepositionSublimation { +struct UnitWrap::UnitTest::TestIceDepositionSublimation : public UnitWrap::UnitTest::Base { - static void run_property(){ + void run_property() { //Note that a lot of property tests are included in run_bfb for simplicity //Choose default values (just grabbed a row from the array in run_bfb) @@ -30,13 +30,13 @@ struct UnitWrap::UnitTest::TestIceDepositionSublimation { //init output vars Spack qv2qi_vapdep_tend, qi2qv_sublim_tend, ni_sublim_tend, qc2qi_berg_tend; - + //CHECK THAT UNREASONABLY LARGE VAPOR DEPOSITION DOESN'T LEAVE QV SUBSATURATED WRT QI Spack epsi_tmp=1e6; //make 1/(sat removal timescale) huge so vapdep rate removes all supersat in 1 dt. Functions::ice_deposition_sublimation(qi_incld, ni_incld, T_atm, qv_sat_l, qv_sat_i, epsi_tmp, abi, qv, inv_dt, qv2qi_vapdep_tend, qi2qv_sublim_tend, ni_sublim_tend, qc2qi_berg_tend); REQUIRE( (qv2qi_vapdep_tend[0]==0 || std::abs( qv2qi_vapdep_tend[0] - (qv[0] - qv_sat_i[0])*inv_dt) <1e-8) ); - + //CHECK THAT HUGE SUBLIMATION DOESN'T LEAVE QV SUPERSATURATED WRT QI Spack qv_sat_i_tmp=1e-2; Functions::ice_deposition_sublimation(qi_incld, ni_incld, T_atm, qv_sat_l, qv_sat_i_tmp, @@ -46,10 +46,10 @@ struct UnitWrap::UnitTest::TestIceDepositionSublimation { //CHECK BEHAVIOR AS DT->0? } - - static void run_bfb() + + void run_bfb() { - IceDepositionSublimationData f90_data[max_pack_size] = { + IceDepositionSublimationData baseline_data[max_pack_size] = { {1.0000E-04,4.5010E+05,2.8750E+02,1.1279E-02,1.1279E-02,0.0000E+00,3.3648E+00,5.0000E-03,1.666667e-02}, {5.1000E-03,4.5370E+05,2.8542E+02,9.9759E-03,9.9759E-03,0.0000E+00,3.1223E+00,5.0000E-03,1.666667e-02}, {5.1000E-03,4.5742E+05,2.8334E+02,8.8076E-03,8.8076E-03,0.0000E+00,2.9014E+00,5.0000E-03,1.666667e-02}, @@ -67,25 +67,25 @@ struct UnitWrap::UnitTest::TestIceDepositionSublimation { {5.1000E-03,5.1317E+05,2.5834E+02,1.6757E-03,1.4491E-03,6.0620E-02,1.3763E+00,5.0000E-03,1.666667e-02}, {5.0000E-08,5.4479E+05,2.4793E+02,7.5430E-04,5.8895E-04,4.6769E-04,1.1661E+00,1.5278E-04,1.666667e-02}, }; - - static constexpr Int num_runs = sizeof(f90_data) / sizeof(IceDepositionSublimationData); // Generate random input data - // Alternatively, you can use the f90_data construtors/initializer lists to hardcode data - //for (auto& d : f90_data) { + // Alternatively, you can use the baseline_data construtors/initializer lists to hardcode data + //for (auto& d : baseline_data) { // d.randomize(); //} - // Create copies of data for use by cxx and sync it to device. Needs to happen before fortran calls so that + // Create copies of data for use by cxx and sync it to device. Needs to happen before reads so that // inout data is in original state view_1d cxx_device("cxx_device", max_pack_size); const auto cxx_host = Kokkos::create_mirror_view(cxx_device); - std::copy(&f90_data[0], &f90_data[0] + max_pack_size, cxx_host.data()); + std::copy(&baseline_data[0], &baseline_data[0] + max_pack_size, cxx_host.data()); Kokkos::deep_copy(cxx_device, cxx_host); - // Get data from fortran - for (auto& d : f90_data) { - ice_deposition_sublimation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + baseline_data[i].read(Base::m_fid); + } } // Get data from cxx. Run ice_deposition_sublimation from a kernel and copy results back to host @@ -110,7 +110,6 @@ struct UnitWrap::UnitTest::TestIceDepositionSublimation { // Init outputs Spack ni_sublim_tend(0), qi2qv_sublim_tend(0), qc2qi_berg_tend(0), qv2qi_vapdep_tend(0); - Functions::ice_deposition_sublimation(qi_incld, ni_incld, T_atm, qv_sat_l, qv_sat_i, epsi, abi, qv, inv_dt, qv2qi_vapdep_tend, qi2qv_sublim_tend, ni_sublim_tend, qc2qi_berg_tend); // Copy spacks back into cxx_device view @@ -120,35 +119,40 @@ struct UnitWrap::UnitTest::TestIceDepositionSublimation { cxx_device(vs).qc2qi_berg_tend = qc2qi_berg_tend[s]; cxx_device(vs).qv2qi_vapdep_tend = qv2qi_vapdep_tend[s]; } - }); Kokkos::deep_copy(cxx_host, cxx_device); - for (Int i = 0; i < num_runs; ++i) { - // Verify BFB results - IceDepositionSublimationData& d_f90 = f90_data[i]; - IceDepositionSublimationData& d_cxx = cxx_host[i]; - REQUIRE(d_f90.qv2qi_vapdep_tend == d_cxx.qv2qi_vapdep_tend); - REQUIRE(d_f90.qi2qv_sublim_tend == d_cxx.qi2qv_sublim_tend); - REQUIRE(d_f90.ni_sublim_tend == d_cxx.ni_sublim_tend); - REQUIRE(d_f90.qc2qi_berg_tend == d_cxx.qc2qi_berg_tend); - - //MAKE SURE OUTPUT IS WITHIN EXPECTED BOUNDS: - REQUIRE(d_cxx.qv2qi_vapdep_tend >=0); - REQUIRE(d_cxx.qi2qv_sublim_tend >=0); - REQUIRE(d_cxx.ni_sublim_tend >=0); - REQUIRE(d_cxx.qc2qi_berg_tend >=0); - - //vapdep should only occur when qv>qv_sat_i - REQUIRE( (d_cxx.qv2qi_vapdep_tend==0 || d_cxx.qv + d_cxx.qv2qi_vapdep_tend*d_cxx.inv_dt >= d_cxx.qv_sat_i) ); - //sublim should only occur when qvfrz, berg and vapdep should be 0: - REQUIRE( (d_cxx.T_atmm_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + // Verify BFB results + IceDepositionSublimationData& d_f90 = baseline_data[i]; + IceDepositionSublimationData& d_cxx = cxx_host[i]; + REQUIRE(d_f90.qv2qi_vapdep_tend == d_cxx.qv2qi_vapdep_tend); + REQUIRE(d_f90.qi2qv_sublim_tend == d_cxx.qi2qv_sublim_tend); + REQUIRE(d_f90.ni_sublim_tend == d_cxx.ni_sublim_tend); + REQUIRE(d_f90.qc2qi_berg_tend == d_cxx.qc2qi_berg_tend); + + //MAKE SURE OUTPUT IS WITHIN EXPECTED BOUNDS: + REQUIRE(d_cxx.qv2qi_vapdep_tend >=0); + REQUIRE(d_cxx.qi2qv_sublim_tend >=0); + REQUIRE(d_cxx.ni_sublim_tend >=0); + REQUIRE(d_cxx.qc2qi_berg_tend >=0); + + //vapdep should only occur when qv>qv_sat_i + REQUIRE( (d_cxx.qv2qi_vapdep_tend==0 || d_cxx.qv + d_cxx.qv2qi_vapdep_tend*d_cxx.inv_dt >= d_cxx.qv_sat_i) ); + //sublim should only occur when qvfrz, berg and vapdep should be 0: + REQUIRE( (d_cxx.T_atmm_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cxx_host(s).write(Base::m_fid); + } } } // run_bfb @@ -162,16 +166,18 @@ namespace { TEST_CASE("ice_deposition_sublimation_property", "[p3]") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestIceDepositionSublimation; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceDepositionSublimation; - TestStruct::run_property(); + T t; + t.run_property(); } - + TEST_CASE("ice_deposition_sublimation_bfb", "[p3]") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestIceDepositionSublimation; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceDepositionSublimation; - TestStruct::run_bfb(); + T t; + t.run_bfb(); } } // empty namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_ice_melting_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ice_melting_unit_tests.cpp index 28c6582f8a14..4e24cc8be0e0 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ice_melting_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ice_melting_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,10 +19,10 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestP3IceMelting +struct UnitWrap::UnitTest::TestP3IceMelting : public UnitWrap::UnitTest::Base { -static void ice_melting_bfb(){ +void ice_melting_bfb() { constexpr Scalar latvap = C::LatVap; constexpr Scalar latice = C::LatIce; @@ -57,9 +57,11 @@ static void ice_melting_bfb(){ std::copy(&IceMelt[0], &IceMelt[0] + max_pack_size, IceMelt_host.data()); Kokkos::deep_copy(IceMelt_device, IceMelt_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - ice_melting(IceMelt[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + IceMelt[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -99,13 +101,19 @@ static void ice_melting_bfb(){ Kokkos::deep_copy(IceMelt_host, IceMelt_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(IceMelt[s].qi2qr_melt_tend == IceMelt_host(s).qi2qr_melt_tend); REQUIRE(IceMelt[s].ni2nr_melt_tend == IceMelt_host(s).ni2nr_melt_tend); } } -}; // TestP3IceMelting + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + IceMelt_host(s).write(Base::m_fid); + } + } + +} }; // UnitWrap @@ -113,11 +121,13 @@ static void ice_melting_bfb(){ } // namespace p3 } // namespace scream -namespace{ +namespace { -TEST_CASE("p3_ice_melting_test", "[p3_ice_melting_test]"){ - scream::p3::unit_test::UnitWrap::UnitTest::TestP3IceMelting::ice_melting_bfb(); +TEST_CASE("p3_ice_melting_test", "[p3_ice_melting_test]") { + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestP3IceMelting; + + T t; + t.ice_melting_bfb(); } } // namespace - diff --git a/components/eamxx/src/physics/p3/tests/p3_ice_nucleation_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ice_nucleation_unit_tests.cpp index 4e54b8837e04..7eeb4fa875ec 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ice_nucleation_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ice_nucleation_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,9 +19,9 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestIceNucleation { +struct UnitWrap::UnitTest::TestIceNucleation : public UnitWrap::UnitTest::Base { - static void run_ice_nucleation_bfb() + void run_ice_nucleation_bfb() { using KTH = KokkosTypes; @@ -54,10 +54,13 @@ struct UnitWrap::UnitTest::TestIceNucleation { {2.702E+02, 1.069E+00, 0.323E+03, 2.221E+01, 9.952E-01, inv_dt, do_predict_nc, do_prescribed_CCN } }; - // Run the fortran code - for (Int i = 0; i < max_pack_size; ++i) { - ice_nucleation(self[i]); - } + std::string root_name = "ice_nucleation"; + std::string file_name = root_name + (do_predict_nc ? "1" : "0") + (do_prescribed_CCN ? "1" : "0"); + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + self[i].read(Base::m_fid); + } + } // Sync to device KTH::view_1d self_host("self_host", max_pack_size); @@ -94,17 +97,22 @@ struct UnitWrap::UnitTest::TestIceNucleation { Kokkos::deep_copy(self_host, self_device); - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(self[s].qv2qi_nucleat_tend == self_host(s).qv2qi_nucleat_tend); REQUIRE(self[s].ni_nucleat_tend == self_host(s).ni_nucleat_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + self_host(s).write(Base::m_fid); + } + } } //end for do_predict_nc } //end for do_prescribed_CCN } - static void run_ice_nucleation_phys() + void run_ice_nucleation_phys() { // TODO } @@ -118,10 +126,11 @@ namespace { TEST_CASE("p3_ice_nucleation", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestIceNucleation; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceNucleation; - TD::run_ice_nucleation_phys(); - TD::run_ice_nucleation_bfb(); + T t; + t.run_ice_nucleation_phys(); + t.run_ice_nucleation_bfb(); } } diff --git a/components/eamxx/src/physics/p3/tests/p3_ice_relaxation_timescale_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ice_relaxation_timescale_unit_tests.cpp index a75b55fdbece..59768bbf82c6 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ice_relaxation_timescale_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ice_relaxation_timescale_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,9 +19,9 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestIceRelaxationTimescale { +struct UnitWrap::UnitTest::TestIceRelaxationTimescale : public UnitWrap::UnitTest::Base { - static void run_ice_relaxation_timescale_bfb() + void run_ice_relaxation_timescale_bfb() { using KTH = KokkosTypes; @@ -49,10 +49,12 @@ struct UnitWrap::UnitTest::TestIceRelaxationTimescale { {1.352E+01, 3.210E+03, 1.069E+00, 0.123E+00, 3.456E+00, 1.221E-02, 9.952E-07, 6.596E-05, 4.532E-01, 1.734E+04} }; - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - ice_relaxation_timescale(self[i]); - } + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + self[i].read(Base::m_fid); + } + } // Sync to device KTH::view_1d self_host("self_host", max_pack_size); @@ -93,15 +95,20 @@ struct UnitWrap::UnitTest::TestIceRelaxationTimescale { Kokkos::deep_copy(self_host, self_device); - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(self[s].epsi == self_host(s).epsi); REQUIRE(self[s].epsi_tot == self_host(s).epsi_tot); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + self_host(s).write(Base::m_fid); + } + } } - static void run_ice_relaxation_timescale_phys() + void run_ice_relaxation_timescale_phys() { // TODO } @@ -115,10 +122,11 @@ namespace { TEST_CASE("p3_ice_relaxation_timescale", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestIceRelaxationTimescale; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceRelaxationTimescale; - TD::run_ice_relaxation_timescale_phys(); - TD::run_ice_relaxation_timescale_bfb(); + T t; + t.run_ice_relaxation_timescale_phys(); + t.run_ice_relaxation_timescale_bfb(); } } diff --git a/components/eamxx/src/physics/p3/tests/p3_ice_sed_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ice_sed_unit_tests.cpp index c04aa55be00a..faa6da1596ef 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ice_sed_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ice_sed_unit_tests.cpp @@ -4,8 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,36 +18,36 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestIceSed { +struct UnitWrap::UnitTest::TestIceSed : public UnitWrap::UnitTest::Base { -static void run_phys_calc_bulk_rhime() +void run_phys_calc_bulk_rhime() { // TODO } -static void run_phys_ice_sed() +void run_phys_ice_sed() { // TODO } -static void run_phys_homogeneous_freezing() +void run_phys_homogeneous_freezing() { // TODO } -static void run_phys() +void run_phys() { run_phys_calc_bulk_rhime(); run_phys_ice_sed(); run_phys_homogeneous_freezing(); } -static void run_bfb_calc_bulk_rhime() +void run_bfb_calc_bulk_rhime() { constexpr Scalar qsmall = C::QSMALL; // Load some lookup inputs, need at least one per pack value - CalcBulkRhoRimeData cbrr_fortran[max_pack_size] = { + CalcBulkRhoRimeData cbrr_baseline[max_pack_size] = { // qi_tot, qi_rim, bi_rim {9.999978E-08, 9.999978E-03, 1.111108E-10}, {0.000000E+00, 8.571428E-05, 1.000000E-02}, @@ -71,17 +70,17 @@ static void run_bfb_calc_bulk_rhime() {5.164017E-10, 0.000000E+00, 0.000000E+00}, }; - // Sync to device, needs to happen before fortran calls so that + // Sync to device, needs to happen before reads so that // inout data is in original state view_1d cbrr_device("cbrr", max_pack_size); const auto cbrr_host = Kokkos::create_mirror_view(cbrr_device); - std::copy(&cbrr_fortran[0], &cbrr_fortran[0] + max_pack_size, cbrr_host.data()); + std::copy(&cbrr_baseline[0], &cbrr_baseline[0] + max_pack_size, cbrr_host.data()); Kokkos::deep_copy(cbrr_device, cbrr_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - if (cbrr_fortran[i].qi_tot > qsmall) { - calc_bulk_rho_rime(cbrr_fortran[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + cbrr_baseline[i].read(Base::m_fid); } } @@ -114,20 +113,25 @@ static void run_bfb_calc_bulk_rhime() Kokkos::deep_copy(cbrr_host, cbrr_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { - REQUIRE(cbrr_fortran[s].qi_rim == cbrr_host(s).qi_rim); - REQUIRE(cbrr_fortran[s].bi_rim == cbrr_host(s).bi_rim); - REQUIRE(cbrr_fortran[s].rho_rime == cbrr_host(s).rho_rime); + REQUIRE(cbrr_baseline[s].qi_rim == cbrr_host(s).qi_rim); + REQUIRE(cbrr_baseline[s].bi_rim == cbrr_host(s).bi_rim); + REQUIRE(cbrr_baseline[s].rho_rime == cbrr_host(s).rho_rime); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cbrr_host(s).write(Base::m_fid); } } } -static void run_bfb_ice_sed() +void run_bfb_ice_sed() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); - IceSedData isds_fortran[] = { + IceSedData isds_baseline[] = { // kts, kte, ktop, kbot, kdir, dt, inv_dt, precip_ice_surf IceSedData(1, 72, 27, 72, -1, 1.800E+03, 5.556E-04, 0.0), IceSedData(1, 72, 72, 27, 1, 1.800E+03, 5.556E-04, 1.0), @@ -135,65 +139,72 @@ static void run_bfb_ice_sed() IceSedData(1, 72, 27, 27, 1, 1.800E+03, 5.556E-04, 2.0), }; - static constexpr Int num_runs = sizeof(isds_fortran) / sizeof(IceSedData); + static constexpr Int num_runs = sizeof(isds_baseline) / sizeof(IceSedData); // Set up random input data - for (auto& d : isds_fortran) { + for (auto& d : isds_baseline) { d.randomize(engine, { {d.qi_incld, {C::QSMALL/2, C::QSMALL*2}} }); } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state IceSedData isds_cxx[num_runs] = { - IceSedData(isds_fortran[0]), - IceSedData(isds_fortran[1]), - IceSedData(isds_fortran[2]), - IceSedData(isds_fortran[3]), + IceSedData(isds_baseline[0]), + IceSedData(isds_baseline[1]), + IceSedData(isds_baseline[2]), + IceSedData(isds_baseline[3]), }; - // Get data from fortran - for (auto& d : isds_fortran) { - ice_sedimentation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < num_runs; ++i) { + isds_baseline[i].read(Base::m_fid); + } } // Get data from cxx for (auto& d : isds_cxx) { - ice_sedimentation_f(d.kts, d.kte, d.ktop, d.kbot, d.kdir, + ice_sedimentation_host(d.kts, d.kte, d.ktop, d.kbot, d.kdir, d.rho, d.inv_rho, d.rhofaci, d.cld_frac_i, d.inv_dz, d.dt, d.inv_dt, d.qi, d.qi_incld, d.ni, d.qm, d.qm_incld, d.bm, d.bm_incld, d.ni_incld, &d.precip_ice_surf, d.qi_tend, d.ni_tend); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { // Due to pack issues, we must restrict checks to the active k space - Int start = std::min(isds_fortran[i].kbot, isds_fortran[i].ktop) - 1; // 0-based indx - Int end = std::max(isds_fortran[i].kbot, isds_fortran[i].ktop); // 0-based indx + Int start = std::min(isds_baseline[i].kbot, isds_baseline[i].ktop) - 1; // 0-based indx + Int end = std::max(isds_baseline[i].kbot, isds_baseline[i].ktop); // 0-based indx for (Int k = start; k < end; ++k) { - REQUIRE(isds_fortran[i].qi[k] == isds_cxx[i].qi[k]); - REQUIRE(isds_fortran[i].qi_incld[k] == isds_cxx[i].qi_incld[k]); - REQUIRE(isds_fortran[i].ni[k] == isds_cxx[i].ni[k]); - REQUIRE(isds_fortran[i].ni_incld[k] == isds_cxx[i].ni_incld[k]); - REQUIRE(isds_fortran[i].qm[k] == isds_cxx[i].qm[k]); - REQUIRE(isds_fortran[i].qm_incld[k] == isds_cxx[i].qm_incld[k]); - REQUIRE(isds_fortran[i].bm[k] == isds_cxx[i].bm[k]); - REQUIRE(isds_fortran[i].bm_incld[k] == isds_cxx[i].bm_incld[k]); - REQUIRE(isds_fortran[i].qi_tend[k] == isds_cxx[i].qi_tend[k]); - REQUIRE(isds_fortran[i].ni_tend[k] == isds_cxx[i].ni_tend[k]); + REQUIRE(isds_baseline[i].qi[k] == isds_cxx[i].qi[k]); + REQUIRE(isds_baseline[i].qi_incld[k] == isds_cxx[i].qi_incld[k]); + REQUIRE(isds_baseline[i].ni[k] == isds_cxx[i].ni[k]); + REQUIRE(isds_baseline[i].ni_incld[k] == isds_cxx[i].ni_incld[k]); + REQUIRE(isds_baseline[i].qm[k] == isds_cxx[i].qm[k]); + REQUIRE(isds_baseline[i].qm_incld[k] == isds_cxx[i].qm_incld[k]); + REQUIRE(isds_baseline[i].bm[k] == isds_cxx[i].bm[k]); + REQUIRE(isds_baseline[i].bm_incld[k] == isds_cxx[i].bm_incld[k]); + REQUIRE(isds_baseline[i].qi_tend[k] == isds_cxx[i].qi_tend[k]); + REQUIRE(isds_baseline[i].ni_tend[k] == isds_cxx[i].ni_tend[k]); } - REQUIRE(isds_fortran[i].precip_ice_surf == isds_cxx[i].precip_ice_surf); + REQUIRE(isds_baseline[i].precip_ice_surf == isds_cxx[i].precip_ice_surf); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + isds_cxx[i].write(Base::m_fid); } } } -static void run_bfb_homogeneous_freezing() +void run_bfb_homogeneous_freezing() { constexpr Scalar latice = C::LatIce; - auto engine = setup_random_test(); + auto engine = Base::get_engine(); - HomogeneousFreezingData hfds_fortran[] = { + HomogeneousFreezingData hfds_baseline[] = { // kts, kte, ktop, kbot, kdir HomogeneousFreezingData(1, 72, 27, 72, -1), HomogeneousFreezingData(1, 72, 72, 27, 1), @@ -201,10 +212,10 @@ static void run_bfb_homogeneous_freezing() HomogeneousFreezingData(1, 72, 27, 27, 1), }; - static constexpr Int num_runs = sizeof(hfds_fortran) / sizeof(HomogeneousFreezingData); + static constexpr Int num_runs = sizeof(hfds_baseline) / sizeof(HomogeneousFreezingData); // Set up random input data - for (auto& d : hfds_fortran) { + for (auto& d : hfds_baseline) { const auto qsmall_r = std::make_pair(C::QSMALL/2, C::QSMALL*2); d.randomize(engine, { {d.T_atm, {C::T_homogfrz - 10, C::T_homogfrz + 10}}, {d.qc, qsmall_r}, {d.qr, qsmall_r} }); @@ -215,48 +226,56 @@ static void run_bfb_homogeneous_freezing() } } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state HomogeneousFreezingData hfds_cxx[num_runs] = { - HomogeneousFreezingData(hfds_fortran[0]), - HomogeneousFreezingData(hfds_fortran[1]), - HomogeneousFreezingData(hfds_fortran[2]), - HomogeneousFreezingData(hfds_fortran[3]), + HomogeneousFreezingData(hfds_baseline[0]), + HomogeneousFreezingData(hfds_baseline[1]), + HomogeneousFreezingData(hfds_baseline[2]), + HomogeneousFreezingData(hfds_baseline[3]), }; - // Get data from fortran - for (auto& d : hfds_fortran) { - homogeneous_freezing(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (auto& d : hfds_baseline) { + d.read(Base::m_fid); + } } // Get data from cxx for (auto& d : hfds_cxx) { - homogeneous_freezing_f(d.kts, d.kte, d.ktop, d.kbot, d.kdir, + homogeneous_freezing_host(d.kts, d.kte, d.ktop, d.kbot, d.kdir, d.T_atm, d.inv_exner, d.qc, d.nc, d.qr, d.nr, d.qi, d.ni, d.qm, d.bm, d.th_atm); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { // Due to pack issues, we must restrict checks to the active k space - Int start = std::min(hfds_fortran[i].kbot, hfds_fortran[i].ktop) - 1; // 0-based indx - Int end = std::max(hfds_fortran[i].kbot, hfds_fortran[i].ktop); // 0-based indx + Int start = std::min(hfds_baseline[i].kbot, hfds_baseline[i].ktop) - 1; // 0-based indx + Int end = std::max(hfds_baseline[i].kbot, hfds_baseline[i].ktop); // 0-based indx for (Int k = start; k < end; ++k) { - REQUIRE(hfds_fortran[i].qc[k] == hfds_cxx[i].qc[k]); - REQUIRE(hfds_fortran[i].nc[k] == hfds_cxx[i].nc[k]); - REQUIRE(hfds_fortran[i].qr[k] == hfds_cxx[i].qr[k]); - REQUIRE(hfds_fortran[i].nr[k] == hfds_cxx[i].nr[k]); - REQUIRE(hfds_fortran[i].qi[k] == hfds_cxx[i].qi[k]); - REQUIRE(hfds_fortran[i].ni[k] == hfds_cxx[i].ni[k]); - REQUIRE(hfds_fortran[i].qm[k] == hfds_cxx[i].qm[k]); - REQUIRE(hfds_fortran[i].bm[k] == hfds_cxx[i].bm[k]); - REQUIRE(hfds_fortran[i].th_atm[k] == hfds_cxx[i].th_atm[k]); + REQUIRE(hfds_baseline[i].qc[k] == hfds_cxx[i].qc[k]); + REQUIRE(hfds_baseline[i].nc[k] == hfds_cxx[i].nc[k]); + REQUIRE(hfds_baseline[i].qr[k] == hfds_cxx[i].qr[k]); + REQUIRE(hfds_baseline[i].nr[k] == hfds_cxx[i].nr[k]); + REQUIRE(hfds_baseline[i].qi[k] == hfds_cxx[i].qi[k]); + REQUIRE(hfds_baseline[i].ni[k] == hfds_cxx[i].ni[k]); + REQUIRE(hfds_baseline[i].qm[k] == hfds_cxx[i].qm[k]); + REQUIRE(hfds_baseline[i].bm[k] == hfds_cxx[i].bm[k]); + REQUIRE(hfds_baseline[i].th_atm[k] == hfds_cxx[i].th_atm[k]); } } } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + hfds_cxx[i].write(Base::m_fid); + } + } + } -static void run_bfb() +void run_bfb() { run_bfb_calc_bulk_rhime(); run_bfb_ice_sed(); @@ -273,12 +292,11 @@ namespace { TEST_CASE("p3_ice_sed", "[p3_functions]") { - using TCS = scream::p3::unit_test::UnitWrap::UnitTest::TestIceSed; - - TCS::run_phys(); - TCS::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceSed; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_ice_supersat_conservation_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ice_supersat_conservation_tests.cpp index 5873b8335c38..dcbdfc618263 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ice_supersat_conservation_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ice_supersat_conservation_tests.cpp @@ -4,8 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -14,38 +13,40 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestIceSupersatConservation { +struct UnitWrap::UnitTest::TestIceSupersatConservation : public UnitWrap::UnitTest::Base { - static void run_bfb() + void run_bfb() { constexpr Scalar latvap = C::LatVap; constexpr Scalar latice = C::LatIce; - auto engine = setup_random_test(); + auto engine = Base::get_engine(); - IceSupersatConservationData f90_data[max_pack_size]; + IceSupersatConservationData baseline_data[max_pack_size]; // Generate random input data - // Alternatively, you can use the f90_data construtors/initializer lists to hardcode data - for (auto& d : f90_data) { + // Alternatively, you can use the baseline_data construtors/initializer lists to hardcode data + for (auto& d : baseline_data) { d.randomize(engine); - d.dt = f90_data[0].dt; // hold this fixed, it is not packed data + d.dt = baseline_data[0].dt; // hold this fixed, it is not packed data // C++ impl uses constants for latent_heat values. Manually set here // so F90 can match d.latent_heat_sublim = latvap+latice; } - // Create copies of data for use by cxx and sync it to device. Needs to happen before fortran calls so that + // Create copies of data for use by cxx and sync it to device. Needs to happen before reads so that // inout data is in original state view_1d cxx_device("cxx_device", max_pack_size); const auto cxx_host = Kokkos::create_mirror_view(cxx_device); - std::copy(&f90_data[0], &f90_data[0] + max_pack_size, cxx_host.data()); + std::copy(&baseline_data[0], &baseline_data[0] + max_pack_size, cxx_host.data()); Kokkos::deep_copy(cxx_device, cxx_host); - // Get data from fortran - for (auto& d : f90_data) { - ice_supersat_conservation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + baseline_data[i].read(Base::m_fid); + } } // Get data from cxx. Run ice_supersat_conservation from a kernel and copy results back to host @@ -72,20 +73,24 @@ struct UnitWrap::UnitTest::TestIceSupersatConservation { cxx_device(vs).qidep = qidep[s]; cxx_device(vs).qinuc = qinuc[s]; } - }); Kokkos::deep_copy(cxx_host, cxx_device); // Verify BFB results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < max_pack_size; ++i) { - IceSupersatConservationData& d_f90 = f90_data[i]; + IceSupersatConservationData& d_f90 = baseline_data[i]; IceSupersatConservationData& d_cxx = cxx_host[i]; REQUIRE(d_f90.qidep == d_cxx.qidep); REQUIRE(d_f90.qinuc == d_cxx.qinuc); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cxx_host(s).write(Base::m_fid); + } + } } // run_bfb }; @@ -98,9 +103,10 @@ namespace { TEST_CASE("ice_supersat_conservation_bfb", "[p3]") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestIceSupersatConservation; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIceSupersatConservation; - TestStruct::run_bfb(); + T t; + t.run_bfb(); } } // empty namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_ice_tables_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ice_tables_unit_tests.cpp index 091d05895fcc..ea3fdaccf7e8 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ice_tables_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ice_tables_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -22,9 +22,9 @@ namespace unit_test { */ template -struct UnitWrap::UnitTest::TestTableIce { +struct UnitWrap::UnitTest::TestTableIce : public UnitWrap::UnitTest::Base { - static void test_read_lookup_tables_bfb() + void test_read_lookup_tables_bfb() { // Read in ice tables view_ice_table ice_table_vals; @@ -32,7 +32,7 @@ struct UnitWrap::UnitTest::TestTableIce { Functions::init_kokkos_ice_lookup_tables(ice_table_vals, collect_table_vals); // Get data from fortran - P3InitAFortranData d; + P3InitAP3Data d; p3_init_a(d); // Copy device data to host @@ -62,7 +62,7 @@ struct UnitWrap::UnitTest::TestTableIce { } template - static void init_table_linear_dimension(View& table, int linear_dimension) + void init_table_linear_dimension(View& table, int linear_dimension) { // set up views using NonConstView = typename View::non_const_type; @@ -96,7 +96,7 @@ struct UnitWrap::UnitTest::TestTableIce { table = view_device; } - static void run_bfb() + void run_bfb() { using KTH = KokkosTypes; @@ -199,14 +199,6 @@ struct UnitWrap::UnitTest::TestTableIce { {lid[15], lidb[15], access_table_index} }; - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - find_lookuptable_indices_1a(lid[i]); - find_lookuptable_indices_1b(lidb[i]); - access_lookup_table(altd[i]); - access_lookup_table_coll(altcd[i]); - } - // Sync to device KTH::view_1d lid_host("lid_host", max_pack_size); KTH::view_1d lidb_host("lidb_host", max_pack_size); @@ -217,6 +209,16 @@ struct UnitWrap::UnitTest::TestTableIce { Kokkos::deep_copy(lid_device, lid_host); Kokkos::deep_copy(lidb_device, lidb_host); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + lid[i].read(Base::m_fid); + lidb[i].read(Base::m_fid); + altd[i].read(Base::m_fid); + altcd[i].read(Base::m_fid); + } + } + // Run the lookup from a kernel and copy results back to host view_2d int_results("int results", 5, max_pack_size); view_2d real_results("real results", 7, max_pack_size); @@ -270,15 +272,14 @@ struct UnitWrap::UnitTest::TestTableIce { Kokkos::deep_copy(real_results_mirror, real_results); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for(int s = 0; s < max_pack_size; ++s) { - // +1 for O vs 1-based indexing - REQUIRE(int_results_mirror(0, s)+1 == lid[s].dumi); - REQUIRE(int_results_mirror(1, s)+1 == lid[s].dumjj); - REQUIRE(int_results_mirror(2, s)+1 == lid[s].dumii); - REQUIRE(int_results_mirror(3, s)+1 == lid[s].dumzz); + REQUIRE(int_results_mirror(0, s) == lid[s].dumi); + REQUIRE(int_results_mirror(1, s) == lid[s].dumjj); + REQUIRE(int_results_mirror(2, s) == lid[s].dumii); + REQUIRE(int_results_mirror(3, s) == lid[s].dumzz); - REQUIRE(int_results_mirror(4, s)+1 == lidb[s].dumj); + REQUIRE(int_results_mirror(4, s) == lidb[s].dumj); REQUIRE(real_results_mirror(0, s) == lid[s].dum1); REQUIRE(real_results_mirror(1, s) == lid[s].dum4); @@ -292,9 +293,35 @@ struct UnitWrap::UnitTest::TestTableIce { REQUIRE(real_results_mirror(6, s) == altcd[s].proc); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + lid[s].dumi = int_results_mirror(0, s); + lid[s].dumjj = int_results_mirror(1, s); + lid[s].dumii = int_results_mirror(2, s); + lid[s].dumzz = int_results_mirror(3, s); + + lidb[s].dumj = int_results_mirror(4, s); + + lid[s].dum1 = real_results_mirror(0, s); + lid[s].dum4 = real_results_mirror(1, s); + lid[s].dum5 = real_results_mirror(2, s); + lid[s].dum6 = real_results_mirror(3, s); + + lidb[s].dum3 = real_results_mirror(4, s); + + altd[s].proc = real_results_mirror(5, s); + + altcd[s].proc = real_results_mirror(6, s); + + lid[s].write(Base::m_fid); + lidb[s].write(Base::m_fid); + altd[s].write(Base::m_fid); + altcd[s].write(Base::m_fid); + } + } } - static void run_phys() + void run_phys() { #if 0 view_ice_table ice_table_vals; @@ -343,11 +370,12 @@ namespace { TEST_CASE("p3_ice_tables", "[p3_functions]") { - using TTI = scream::p3::unit_test::UnitWrap::UnitTest::TestTableIce; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestTableIce; - TTI::test_read_lookup_tables_bfb(); - TTI::run_phys(); - TTI::run_bfb(); + T t; + t.test_read_lookup_tables_bfb(); + t.run_phys(); + t.run_bfb(); } } diff --git a/components/eamxx/src/physics/p3/tests/p3_incloud_mixingratios_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_incloud_mixingratios_unit_tests.cpp index 4a405fcc7c43..eae1454c36a0 100644 --- a/components/eamxx/src/physics/p3/tests/p3_incloud_mixingratios_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_incloud_mixingratios_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,9 +19,9 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestIncloudMixing { +struct UnitWrap::UnitTest::TestIncloudMixing : public UnitWrap::UnitTest::Base { - static void run_incloud_mixing_bfb() + void run_incloud_mixing_bfb() { using KTH = KokkosTypes; @@ -69,9 +69,11 @@ struct UnitWrap::UnitTest::TestIncloudMixing { std::copy(&self[0], &self[0] + max_pack_size, self_host.data()); Kokkos::deep_copy(self_device, self_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - calculate_incloud_mixingratios(self[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + self[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -115,7 +117,7 @@ struct UnitWrap::UnitTest::TestIncloudMixing { Kokkos::deep_copy(self_host, self_device); - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(self[s].qc_incld == self_host(s).qc_incld); REQUIRE(self[s].qr_incld == self_host(s).qr_incld); @@ -127,9 +129,14 @@ struct UnitWrap::UnitTest::TestIncloudMixing { REQUIRE(self[s].bm_incld == self_host(s).bm_incld); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + self_host(s).write(Base::m_fid); + } + } } - static void run_incloud_mixing_phys() + void run_incloud_mixing_phys() { // TODO } @@ -143,10 +150,11 @@ namespace { TEST_CASE("p3_incloud_mixingratios", "[p3_functions]") { - using TD = scream::p3::unit_test::UnitWrap::UnitTest::TestIncloudMixing; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestIncloudMixing; - TD::run_incloud_mixing_phys(); - TD::run_incloud_mixing_bfb(); + T t; + t.run_incloud_mixing_phys(); + t.run_incloud_mixing_bfb(); } } diff --git a/components/eamxx/src/physics/p3/tests/p3_main_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_main_unit_tests.cpp index a804bd8756d5..4fb471c3cf5b 100644 --- a/components/eamxx/src/physics/p3/tests/p3_main_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_main_unit_tests.cpp @@ -4,8 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -19,29 +18,29 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestP3Main { +struct UnitWrap::UnitTest::TestP3Main : public UnitWrap::UnitTest::Base { -static void run_phys_p3_main_part1() +void run_phys_p3_main_part1() { // TODO } -static void run_phys_p3_main_part2() +void run_phys_p3_main_part2() { // TODO } -static void run_phys_p3_main_part3() +void run_phys_p3_main_part3() { // TODO } -static void run_phys_p3_main() +void run_phys_p3_main() { // TODO } -static void run_phys() +void run_phys() { run_phys_p3_main_part1(); run_phys_p3_main_part2(); @@ -49,9 +48,9 @@ static void run_phys() run_phys_p3_main(); } -static void run_bfb_p3_main_part1() +void run_bfb_p3_main_part1() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); constexpr Scalar qsmall = C::QSMALL; //PMC wouldn't it make more sense to define qsmall at a higher level since used in part1, part2, and part3? constexpr Scalar T_zerodegc = C::T_zerodegc; @@ -60,7 +59,7 @@ static void run_bfb_p3_main_part1() constexpr Scalar latvap = C::LatVap; constexpr Scalar latice = C::LatIce; - P3MainPart1Data isds_fortran[] = { + P3MainPart1Data isds_baseline[] = { // kts, kte, ktop, kbot, kdir, do_predict_nc, do_prescribed_CCN, dt P3MainPart1Data(1, 72, 1, 72, 1, false, true, 1.800E+03), P3MainPart1Data(1, 72, 1, 72, 1, true, true, 1.800E+03), @@ -68,9 +67,9 @@ static void run_bfb_p3_main_part1() P3MainPart1Data(1, 72, 72, 1, -1, true, false, 1.800E+03), }; - static constexpr Int num_runs = sizeof(isds_fortran) / sizeof(P3MainPart1Data); + static constexpr Int num_runs = sizeof(isds_baseline) / sizeof(P3MainPart1Data); - for (auto& d : isds_fortran) { + for (auto& d : isds_baseline) { const auto qsmall_r = std::make_pair(0, qsmall*2); //PMC this range seems inappropriately small d.randomize(engine, { {d.T_atm, {T_zerodegc - 10, T_zerodegc + 10}}, @@ -86,23 +85,25 @@ static void run_bfb_p3_main_part1() } } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state P3MainPart1Data isds_cxx[num_runs] = { - P3MainPart1Data(isds_fortran[0]), - P3MainPart1Data(isds_fortran[1]), - P3MainPart1Data(isds_fortran[2]), - P3MainPart1Data(isds_fortran[3]), + P3MainPart1Data(isds_baseline[0]), + P3MainPart1Data(isds_baseline[1]), + P3MainPart1Data(isds_baseline[2]), + P3MainPart1Data(isds_baseline[3]), }; - // Get data from fortran - for (auto& d : isds_fortran) { - p3_main_part1(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (auto& d : isds_baseline) { + d.read(Base::m_fid); + } } // Get data from cxx for (auto& d : isds_cxx) { - p3_main_part1_f(d.kts, d.kte, d.ktop, d.kbot, d.kdir, d.do_predict_nc, d.do_prescribed_CCN, d.dt, + p3_main_part1_host(d.kts, d.kte, d.ktop, d.kbot, d.kdir, d.do_predict_nc, d.do_prescribed_CCN, d.dt, d.pres, d.dpres, d.dz, d.nc_nuceat_tend, d.nccn_prescribed, d.inv_exner, d.exner, d.inv_cld_frac_l, d.inv_cld_frac_i, d.inv_cld_frac_r, d.T_atm, d.rho, d.inv_rho, d.qv_sat_l, d.qv_sat_i, d.qv_supersat_i, d.rhofacr, d.rhofaci, @@ -111,48 +112,53 @@ static void run_bfb_p3_main_part1() &d.is_nucleat_possible, &d.is_hydromet_present); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { - Int start = std::min(isds_fortran[i].kbot, isds_fortran[i].ktop) - 1; // 0-based indx - Int end = std::max(isds_fortran[i].kbot, isds_fortran[i].ktop); // 0-based indx + Int start = std::min(isds_baseline[i].kbot, isds_baseline[i].ktop) - 1; // 0-based indx + Int end = std::max(isds_baseline[i].kbot, isds_baseline[i].ktop); // 0-based indx for (Int k = start; k < end; ++k) { - REQUIRE(isds_fortran[i].T_atm[k] == isds_cxx[i].T_atm[k]); - REQUIRE(isds_fortran[i].rho[k] == isds_cxx[i].rho[k]); - REQUIRE(isds_fortran[i].inv_rho[k] == isds_cxx[i].inv_rho[k]); - REQUIRE(isds_fortran[i].qv_sat_l[k] == isds_cxx[i].qv_sat_l[k]); - REQUIRE(isds_fortran[i].qv_sat_i[k] == isds_cxx[i].qv_sat_i[k]); - REQUIRE(isds_fortran[i].qv_supersat_i[k] == isds_cxx[i].qv_supersat_i[k]); - REQUIRE(isds_fortran[i].rhofacr[k] == isds_cxx[i].rhofacr[k]); - REQUIRE(isds_fortran[i].rhofaci[k] == isds_cxx[i].rhofaci[k]); - REQUIRE(isds_fortran[i].acn[k] == isds_cxx[i].acn[k]); - REQUIRE(isds_fortran[i].qv[k] == isds_cxx[i].qv[k]); - REQUIRE(isds_fortran[i].th_atm[k] == isds_cxx[i].th_atm[k]); - REQUIRE(isds_fortran[i].qc[k] == isds_cxx[i].qc[k]); - REQUIRE(isds_fortran[i].nc[k] == isds_cxx[i].nc[k]); - REQUIRE(isds_fortran[i].qr[k] == isds_cxx[i].qr[k]); - REQUIRE(isds_fortran[i].nr[k] == isds_cxx[i].nr[k]); - REQUIRE(isds_fortran[i].qi[k] == isds_cxx[i].qi[k]); - REQUIRE(isds_fortran[i].ni[k] == isds_cxx[i].ni[k]); - REQUIRE(isds_fortran[i].qm[k] == isds_cxx[i].qm[k]); - REQUIRE(isds_fortran[i].bm[k] == isds_cxx[i].bm[k]); - REQUIRE(isds_fortran[i].qc_incld[k] == isds_cxx[i].qc_incld[k]); - REQUIRE(isds_fortran[i].qr_incld[k] == isds_cxx[i].qr_incld[k]); - REQUIRE(isds_fortran[i].qi_incld[k] == isds_cxx[i].qi_incld[k]); - REQUIRE(isds_fortran[i].qm_incld[k] == isds_cxx[i].qm_incld[k]); - REQUIRE(isds_fortran[i].nc_incld[k] == isds_cxx[i].nc_incld[k]); - REQUIRE(isds_fortran[i].nr_incld[k] == isds_cxx[i].nr_incld[k]); - REQUIRE(isds_fortran[i].ni_incld[k] == isds_cxx[i].ni_incld[k]); - REQUIRE(isds_fortran[i].bm_incld[k] == isds_cxx[i].bm_incld[k]); + REQUIRE(isds_baseline[i].T_atm[k] == isds_cxx[i].T_atm[k]); + REQUIRE(isds_baseline[i].rho[k] == isds_cxx[i].rho[k]); + REQUIRE(isds_baseline[i].inv_rho[k] == isds_cxx[i].inv_rho[k]); + REQUIRE(isds_baseline[i].qv_sat_l[k] == isds_cxx[i].qv_sat_l[k]); + REQUIRE(isds_baseline[i].qv_sat_i[k] == isds_cxx[i].qv_sat_i[k]); + REQUIRE(isds_baseline[i].qv_supersat_i[k] == isds_cxx[i].qv_supersat_i[k]); + REQUIRE(isds_baseline[i].rhofacr[k] == isds_cxx[i].rhofacr[k]); + REQUIRE(isds_baseline[i].rhofaci[k] == isds_cxx[i].rhofaci[k]); + REQUIRE(isds_baseline[i].acn[k] == isds_cxx[i].acn[k]); + REQUIRE(isds_baseline[i].qv[k] == isds_cxx[i].qv[k]); + REQUIRE(isds_baseline[i].th_atm[k] == isds_cxx[i].th_atm[k]); + REQUIRE(isds_baseline[i].qc[k] == isds_cxx[i].qc[k]); + REQUIRE(isds_baseline[i].nc[k] == isds_cxx[i].nc[k]); + REQUIRE(isds_baseline[i].qr[k] == isds_cxx[i].qr[k]); + REQUIRE(isds_baseline[i].nr[k] == isds_cxx[i].nr[k]); + REQUIRE(isds_baseline[i].qi[k] == isds_cxx[i].qi[k]); + REQUIRE(isds_baseline[i].ni[k] == isds_cxx[i].ni[k]); + REQUIRE(isds_baseline[i].qm[k] == isds_cxx[i].qm[k]); + REQUIRE(isds_baseline[i].bm[k] == isds_cxx[i].bm[k]); + REQUIRE(isds_baseline[i].qc_incld[k] == isds_cxx[i].qc_incld[k]); + REQUIRE(isds_baseline[i].qr_incld[k] == isds_cxx[i].qr_incld[k]); + REQUIRE(isds_baseline[i].qi_incld[k] == isds_cxx[i].qi_incld[k]); + REQUIRE(isds_baseline[i].qm_incld[k] == isds_cxx[i].qm_incld[k]); + REQUIRE(isds_baseline[i].nc_incld[k] == isds_cxx[i].nc_incld[k]); + REQUIRE(isds_baseline[i].nr_incld[k] == isds_cxx[i].nr_incld[k]); + REQUIRE(isds_baseline[i].ni_incld[k] == isds_cxx[i].ni_incld[k]); + REQUIRE(isds_baseline[i].bm_incld[k] == isds_cxx[i].bm_incld[k]); } - REQUIRE( isds_fortran[i].is_hydromet_present == isds_cxx[i].is_hydromet_present ); - REQUIRE( isds_fortran[i].is_nucleat_possible == isds_cxx[i].is_nucleat_possible ); + REQUIRE( isds_baseline[i].is_hydromet_present == isds_cxx[i].is_hydromet_present ); + REQUIRE( isds_baseline[i].is_nucleat_possible == isds_cxx[i].is_nucleat_possible ); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + isds_cxx[i].write(Base::m_fid); } } } -static void run_bfb_p3_main_part2() +void run_bfb_p3_main_part2() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); constexpr Scalar qsmall = C::QSMALL; constexpr Scalar T_zerodegc = C::T_zerodegc; @@ -161,7 +167,7 @@ static void run_bfb_p3_main_part2() constexpr Scalar latvap = C::LatVap; constexpr Scalar latice = C::LatIce; - P3MainPart2Data isds_fortran[] = { + P3MainPart2Data isds_baseline[] = { // kts, kte, ktop, kbot, kdir, do_predict_nc, do_prescribed_CCN, dt P3MainPart2Data(1, 72, 1, 72, 1, false, true, 1.800E+03), P3MainPart2Data(1, 72, 1, 72, 1, true, true, 1.800E+03), @@ -169,9 +175,9 @@ static void run_bfb_p3_main_part2() P3MainPart2Data(1, 72, 72, 1, -1, true, false, 1.800E+03), }; - static constexpr Int num_runs = sizeof(isds_fortran) / sizeof(P3MainPart2Data); + static constexpr Int num_runs = sizeof(isds_baseline) / sizeof(P3MainPart2Data); - for (auto& d : isds_fortran) { + for (auto& d : isds_baseline) { const auto qsmall_r = std::make_pair(0, qsmall*2); d.randomize(engine, { {d.T_atm, {T_zerodegc - 10, T_zerodegc + 10}}, @@ -188,23 +194,25 @@ static void run_bfb_p3_main_part2() } } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state P3MainPart2Data isds_cxx[num_runs] = { - P3MainPart2Data(isds_fortran[0]), - P3MainPart2Data(isds_fortran[1]), - P3MainPart2Data(isds_fortran[2]), - P3MainPart2Data(isds_fortran[3]), + P3MainPart2Data(isds_baseline[0]), + P3MainPart2Data(isds_baseline[1]), + P3MainPart2Data(isds_baseline[2]), + P3MainPart2Data(isds_baseline[3]), }; - // Get data from fortran - for (auto& d : isds_fortran) { - p3_main_part2(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (auto& d : isds_baseline) { + d.read(Base::m_fid); + } } // Get data from cxx for (auto& d : isds_cxx) { - p3_main_part2_f( + p3_main_part2_host( d.kts, d.kte, d.kbot, d.ktop, d.kdir, d.do_predict_nc, d.do_prescribed_CCN, d.dt, d.inv_dt, d.pres, d.dpres, d.dz, d.nc_nuceat_tend, d.inv_exner, d.exner, d.inv_cld_frac_l, d.inv_cld_frac_i, d.inv_cld_frac_r, d.ni_activated, d.inv_qc_relvar, d.cld_frac_i, d.cld_frac_l, d.cld_frac_r, d.qv_prev, d.t_prev, @@ -215,75 +223,80 @@ static void run_bfb_p3_main_part2() d.prctot, &d.is_hydromet_present); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { - Int start = std::min(isds_fortran[i].kbot, isds_fortran[i].ktop) - 1; // 0-based indx - Int end = std::max(isds_fortran[i].kbot, isds_fortran[i].ktop); // 0-based indx + Int start = std::min(isds_baseline[i].kbot, isds_baseline[i].ktop) - 1; // 0-based indx + Int end = std::max(isds_baseline[i].kbot, isds_baseline[i].ktop); // 0-based indx for (Int k = start; k < end; ++k) { - REQUIRE(isds_fortran[i].T_atm[k] == isds_cxx[i].T_atm[k]); - REQUIRE(isds_fortran[i].rho[k] == isds_cxx[i].rho[k]); - REQUIRE(isds_fortran[i].inv_rho[k] == isds_cxx[i].inv_rho[k]); - REQUIRE(isds_fortran[i].qv_sat_l[k] == isds_cxx[i].qv_sat_l[k]); - REQUIRE(isds_fortran[i].qv_sat_i[k] == isds_cxx[i].qv_sat_i[k]); - REQUIRE(isds_fortran[i].qv_supersat_i[k] == isds_cxx[i].qv_supersat_i[k]); - REQUIRE(isds_fortran[i].rhofacr[k] == isds_cxx[i].rhofacr[k]); - REQUIRE(isds_fortran[i].rhofaci[k] == isds_cxx[i].rhofaci[k]); - REQUIRE(isds_fortran[i].acn[k] == isds_cxx[i].acn[k]); - REQUIRE(isds_fortran[i].qv[k] == isds_cxx[i].qv[k]); - REQUIRE(isds_fortran[i].th_atm[k] == isds_cxx[i].th_atm[k]); - REQUIRE(isds_fortran[i].qc[k] == isds_cxx[i].qc[k]); - REQUIRE(isds_fortran[i].nc[k] == isds_cxx[i].nc[k]); - REQUIRE(isds_fortran[i].qr[k] == isds_cxx[i].qr[k]); - REQUIRE(isds_fortran[i].nr[k] == isds_cxx[i].nr[k]); - REQUIRE(isds_fortran[i].qi[k] == isds_cxx[i].qi[k]); - REQUIRE(isds_fortran[i].ni[k] == isds_cxx[i].ni[k]); - REQUIRE(isds_fortran[i].qm[k] == isds_cxx[i].qm[k]); - REQUIRE(isds_fortran[i].bm[k] == isds_cxx[i].bm[k]); - REQUIRE(isds_fortran[i].latent_heat_vapor[k] == latvap); - REQUIRE(isds_fortran[i].latent_heat_sublim[k] == (latvap+latice)); - REQUIRE(isds_fortran[i].latent_heat_fusion[k] == latice); - REQUIRE(isds_fortran[i].qc_incld[k] == isds_cxx[i].qc_incld[k]); - REQUIRE(isds_fortran[i].qr_incld[k] == isds_cxx[i].qr_incld[k]); - REQUIRE(isds_fortran[i].qi_incld[k] == isds_cxx[i].qi_incld[k]); - REQUIRE(isds_fortran[i].qm_incld[k] == isds_cxx[i].qm_incld[k]); - REQUIRE(isds_fortran[i].nc_incld[k] == isds_cxx[i].nc_incld[k]); - REQUIRE(isds_fortran[i].nr_incld[k] == isds_cxx[i].nr_incld[k]); - REQUIRE(isds_fortran[i].ni_incld[k] == isds_cxx[i].ni_incld[k]); - REQUIRE(isds_fortran[i].bm_incld[k] == isds_cxx[i].bm_incld[k]); - REQUIRE(isds_fortran[i].mu_c[k] == isds_cxx[i].mu_c[k]); - REQUIRE(isds_fortran[i].nu[k] == isds_cxx[i].nu[k]); - REQUIRE(isds_fortran[i].lamc[k] == isds_cxx[i].lamc[k]); - REQUIRE(isds_fortran[i].cdist[k] == isds_cxx[i].cdist[k]); - REQUIRE(isds_fortran[i].cdist1[k] == isds_cxx[i].cdist1[k]); - REQUIRE(isds_fortran[i].cdistr[k] == isds_cxx[i].cdistr[k]); - REQUIRE(isds_fortran[i].mu_r[k] == isds_cxx[i].mu_r[k]); - REQUIRE(isds_fortran[i].lamr[k] == isds_cxx[i].lamr[k]); - REQUIRE(isds_fortran[i].logn0r[k] == isds_cxx[i].logn0r[k]); - REQUIRE(isds_fortran[i].qv2qi_depos_tend[k] == isds_cxx[i].qv2qi_depos_tend[k]); - REQUIRE(isds_fortran[i].precip_total_tend[k] == isds_cxx[i].precip_total_tend[k]); - REQUIRE(isds_fortran[i].nevapr[k] == isds_cxx[i].nevapr[k]); - REQUIRE(isds_fortran[i].qr_evap_tend[k] == isds_cxx[i].qr_evap_tend[k]); - REQUIRE(isds_fortran[i].vap_liq_exchange[k] == isds_cxx[i].vap_liq_exchange[k]); - REQUIRE(isds_fortran[i].vap_ice_exchange[k] == isds_cxx[i].vap_ice_exchange[k]); - REQUIRE(isds_fortran[i].liq_ice_exchange[k] == isds_cxx[i].liq_ice_exchange[k]); - REQUIRE(isds_fortran[i].pratot[k] == isds_cxx[i].pratot[k]); - REQUIRE(isds_fortran[i].prctot[k] == isds_cxx[i].prctot[k]); + REQUIRE(isds_baseline[i].T_atm[k] == isds_cxx[i].T_atm[k]); + REQUIRE(isds_baseline[i].rho[k] == isds_cxx[i].rho[k]); + REQUIRE(isds_baseline[i].inv_rho[k] == isds_cxx[i].inv_rho[k]); + REQUIRE(isds_baseline[i].qv_sat_l[k] == isds_cxx[i].qv_sat_l[k]); + REQUIRE(isds_baseline[i].qv_sat_i[k] == isds_cxx[i].qv_sat_i[k]); + REQUIRE(isds_baseline[i].qv_supersat_i[k] == isds_cxx[i].qv_supersat_i[k]); + REQUIRE(isds_baseline[i].rhofacr[k] == isds_cxx[i].rhofacr[k]); + REQUIRE(isds_baseline[i].rhofaci[k] == isds_cxx[i].rhofaci[k]); + REQUIRE(isds_baseline[i].acn[k] == isds_cxx[i].acn[k]); + REQUIRE(isds_baseline[i].qv[k] == isds_cxx[i].qv[k]); + REQUIRE(isds_baseline[i].th_atm[k] == isds_cxx[i].th_atm[k]); + REQUIRE(isds_baseline[i].qc[k] == isds_cxx[i].qc[k]); + REQUIRE(isds_baseline[i].nc[k] == isds_cxx[i].nc[k]); + REQUIRE(isds_baseline[i].qr[k] == isds_cxx[i].qr[k]); + REQUIRE(isds_baseline[i].nr[k] == isds_cxx[i].nr[k]); + REQUIRE(isds_baseline[i].qi[k] == isds_cxx[i].qi[k]); + REQUIRE(isds_baseline[i].ni[k] == isds_cxx[i].ni[k]); + REQUIRE(isds_baseline[i].qm[k] == isds_cxx[i].qm[k]); + REQUIRE(isds_baseline[i].bm[k] == isds_cxx[i].bm[k]); + REQUIRE(isds_baseline[i].latent_heat_vapor[k] == latvap); + REQUIRE(isds_baseline[i].latent_heat_sublim[k] == (latvap+latice)); + REQUIRE(isds_baseline[i].latent_heat_fusion[k] == latice); + REQUIRE(isds_baseline[i].qc_incld[k] == isds_cxx[i].qc_incld[k]); + REQUIRE(isds_baseline[i].qr_incld[k] == isds_cxx[i].qr_incld[k]); + REQUIRE(isds_baseline[i].qi_incld[k] == isds_cxx[i].qi_incld[k]); + REQUIRE(isds_baseline[i].qm_incld[k] == isds_cxx[i].qm_incld[k]); + REQUIRE(isds_baseline[i].nc_incld[k] == isds_cxx[i].nc_incld[k]); + REQUIRE(isds_baseline[i].nr_incld[k] == isds_cxx[i].nr_incld[k]); + REQUIRE(isds_baseline[i].ni_incld[k] == isds_cxx[i].ni_incld[k]); + REQUIRE(isds_baseline[i].bm_incld[k] == isds_cxx[i].bm_incld[k]); + REQUIRE(isds_baseline[i].mu_c[k] == isds_cxx[i].mu_c[k]); + REQUIRE(isds_baseline[i].nu[k] == isds_cxx[i].nu[k]); + REQUIRE(isds_baseline[i].lamc[k] == isds_cxx[i].lamc[k]); + REQUIRE(isds_baseline[i].cdist[k] == isds_cxx[i].cdist[k]); + REQUIRE(isds_baseline[i].cdist1[k] == isds_cxx[i].cdist1[k]); + REQUIRE(isds_baseline[i].cdistr[k] == isds_cxx[i].cdistr[k]); + REQUIRE(isds_baseline[i].mu_r[k] == isds_cxx[i].mu_r[k]); + REQUIRE(isds_baseline[i].lamr[k] == isds_cxx[i].lamr[k]); + REQUIRE(isds_baseline[i].logn0r[k] == isds_cxx[i].logn0r[k]); + REQUIRE(isds_baseline[i].qv2qi_depos_tend[k] == isds_cxx[i].qv2qi_depos_tend[k]); + REQUIRE(isds_baseline[i].precip_total_tend[k] == isds_cxx[i].precip_total_tend[k]); + REQUIRE(isds_baseline[i].nevapr[k] == isds_cxx[i].nevapr[k]); + REQUIRE(isds_baseline[i].qr_evap_tend[k] == isds_cxx[i].qr_evap_tend[k]); + REQUIRE(isds_baseline[i].vap_liq_exchange[k] == isds_cxx[i].vap_liq_exchange[k]); + REQUIRE(isds_baseline[i].vap_ice_exchange[k] == isds_cxx[i].vap_ice_exchange[k]); + REQUIRE(isds_baseline[i].liq_ice_exchange[k] == isds_cxx[i].liq_ice_exchange[k]); + REQUIRE(isds_baseline[i].pratot[k] == isds_cxx[i].pratot[k]); + REQUIRE(isds_baseline[i].prctot[k] == isds_cxx[i].prctot[k]); } - REQUIRE( isds_fortran[i].is_hydromet_present == isds_cxx[i].is_hydromet_present ); + REQUIRE( isds_baseline[i].is_hydromet_present == isds_cxx[i].is_hydromet_present ); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + isds_cxx[i].write(Base::m_fid); } } } -static void run_bfb_p3_main_part3() +void run_bfb_p3_main_part3() { constexpr Scalar latvap = C::LatVap; constexpr Scalar latice = C::LatIce; - auto engine = setup_random_test(); + auto engine = Base::get_engine(); constexpr Scalar qsmall = C::QSMALL; - P3MainPart3Data isds_fortran[] = { + P3MainPart3Data isds_baseline[] = { // kts, kte, ktop, kbot, kdir P3MainPart3Data(1, 72, 1, 72, 1), P3MainPart3Data(1, 72, 1, 72, 1), @@ -291,9 +304,9 @@ static void run_bfb_p3_main_part3() P3MainPart3Data(1, 72, 72, 1, -1), }; - static constexpr Int num_runs = sizeof(isds_fortran) / sizeof(P3MainPart3Data); + static constexpr Int num_runs = sizeof(isds_baseline) / sizeof(P3MainPart3Data); - for (auto& d : isds_fortran) { + for (auto& d : isds_baseline) { const auto qsmall_r = std::make_pair(0, qsmall*2); d.randomize(engine, { {d.qc, qsmall_r}, {d.qr, qsmall_r}, {d.qi, qsmall_r} }); @@ -305,23 +318,25 @@ static void run_bfb_p3_main_part3() } } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state P3MainPart3Data isds_cxx[num_runs] = { - P3MainPart3Data(isds_fortran[0]), - P3MainPart3Data(isds_fortran[1]), - P3MainPart3Data(isds_fortran[2]), - P3MainPart3Data(isds_fortran[3]), + P3MainPart3Data(isds_baseline[0]), + P3MainPart3Data(isds_baseline[1]), + P3MainPart3Data(isds_baseline[2]), + P3MainPart3Data(isds_baseline[3]), }; - // Get data from fortran - for (auto& d : isds_fortran) { - p3_main_part3(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (auto& d : isds_baseline) { + d.read(Base::m_fid); + } } // Get data from cxx for (auto& d : isds_cxx) { - p3_main_part3_f( + p3_main_part3_host( d.kts, d.kte, d.kbot, d.ktop, d.kdir, d.inv_exner, d.cld_frac_l, d.cld_frac_r, d.cld_frac_i, d.rho, d.inv_rho, d.rhofaci, d.qv, d.th_atm, d.qc, d.nc, d.qr, d.nr, d.qi, d.ni, d.qm, d.bm, @@ -329,59 +344,64 @@ static void run_bfb_p3_main_part3() d. ze_rain, d.ze_ice, d.diag_vm_qi, d.diag_eff_radius_qi, d.diag_diam_qi, d.rho_qi, d.diag_equiv_reflectivity, d.diag_eff_radius_qc, d.diag_eff_radius_qr); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { - Int start = std::min(isds_fortran[i].kbot, isds_fortran[i].ktop) - 1; // 0-based indx - Int end = std::max(isds_fortran[i].kbot, isds_fortran[i].ktop); // 0-based indx + Int start = std::min(isds_baseline[i].kbot, isds_baseline[i].ktop) - 1; // 0-based indx + Int end = std::max(isds_baseline[i].kbot, isds_baseline[i].ktop); // 0-based indx for (Int k = start; k < end; ++k) { - REQUIRE(isds_fortran[i].rho[k] == isds_cxx[i].rho[k]); - REQUIRE(isds_fortran[i].inv_rho[k] == isds_cxx[i].inv_rho[k]); - REQUIRE(isds_fortran[i].rhofaci[k] == isds_cxx[i].rhofaci[k]); - REQUIRE(isds_fortran[i].qv[k] == isds_cxx[i].qv[k]); - REQUIRE(isds_fortran[i].th_atm[k] == isds_cxx[i].th_atm[k]); - REQUIRE(isds_fortran[i].qc[k] == isds_cxx[i].qc[k]); - REQUIRE(isds_fortran[i].nc[k] == isds_cxx[i].nc[k]); - REQUIRE(isds_fortran[i].qr[k] == isds_cxx[i].qr[k]); - REQUIRE(isds_fortran[i].nr[k] == isds_cxx[i].nr[k]); - REQUIRE(isds_fortran[i].qi[k] == isds_cxx[i].qi[k]); - REQUIRE(isds_fortran[i].ni[k] == isds_cxx[i].ni[k]); - REQUIRE(isds_fortran[i].qm[k] == isds_cxx[i].qm[k]); - REQUIRE(isds_fortran[i].bm[k] == isds_cxx[i].bm[k]); - REQUIRE(isds_fortran[i].latent_heat_vapor[k] == latvap); - REQUIRE(isds_fortran[i].latent_heat_sublim[k] == latvap+latice); - REQUIRE(isds_fortran[i].mu_c[k] == isds_cxx[i].mu_c[k]); - REQUIRE(isds_fortran[i].nu[k] == isds_cxx[i].nu[k]); - REQUIRE(isds_fortran[i].lamc[k] == isds_cxx[i].lamc[k]); - REQUIRE(isds_fortran[i].mu_r[k] == isds_cxx[i].mu_r[k]); - REQUIRE(isds_fortran[i].lamr[k] == isds_cxx[i].lamr[k]); - REQUIRE(isds_fortran[i].vap_liq_exchange[k] == isds_cxx[i].vap_liq_exchange[k]); - REQUIRE(isds_fortran[i].ze_rain[k] == isds_cxx[i].ze_rain[k]); - REQUIRE(isds_fortran[i].ze_ice[k] == isds_cxx[i].ze_ice[k]); - REQUIRE(isds_fortran[i].diag_vm_qi[k] == isds_cxx[i].diag_vm_qi[k]); - REQUIRE(isds_fortran[i].diag_eff_radius_qi[k] == isds_cxx[i].diag_eff_radius_qi[k]); - REQUIRE(isds_fortran[i].diag_diam_qi[k] == isds_cxx[i].diag_diam_qi[k]); - REQUIRE(isds_fortran[i].rho_qi[k] == isds_cxx[i].rho_qi[k]); - REQUIRE(isds_fortran[i].diag_equiv_reflectivity[k] == isds_cxx[i].diag_equiv_reflectivity[k]); - REQUIRE(isds_fortran[i].diag_eff_radius_qc[k] == isds_cxx[i].diag_eff_radius_qc[k]); - REQUIRE(isds_fortran[i].diag_eff_radius_qr[k] == isds_cxx[i].diag_eff_radius_qr[k]); + REQUIRE(isds_baseline[i].rho[k] == isds_cxx[i].rho[k]); + REQUIRE(isds_baseline[i].inv_rho[k] == isds_cxx[i].inv_rho[k]); + REQUIRE(isds_baseline[i].rhofaci[k] == isds_cxx[i].rhofaci[k]); + REQUIRE(isds_baseline[i].qv[k] == isds_cxx[i].qv[k]); + REQUIRE(isds_baseline[i].th_atm[k] == isds_cxx[i].th_atm[k]); + REQUIRE(isds_baseline[i].qc[k] == isds_cxx[i].qc[k]); + REQUIRE(isds_baseline[i].nc[k] == isds_cxx[i].nc[k]); + REQUIRE(isds_baseline[i].qr[k] == isds_cxx[i].qr[k]); + REQUIRE(isds_baseline[i].nr[k] == isds_cxx[i].nr[k]); + REQUIRE(isds_baseline[i].qi[k] == isds_cxx[i].qi[k]); + REQUIRE(isds_baseline[i].ni[k] == isds_cxx[i].ni[k]); + REQUIRE(isds_baseline[i].qm[k] == isds_cxx[i].qm[k]); + REQUIRE(isds_baseline[i].bm[k] == isds_cxx[i].bm[k]); + REQUIRE(isds_baseline[i].latent_heat_vapor[k] == latvap); + REQUIRE(isds_baseline[i].latent_heat_sublim[k] == latvap+latice); + REQUIRE(isds_baseline[i].mu_c[k] == isds_cxx[i].mu_c[k]); + REQUIRE(isds_baseline[i].nu[k] == isds_cxx[i].nu[k]); + REQUIRE(isds_baseline[i].lamc[k] == isds_cxx[i].lamc[k]); + REQUIRE(isds_baseline[i].mu_r[k] == isds_cxx[i].mu_r[k]); + REQUIRE(isds_baseline[i].lamr[k] == isds_cxx[i].lamr[k]); + REQUIRE(isds_baseline[i].vap_liq_exchange[k] == isds_cxx[i].vap_liq_exchange[k]); + REQUIRE(isds_baseline[i].ze_rain[k] == isds_cxx[i].ze_rain[k]); + REQUIRE(isds_baseline[i].ze_ice[k] == isds_cxx[i].ze_ice[k]); + REQUIRE(isds_baseline[i].diag_vm_qi[k] == isds_cxx[i].diag_vm_qi[k]); + REQUIRE(isds_baseline[i].diag_eff_radius_qi[k] == isds_cxx[i].diag_eff_radius_qi[k]); + REQUIRE(isds_baseline[i].diag_diam_qi[k] == isds_cxx[i].diag_diam_qi[k]); + REQUIRE(isds_baseline[i].rho_qi[k] == isds_cxx[i].rho_qi[k]); + REQUIRE(isds_baseline[i].diag_equiv_reflectivity[k] == isds_cxx[i].diag_equiv_reflectivity[k]); + REQUIRE(isds_baseline[i].diag_eff_radius_qc[k] == isds_cxx[i].diag_eff_radius_qc[k]); + REQUIRE(isds_baseline[i].diag_eff_radius_qr[k] == isds_cxx[i].diag_eff_radius_qr[k]); } } } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + isds_cxx[i].write(Base::m_fid); + } + } } -static void run_bfb_p3_main() +void run_bfb_p3_main() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); - P3MainData isds_fortran[] = { + P3MainData isds_baseline[] = { // its, ite, kts, kte, it, dt, do_predict_nc, do_prescribed_CCN P3MainData(1, 10, 1, 72, 1, 1.800E+03, false, true), P3MainData(1, 10, 1, 72, 1, 1.800E+03, true, false), }; - static constexpr Int num_runs = sizeof(isds_fortran) / sizeof(P3MainData); + static constexpr Int num_runs = sizeof(isds_baseline) / sizeof(P3MainData); - for (auto& d : isds_fortran) { + for (auto& d : isds_baseline) { d.randomize(engine, { {d.pres , {1.00000000E+02 , 9.87111111E+04}}, {d.dz , {1.22776609E+02 , 3.49039167E+04}}, @@ -409,22 +429,24 @@ static void run_bfb_p3_main() }); } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state P3MainData isds_cxx[num_runs] = { - P3MainData(isds_fortran[0]), - P3MainData(isds_fortran[1]), + P3MainData(isds_baseline[0]), + P3MainData(isds_baseline[1]), }; - // Get data from fortran - for (auto& d : isds_fortran) { - p3_main(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (auto& d : isds_baseline) { + d.read(Base::m_fid); + } } // Get data from cxx for (auto& d : isds_cxx) { d.template transpose(); - p3_main_f( + p3_main_host( d.qc, d.nc, d.qr, d.nr, d.th_atm, d.qv, d.dt, d.qi, d.qm, d.ni, d.bm, d.pres, d.dz, d.nc_nuceat_tend, d.nccn_prescribed, d.ni_activated, d.inv_qc_relvar, d.it, d.precip_liq_surf, d.precip_ice_surf, d.its, d.ite, d.kts, d.kte, d.diag_eff_radius_qc, d.diag_eff_radius_qi, d.diag_eff_radius_qr, @@ -434,11 +456,11 @@ static void run_bfb_p3_main() d.template transpose(); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { - const auto& df90 = isds_fortran[i]; - const auto& dcxx = isds_fortran[i]; - const auto tot = isds_fortran[i].total(df90.qc); + const auto& df90 = isds_baseline[i]; + const auto& dcxx = isds_baseline[i]; + const auto tot = isds_baseline[i].total(df90.qc); for (Int t = 0; t < tot; ++t) { REQUIRE(df90.qc[t] == dcxx.qc[t]); REQUIRE(df90.nc[t] == dcxx.nc[t]); @@ -474,9 +496,14 @@ static void run_bfb_p3_main() REQUIRE(df90.precip_ice_surf[tot] == dcxx.precip_ice_surf[tot]); } } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + isds_cxx[i].write(Base::m_fid); + } + } } -static void run_bfb() +void run_bfb() { run_bfb_p3_main_part1(); run_bfb_p3_main_part2(); @@ -494,12 +521,11 @@ namespace { TEST_CASE("p3_main", "[p3_functions]") { - using TP3 = scream::p3::unit_test::UnitWrap::UnitTest::TestP3Main; - - TP3::run_phys(); - TP3::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestP3Main; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_nc_conservation_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_nc_conservation_tests.cpp index ffe7ea504e13..175247bb501d 100644 --- a/components/eamxx/src/physics/p3/tests/p3_nc_conservation_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_nc_conservation_tests.cpp @@ -4,8 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -14,31 +13,33 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestNcConservation { +struct UnitWrap::UnitTest::TestNcConservation : public UnitWrap::UnitTest::Base { - static void run_bfb() + void run_bfb() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); - NcConservationData f90_data[max_pack_size]; + NcConservationData baseline_data[max_pack_size]; // Generate random input data - // Alternatively, you can use the f90_data construtors/initializer lists to hardcode data - for (auto& d : f90_data) { + // Alternatively, you can use the baseline_data construtors/initializer lists to hardcode data + for (auto& d : baseline_data) { d.randomize(engine); - d.dt = f90_data[0].dt; // Hold this fixed, this is not packed data + d.dt = baseline_data[0].dt; // Hold this fixed, this is not packed data } - // Create copies of data for use by cxx and sync it to device. Needs to happen before fortran calls so that + // Create copies of data for use by cxx and sync it to device. Needs to happen before reads so that // inout data is in original state view_1d cxx_device("cxx_device", max_pack_size); const auto cxx_host = Kokkos::create_mirror_view(cxx_device); - std::copy(&f90_data[0], &f90_data[0] + max_pack_size, cxx_host.data()); + std::copy(&baseline_data[0], &baseline_data[0] + max_pack_size, cxx_host.data()); Kokkos::deep_copy(cxx_device, cxx_host); - // Get data from fortran - for (auto& d : f90_data) { - nc_conservation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + baseline_data[i].read(Base::m_fid); + } } // Get data from cxx. Run nc_conservation from a kernel and copy results back to host @@ -71,14 +72,19 @@ struct UnitWrap::UnitTest::TestNcConservation { Kokkos::deep_copy(cxx_host, cxx_device); // Verify BFB results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < max_pack_size; ++i) { - NcConservationData& d_f90 = f90_data[i]; + NcConservationData& d_baseline = baseline_data[i]; NcConservationData& d_cxx = cxx_host[i]; - REQUIRE(d_f90.nc_collect_tend == d_cxx.nc_collect_tend); - REQUIRE(d_f90.nc2ni_immers_freeze_tend == d_cxx.nc2ni_immers_freeze_tend); - REQUIRE(d_f90.nc_accret_tend == d_cxx.nc_accret_tend); - REQUIRE(d_f90.nc2nr_autoconv_tend == d_cxx.nc2nr_autoconv_tend); + REQUIRE(d_baseline.nc_collect_tend == d_cxx.nc_collect_tend); + REQUIRE(d_baseline.nc2ni_immers_freeze_tend == d_cxx.nc2ni_immers_freeze_tend); + REQUIRE(d_baseline.nc_accret_tend == d_cxx.nc_accret_tend); + REQUIRE(d_baseline.nc2nr_autoconv_tend == d_cxx.nc2nr_autoconv_tend); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cxx_host(s).write(Base::m_fid); } } } // run_bfb @@ -93,9 +99,10 @@ namespace { TEST_CASE("nc_conservation_bfb", "[p3]") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestNcConservation; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestNcConservation; - TestStruct::run_bfb(); + T t; + t.run_bfb(); } } // empty namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_ni_conservation_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_ni_conservation_tests.cpp index 3aa3428825cd..b8cfdf4333a1 100644 --- a/components/eamxx/src/physics/p3/tests/p3_ni_conservation_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_ni_conservation_tests.cpp @@ -4,8 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -14,31 +13,33 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestNiConservation { +struct UnitWrap::UnitTest::TestNiConservation : public UnitWrap::UnitTest::Base { - static void run_bfb() + void run_bfb() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); - NiConservationData f90_data[max_pack_size]; + NiConservationData baseline_data[max_pack_size]; // Generate random input data - // Alternatively, you can use the f90_data construtors/initializer lists to hardcode data - for (auto& d : f90_data) { + // Alternatively, you can use the baseline_data construtors/initializer lists to hardcode data + for (auto& d : baseline_data) { d.randomize(engine); - d.dt = f90_data[0].dt; // hold dt fixed, it is not packed data + d.dt = baseline_data[0].dt; // hold dt fixed, it is not packed data } - // Create copies of data for use by cxx and sync it to device. Needs to happen before fortran calls so that + // Create copies of data for use by cxx and sync it to device. Needs to happen before reads so that // inout data is in original state view_1d cxx_device("cxx_device", max_pack_size); const auto cxx_host = Kokkos::create_mirror_view(cxx_device); - std::copy(&f90_data[0], &f90_data[0] + max_pack_size, cxx_host.data()); + std::copy(&baseline_data[0], &baseline_data[0] + max_pack_size, cxx_host.data()); Kokkos::deep_copy(cxx_device, cxx_host); - // Get data from fortran - for (auto& d : f90_data) { - ni_conservation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + baseline_data[i].read(Base::m_fid); + } } // Get data from cxx. Run ni_conservation from a kernel and copy results back to host @@ -71,17 +72,21 @@ struct UnitWrap::UnitTest::TestNiConservation { Kokkos::deep_copy(cxx_host, cxx_device); // Verify BFB results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < max_pack_size; ++i) { - NiConservationData& d_f90 = f90_data[i]; + NiConservationData& d_baseline = baseline_data[i]; NiConservationData& d_cxx = cxx_host[i]; - REQUIRE(d_f90.ni2nr_melt_tend == d_cxx.ni2nr_melt_tend); - REQUIRE(d_f90.ni_sublim_tend == d_cxx.ni_sublim_tend); - REQUIRE(d_f90.ni_selfcollect_tend == d_cxx.ni_selfcollect_tend); + REQUIRE(d_baseline.ni2nr_melt_tend == d_cxx.ni2nr_melt_tend); + REQUIRE(d_baseline.ni_sublim_tend == d_cxx.ni_sublim_tend); + REQUIRE(d_baseline.ni_selfcollect_tend == d_cxx.ni_selfcollect_tend); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cxx_host(s).write(Base::m_fid); } } } // run_bfb - }; } // namespace unit_test @@ -92,9 +97,10 @@ namespace { TEST_CASE("ni_conservation_bfb", "[p3]") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestNiConservation; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestNiConservation; - TestStruct::run_bfb(); + T t; + t.run_bfb(); } } // empty namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_nr_conservation_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_nr_conservation_tests.cpp index fb9e1e758b42..dc9a44af88d0 100644 --- a/components/eamxx/src/physics/p3/tests/p3_nr_conservation_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_nr_conservation_tests.cpp @@ -4,8 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -14,32 +13,34 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestNrConservation { +struct UnitWrap::UnitTest::TestNrConservation : public UnitWrap::UnitTest::Base { - static void run_bfb() + void run_bfb() { - auto engine = setup_random_test(); + auto engine = Base::get_engine(); - NrConservationData f90_data[max_pack_size]; + NrConservationData baseline_data[max_pack_size]; // Generate random input data - // Alternatively, you can use the f90_data construtors/initializer lists to hardcode data - for (auto& d : f90_data) { + // Alternatively, you can use the baseline_data construtors/initializer lists to hardcode data + for (auto& d : baseline_data) { d.randomize(engine); - d.dt = f90_data[0].dt; // hold dt fixed, it is not packed data - d.nmltratio = f90_data[0].nmltratio; // hold nmltratio fixed, it is not packed data + d.dt = baseline_data[0].dt; // hold dt fixed, it is not packed data + d.nmltratio = baseline_data[0].nmltratio; // hold nmltratio fixed, it is not packed data } - // Create copies of data for use by cxx and sync it to device. Needs to happen before fortran calls so that + // Create copies of data for use by cxx and sync it to device. Needs to happen before reads so that // inout data is in original state view_1d cxx_device("cxx_device", max_pack_size); const auto cxx_host = Kokkos::create_mirror_view(cxx_device); - std::copy(&f90_data[0], &f90_data[0] + max_pack_size, cxx_host.data()); + std::copy(&baseline_data[0], &baseline_data[0] + max_pack_size, cxx_host.data()); Kokkos::deep_copy(cxx_device, cxx_host); - // Get data from fortran - for (auto& d : f90_data) { - nr_conservation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + baseline_data[i].read(Base::m_fid); + } } // Get data from cxx. Run nr_conservation from a kernel and copy results back to host @@ -75,14 +76,19 @@ struct UnitWrap::UnitTest::TestNrConservation { Kokkos::deep_copy(cxx_host, cxx_device); // Verify BFB results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < max_pack_size; ++i) { - NrConservationData& d_f90 = f90_data[i]; + NrConservationData& d_baseline = baseline_data[i]; NrConservationData& d_cxx = cxx_host[i]; - REQUIRE(d_f90.nr_collect_tend == d_cxx.nr_collect_tend); - REQUIRE(d_f90.nr2ni_immers_freeze_tend == d_cxx.nr2ni_immers_freeze_tend); - REQUIRE(d_f90.nr_selfcollect_tend == d_cxx.nr_selfcollect_tend); - REQUIRE(d_f90.nr_evap_tend == d_cxx.nr_evap_tend); + REQUIRE(d_baseline.nr_collect_tend == d_cxx.nr_collect_tend); + REQUIRE(d_baseline.nr2ni_immers_freeze_tend == d_cxx.nr2ni_immers_freeze_tend); + REQUIRE(d_baseline.nr_selfcollect_tend == d_cxx.nr_selfcollect_tend); + REQUIRE(d_baseline.nr_evap_tend == d_cxx.nr_evap_tend); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cxx_host(s).write(Base::m_fid); } } } // run_bfb @@ -97,9 +103,10 @@ namespace { TEST_CASE("nr_conservation_bfb", "[p3]") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestNrConservation; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestNrConservation; - TestStruct::run_bfb(); + T t; + t.run_bfb(); } } // empty namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_prevent_liq_supersaturation_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_prevent_liq_supersaturation_tests.cpp index a1b270562819..1b439aca7aac 100644 --- a/components/eamxx/src/physics/p3/tests/p3_prevent_liq_supersaturation_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_prevent_liq_supersaturation_tests.cpp @@ -3,8 +3,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" #include "share/scream_types.hpp" #include "physics/share/physics_functions.hpp" @@ -15,9 +14,9 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestPreventLiqSupersaturation { +struct UnitWrap::UnitTest::TestPreventLiqSupersaturation : public UnitWrap::UnitTest::Base { - static void run_property() + void run_property() //Conceptual tests for prevent_liq_supersaturation. Note many conceptual tests make sense to run on //random data, so are included in run_bfb rather than here. { @@ -88,32 +87,32 @@ struct UnitWrap::UnitTest::TestPreventLiqSupersaturation { } //end run_property - static void run_bfb() + void run_bfb() { constexpr Scalar latvap = C::LatVap; constexpr Scalar latice = C::LatIce; - auto engine = setup_random_test(); + auto engine = Base::get_engine(); - PreventLiqSupersaturationData f90_data[max_pack_size]; + PreventLiqSupersaturationData baseline_data[max_pack_size]; // Generate random input data - // Alternatively, you can use the f90_data construtors/initializer lists to hardcode data - for (auto& d : f90_data) { + // Alternatively, you can use the baseline_data construtors/initializer lists to hardcode data + for (auto& d : baseline_data) { d.randomize(engine); - d.dt = f90_data[0].dt; // Hold this fixed, this is not packed data + d.dt = baseline_data[0].dt; // Hold this fixed, this is not packed data // C++ impl uses constants for latent_heat values. Manually set here - // so F90 can match + // so BASELINE can match d.latent_heat_vapor = latvap; d.latent_heat_sublim = latvap+latice; } // Create copies of data for use by cxx and sync it to device. Needs to happen before - // fortran calls so that inout data is in original state + // reads so that inout data is in original state view_1d cxx_device("cxx_device", max_pack_size); const auto cxx_host = Kokkos::create_mirror_view(cxx_device); - std::copy(&f90_data[0], &f90_data[0] + max_pack_size, cxx_host.data()); + std::copy(&baseline_data[0], &baseline_data[0] + max_pack_size, cxx_host.data()); Kokkos::deep_copy(cxx_device, cxx_host); // Save copy of inout vars to check that prevent_liq_supersaturation always makes them smaller @@ -123,9 +122,11 @@ struct UnitWrap::UnitTest::TestPreventLiqSupersaturation { qr2qv_evap_tend_init[i] = cxx_host(i).qr2qv_evap_tend; } - // Get data from fortran - for (auto& d : f90_data) { - prevent_liq_supersaturation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + baseline_data[i].read(Base::m_fid); + } } // Get data from cxx. Run prevent_liq_supersaturation from a kernel and copy results back to host @@ -158,13 +159,13 @@ struct UnitWrap::UnitTest::TestPreventLiqSupersaturation { Kokkos::deep_copy(cxx_host, cxx_device); - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < max_pack_size; ++i) { // Verify BFB results - PreventLiqSupersaturationData& d_f90 = f90_data[i]; + PreventLiqSupersaturationData& d_baseline = baseline_data[i]; PreventLiqSupersaturationData& d_cxx = cxx_host[i]; - REQUIRE(d_f90.qi2qv_sublim_tend == d_cxx.qi2qv_sublim_tend); - REQUIRE(d_f90.qr2qv_evap_tend == d_cxx.qr2qv_evap_tend); + REQUIRE(d_baseline.qi2qv_sublim_tend == d_cxx.qi2qv_sublim_tend); + REQUIRE(d_baseline.qr2qv_evap_tend == d_cxx.qr2qv_evap_tend); //Verify tendencies are always >=0: REQUIRE(d_cxx.qi2qv_sublim_tend>=0); @@ -175,8 +176,12 @@ struct UnitWrap::UnitTest::TestPreventLiqSupersaturation { REQUIRE(d_cxx.qr2qv_evap_tend<=qr2qv_evap_tend_init[i]); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cxx_host(s).write(Base::m_fid); + } + } } // run_bfb - }; } // namespace unit_test @@ -187,14 +192,18 @@ namespace { TEST_CASE("prevent_liq_supersaturation_property", "[p3]") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestPreventLiqSupersaturation; - TestStruct::run_property(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestPreventLiqSupersaturation; + + T t; + t.run_property(); } TEST_CASE("prevent_liq_supersaturation_bfb", "[p3]") { - using TestStruct = scream::p3::unit_test::UnitWrap::UnitTest::TestPreventLiqSupersaturation; - TestStruct::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestPreventLiqSupersaturation; + + T t; + t.run_bfb(); } } // empty namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_rain_imm_freezing_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_rain_imm_freezing_unit_tests.cpp index ae142ae77ace..935842cb6d98 100644 --- a/components/eamxx/src/physics/p3/tests/p3_rain_imm_freezing_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_rain_imm_freezing_unit_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -18,14 +18,14 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestRainImmersionFreezing { +struct UnitWrap::UnitTest::TestRainImmersionFreezing : public UnitWrap::UnitTest::Base { -static void run_phys() +void run_phys() { // TODO } -static void run_bfb() +void run_bfb() { // This is the threshold for whether the qc and qr cloud mixing ratios are // large enough to affect the warm-phase process rates qc2qr_accret_tend and nc_accret_tend. @@ -69,9 +69,11 @@ static void run_bfb() host_data.data()); Kokkos::deep_copy(device_data, host_data); - // Run the Fortran subroutine. - for (Int i = 0; i < max_pack_size; ++i) { - rain_immersion_freezing(rain_imm_freezing_data[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + rain_imm_freezing_data[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -106,12 +108,17 @@ static void run_bfb() Kokkos::deep_copy(host_data, device_data); // Validate results. - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(rain_imm_freezing_data[s].qr2qi_immers_freeze_tend == host_data[s].qr2qi_immers_freeze_tend); REQUIRE(rain_imm_freezing_data[s].nr2ni_immers_freeze_tend == host_data[s].nr2ni_immers_freeze_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + host_data(s).write(Base::m_fid); + } + } } }; @@ -124,12 +131,11 @@ namespace { TEST_CASE("p3_rain_immersion_freezing", "[p3_functions]") { - using TRIF = scream::p3::unit_test::UnitWrap::UnitTest::TestRainImmersionFreezing; - - TRIF::run_phys(); - TRIF::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestRainImmersionFreezing; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_rain_sed_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_rain_sed_unit_tests.cpp index 443b3801404b..cd4d1955aede 100644 --- a/components/eamxx/src/physics/p3/tests/p3_rain_sed_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_rain_sed_unit_tests.cpp @@ -4,9 +4,8 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "p3_f90.hpp" -#include "share/util/scream_setup_random_test.hpp" +#include "p3_test_data.hpp" +#include "p3_data.hpp" #include "p3_unit_tests_common.hpp" @@ -20,25 +19,25 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestRainSed { +struct UnitWrap::UnitTest::TestRainSed : public UnitWrap::UnitTest::Base { -static void run_phys_rain_vel() +void run_phys_rain_vel() { // TODO } -static void run_phys_rain_sed() +void run_phys_rain_sed() { // TODO } -static void run_phys() +void run_phys() { run_phys_rain_vel(); run_phys_rain_sed(); } -static void run_bfb_rain_vel() +void run_bfb_rain_vel() { // Read in tables view_2d_table vn_table_vals; view_2d_table vm_table_vals; view_2d_table revap_table_vals; @@ -46,7 +45,7 @@ static void run_bfb_rain_vel() Functions::init_kokkos_tables(vn_table_vals, vm_table_vals, revap_table_vals, mu_r_table_vals, dnu); // Load some lookup inputs, need at least one per pack value - ComputeRainFallVelocityData crfv_fortran[max_pack_size] = { + ComputeRainFallVelocityData crfv_baseline[max_pack_size] = { // qr_incld, rhofacr, nr_incld {1.1030E-04, 1.3221E+00, 6.2964E+05}, {2.1437E-13, 1.0918E+00, 6.5337E+07}, @@ -70,16 +69,18 @@ static void run_bfb_rain_vel() }; - // Sync to device, needs to happen before fortran calls so that + // Sync to device, needs to happen before reads so that // inout data is in original state view_1d crfv_device("crfv", max_pack_size); const auto crfv_host = Kokkos::create_mirror_view(crfv_device); - std::copy(&crfv_fortran[0], &crfv_fortran[0] + max_pack_size, crfv_host.data()); + std::copy(&crfv_baseline[0], &crfv_baseline[0] + max_pack_size, crfv_host.data()); Kokkos::deep_copy(crfv_device, crfv_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - compute_rain_fall_velocity(crfv_fortran[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + crfv_baseline[i].read(Base::m_fid); + } } // Calc bulk rime from a kernel and copy results back to host @@ -112,21 +113,27 @@ static void run_bfb_rain_vel() // Sync back to host Kokkos::deep_copy(crfv_host, crfv_device); - // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { + // Validate results for (Int s = 0; s < max_pack_size; ++s) { - REQUIRE(crfv_fortran[s].nr_incld == crfv_host(s).nr_incld); - REQUIRE(crfv_fortran[s].mu_r == crfv_host(s).mu_r); - REQUIRE(crfv_fortran[s].lamr == crfv_host(s).lamr); - REQUIRE(crfv_fortran[s].V_qr == crfv_host(s).V_qr); - REQUIRE(crfv_fortran[s].V_nr == crfv_host(s).V_nr); + REQUIRE(crfv_baseline[s].nr_incld == crfv_host(s).nr_incld); + REQUIRE(crfv_baseline[s].mu_r == crfv_host(s).mu_r); + REQUIRE(crfv_baseline[s].lamr == crfv_host(s).lamr); + REQUIRE(crfv_baseline[s].V_qr == crfv_host(s).V_qr); + REQUIRE(crfv_baseline[s].V_nr == crfv_host(s).V_nr); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + crfv_host(s).write(Base::m_fid); } } } -static void run_bfb_rain_sed() +void run_bfb_rain_sed() { - auto engine = setup_random_test(); + // With stored baselines, we must use a fixed seed! + auto engine = Base::get_engine(); // F90 is quite slow on weaver, so we decrease dt to reduce // the number of steps in rain_sed. @@ -136,7 +143,7 @@ static void run_bfb_rain_sed() constexpr Scalar dt = 1.800E+03; #endif - RainSedData rsds_fortran[] = { + RainSedData rsds_baseline[] = { // kts, kte, ktop, kbot, kdir, dt, inv_dt, precip_liq_surf RainSedData(1, 72, 27, 72, -1, dt, 1/dt, 0.0), RainSedData(1, 72, 72, 27, 1, dt, 1/dt, 1.0), @@ -144,25 +151,27 @@ static void run_bfb_rain_sed() RainSedData(1, 72, 27, 27, 1, dt, 1/dt, 2.0), }; - static constexpr Int num_runs = sizeof(rsds_fortran) / sizeof(RainSedData); + static constexpr Int num_runs = sizeof(rsds_baseline) / sizeof(RainSedData); // Set up random input data - for (auto& d : rsds_fortran) { + for (auto& d : rsds_baseline) { d.randomize(engine, { {d.qr_incld, {C::QSMALL/2, C::QSMALL*2}} }); } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state RainSedData rsds_cxx[num_runs] = { - RainSedData(rsds_fortran[0]), - RainSedData(rsds_fortran[1]), - RainSedData(rsds_fortran[2]), - RainSedData(rsds_fortran[3]), + RainSedData(rsds_baseline[0]), + RainSedData(rsds_baseline[1]), + RainSedData(rsds_baseline[2]), + RainSedData(rsds_baseline[3]), }; - // Get data from fortran - for (auto& d : rsds_fortran) { - rain_sedimentation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (auto& d : rsds_baseline) { + d.read(Base::m_fid); + } } // Get data from cxx @@ -173,35 +182,40 @@ static void run_bfb_rain_sed() #if defined(SCREAM_FORCE_RUN_DIFF) inv_dt *= 2; #endif - rain_sedimentation_f(d.kts, d.kte, d.ktop, d.kbot, d.kdir, + rain_sedimentation_host(d.kts, d.kte, d.ktop, d.kbot, d.kdir, d.qr_incld, d.rho, d.inv_rho, d.rhofacr, d.cld_frac_r, d.inv_dz, d.dt, inv_dt, d.qr, d.nr, d.nr_incld, d.mu_r, d.lamr, &d.precip_liq_surf, d.precip_liq_flux, d.qr_tend, d.nr_tend); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { // Due to pack issues, we must restrict checks to the active k space - Int start = std::min(rsds_fortran[i].kbot, rsds_fortran[i].ktop) - 1; // 0-based indx - Int end = std::max(rsds_fortran[i].kbot, rsds_fortran[i].ktop); // 0-based indx + Int start = std::min(rsds_baseline[i].kbot, rsds_baseline[i].ktop) - 1; // 0-based indx + Int end = std::max(rsds_baseline[i].kbot, rsds_baseline[i].ktop); // 0-based indx for (Int k = start; k < end; ++k) { - REQUIRE(rsds_fortran[i].qr[k] == rsds_cxx[i].qr[k]); - REQUIRE(rsds_fortran[i].nr[k] == rsds_cxx[i].nr[k]); - REQUIRE(rsds_fortran[i].nr_incld[k] == rsds_cxx[i].nr_incld[k]); - REQUIRE(rsds_fortran[i].mu_r[k] == rsds_cxx[i].mu_r[k]); - REQUIRE(rsds_fortran[i].lamr[k] == rsds_cxx[i].lamr[k]); - REQUIRE(rsds_fortran[i].precip_liq_flux[k] == rsds_cxx[i].precip_liq_flux[k]); - REQUIRE(rsds_fortran[i].qr_tend[k] == rsds_cxx[i].qr_tend[k]); - REQUIRE(rsds_fortran[i].nr_tend[k] == rsds_cxx[i].nr_tend[k]); + REQUIRE(rsds_baseline[i].qr[k] == rsds_cxx[i].qr[k]); + REQUIRE(rsds_baseline[i].nr[k] == rsds_cxx[i].nr[k]); + REQUIRE(rsds_baseline[i].nr_incld[k] == rsds_cxx[i].nr_incld[k]); + REQUIRE(rsds_baseline[i].mu_r[k] == rsds_cxx[i].mu_r[k]); + REQUIRE(rsds_baseline[i].lamr[k] == rsds_cxx[i].lamr[k]); + REQUIRE(rsds_baseline[i].precip_liq_flux[k] == rsds_cxx[i].precip_liq_flux[k]); + REQUIRE(rsds_baseline[i].qr_tend[k] == rsds_cxx[i].qr_tend[k]); + REQUIRE(rsds_baseline[i].nr_tend[k] == rsds_cxx[i].nr_tend[k]); } - REQUIRE(rsds_fortran[i].precip_liq_flux[end] == rsds_cxx[i].precip_liq_flux[end]); - REQUIRE(rsds_fortran[i].precip_liq_surf == rsds_cxx[i].precip_liq_surf); + REQUIRE(rsds_baseline[i].precip_liq_flux[end] == rsds_cxx[i].precip_liq_flux[end]); + REQUIRE(rsds_baseline[i].precip_liq_surf == rsds_cxx[i].precip_liq_surf); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + rsds_cxx[i].write(Base::m_fid); } } } -static void run_bfb() +void run_bfb() { run_bfb_rain_vel(); run_bfb_rain_sed(); @@ -217,14 +231,11 @@ namespace { TEST_CASE("p3_rain_sed", "[p3_functions]") { - using TRS = scream::p3::unit_test::UnitWrap::UnitTest::TestRainSed; - - scream::p3::p3_init(); // need fortran table data - - TRS::run_phys(); - TRS::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestRainSed; - scream::p3::P3GlobalForFortran::deinit(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_rain_self_collection_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_rain_self_collection_tests.cpp index a8c0dbc07dd1..26440b6680bf 100644 --- a/components/eamxx/src/physics/p3/tests/p3_rain_self_collection_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_rain_self_collection_tests.cpp @@ -4,7 +4,7 @@ #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -22,9 +22,9 @@ namespace unit_test { * Unit-tests for p3 ice collection functions. */ template -struct UnitWrap::UnitTest::TestRainSelfCollection { +struct UnitWrap::UnitTest::TestRainSelfCollection : public UnitWrap::UnitTest::Base { - static void run_rain_self_collection_bfb_tests(){ + void run_rain_self_collection_bfb_tests() { RainSelfCollectionData dc[max_pack_size] = { // rho, qr_incld, nr_incld, nr_selfcollect_tend @@ -56,9 +56,11 @@ struct UnitWrap::UnitTest::TestRainSelfCollection { std::copy(&dc[0], &dc[0] + max_pack_size, dc_host.data()); Kokkos::deep_copy(dc_device, dc_host); - //Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - rain_self_collection(dc[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + dc[i].read(Base::m_fid); + } } //Run function from a kernal and copy results back to the host @@ -91,7 +93,7 @@ struct UnitWrap::UnitTest::TestRainSelfCollection { Kokkos::deep_copy(dc_host, dc_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(dc[s].rho == dc_host(s).rho); REQUIRE(dc[s].qr_incld == dc_host(s).qr_incld); @@ -99,9 +101,14 @@ struct UnitWrap::UnitTest::TestRainSelfCollection { REQUIRE(dc[s].nr_selfcollect_tend == dc_host(s).nr_selfcollect_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + dc_host(s).write(Base::m_fid); + } + } } - static void run_bfb(){ + void run_bfb() { run_rain_self_collection_bfb_tests(); } @@ -114,7 +121,10 @@ struct UnitWrap::UnitTest::TestRainSelfCollection { namespace { TEST_CASE("p3_rain_self_collection_test", "[p3_rain_self_collection_test"){ - scream::p3::unit_test::UnitWrap::UnitTest::TestRainSelfCollection::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestRainSelfCollection; + + T t; + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_run_and_cmp.cpp b/components/eamxx/src/physics/p3/tests/p3_run_and_cmp.cpp index ed252b5034c4..ff069032013f 100644 --- a/components/eamxx/src/physics/p3/tests/p3_run_and_cmp.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_run_and_cmp.cpp @@ -3,7 +3,7 @@ #include "share/util/scream_utils.hpp" #include "p3_main_wrap.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_ic_cases.hpp" #include "ekat/util/ekat_file_utils.hpp" @@ -16,6 +16,7 @@ namespace { using namespace scream; using namespace scream::p3; +using P3F = Functions; /* * p3_run_and_cmp can be run in 2 modes. First, generate_baseline @@ -35,10 +36,10 @@ using namespace scream::p3; * large discrepancies. */ Int compare (const double& tol, - const FortranData::Ptr& ref, const FortranData::Ptr& d) { + const P3Data::Ptr& ref, const P3Data::Ptr& d) { Int nerr = 0; - FortranDataIterator refi(ref), di(d); + P3DataIterator refi(ref), di(d); EKAT_ASSERT(refi.nfield() == di.nfield()); for (Int i = 0, n = refi.nfield(); i < n; ++i) { const auto& fr = refi.getfield(i); @@ -75,7 +76,7 @@ struct Baseline { } } - Int generate_baseline (const std::string& filename, bool use_fortran) { + Int generate_baseline (const std::string& filename) { auto fid = ekat::FILEPtr(fopen(filename.c_str(), "w")); EKAT_REQUIRE_MSG( fid, "generate_baseline can't write " << filename); Int nerr = 0; @@ -87,22 +88,19 @@ struct Baseline { for (Int r = -1; r < ps.repeat; ++r) { const auto d = ic::Factory::create(ps.ic, ps.ncol, ps.nlev); set_params(ps, *d); - p3_init(); + P3F::p3_init(); if (ps.repeat > 0 && r == -1) { std::cout << "Running P3 with ni=" << d->ncol << ", nk=" << d->nlev << ", dt=" << d->dt << ", ts=" << d->it << ", predict_nc=" << d->do_predict_nc - << ", prescribed_CCN=" << d->do_prescribed_CCN; - - if (!use_fortran) { - std::cout << ", small_packn=" << SCREAM_SMALL_PACK_SIZE; - } - std::cout << std::endl; + << ", prescribed_CCN=" << d->do_prescribed_CCN + << ", small_packn=" << SCREAM_SMALL_PACK_SIZE + << std::endl; } for (int it=0; it 0) { // do not count the "cold" run total_duration_microsec += current_microsec; @@ -123,29 +121,43 @@ struct Baseline { return nerr; } - Int run_and_cmp (const std::string& filename, const double& tol, bool use_fortran) { - auto fid = ekat::FILEPtr(fopen(filename.c_str(), "r")); - EKAT_REQUIRE_MSG( fid, "generate_baseline can't read " << filename); + Int run_and_cmp (const std::string& filename, const double& tol, bool no_baseline) { + ekat::FILEPtr fid; + if (!no_baseline) { + fid = ekat::FILEPtr(fopen(filename.c_str(), "r")); + EKAT_REQUIRE_MSG( fid, "generate_baseline can't read " << filename); + } Int nerr = 0, ne; int case_num = 0; for (auto ps : params_) { case_num++; - // Read the reference impl's data from the baseline file. - const auto d_ref = ic::Factory::create(ps.ic, ps.ncol, ps.nlev); - set_params(ps, *d_ref); - // Now run a sequence of other impls. This includes the reference - // implementation b/c it's likely we'll want to change it as we go. - { + if (no_baseline) { const auto d = ic::Factory::create(ps.ic, ps.ncol, ps.nlev); set_params(ps, *d); - p3_init(); + P3F::p3_init(); for (int it=0; it params_; - static void write (const ekat::FILEPtr& fid, const FortranData::Ptr& d) { - FortranDataIterator fdi(d); + static void write (const ekat::FILEPtr& fid, const P3Data::Ptr& d) { + P3DataIterator fdi(d); for (Int i = 0, n = fdi.nfield(); i < n; ++i) { const auto& f = fdi.getfield(i); ekat::write(&f.dim, 1, fid); @@ -182,8 +194,8 @@ struct Baseline { } } - static void read (const ekat::FILEPtr& fid, const FortranData::Ptr& d) { - FortranDataIterator fdi(d); + static void read (const ekat::FILEPtr& fid, const P3Data::Ptr& d) { + P3DataIterator fdi(d); for (Int i = 0, n = fdi.nfield(); i < n; ++i) { const auto& f = fdi.getfield(i); int dim, ds[3]; @@ -220,22 +232,24 @@ int main (int argc, char** argv) { if (argc == 1) { std::cout << - argv[0] << " [options] baseline-filename\n" + argv[0] << " [options] \n" "Options:\n" " -g Generate baseline file. Default False.\n" - " -f Use fortran impls instead of c++. Default False.\n" + " -c Compare baseline file. Default False.\n" + " -n Run without baseline actions. Default True.\n" + " -b Path to directory containing baselines.\n" " -t Tolerance for relative error. Default 0.\n" " -s Number of timesteps. Default=6.\n" " -dt Length of timestep. Default=300.\n" " -i Number of columns. Default=3.\n" " -k Number of vertical levels. Default=72.\n" " -r Number of repetitions, implies timing run (generate + no I/O). Default=0.\n" - " -p yes|no|both. Default=both.\n" - " -c yes|no|both. Default=both.\n"; + " --predict-nc yes|no|both. Default=both.\n" + " --prescribed-ccn yes|no|both. Default=both.\n"; return 1; } - bool generate = false, use_fortran = false; + bool generate = false, no_baseline = true; scream::Real tol = SCREAM_BFB_TESTING ? 0 : std::numeric_limits::infinity(); Int timesteps = 6; Int dt = 300; @@ -247,8 +261,8 @@ int main (int argc, char** argv) { std::string prescribed_ccn = "both"; std::string baseline_fn; for (int i = 1; i < argc-1; ++i) { - if (ekat::argv_matches(argv[i], "-g", "--generate")) generate = true; - if (ekat::argv_matches(argv[i], "-f", "--fortran")) use_fortran = true; + if (ekat::argv_matches(argv[i], "-g", "--generate")) { generate = true; no_baseline = false; } + if (ekat::argv_matches(argv[i], "-c", "--compare")) { no_baseline = false; } if (ekat::argv_matches(argv[i], "-t", "--tol")) { expect_another_arg(i, argc); ++i; @@ -291,14 +305,14 @@ int main (int argc, char** argv) { generate = true; } } - if (ekat::argv_matches(argv[i], "-p", "--predict-nc")) { + if (ekat::argv_matches(argv[i], "-pn", "--predict-nc")) { expect_another_arg(i, argc); ++i; predict_nc = std::string(argv[i]); EKAT_REQUIRE_MSG(predict_nc == "yes" || predict_nc == "no" || predict_nc == "both", "Predict option value must be one of yes|no|both"); } - if (ekat::argv_matches(argv[i], "-c", "--prescribed-ccn")) { + if (ekat::argv_matches(argv[i], "-pc", "--prescribed-ccn")) { expect_another_arg(i, argc); ++i; prescribed_ccn = std::string(argv[i]); @@ -307,18 +321,22 @@ int main (int argc, char** argv) { } } - // Decorate baseline name with precision. - baseline_fn += std::to_string(sizeof(scream::Real)); + // Compute full baseline file name with precision. + baseline_fn += "/p3_run_and_cmp.baseline" + std::to_string(sizeof(scream::Real)); scream::initialize_scream_session(argc, argv); { Baseline bln(timesteps, static_cast(dt), ncol, nlev, repeat, predict_nc, prescribed_ccn); if (generate) { std::cout << "Generating to " << baseline_fn << "\n"; - nerr += bln.generate_baseline(baseline_fn, use_fortran); - } else { + nerr += bln.generate_baseline(baseline_fn); + } else if (no_baseline) { + printf("Running with no baseline actions\n"); + nerr += bln.run_and_cmp(baseline_fn, tol, no_baseline); + } + else { printf("Comparing with %s at tol %1.1e\n", baseline_fn.c_str(), tol); - nerr += bln.run_and_cmp(baseline_fn, tol, use_fortran); + nerr += bln.run_and_cmp(baseline_fn, tol, no_baseline); } P3GlobalForFortran::deinit(); } diff --git a/components/eamxx/src/physics/p3/tests/p3_subgrid_variance_scaling_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_subgrid_variance_scaling_unit_tests.cpp index 9a728b6c57e6..c58ac68b4a6a 100644 --- a/components/eamxx/src/physics/p3/tests/p3_subgrid_variance_scaling_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_subgrid_variance_scaling_unit_tests.cpp @@ -3,7 +3,7 @@ #include "share/scream_types.hpp" #include "ekat/ekat_pack.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "p3_unit_tests_common.hpp" @@ -19,11 +19,11 @@ namespace p3 { namespace unit_test { template -struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling +struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling : public UnitWrap::UnitTest::Base { //----------------------------------------------------------------- - static void run_bfb_tests(){ + void run_bfb_tests() { //test that C++ and F90 implementations are BFB //Set of relvar values to loop over @@ -36,9 +36,7 @@ struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling //Set of exponents to loop over Scalar expons[3] = {1.0,2.47,0.1}; - //initialize struct required for F90 call - SubgridVarianceScalingData f_data; - Scalar f_scaling; + Scalar baseline_scaling; //Make C++ output available on host and device view_1d scaling_device("c scaling",1); @@ -47,11 +45,11 @@ struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling for (Int i = 0; i < 3; ++i) { // loop over exponents for (Int j = 0; j < 16; ++j) { // loop over relvars - // Get F90 solution + // Get baseline solution // ---------------------------------- - f_data.relvar=relvars[j]; - f_data.expon =expons[i]; - f_scaling = subgrid_variance_scaling(f_data); + if (this->m_baseline_action == COMPARE) { + ekat::read(&baseline_scaling, 1, Base::m_fid); + } // Get C++ solution // ---------------------------------- @@ -72,8 +70,11 @@ struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling Kokkos::deep_copy(scaling_host, scaling_device); // Validate results - if (SCREAM_BFB_TESTING) { - REQUIRE(f_scaling == scaling_host(0) ); + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { + REQUIRE(baseline_scaling == scaling_host(0) ); + } + else if (this->m_baseline_action == GENERATE) { + ekat::write(&scaling_host(0), 1, Base::m_fid); } } //end loop over relvar[j] } //end loop over expons[i] @@ -81,7 +82,7 @@ struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling //----------------------------------------------------------------- KOKKOS_FUNCTION static void subgrid_variance_scaling_linearity_test(const Scalar& relvar, - int& errors){ + int& errors) { //If expon=1, subgrid_variance_scaling should be 1 Scalar tol = C::macheps * 1e3; //1e3 is scale factor to make pass, essentially an estimate of numerical error @@ -97,7 +98,7 @@ struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling } //----------------------------------------------------------------- - KOKKOS_FUNCTION static void subgrid_variance_scaling_relvar1_test(int& errors){ + KOKKOS_FUNCTION static void subgrid_variance_scaling_relvar1_test(int& errors) { //If relvar=1, subgrid_variance_scaling should be factorial(expon) Scalar tol = C::macheps * 1e3; //1e3 is scale factor to make pass, essentially an estimate of numerical error @@ -116,7 +117,7 @@ struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling } //----------------------------------------------------------------- - KOKKOS_FUNCTION static void subgrid_variance_scaling_relvar3_test(int& errors){ + KOKKOS_FUNCTION static void subgrid_variance_scaling_relvar3_test(int& errors) { //If expon=3, subgrid variance scaling should be relvar^3+3*relvar^2+2*relvar/relvar^3 Scalar tol = C::macheps * 100; //100 is a fudge factor to make sure tests pass. 10 was too small for gnu on CPU. @@ -151,7 +152,7 @@ struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling } //end relvar3_test //----------------------------------------------------------------- - static void run_property_tests(){ + void run_property_tests() { /*This function executes all the SGS variance scaling tests by looping *over a bunch of test and summing their return statuses. *If that sum is zero, no errors have occurred. Otherwise you have errors. @@ -189,12 +190,14 @@ struct UnitWrap::UnitTest::TestP3SubgridVarianceScaling } // namespace p3 } // namespace scream -namespace{ +namespace { TEST_CASE("p3_subgrid_variance_scaling_test", "[p3_subgrid_variance_scaling_test]"){ - scream::p3::unit_test::UnitWrap::UnitTest::TestP3SubgridVarianceScaling::run_bfb_tests(); - scream::p3::unit_test::UnitWrap::UnitTest::TestP3SubgridVarianceScaling::run_property_tests(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestP3SubgridVarianceScaling; + + T t; + t.run_bfb_tests(); + t.run_property_tests(); } } // namespace - diff --git a/components/eamxx/src/physics/p3/tests/p3_table3_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_table3_unit_tests.cpp index c99d156004e7..57197fea6c8e 100644 --- a/components/eamxx/src/physics/p3/tests/p3_table3_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_table3_unit_tests.cpp @@ -3,8 +3,8 @@ #include "p3_unit_tests_common.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" -#include "p3_f90.hpp" +#include "p3_test_data.hpp" +#include "p3_data.hpp" #include "share/scream_types.hpp" #include "ekat/ekat_pack.hpp" @@ -44,7 +44,7 @@ namespace unit_test { // refinement, where the mesh is a 1D mesh transecting the table domain. template -struct UnitWrap::UnitTest::TestTable3 { +struct UnitWrap::UnitTest::TestTable3 : public UnitWrap::UnitTest::Base { KOKKOS_FUNCTION static Scalar calc_lamr (const Scalar& mu_r, const Scalar& alpha) { // Parameters for lower and upper bounds, derived above, multiplied by @@ -68,7 +68,7 @@ struct UnitWrap::UnitTest::TestTable3 { return Functions::apply_table(table, t3); } - static void run () { + void run () { // This test doesn't use mu_r_table_vals, as that is not a table3 type. It // doesn't matter whether we use vm_table_vals or vn_table_vals, as the table values // don't matter in what we are testing; we are testing interpolation @@ -170,9 +170,10 @@ namespace { TEST_CASE("p3_tables", "[p3_functions]") { - scream::p3::p3_init(); // need fortran table data + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestTable3; - scream::p3::unit_test::UnitWrap::UnitTest::TestTable3::run(); + T t; + t.run(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_tests.cpp index d1a64f48520c..858a231094d4 100644 --- a/components/eamxx/src/physics/p3/tests/p3_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_tests.cpp @@ -1,19 +1,19 @@ #include "catch2/catch.hpp" -#include "p3_f90.hpp" +#include "p3_data.hpp" #include "p3_main_wrap.hpp" #include "p3_ic_cases.hpp" namespace { -TEST_CASE("FortranData", "p3") { - int val = scream::p3::test_FortranData(); +TEST_CASE("P3Data", "p3") { + int val = scream::p3::test_P3Data(); REQUIRE(val == 0); } -TEST_CASE("FortranDataIterator", "p3") { +TEST_CASE("P3DataIterator", "p3") { using scream::p3::ic::Factory; const auto d = Factory::create(Factory::mixed); - scream::p3::FortranDataIterator fdi(d); + scream::p3::P3DataIterator fdi(d); REQUIRE(fdi.nfield() == 35); const auto& f = fdi.getfield(0); REQUIRE(f.dim == 2); @@ -29,13 +29,8 @@ TEST_CASE("p3_init", "p3") { REQUIRE(nerr == 0); } -TEST_CASE("p3_ic_f", "p3") { - int nerr = scream::p3::test_p3_ic(true); - REQUIRE(nerr == 0); -} - TEST_CASE("p3_ic_c", "p3") { - int nerr = scream::p3::test_p3_ic(false); + int nerr = scream::p3::test_p3_ic(); REQUIRE(nerr == 0); } diff --git a/components/eamxx/src/physics/p3/tests/p3_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_unit_tests.cpp index 3b994cfdad5d..91e3db2f2976 100644 --- a/components/eamxx/src/physics/p3/tests/p3_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_unit_tests.cpp @@ -5,7 +5,7 @@ #include "ekat/kokkos/ekat_kokkos_utils.hpp" #include "ekat/util/ekat_arch.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "p3_unit_tests_common.hpp" @@ -21,10 +21,10 @@ namespace unit_test { * Unit-tests for p3_functions. */ template -struct UnitWrap::UnitTest::TestP3Conservation +struct UnitWrap::UnitTest::TestP3Conservation : public UnitWrap::UnitTest::Base { - static void cloud_water_conservation_tests_device() { + void cloud_water_conservation_tests_device() { using KTH = KokkosTypes; @@ -78,7 +78,7 @@ struct UnitWrap::UnitTest::TestP3Conservation REQUIRE(cwdc_host[0].qc2qr_autoconv_tend * cwdc[0].dt <= cwdc_host[0].qc); } - static void rain_water_conservation_tests_device() { + void rain_water_conservation_tests_device() { using KTH = KokkosTypes; RainWaterConservationData rwdc[1] = {{sp(1e-5), 0.0, 0.0, 0.0, 0.0, sp(1.1), sp(1e-4), 0.0, 0.0 }}; @@ -131,7 +131,7 @@ struct UnitWrap::UnitTest::TestP3Conservation REQUIRE( rwdc_host(0).qr2qv_evap_tend * rwdc_host(0).dt <= rwdc_host(0).qr); } - static void ice_water_conservation_tests_device(){ + void ice_water_conservation_tests_device() { using KTH = KokkosTypes; IceWaterConservationData iwdc[1] = {{sp(1e-5), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, sp(1.1), sp(1e-4), 0.0}}; @@ -173,7 +173,7 @@ struct UnitWrap::UnitTest::TestP3Conservation } - static void run() + void run() { cloud_water_conservation_tests_device(); @@ -182,7 +182,7 @@ struct UnitWrap::UnitTest::TestP3Conservation ice_water_conservation_tests_device(); } - static void cloud_water_conservation_unit_bfb_tests(){ + void cloud_water_conservation_unit_bfb_tests() { using KTH = KokkosTypes; @@ -222,9 +222,11 @@ struct UnitWrap::UnitTest::TestP3Conservation std::copy(&cwdc[0], &cwdc[0] + max_pack_size, cwdc_host.data()); Kokkos::deep_copy(cwdc_device, cwdc_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - cloud_water_conservation(cwdc[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + cwdc[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -263,7 +265,7 @@ struct UnitWrap::UnitTest::TestP3Conservation Kokkos::deep_copy(cwdc_host, cwdc_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(cwdc[s].qc == cwdc_host(s).qc); REQUIRE(cwdc[s].qc2qr_autoconv_tend == cwdc_host(s).qc2qr_autoconv_tend); @@ -275,9 +277,14 @@ struct UnitWrap::UnitTest::TestP3Conservation REQUIRE(cwdc[s].qv2qi_vapdep_tend == cwdc_host(s).qv2qi_vapdep_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + cwdc_host(s).write(Base::m_fid); + } + } } - static void ice_water_conservation_unit_bfb_tests() + void ice_water_conservation_unit_bfb_tests() { using KTH = KokkosTypes; @@ -312,9 +319,11 @@ struct UnitWrap::UnitTest::TestP3Conservation std::copy(&iwdc[0], &iwdc[0] + max_pack_size, iwdc_host.data()); Kokkos::deep_copy(iwdc_device, iwdc_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - ice_water_conservation(iwdc[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + iwdc[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -356,7 +365,7 @@ struct UnitWrap::UnitTest::TestP3Conservation Kokkos::deep_copy(iwdc_host, iwdc_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(iwdc[s].qi == iwdc_host(s).qi); REQUIRE(iwdc[s].qv2qi_vapdep_tend == iwdc_host(s).qv2qi_vapdep_tend ); @@ -370,9 +379,14 @@ struct UnitWrap::UnitTest::TestP3Conservation REQUIRE(iwdc[s].qi2qr_melt_tend == iwdc_host(s).qi2qr_melt_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + iwdc_host(s).write(Base::m_fid); + } + } } - static void rain_water_conservation_unit_bfb_tests(){ + void rain_water_conservation_unit_bfb_tests() { using KTH = KokkosTypes; @@ -407,9 +421,11 @@ struct UnitWrap::UnitTest::TestP3Conservation std::copy(&rwdc[0], &rwdc[0] + max_pack_size, rwdc_host.data()); Kokkos::deep_copy(rwdc_device, rwdc_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - rain_water_conservation(rwdc[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + rwdc[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -448,7 +464,7 @@ struct UnitWrap::UnitTest::TestP3Conservation Kokkos::deep_copy(rwdc_host, rwdc_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(rwdc[s].qr == rwdc_host(s).qr); REQUIRE(rwdc[s].qc2qr_autoconv_tend == rwdc_host(s).qc2qr_autoconv_tend); @@ -460,9 +476,14 @@ struct UnitWrap::UnitTest::TestP3Conservation REQUIRE(rwdc[s].qr2qi_immers_freeze_tend == rwdc_host(s).qr2qi_immers_freeze_tend); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + rwdc_host(s).write(Base::m_fid); + } + } } - static void run_bfb() { + void run_bfb() { cloud_water_conservation_unit_bfb_tests(); rain_water_conservation_unit_bfb_tests(); @@ -473,9 +494,9 @@ struct UnitWrap::UnitTest::TestP3Conservation }; template -struct UnitWrap::UnitTest::TestP3UpdatePrognosticIce +struct UnitWrap::UnitTest::TestP3UpdatePrognosticIce : public UnitWrap::UnitTest::Base { - static void update_prognostic_ice_unit_bfb_tests() { + void update_prognostic_ice_unit_bfb_tests() { constexpr Scalar nmltratio = C::nmltratio; constexpr Scalar dt = 1.8000E+03; @@ -483,7 +504,7 @@ struct UnitWrap::UnitTest::TestP3UpdatePrognosticIce constexpr Scalar latvap = C::LatVap; constexpr Scalar latice = C::LatIce; - //fortran generated data is input to the following + //baseline generated data is input to the following P3UpdatePrognosticIceData pupidc[max_pack_size] = { {4.9078E-19, 1.5312E-09, 4.4387E-09, 3.7961E+06, 1.7737E-04, 0.0000E+00, 3.8085E-08, 5.1281E+04, 1.9251E-15, @@ -591,9 +612,11 @@ struct UnitWrap::UnitTest::TestP3UpdatePrognosticIce std::copy(&pupidc[0], &pupidc[0] + max_pack_size, pupidc_host.data()); Kokkos::deep_copy(pupidc_device, pupidc_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - update_prognostic_ice(pupidc[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + pupidc[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -679,7 +702,7 @@ struct UnitWrap::UnitTest::TestP3UpdatePrognosticIce Kokkos::deep_copy(pupidc_host, pupidc_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(pupidc[s].th_atm == pupidc_host(s).th_atm); REQUIRE(pupidc[s].qc == pupidc_host(s).qc); @@ -693,22 +716,27 @@ struct UnitWrap::UnitTest::TestP3UpdatePrognosticIce REQUIRE(pupidc[s].bm == pupidc_host(s).bm ); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + pupidc_host(s).write(Base::m_fid); + } + } } - static void run_bfb(){ + void run_bfb() { update_prognostic_ice_unit_bfb_tests(); } }; //TestP3UpdatePrognosticIce template -struct UnitWrap::UnitTest::TestGetTimeSpacePhysVariables +struct UnitWrap::UnitTest::TestGetTimeSpacePhysVariables : public UnitWrap::UnitTest::Base { - static void get_time_space_phys_variables_unit_bfb_tests(){ + void get_time_space_phys_variables_unit_bfb_tests() { constexpr Scalar latvap = C::LatVap; constexpr Scalar latice = C::LatIce; - //fortran generated data is input to the following + //baseline generated data is input to the following GetTimeSpacePhysVarsData gtspvd[max_pack_size] = { // T_atm, pres, rho, latent_heat_vapor, latent_heat_sublim, qv_sat_l, qv_sat_i {2.9792E+02, 9.8711E+04, 1.1532E+00, latvap, latvap+latice, 2.0321E-02, 2.0321E-02}, @@ -737,9 +765,11 @@ struct UnitWrap::UnitTest::TestGetTimeSpacePhysVariables std::copy(>spvd[0], >spvd[0] + max_pack_size, gtspvd_host.data()); Kokkos::deep_copy(gtspvd_device, gtspvd_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - get_time_space_phys_variables(gtspvd[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + gtspvd[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -794,7 +824,7 @@ struct UnitWrap::UnitTest::TestGetTimeSpacePhysVariables Kokkos::deep_copy(gtspvd_host, gtspvd_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(gtspvd[s].mu == gtspvd_host(s).mu); REQUIRE(gtspvd[s].dv == gtspvd_host(s).dv); @@ -807,20 +837,25 @@ struct UnitWrap::UnitTest::TestGetTimeSpacePhysVariables REQUIRE(gtspvd[s].eii == gtspvd_host(s).eii); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + gtspvd_host(s).write(Base::m_fid); + } + } } - static void run_bfb(){ + void run_bfb() { get_time_space_phys_variables_unit_bfb_tests(); } }; //TestGetTimeSpacePhysVariables template -struct UnitWrap::UnitTest::TestP3UpdatePrognosticLiq +struct UnitWrap::UnitTest::TestP3UpdatePrognosticLiq : public UnitWrap::UnitTest::Base { - static void update_prognostic_liquid_unit_bfb_tests(){ + void update_prognostic_liquid_unit_bfb_tests() { constexpr Scalar latvap = C::LatVap; - //fortran generated data is input to the following + //baseline generated data is input to the following P3UpdatePrognosticLiqData pupldc[max_pack_size] = { {1.0631E-12, 1.0631E+00, 1.5833E-12, 1.5833E+00, 2.4190E-02, 0.0000E+00, 0.0000E+00, 0.0000E+00, 4.2517E+00, @@ -896,9 +931,11 @@ struct UnitWrap::UnitTest::TestP3UpdatePrognosticLiq std::copy(&pupldc[0], &pupldc[0] + max_pack_size, pupldc_host.data()); Kokkos::deep_copy(pupldc_device, pupldc_host); - // Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - update_prognostic_liquid(pupldc[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + pupldc[i].read(Base::m_fid); + } } // Run the lookup from a kernel and copy results back to host @@ -971,7 +1008,7 @@ struct UnitWrap::UnitTest::TestP3UpdatePrognosticLiq Kokkos::deep_copy(pupldc_host, pupldc_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(pupldc[s].th_atm == pupldc_host(s).th_atm); REQUIRE(pupldc[s].qv == pupldc_host(s).qv); @@ -981,18 +1018,23 @@ struct UnitWrap::UnitTest::TestP3UpdatePrognosticLiq REQUIRE(pupldc[s].nr == pupldc_host(s).nr); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + pupldc_host(s).write(Base::m_fid); + } + } } - static void run_bfb(){ + void run_bfb() { update_prognostic_liquid_unit_bfb_tests(); } }; //TestP3UpdatePrognosticLiq template -struct UnitWrap::UnitTest::TestP3FunctionsImposeMaxTotalNi +struct UnitWrap::UnitTest::TestP3FunctionsImposeMaxTotalNi : public UnitWrap::UnitTest::Base { - static void impose_max_total_ni_bfb_test(){ + void impose_max_total_ni_bfb_test() { constexpr Scalar max_total_ni = 740.0e3; ImposeMaxTotalNiData dc[max_pack_size]= { @@ -1026,9 +1068,11 @@ struct UnitWrap::UnitTest::TestP3FunctionsImposeMaxTotalNi std::copy(&dc[0], &dc[0] + max_pack_size, dc_host.data()); Kokkos::deep_copy(dc_device, dc_host); - //Get data from fortran - for (Int i = 0; i < max_pack_size; ++i) { - impose_max_total_ni(dc[i]); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (Int i = 0; i < max_pack_size; ++i) { + dc[i].read(Base::m_fid); + } } //Run function from a kernal and copy results back to the host @@ -1054,15 +1098,20 @@ struct UnitWrap::UnitTest::TestP3FunctionsImposeMaxTotalNi Kokkos::deep_copy(dc_host, dc_device); // Validate results - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int s = 0; s < max_pack_size; ++s) { REQUIRE(dc[s].ni_local == dc_host(s).ni_local); REQUIRE(dc[s].inv_rho_local == dc_host(s).inv_rho_local); } } + else if (this->m_baseline_action == GENERATE) { + for (Int s = 0; s < max_pack_size; ++s) { + dc_host(s).write(Base::m_fid); + } + } } - static void run_bfb(){ + void run_bfb() { impose_max_total_ni_bfb_test(); } @@ -1075,24 +1124,39 @@ struct UnitWrap::UnitTest::TestP3FunctionsImposeMaxTotalNi namespace { TEST_CASE("p3_conservation_test", "[p3_unit_tests]"){ - scream::p3::unit_test::UnitWrap::UnitTest::TestP3Conservation::run(); - scream::p3::unit_test::UnitWrap::UnitTest::TestP3Conservation::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestP3Conservation; + + T t; + t.run(); + t.run_bfb(); } TEST_CASE("p3_get_time_space_phys_variables_test", "[p3_unit_tests]"){ - scream::p3::unit_test::UnitWrap::UnitTest::TestGetTimeSpacePhysVariables::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestGetTimeSpacePhysVariables; + + T t; + t.run_bfb(); } TEST_CASE("p3_update_prognostic_ice_test", "[p3_unit_tests]"){ - scream::p3::unit_test::UnitWrap::UnitTest::TestP3UpdatePrognosticIce::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestP3UpdatePrognosticIce; + + T t; + t.run_bfb(); } TEST_CASE("p3_update_prognostic_liquid_test", "[p3_unit_tests]"){ - scream::p3::unit_test::UnitWrap::UnitTest::TestP3UpdatePrognosticLiq::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestP3UpdatePrognosticLiq; + + T t; + t.run_bfb(); } TEST_CASE("p3_impose_max_total_ni_test", "[p3_unit_tests]"){ - scream::p3::unit_test::UnitWrap::UnitTest::TestP3FunctionsImposeMaxTotalNi::run_bfb(); + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestP3FunctionsImposeMaxTotalNi; + + T t; + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/p3/tests/p3_upwind_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_upwind_unit_tests.cpp index fde2ca644cbf..6e83a8ee4eaa 100644 --- a/components/eamxx/src/physics/p3/tests/p3_upwind_unit_tests.cpp +++ b/components/eamxx/src/physics/p3/tests/p3_upwind_unit_tests.cpp @@ -3,11 +3,9 @@ #include "p3_unit_tests_common.hpp" #include "p3_functions.hpp" -#include "p3_functions_f90.hpp" +#include "p3_test_data.hpp" #include "share/scream_types.hpp" -#include "share/util/scream_setup_random_test.hpp" -#include "share/util/scream_setup_random_test.hpp" #include "ekat/ekat_pack.hpp" #include "ekat/kokkos/ekat_kokkos_utils.hpp" @@ -36,9 +34,9 @@ namespace unit_test { // cells in the domain are 0. This lets us check the restricted-domain usage of // the upwind routine in the first time step. template -struct UnitWrap::UnitTest::TestUpwind { +struct UnitWrap::UnitTest::TestUpwind : public UnitWrap::UnitTest::Base { -static void run_phys() +void run_phys() { using ekat::repack; constexpr auto SPS = SCREAM_SMALL_PACK_SIZE; @@ -201,11 +199,12 @@ static void run_phys() } } -static void run_bfb() +void run_bfb() { - auto engine = setup_random_test(); + // With stored baselines, we must use a fixed seed! + auto engine = Base::get_engine(); - CalcUpwindData cuds_fortran[] = { + CalcUpwindData cuds_baseline[] = { // kts, kte, kdir, kbot, k_qxtop, na, dt_sub, CalcUpwindData( 1, 72, -1, 72, 36, 2, 1.833E+03), CalcUpwindData( 1, 72, 1, 36, 72, 2, 1.833E+03), @@ -216,28 +215,30 @@ static void run_bfb() CalcUpwindData( 1, 32, -1, 21, 7, 1, 1.833E+03), }; - static constexpr Int num_runs = sizeof(cuds_fortran) / sizeof(CalcUpwindData); + static constexpr Int num_runs = sizeof(cuds_baseline) / sizeof(CalcUpwindData); // Set up random input data - for (auto& d : cuds_fortran) { + for (auto& d : cuds_baseline) { d.randomize(engine); } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state CalcUpwindData cuds_cxx[num_runs] = { - CalcUpwindData(cuds_fortran[0]), - CalcUpwindData(cuds_fortran[1]), - CalcUpwindData(cuds_fortran[2]), - CalcUpwindData(cuds_fortran[3]), - CalcUpwindData(cuds_fortran[4]), - CalcUpwindData(cuds_fortran[5]), - CalcUpwindData(cuds_fortran[6]), + CalcUpwindData(cuds_baseline[0]), + CalcUpwindData(cuds_baseline[1]), + CalcUpwindData(cuds_baseline[2]), + CalcUpwindData(cuds_baseline[3]), + CalcUpwindData(cuds_baseline[4]), + CalcUpwindData(cuds_baseline[5]), + CalcUpwindData(cuds_baseline[6]), }; - // Get data from fortran - for (auto& d : cuds_fortran) { - calc_first_order_upwind_step(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (auto& d : cuds_baseline) { + d.read(Base::m_fid); + } } // Get data from cxx @@ -245,23 +246,23 @@ static void run_bfb() for (auto& d : cuds_cxx) { Real** fluxes, **vs, **qnx; d.convert_to_ptr_arr(tmp1, fluxes, vs, qnx); - calc_first_order_upwind_step_f( + calc_first_order_upwind_step_host( d.kts, d.kte, d.kdir, d.kbot, d.k_qxtop, d.dt_sub, d.rho, d.inv_rho, d.inv_dz, d.num_arrays, fluxes, vs, qnx); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { // Due to pack issues, we must restrict checks to the active k space - Int start = std::min(cuds_fortran[i].kbot, cuds_fortran[i].k_qxtop) - 1; // 0-based indx - Int end = std::max(cuds_fortran[i].kbot, cuds_fortran[i].k_qxtop); // 0-based indx + Int start = std::min(cuds_baseline[i].kbot, cuds_baseline[i].k_qxtop) - 1; // 0-based indx + Int end = std::max(cuds_baseline[i].kbot, cuds_baseline[i].k_qxtop); // 0-based indx Real** fluxesf90, **vsf90, **qnxf90, **fluxescxx, **vscxx, **qnxcxx; - cuds_fortran[i].convert_to_ptr_arr(tmp1, fluxesf90, vsf90, qnxf90); + cuds_baseline[i].convert_to_ptr_arr(tmp1, fluxesf90, vsf90, qnxf90); cuds_cxx[i].convert_to_ptr_arr(tmp1, fluxescxx, vscxx, qnxcxx); - for (int n = 0; n < cuds_fortran[i].num_arrays; ++n) { + for (int n = 0; n < cuds_baseline[i].num_arrays; ++n) { for (Int k = start; k < end; ++k) { REQUIRE(fluxesf90[n][k] == fluxescxx[n][k]); REQUIRE(qnxf90[n][k] == qnxcxx[n][k]); @@ -269,23 +270,29 @@ static void run_bfb() } } } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + cuds_cxx[i].write(Base::m_fid); + } + } } }; template -struct UnitWrap::UnitTest::TestGenSed { +struct UnitWrap::UnitTest::TestGenSed : public UnitWrap::UnitTest::Base { -static void run_phys() +void run_phys() { // TODO } -static void run_bfb() +void run_bfb() { - auto engine = setup_random_test(); + // With stored baselines, we must use a fixed seed! + auto engine = Base::get_engine(); - GenSedData gsds_fortran[] = { + GenSedData gsds_baseline[] = { // kts, kte, kdir, k_qxtop, k_qxbot, kbot, Co_max, dt_left, prt_accum, num_arrays GenSedData(1, 72, -1, 36, 72, 72, 9.196E-02, 1.818E+01, 4.959E-05, 2), GenSedData(1, 72, -1, 36, 57, 72, 4.196E-01, 1.418E+02, 4.959E-06, 1), @@ -293,25 +300,27 @@ static void run_bfb() GenSedData(1, 72, -1, 72, 72, 72, 4.196E-01, 1.418E+02, 4.959E-06, 1), }; - static constexpr Int num_runs = sizeof(gsds_fortran) / sizeof(GenSedData); + static constexpr Int num_runs = sizeof(gsds_baseline) / sizeof(GenSedData); // Set up random input data - for (auto& d : gsds_fortran) { + for (auto& d : gsds_baseline) { d.randomize(engine); } - // Create copies of data for use by cxx. Needs to happen before fortran calls so that + // Create copies of data for use by cxx. Needs to happen before reads so that // inout data is in original state GenSedData gsds_cxx[num_runs] = { - GenSedData(gsds_fortran[0]), - GenSedData(gsds_fortran[1]), - GenSedData(gsds_fortran[2]), - GenSedData(gsds_fortran[3]), + GenSedData(gsds_baseline[0]), + GenSedData(gsds_baseline[1]), + GenSedData(gsds_baseline[2]), + GenSedData(gsds_baseline[3]), }; - // Get data from fortran - for (auto& d : gsds_fortran) { - generalized_sedimentation(d); + // Read baseline data + if (this->m_baseline_action == COMPARE) { + for (auto& d : gsds_baseline) { + d.read(Base::m_fid); + } } // Get data from cxx @@ -319,31 +328,36 @@ static void run_bfb() for (auto& d : gsds_cxx) { Real** fluxes, **vs, **qnx; d.convert_to_ptr_arr(tmp1, fluxes, vs, qnx); - generalized_sedimentation_f(d.kts, d.kte, d.kdir, d.k_qxtop, + generalized_sedimentation_host(d.kts, d.kte, d.kdir, d.k_qxtop, &d.k_qxbot, d.kbot, d.Co_max, &d.dt_left, &d.prt_accum, d.inv_dz, d.inv_rho, d.rho, d.num_arrays, fluxes, vs, qnx); } - if (SCREAM_BFB_TESTING) { + if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) { for (Int i = 0; i < num_runs; ++i) { // Due to pack issues, we must restrict checks to the active k space - Int start = std::min(gsds_fortran[i].k_qxbot, gsds_fortran[i].k_qxtop) - 1; // 0-based indx - Int end = std::max(gsds_fortran[i].k_qxbot, gsds_fortran[i].k_qxtop); // 0-based indx + Int start = std::min(gsds_baseline[i].k_qxbot, gsds_baseline[i].k_qxtop) - 1; // 0-based indx + Int end = std::max(gsds_baseline[i].k_qxbot, gsds_baseline[i].k_qxtop); // 0-based indx Real** fluxesf90, **vsf90, **qnxf90, **fluxescxx, **vscxx, **qnxcxx; - gsds_fortran[i].convert_to_ptr_arr(tmp1, fluxesf90, vsf90, qnxf90); + gsds_baseline[i].convert_to_ptr_arr(tmp1, fluxesf90, vsf90, qnxf90); gsds_cxx[i].convert_to_ptr_arr(tmp1, fluxescxx, vscxx, qnxcxx); - for (int n = 0; n < gsds_fortran[i].num_arrays; ++n) { + for (int n = 0; n < gsds_baseline[i].num_arrays; ++n) { for (Int k = start; k < end; ++k) { REQUIRE(fluxesf90[n][k] == fluxescxx[n][k]); REQUIRE(qnxf90[n][k] == qnxcxx[n][k]); } } - REQUIRE(gsds_fortran[i].k_qxbot == gsds_cxx[i].k_qxbot); - REQUIRE(gsds_fortran[i].dt_left == gsds_cxx[i].dt_left); - REQUIRE(gsds_fortran[i].prt_accum == gsds_cxx[i].prt_accum); + REQUIRE(gsds_baseline[i].k_qxbot == gsds_cxx[i].k_qxbot); + REQUIRE(gsds_baseline[i].dt_left == gsds_cxx[i].dt_left); + REQUIRE(gsds_baseline[i].prt_accum == gsds_cxx[i].prt_accum); + } + } + else if (this->m_baseline_action == GENERATE) { + for (Int i = 0; i < num_runs; ++i) { + gsds_cxx[i].write(Base::m_fid); } } } @@ -358,18 +372,20 @@ namespace { TEST_CASE("p3_upwind", "[p3_functions]") { - using TU = scream::p3::unit_test::UnitWrap::UnitTest::TestUpwind; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestUpwind; - TU::run_phys(); - TU::run_bfb(); + T t; + t.run_phys(); + t.run_bfb(); } TEST_CASE("p3_gen_sed", "[p3_functions]") { - using TG = scream::p3::unit_test::UnitWrap::UnitTest::TestGenSed; + using T = scream::p3::unit_test::UnitWrap::UnitTest::TestGenSed; - TG::run_phys(); - TG::run_bfb(); + T t; + t.run_phys(); + t.run_bfb(); } } // namespace diff --git a/components/eamxx/src/physics/share/physics_test_data.cpp b/components/eamxx/src/physics/share/physics_test_data.cpp index 4a13528e98b6..f6c6d733fd0e 100644 --- a/components/eamxx/src/physics/share/physics_test_data.cpp +++ b/components/eamxx/src/physics/share/physics_test_data.cpp @@ -26,4 +26,21 @@ PhysicsTestData& PhysicsTestData::assignment_impl(const PhysicsTestData& rhs) return *this; } +void PhysicsTestData::read(const ekat::FILEPtr& fid) +{ + EKAT_REQUIRE_MSG(fid, + "Tried to read from missing file. You may have forgotten to generate baselines for some BFB unit tests"); + m_reals.read(fid); + m_ints.read(fid); + m_bools.read(fid); +} + +void PhysicsTestData::write(const ekat::FILEPtr& fid) const +{ + m_reals.write(fid); + m_ints.write(fid); + m_bools.write(fid); +} + + } // namespace scream diff --git a/components/eamxx/src/physics/share/physics_test_data.hpp b/components/eamxx/src/physics/share/physics_test_data.hpp index 099480b44393..ddd7d77fa860 100644 --- a/components/eamxx/src/physics/share/physics_test_data.hpp +++ b/components/eamxx/src/physics/share/physics_test_data.hpp @@ -5,6 +5,7 @@ #include "ekat/util/ekat_math_utils.hpp" #include "ekat/ekat_assert.hpp" +#include "ekat/util/ekat_file_utils.hpp" #include #include @@ -68,34 +69,81 @@ struct SHOCGridData : public PhysicsTestData { #define PTD_DATA_COPY_CTOR(name, num_args) \ name(const name& rhs) : name(PTD_ONES(num_args)) { *this = rhs; } -#define PTD_ASS0( ) ((void) (0)) -#define PTD_ASS1(a ) a = rhs.a -#define PTD_ASS2(a, b ) PTD_ASS1(a) ; b = rhs.b -#define PTD_ASS3(a, b, c ) PTD_ASS2(a, b) ; c = rhs.c -#define PTD_ASS4(a, b, c, d ) PTD_ASS3(a, b, c) ; d = rhs.d -#define PTD_ASS5(a, b, c, d, e ) PTD_ASS4(a, b, c, d) ; e = rhs.e -#define PTD_ASS6(a, b, c, d, e, f ) PTD_ASS5(a, b, c, d, e) ; f = rhs.f -#define PTD_ASS7(a, b, c, d, e, f, g ) PTD_ASS6(a, b, c, d, e, f) ; g = rhs.g -#define PTD_ASS8(a, b, c, d, e, f, g, h ) PTD_ASS7(a, b, c, d, e, f, g) ; h = rhs.h -#define PTD_ASS9(a, b, c, d, e, f, g, h, i ) PTD_ASS8(a, b, c, d, e, f, g, h) ; i = rhs.i -#define PTD_ASS10(a, b, c, d, e, f, g, h, i, j ) PTD_ASS9(a, b, c, d, e, f, g, h, i) ; j = rhs.j -#define PTD_ASS11(a, b, c, d, e, f, g, h, i, j, k ) PTD_ASS10(a, b, c, d, e, f, g, h, i, j) ; k = rhs.k -#define PTD_ASS12(a, b, c, d, e, f, g, h, i, j, k, l ) PTD_ASS11(a, b, c, d, e, f, g, h, i, j, k) ; l = rhs.l -#define PTD_ASS13(a, b, c, d, e, f, g, h, i, j, k, l, m ) PTD_ASS12(a, b, c, d, e, f, g, h, i, j, k, l) ; m = rhs.m -#define PTD_ASS14(a, b, c, d, e, f, g, h, i, j, k, l, m, n ) PTD_ASS13(a, b, c, d, e, f, g, h, i, j, k, l, m) ; n = rhs.n -#define PTD_ASS15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o ) PTD_ASS14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) ; o = rhs.o -#define PTD_ASS16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p ) PTD_ASS15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) ; p = rhs.p -#define PTD_ASS17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q ) PTD_ASS16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) ; q = rhs.q -#define PTD_ASS18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r ) PTD_ASS17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) ; r = rhs.r -#define PTD_ASS19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s ) PTD_ASS18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) ; s = rhs.s -#define PTD_ASS20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ) PTD_ASS19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) ; t = rhs.t +#define PTD_ASS0() ((void) (0)) +#define PTD_ASS1(first) first = rhs.first; PTD_ASS0() +#define PTD_ASS2(first, ...) first = rhs.first; PTD_ASS1(__VA_ARGS__) +#define PTD_ASS3(first, ...) first = rhs.first; PTD_ASS2(__VA_ARGS__) +#define PTD_ASS4(first, ...) first = rhs.first; PTD_ASS3(__VA_ARGS__) +#define PTD_ASS5(first, ...) first = rhs.first; PTD_ASS4(__VA_ARGS__) +#define PTD_ASS6(first, ...) first = rhs.first; PTD_ASS5(__VA_ARGS__) +#define PTD_ASS7(first, ...) first = rhs.first; PTD_ASS6(__VA_ARGS__) +#define PTD_ASS8(first, ...) first = rhs.first; PTD_ASS7(__VA_ARGS__) +#define PTD_ASS9(first, ...) first = rhs.first; PTD_ASS8(__VA_ARGS__) +#define PTD_ASS10(first, ...) first = rhs.first; PTD_ASS9(__VA_ARGS__) +#define PTD_ASS11(first, ...) first = rhs.first; PTD_ASS10(__VA_ARGS__) +#define PTD_ASS12(first, ...) first = rhs.first; PTD_ASS11(__VA_ARGS__) +#define PTD_ASS13(first, ...) first = rhs.first; PTD_ASS12(__VA_ARGS__) +#define PTD_ASS14(first, ...) first = rhs.first; PTD_ASS13(__VA_ARGS__) +#define PTD_ASS15(first, ...) first = rhs.first; PTD_ASS14(__VA_ARGS__) +#define PTD_ASS16(first, ...) first = rhs.first; PTD_ASS15(__VA_ARGS__) +#define PTD_ASS17(first, ...) first = rhs.first; PTD_ASS16(__VA_ARGS__) +#define PTD_ASS18(first, ...) first = rhs.first; PTD_ASS17(__VA_ARGS__) +#define PTD_ASS19(first, ...) first = rhs.first; PTD_ASS18(__VA_ARGS__) +#define PTD_ASS20(first, ...) first = rhs.first; PTD_ASS19(__VA_ARGS__) + +#define PTD_RW0(action) ((void) (0)) +#define PTD_RW1(action, first) ekat::action(&first, 1, fid); PTD_RW0(action) +#define PTD_RW2(action, first, ...) ekat::action(&first, 1, fid); PTD_RW1(action, __VA_ARGS__) +#define PTD_RW3(action, first, ...) ekat::action(&first, 1, fid); PTD_RW2(action, __VA_ARGS__) +#define PTD_RW4(action, first, ...) ekat::action(&first, 1, fid); PTD_RW3(action, __VA_ARGS__) +#define PTD_RW5(action, first, ...) ekat::action(&first, 1, fid); PTD_RW4(action, __VA_ARGS__) +#define PTD_RW6(action, first, ...) ekat::action(&first, 1, fid); PTD_RW5(action, __VA_ARGS__) +#define PTD_RW7(action, first, ...) ekat::action(&first, 1, fid); PTD_RW6(action, __VA_ARGS__) +#define PTD_RW8(action, first, ...) ekat::action(&first, 1, fid); PTD_RW7(action, __VA_ARGS__) +#define PTD_RW9(action, first, ...) ekat::action(&first, 1, fid); PTD_RW8(action, __VA_ARGS__) +#define PTD_RW10(action, first, ...) ekat::action(&first, 1, fid); PTD_RW9(action, __VA_ARGS__) +#define PTD_RW11(action, first, ...) ekat::action(&first, 1, fid); PTD_RW10(action, __VA_ARGS__) +#define PTD_RW12(action, first, ...) ekat::action(&first, 1, fid); PTD_RW11(action, __VA_ARGS__) +#define PTD_RW13(action, first, ...) ekat::action(&first, 1, fid); PTD_RW12(action, __VA_ARGS__) +#define PTD_RW14(action, first, ...) ekat::action(&first, 1, fid); PTD_RW13(action, __VA_ARGS__) +#define PTD_RW15(action, first, ...) ekat::action(&first, 1, fid); PTD_RW14(action, __VA_ARGS__) +#define PTD_RW16(action, first, ...) ekat::action(&first, 1, fid); PTD_RW15(action, __VA_ARGS__) +#define PTD_RW17(action, first, ...) ekat::action(&first, 1, fid); PTD_RW16(action, __VA_ARGS__) +#define PTD_RW18(action, first, ...) ekat::action(&first, 1, fid); PTD_RW17(action, __VA_ARGS__) +#define PTD_RW19(action, first, ...) ekat::action(&first, 1, fid); PTD_RW18(action, __VA_ARGS__) +#define PTD_RW20(action, first, ...) ekat::action(&first, 1, fid); PTD_RW19(action, __VA_ARGS__) +#define PTD_RW21(action, first, ...) ekat::action(&first, 1, fid); PTD_RW20(action, __VA_ARGS__) +#define PTD_RW22(action, first, ...) ekat::action(&first, 1, fid); PTD_RW21(action, __VA_ARGS__) +#define PTD_RW23(action, first, ...) ekat::action(&first, 1, fid); PTD_RW22(action, __VA_ARGS__) +#define PTD_RW24(action, first, ...) ekat::action(&first, 1, fid); PTD_RW23(action, __VA_ARGS__) +#define PTD_RW25(action, first, ...) ekat::action(&first, 1, fid); PTD_RW24(action, __VA_ARGS__) +#define PTD_RW26(action, first, ...) ekat::action(&first, 1, fid); PTD_RW25(action, __VA_ARGS__) +#define PTD_RW27(action, first, ...) ekat::action(&first, 1, fid); PTD_RW26(action, __VA_ARGS__) +#define PTD_RW28(action, first, ...) ekat::action(&first, 1, fid); PTD_RW27(action, __VA_ARGS__) +#define PTD_RW29(action, first, ...) ekat::action(&first, 1, fid); PTD_RW28(action, __VA_ARGS__) +#define PTD_RW30(action, first, ...) ekat::action(&first, 1, fid); PTD_RW29(action, __VA_ARGS__) +#define PTD_RW31(action, first, ...) ekat::action(&first, 1, fid); PTD_RW30(action, __VA_ARGS__) #define PTD_ASSIGN_OP(name, num_scalars, ...) \ name& operator=(const name& rhs) { PTD_ASS##num_scalars(__VA_ARGS__); assignment_impl(rhs); return *this; } +#define PTD_RW_SCALARS(num_scalars, ...) \ + void read_scalars(const ekat::FILEPtr& fid) { EKAT_REQUIRE_MSG(fid, "Tried to read from missing file. You may have forgotten to generate baselines for some BFB unit tests"); PTD_RW##num_scalars(read, __VA_ARGS__); } \ + void write_scalars(const ekat::FILEPtr& fid) const { PTD_RW##num_scalars(write, __VA_ARGS__); } + +#define PTD_RW_SCALARS_ONLY(num_scalars, ...) \ + void read(const ekat::FILEPtr& fid) { EKAT_REQUIRE_MSG(fid, "Tried to read from missing file. You may have forgotten to generate baselines for some BFB unit tests"); PTD_RW##num_scalars(read, __VA_ARGS__); } \ + void write(const ekat::FILEPtr& fid) const { PTD_RW##num_scalars(write, __VA_ARGS__); } + +#define PTD_RW() \ + void read(const ekat::FILEPtr& fid) { read_scalars(fid); PhysicsTestData::read(fid); } \ + void write(const ekat::FILEPtr& fid) const { write_scalars(fid); PhysicsTestData::write(fid); } + #define PTD_STD_DEF(name, num_scalars, ...) \ PTD_DATA_COPY_CTOR(name, num_scalars); \ - PTD_ASSIGN_OP(name, num_scalars, __VA_ARGS__) + PTD_ASSIGN_OP(name, num_scalars, __VA_ARGS__) \ + PTD_RW() \ + PTD_RW_SCALARS(num_scalars, __VA_ARGS__) namespace scream { @@ -241,6 +289,16 @@ class PhysicsTestData m_data = new_data; } + void read(const ekat::FILEPtr& fid) + { + ekat::read(m_data.data(), m_data.size(), fid); + } + + void write(const ekat::FILEPtr& fid) const + { + ekat::write(m_data.data(), m_data.size(), fid); + } + std::vector > m_dims_list; // list of dims, one per unique set of dims std::vector > m_members_list; // list of member pointers, same outer index space as m_dims_list std::vector m_data; // the member data in a flat vector @@ -336,6 +394,10 @@ class PhysicsTestData } } + void read(const ekat::FILEPtr& fid); + + void write(const ekat::FILEPtr& fid) const; + protected: PhysicsTestData& assignment_impl(const PhysicsTestData& rhs); diff --git a/components/eamxx/src/share/util/scream_setup_random_test.hpp b/components/eamxx/src/share/util/scream_setup_random_test.hpp index 419bd4ee64e9..09f3f3099d88 100644 --- a/components/eamxx/src/share/util/scream_setup_random_test.hpp +++ b/components/eamxx/src/share/util/scream_setup_random_test.hpp @@ -41,9 +41,13 @@ inline int get_random_test_seed(const ekat::Comm* comm=nullptr) } template -Engine setup_random_test(const ekat::Comm* comm=nullptr) +Engine setup_random_test(const ekat::Comm* comm=nullptr, int* return_seed=nullptr) { - return Engine (get_random_test_seed(comm)); + int seed = get_random_test_seed(comm); + if (return_seed != nullptr) { + *return_seed = seed; + } + return Engine (seed); } template