Skip to content

Commit 21b0b0c

Browse files
authored
Merge pull request #2976 from iulian787/iulian787/scream_with_moab_fields_rebase_var
EAMXX uses a different implementation of the atmosphere model, compared to EAM, and moab driver needs to be extended to support a coupled case case tested is --compset F2010-SCREAMv1-MPASSI --res ne4pg2_oQU480 --driver moab this case uses mpas sea ice, CICE is not yet supported by MOAB the implementation follows similar strategy compared to the rest of the models Atmosphere mesh in moab has 4 different instances, similar to EAM, corresponding to coarse spectral mesh ( size 6nene), fine quad mesh (corresponding to GLL quad mesh, size 6nene* (np-1)* (np-1) ) pg2 FV type mesh (size 6nene* pg2 * pg2) point cloud corresponding to mct simplified vertex grid. On the coupler side, we still use just the pg2 FV type mesh, used for intersection and coupling with other models
2 parents b610754 + af5bc64 commit 21b0b0c

File tree

15 files changed

+526
-15
lines changed

15 files changed

+526
-15
lines changed

cime_config/machines/config_machines.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@
443443
<environment_variables compiler="nvidiagpu">
444444
<env name="MPICH_GPU_SUPPORT_ENABLED">1</env>
445445
</environment_variables>
446+
<environment_variables compiler="gnugpu">
447+
<env name="MOAB_ROOT">$SHELL{if [ -z "$MOAB_ROOT" ]; then echo /global/cfs/cdirs/e3sm/software/moab/gnugpu ; else echo "$MOAB_ROOT"; fi}</env>
448+
</environment_variables>
446449
<environment_variables compiler="gnu.*" mpilib="mpich">
447450
<env name="ADIOS2_ROOT">$SHELL{if [ -z "$ADIOS2_ROOT" ]; then echo /global/cfs/cdirs/e3sm/3rdparty/adios2/2.9.1/cray-mpich-8.1.25/gcc-11.2.0; else echo "$ADIOS2_ROOT"; fi}</env>
448451
</environment_variables>

components/eam/src/dynamics/se/dyn_comp.F90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ subroutine dyn_init1(fh, NLFileName, dyn_in, dyn_out)
269269
end if
270270

271271
#ifdef HAVE_MOAB
272-
call create_moab_meshes(par, elem)
272+
call create_moab_meshes(par, elem, fv_nphys)
273273
#endif
274274
! Define the CAM grids (this has to be after dycore spinup).
275275
! Physics-grid will be defined later by phys_grid_init

components/eamxx/src/control/atmosphere_driver.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ void AtmosphereDriver::create_grids()
300300
void AtmosphereDriver::setup_surface_coupling_data_manager(SurfaceCouplingTransferType transfer_type,
301301
const int num_cpl_fields, const int num_scream_fields,
302302
const int field_size, Real* data_ptr,
303+
#ifdef HAVE_MOAB
304+
Real* data_ptr_moab,
305+
#endif
303306
char* names_ptr, int* cpl_indices_ptr, int* vec_comps_ptr,
304307
Real* constant_multiple_ptr, bool* do_transfer_during_init_ptr)
305308
{
@@ -318,6 +321,9 @@ void AtmosphereDriver::setup_surface_coupling_data_manager(SurfaceCouplingTransf
318321
} else EKAT_ERROR_MSG("Error! Unexpected SurfaceCouplingTransferType.");
319322

320323
sc_data_mgr->setup_internals(num_cpl_fields, num_scream_fields, field_size, data_ptr,
324+
#ifdef HAVE_MOAB
325+
data_ptr_moab,
326+
#endif
321327
names_ptr, cpl_indices_ptr, vec_comps_ptr,
322328
constant_multiple_ptr, do_transfer_during_init_ptr);
323329
}

components/eamxx/src/control/atmosphere_driver.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ class AtmosphereDriver
8787
void setup_surface_coupling_data_manager(SurfaceCouplingTransferType transfer_type,
8888
const int num_cpl_fields, const int num_scream_fields,
8989
const int field_size, Real* data_ptr,
90+
#ifdef HAVE_MOAB
91+
Real* data_ptr_moab,
92+
#endif
9093
char* names_ptr, int* cpl_indices_ptr, int* vec_comps_ptr,
9194
Real* constant_multiple_ptr, bool* do_transfer_during_init_ptr);
9295

components/eamxx/src/control/atmosphere_surface_coupling_exporter.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ void SurfaceCouplingExporter::setup_surface_coupling_data(const SCDataManager &s
137137
m_num_cols, m_num_cpl_exports);
138138
m_cpl_exports_view_d = Kokkos::create_mirror_view(DefaultDevice(), m_cpl_exports_view_h);
139139

140+
#ifdef HAVE_MOAB
141+
// The export data is of size num_cpl_exports,ncols. All other data is of size num_scream_exports
142+
m_moab_cpl_exports_view_h = decltype(m_moab_cpl_exports_view_h) (sc_data_manager.get_field_data_moab_ptr(),
143+
m_num_cpl_exports, m_num_cols);
144+
m_moab_cpl_exports_view_d = Kokkos::create_mirror_view(DefaultDevice(), m_moab_cpl_exports_view_h);
145+
#endif
146+
140147
m_export_field_names = new name_t[m_num_scream_exports];
141148
std::memcpy(m_export_field_names, sc_data_manager.get_field_name_ptr(), m_num_scream_exports*32*sizeof(char));
142149

@@ -536,6 +543,12 @@ void SurfaceCouplingExporter::do_export_to_cpl(const bool called_during_initiali
536543
// Any field not exported by scream, or not exported
537544
// during initialization, is set to 0.0
538545
Kokkos::deep_copy(m_cpl_exports_view_d, 0.0);
546+
#ifdef HAVE_MOAB
547+
// Any field not exported by scream, or not exported
548+
// during initialization, is set to 0.0
549+
Kokkos::deep_copy(m_moab_cpl_exports_view_d, 0.0);
550+
const auto moab_cpl_exports_view_d = m_moab_cpl_exports_view_d;
551+
#endif
539552
const auto cpl_exports_view_d = m_cpl_exports_view_d;
540553
const int num_exports = m_num_scream_exports;
541554
const int num_cols = m_num_cols;
@@ -554,9 +567,27 @@ void SurfaceCouplingExporter::do_export_to_cpl(const bool called_during_initiali
554567
cpl_exports_view_d(icol,info.cpl_indx) = info.constant_multiple*info.data[offset];
555568
}
556569
});
570+
#ifdef HAVE_MOAB
571+
Kokkos::parallel_for(export_policy, KOKKOS_LAMBDA(const int& i) {
572+
const int ifield = i / num_cols;
573+
const int icol = i % num_cols;
574+
const auto& info = col_info(ifield);
575+
const auto offset = icol*info.col_stride + info.col_offset;
557576

577+
// if this is during initialization, check whether or not the field should be exported
578+
bool do_export = (not called_during_initialization || info.transfer_during_initialization);
579+
if (do_export) {
580+
moab_cpl_exports_view_d(info.cpl_indx, icol) = info.constant_multiple*info.data[offset];
581+
}
582+
});
583+
#endif
558584
// Deep copy fields from device to cpl host array
559585
Kokkos::deep_copy(m_cpl_exports_view_h,m_cpl_exports_view_d);
586+
#ifdef HAVE_MOAB
587+
// Deep copy fields from device to cpl host array
588+
Kokkos::deep_copy(m_moab_cpl_exports_view_h,m_moab_cpl_exports_view_d);
589+
#endif
590+
560591
}
561592
// =========================================================================================
562593
void SurfaceCouplingExporter::finalize_impl()

components/eamxx/src/control/atmosphere_surface_coupling_exporter.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ class SurfaceCouplingExporter : public AtmosphereProcess
141141
view_2d <DefaultDevice, Real> m_cpl_exports_view_d;
142142
uview_2d<HostDevice, Real> m_cpl_exports_view_h;
143143

144+
#ifdef HAVE_MOAB
145+
// Views storing a 2d array with dims (num_fields, num_cols) for moab cpl export data.
146+
// The field cols strides faster, since that's what moab does (so we can "view" the
147+
// pointer to the whole a2x_am(:,:) array from Fortran)
148+
view_2d <DefaultDevice, Real> m_moab_cpl_exports_view_d;
149+
uview_2d<HostDevice, Real> m_moab_cpl_exports_view_h;
150+
#endif
144151
// Array storing the field names for exports
145152
name_t* m_export_field_names;
146153
std::vector<std::string> m_export_field_names_vector;

components/eamxx/src/control/atmosphere_surface_coupling_importer.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ void SurfaceCouplingImporter::set_grids(const std::shared_ptr<const GridsManager
7474
m_num_cols, m_num_cpl_imports);
7575
m_cpl_imports_view_d = Kokkos::create_mirror_view_and_copy(DefaultDevice(),
7676
m_cpl_imports_view_h);
77+
#ifdef HAVE_MOAB
78+
// The import data is of size num_cpl_imports, ncol. All other data is of size num_scream_imports
79+
m_moab_cpl_imports_view_h = decltype(m_moab_cpl_imports_view_h) (sc_data_manager.get_field_data_moab_ptr(),
80+
m_num_cpl_imports, m_num_cols);
81+
m_moab_cpl_imports_view_d = Kokkos::create_mirror_view_and_copy(DefaultDevice(),
82+
m_moab_cpl_imports_view_h);
83+
#endif
7784
m_import_field_names = new name_t[m_num_scream_imports];
7885
std::memcpy(m_import_field_names, sc_data_manager.get_field_name_ptr(), m_num_scream_imports*32*sizeof(char));
7986

@@ -153,6 +160,12 @@ void SurfaceCouplingImporter::do_import(const bool called_during_initialization)
153160

154161
// Deep copy cpl host array to devic
155162
Kokkos::deep_copy(m_cpl_imports_view_d,m_cpl_imports_view_h);
163+
#ifdef HAVE_MOAB
164+
// Deep copy cpl host array to device
165+
const auto moab_cpl_imports_view_d = m_moab_cpl_imports_view_d;
166+
Kokkos::deep_copy(m_moab_cpl_imports_view_d,m_moab_cpl_imports_view_h);
167+
#endif
168+
156169

157170
// Unpack the fields
158171
auto unpack_policy = policy_type(0,num_imports*num_cols);
@@ -171,6 +184,24 @@ void SurfaceCouplingImporter::do_import(const bool called_during_initialization)
171184
}
172185
});
173186

187+
#ifdef HAVE_MOAB
188+
Kokkos::parallel_for(unpack_policy, KOKKOS_LAMBDA(const int& i) {
189+
190+
const int icol = i / num_imports;
191+
const int ifield = i % num_imports;
192+
193+
const auto& info = col_info(ifield);
194+
195+
auto offset = icol*info.col_stride + info.col_offset;
196+
197+
// if this is during initialization, check whether or not the field should be imported
198+
bool do_import = (not called_during_initialization || info.transfer_during_initialization);
199+
if (do_import) {
200+
info.data[offset] = moab_cpl_imports_view_d(info.cpl_indx, icol)*info.constant_multiple;
201+
}
202+
});
203+
#endif
204+
174205
if (m_iop) {
175206
if (m_iop->get_params().get<bool>("iop_srf_prop")) {
176207
// Overwrite imports with data from IOP file
@@ -232,6 +263,9 @@ void SurfaceCouplingImporter::overwrite_iop_imports (const bool called_during_in
232263
const auto& info_d = col_info_d(ifield);
233264
const auto offset = icol*info_d.col_stride + info_d.col_offset;
234265
info_d.data[offset] = col_val;
266+
#ifdef HAVE_MOAB
267+
// TODO
268+
#endif
235269
});
236270
}
237271
}

components/eamxx/src/control/atmosphere_surface_coupling_importer.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ class SurfaceCouplingImporter : public AtmosphereProcess
8383
view_2d <DefaultDevice, Real> m_cpl_imports_view_d;
8484
uview_2d<HostDevice, Real> m_cpl_imports_view_h;
8585

86+
#ifdef HAVE_MOAB
87+
// Views storing a 2d array with dims (num_fields,num_cols) for import data.
88+
// The colums index strides faster, since that's what moab does (so we can "view" the
89+
// pointer to the whole x2a_am(:,:) array from Fortran)
90+
view_2d <DefaultDevice, Real> m_moab_cpl_imports_view_d;
91+
uview_2d<HostDevice, Real> m_moab_cpl_imports_view_h;
92+
#endif
93+
8694
// Array storing the field names for imports
8795
name_t* m_import_field_names;
8896

components/eamxx/src/dynamics/homme/interface/phys_grid_mod.F90

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,14 @@ subroutine phys_grid_init (pgN)
549549
use gllfvremap_mod, only: gfr_init
550550
use homme_context_mod, only: elem, par
551551
use dimensions_mod, only: nelem, nelemd
552+
#ifdef HAVE_MOAB
553+
use seq_comm_mct, only: MHID, MHFID ! id of homme moab coarse and fine applications
554+
use seq_comm_mct, only: ATMID
555+
use seq_comm_mct, only: mhpgid ! id of pgx moab application
556+
use semoab_mod, only: create_moab_meshes
557+
use iMOAB, only : iMOAB_RegisterApplication
558+
use iso_c_binding
559+
#endif
552560
!
553561
! Input(s)
554562
!
@@ -561,6 +569,10 @@ subroutine phys_grid_init (pgN)
561569
character(2) :: str
562570
type(pg_specs_t), pointer :: pg
563571

572+
#ifdef HAVE_MOAB
573+
integer :: ATM_ID1
574+
character*32 appname
575+
#endif
564576
pg => pg_specs(pgN)
565577

566578
if (pg%inited) then
@@ -612,6 +624,48 @@ subroutine phys_grid_init (pgN)
612624
call compute_global_dofs (pg)
613625
call compute_global_coords (pg)
614626
call compute_global_area (pg)
627+
#ifdef HAVE_MOAB
628+
if (pgN > 0) then
629+
appname="HM_COARSE"//C_NULL_CHAR
630+
ATM_ID1 = 120 !
631+
ierr = iMOAB_RegisterApplication(appname, par%comm, ATM_ID1, MHID)
632+
if (ierr > 0 ) &
633+
call abortmp('Error: cannot register moab app')
634+
if(par%masterproc) then
635+
write(iulog,*) " "
636+
write(iulog,*) "register MOAB app:", trim(appname), " MHID=", MHID
637+
write(iulog,*) " "
638+
endif
639+
appname="HM_FINE"//C_NULL_CHAR
640+
ATM_ID1 = 119 ! this number should not conflict with other components IDs; how do we know?
641+
ierr = iMOAB_RegisterApplication(appname, par%comm, ATM_ID1, MHFID)
642+
if (ierr > 0 ) &
643+
call abortmp('Error: cannot register moab app for fine mesh')
644+
if(par%masterproc) then
645+
write(iulog,*) " "
646+
write(iulog,*) "register MOAB app:", trim(appname), " MHFID=", MHFID
647+
write(iulog,*) " "
648+
endif
649+
appname="HM_PGX"//C_NULL_CHAR
650+
ATM_ID1 = ATMID(1) ! this number should not conflict with other components IDs; how do we know?
651+
!
652+
! in this case, we reuse the main atm id, mhid will not be used for intersection anymore
653+
! still, need to be careful
654+
ierr = iMOAB_RegisterApplication(appname, par%comm, ATM_ID1, mhpgid)
655+
if (ierr > 0 ) &
656+
call abortmp('Error: cannot register moab app for fine mesh')
657+
if(par%masterproc) then
658+
write(iulog,*) " "
659+
write(iulog,*) "register MOAB app:", trim(appname), " MHPGID=", mhpgid
660+
write(iulog,*) " "
661+
endif
662+
! instance distributed moab meshes from elem structures
663+
! 1 ) spectral coarse mesh
664+
! 2 ) GLL fine quad mesh (used mostly for visualization)
665+
! 3 ) pgN FV type mesh, (most of the time pg2 mesh), used for coupling with other components;
666+
call create_moab_meshes(par, elem, pgN)
667+
endif
668+
#endif
615669
end subroutine phys_grid_init
616670

617671

0 commit comments

Comments
 (0)