66#include " share/io/scream_scorpio_interface.hpp"
77#include " share/io/scream_io_utils.hpp"
88#include " share/util/scream_universal_constants.hpp"
9+ #include " physics/share/physics_constants.hpp"
910
1011#include < filesystem>
1112#include < fstream>
@@ -59,17 +60,55 @@ void DataInterpolation::run (const util::TimeStamp& ts)
5960 out.deep_copy (beg);
6061 out.update (end,alpha,1 -alpha);
6162 }
62- // For Dynamic3D profile we also need to compute the source pressure profile
63+
64+ // For Dynamic3D/Dynamic3D profile we also need to compute the source pressure profile
6365 // NOTE: this can't be done in the loop above, since src_p is not a "remapped"
6466 // field in the vertical remapper (also, we need to use ad different ptr)
6567 if (m_vr_type==Dynamic3D) {
6668 // The pressure field is THE LAST registered in the horiz remappers
6769 const auto p_beg = m_horiz_remapper_beg->get_tgt_field (m_nfields);
6870 const auto p_end = m_horiz_remapper_end->get_tgt_field (m_nfields);
6971
70- auto p = m_vremap-> get_source_pressure ( true ); // mid or int doesn't matter
72+ auto p = m_helper_pressure_fields[ " src_p " ];
7173 p.deep_copy (p_beg);
7274 p.update (p_end,alpha,1 -alpha);
75+ } else if (m_vr_type==Dynamic3DRef) {
76+ // The surface pressure field is THE LAST registered in the horiz remappers
77+ const auto ps_beg = m_horiz_remapper_beg->get_tgt_field (m_nfields);
78+ const auto ps_end = m_horiz_remapper_end->get_tgt_field (m_nfields);
79+
80+ auto p = m_helper_pressure_fields[" src_p" ];
81+ auto ps = m_helper_pressure_fields[" p_data" ];
82+ ps.deep_copy (ps_beg);
83+ ps.update (ps_end,alpha,1 -alpha);
84+
85+ // Reconstruct reference p from ps, hyam, and hybm
86+ using KT = KokkosTypes<DefaultDevice>;
87+ using ExeSpace = typename KT::ExeSpace;
88+ using MemberType = typename KT::MemberType;
89+ using ESU = ekat::ExeSpaceUtils<ExeSpace>;
90+ using C = scream::physics::Constants<Real>;
91+ using PT = ekat::Pack<Real,SCREAM_PACK_SIZE>;
92+
93+ auto ps_v = ps.get_view <const Real*>();
94+ auto p_v = p.get_view <PT**>();
95+ auto hyam = m_vert_remapper->get_src_grid ()->get_geometry_data (" hyam" ).get_view <const PT*>();
96+ auto hybm = m_vert_remapper->get_src_grid ()->get_geometry_data (" hybm" ).get_view <const PT*>();
97+
98+ constexpr auto P0 = C::P0;
99+
100+ const int ncols = ps_v.extent (0 );
101+ const int num_vert_packs = p_v.extent (1 );
102+ const auto policy = ESU::get_default_team_policy (ncols, num_vert_packs);
103+
104+ Kokkos::parallel_for (" spa_compute_p_src_loop" , policy,
105+ KOKKOS_LAMBDA (const MemberType& team) {
106+ const int icol = team.league_rank ();
107+ Kokkos::parallel_for (Kokkos::TeamVectorRange (team,num_vert_packs),
108+ [&](const int k) {
109+ p_v (icol,k) = ps_v (icol) * hybm (k) + P0 * hyam (k);
110+ });
111+ });
73112 }
74113
75114 m_vert_remapper->remap_fwd ();
@@ -94,7 +133,7 @@ update_end_fields ()
94133 fields.push_back (m_horiz_remapper_end->get_src_field (i));
95134 }
96135
97- if (m_vr_type==Dynamic3D) {
136+ if (m_vr_type==Dynamic3D or m_vr_type==Dynamic3DRef ) {
98137 // We also need to read the src pressure profile
99138 fields.push_back (m_horiz_remapper_end->get_src_field (m_nfields));
100139 }
@@ -276,6 +315,7 @@ setup_remappers (const std::string& hremap_filename,
276315 int nlevs_data = get_input_files_dimlen (" lev" );
277316 grid_after_hremap->reset_num_vertical_lev (nlevs_data);
278317
318+ std::shared_ptr<VerticalRemapper> vremap;
279319 if (hremap_filename!=" " ) {
280320 m_horiz_remapper_beg = std::make_shared<RefiningRemapperP2P>(grid_after_hremap,hremap_filename);
281321 m_horiz_remapper_end = std::make_shared<RefiningRemapperP2P>(grid_after_hremap,hremap_filename);
@@ -306,10 +346,49 @@ setup_remappers (const std::string& hremap_filename,
306346 }
307347 };
308348
309- m_vert_remapper = m_vremap = std::make_shared<VerticalRemapper>(grid_after_hremap,m_model_grid);
310- m_vremap->set_extrapolation_type (s2et (extrap_type_top),VerticalRemapper::Top);
311- m_vremap->set_extrapolation_type (s2et (extrap_type_bot),VerticalRemapper::Bot);
312- m_vremap->set_mask_value (mask_value);
349+ auto vremap = std::make_shared<VerticalRemapper>(grid_after_hremap,m_model_grid);
350+
351+ vremap->set_extrapolation_type (s2et (extrap_type_top),VerticalRemapper::Top);
352+ vremap->set_extrapolation_type (s2et (extrap_type_bot),VerticalRemapper::Bot);
353+ vremap->set_mask_value (mask_value);
354+
355+ // Setup vertical pressure profiles (which can add 1 extra field to hremap)
356+ // This MUST be done before registering in vremap, since register_field_from_tgt
357+ // REQUIRES to have source pressure profiles set BEFORE.
358+
359+ auto p_layout = vr_type==Static1D ? grid_after_hremap->get_vertical_layout (true )
360+ : grid_after_hremap->get_3d_scalar_layout (true );
361+ auto & src_p = m_helper_pressure_fields [" src_p" ];
362+ src_p = Field (FieldIdentifier (" src_p" ,p_layout,ekat::units::Pa,grid_after_hremap->name ()));
363+ src_p.get_header ().get_alloc_properties ().request_allocation (SCREAM_PACK_SIZE);
364+ src_p.allocate_view ();
365+ if (vr_type==Dynamic3D) {
366+ // We load a full 3d profile, so p_data IS src_p
367+ m_helper_pressure_fields [" p_data" ] = src_p.alias (data_pname);
368+ } else if (vr_type==Dynamic3DRef) {
369+ // We load the surface pressure, and reconstruct src_p via p=ps*hybm(k) + p0*hyam(k)
370+ auto & ps = m_helper_pressure_fields [" p_data" ];
371+ ps = Field (FieldIdentifier (data_pname,grid_after_hremap->get_2d_scalar_layout (),ekat::units::Pa,grid_after_hremap->name ()));
372+ ps.allocate_view ();
373+
374+ // We need to reconstruct the 3d pressure from ps, hybm, and hyam.
375+ // We read and store hyam/hybm in the vremap src grid
376+ auto layout = grid_after_hremap->get_vertical_layout (true );
377+ auto nondim = ekat::units::Units::nondimensional ();
378+ DataType real_t = DataType::RealType;
379+ auto hyam = grid_after_hremap->create_geometry_data (" hyam" ,layout,nondim,real_t ,SCREAM_PACK_SIZE);
380+ auto hybm = grid_after_hremap->create_geometry_data (" hybm" ,layout,nondim,real_t ,SCREAM_PACK_SIZE);
381+ AtmosphereInput hvcoord_reader (m_time_database.files .front (),grid_after_hremap,{hyam,hybm},true );
382+ hvcoord_reader.read_variables ();
383+ } else if (vr_type==Static1D) {
384+ // Can load p now, since it's static
385+ AtmosphereInput src_p_reader (m_time_database.files .front (),grid_after_hremap,{src_p.alias (data_pname)},true );
386+ src_p_reader.read_variables ();
387+ }
388+ vremap->set_source_pressure (m_helper_pressure_fields[" src_p" ],VerticalRemapper::Both);
389+ vremap->set_target_pressure (model_pmid,model_pint);
390+
391+ m_vert_remapper = vremap;
313392 } else {
314393 // If no vert remap is requested, model_grid and grid_after_hremap MUST have same nlevs
315394 int model_nlevs = m_model_grid->get_num_vertical_levels ();
@@ -319,36 +398,6 @@ setup_remappers (const std::string& hremap_filename,
319398 " - input data num vert levels: " + std::to_string (nlevs_data) + " \n " );
320399 m_vert_remapper = std::make_shared<IDR>(grid_after_hremap,SAT);
321400 }
322-
323- // Setup vertical pressure profiles (which can add 1 extra field to hremap)
324- // This MUST be done before registering in vremap, since register_field_from_tgt
325- // REQUIRES to have source pressure profiles set BEFORE.
326- Field data_p;
327- if (vr_type==Dynamic3D) {
328- // We also need to load and remap the pressure from the input files
329- auto hr_tgt_grid = m_horiz_remapper_beg->get_tgt_grid ();
330- auto p_layout = hr_tgt_grid->get_3d_scalar_layout (true );
331- data_p = Field (FieldIdentifier (data_pname,p_layout,ekat::units::Pa,hr_tgt_grid->name ()));
332- data_p.allocate_view ();
333-
334- m_vremap->set_source_pressure (data_p,VerticalRemapper::Both);
335- m_vremap->set_target_pressure (model_pmid,model_pint);
336- } else if (vr_type==Static1D) {
337- auto hr_tgt_grid = m_horiz_remapper_beg->get_tgt_grid ();
338- auto p_layout = hr_tgt_grid->get_vertical_layout (true );
339- data_p = Field (FieldIdentifier (data_pname,p_layout,ekat::units::Pa,hr_tgt_grid->name ()));
340- data_p.allocate_view ();
341-
342- // Use raw scorpio to read this var, since it's not decomposed. Use any file, since it's static
343- auto filename = m_time_database.files .front ();
344- scorpio::register_file (filename,scorpio::Read);
345- scorpio::read_var (filename,data_pname,data_p.get_internal_view_data <Real,Host>());
346- scorpio::release_file (filename);
347- data_p.sync_to_dev ();
348-
349- m_vremap->set_source_pressure (data_p,VerticalRemapper::Both);
350- m_vremap->set_target_pressure (model_pmid,model_pint);
351- }
352401 m_vr_type = vr_type;
353402
354403 // Register fields in the remappers. Vertical first, since we only have model-grid fields
@@ -365,9 +414,10 @@ setup_remappers (const std::string& hremap_filename,
365414 m_horiz_remapper_beg->register_field_from_tgt (f.clone ());
366415 m_horiz_remapper_end->register_field_from_tgt (f.clone ());
367416 }
368- if (vr_type==Dynamic3D) {
369- m_horiz_remapper_beg->register_field_from_tgt (data_p.clone ());
370- m_horiz_remapper_end->register_field_from_tgt (data_p.clone ());
417+ if (vr_type==Dynamic3D or vr_type==Dynamic3DRef) {
418+ const auto & data_p = m_helper_pressure_fields[" p_data" ];
419+ m_horiz_remapper_beg->register_field_from_tgt (data_p.clone (data_pname));
420+ m_horiz_remapper_end->register_field_from_tgt (data_p.clone (data_pname));
371421 }
372422 m_horiz_remapper_beg->registration_ends ();
373423 m_horiz_remapper_end->registration_ends ();
0 commit comments