diff --git a/components/eamxx/src/share/field/field.cpp b/components/eamxx/src/share/field/field.cpp index a002c3b28813..bf1ecbb5dfaa 100644 --- a/components/eamxx/src/share/field/field.cpp +++ b/components/eamxx/src/share/field/field.cpp @@ -137,6 +137,14 @@ subfield (const std::string& sf_name, const ekat::units::Units& sf_units, sf.m_data = m_data; sf.m_is_read_only = m_is_read_only; + if (not sf.m_header->get_alloc_properties().contiguous() and + not sf.host_and_device_share_memory_space()) { + // If subfield is not contiguous and Host and Device do not + // share a memory space, we must initialize the helper field + // for sync_to functions. + sf.initialize_contiguous_helper_field(); + } + return sf; } @@ -178,6 +186,14 @@ Field Field::subfield(const std::string& sf_name, index_end); sf.m_data = m_data; + if (not sf.m_header->get_alloc_properties().contiguous() and + not sf.host_and_device_share_memory_space()) { + // If subfield is not contiguous and Host and Device do not + // share a memory space, we must initialize the helper field + // for sync_to functions. + sf.initialize_contiguous_helper_field(); + } + return sf; } diff --git a/components/eamxx/src/share/field/field.hpp b/components/eamxx/src/share/field/field.hpp index 679f293e3e1c..a3779f1ebf24 100644 --- a/components/eamxx/src/share/field/field.hpp +++ b/components/eamxx/src/share/field/field.hpp @@ -278,6 +278,27 @@ class Field { // Allocate the actual view void allocate_view (); + // Create contiguous helper field for running sync_to_host + // and sync_to_device with non-contiguous fields + void initialize_contiguous_helper_field () { + EKAT_REQUIRE_MSG(not m_header->get_alloc_properties().contiguous(), + "Error! We should not setup contiguous helper field " + "for an already contiguous field.\n"); + EKAT_REQUIRE_MSG(not host_and_device_share_memory_space(), + "Error! We should not setup contiguous helper field for a field " + "when host and device share a memory space.\n"); + + auto id = m_header->get_identifier(); + Field contig(id.alias(name()+std::string("_contiguous"))); + contig.allocate_view(); + + // Sanity check + EKAT_REQUIRE_MSG(contig.get_header().get_alloc_properties().contiguous(), + "Error! Contiguous helper field must be contiguous.\n"); + + m_contiguous_field = std::make_shared(contig); + } + inline bool host_and_device_share_memory_space() const { EKAT_REQUIRE_MSG(is_allocated(), "Error! Must allocate view before querying " @@ -347,6 +368,10 @@ class Field { // Actual data. dual_view_t m_data; + // Field needed for sync host/device in case of non-contiguous + // field when host and device do not share a memory space. + std::shared_ptr m_contiguous_field; + // Whether this field is read-only. This is given // mutable keyword since it needs to be turned off/on // to allow sync_to_host for constant, read-only fields.