1 #ifndef PETSCDEVICE_INTERFACE_INTERNAL_HPP 2 #define PETSCDEVICE_INTERFACE_INTERNAL_HPP 3 4 #include <petsc/private/deviceimpl.h> 5 6 #include <petsc/private/cpp/utility.hpp> // std::pair 7 #include <petsc/private/cpp/functional.hpp> //std::equal_to 8 9 #include <unordered_map> 10 #include <unordered_set> 11 12 #if PetscDefined(USE_DEBUG) && PetscDefined(USE_INFO) 13 #define PETSC_USE_DEBUG_AND_INFO 1 14 #define PetscDebugInfo(dctx, ...) PetscInfo(dctx, __VA_ARGS__) 15 #else 16 #define PetscDebugInfo(dctx, ...) PETSC_SUCCESS 17 #endif 18 19 // this file contains functions needed to bridge the gap between dcontext.cxx and device.cxx 20 // but are not useful enough to put in the impl header 21 PETSC_INTERN PetscErrorCode PetscDeviceContextSetDefaultDeviceForType_Internal(PetscDeviceContext, PetscDeviceType); 22 PETSC_INTERN PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType); 23 PETSC_INTERN PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType); 24 PETSC_INTERN PetscErrorCode PetscDeviceContextSyncClearMap_Internal(PetscDeviceContext); 25 PETSC_INTERN PetscErrorCode PetscDeviceContextCheckNotOrphaned_Internal(PetscDeviceContext); 26 27 // open up namespace std to specialize equal_to for unordered_map 28 namespace std 29 { 30 31 template <> 32 struct equal_to<PetscDeviceContext> { 33 #if PETSC_CPP_VERSION <= 17 34 using result_type = bool; 35 using first_argument_type = PetscDeviceContext; 36 using second_argument_type = PetscDeviceContext; 37 #endif 38 39 constexpr bool operator()(const PetscDeviceContext &x, const PetscDeviceContext &y) const noexcept { return PetscObjectCast(x)->id == PetscObjectCast(y)->id; } 40 }; 41 42 } // namespace std 43 44 namespace 45 { 46 47 // workaround for bug in: 48 // clang: https://bugs.llvm.org/show_bug.cgi?id=36684 49 // gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96645 50 // 51 // see also: 52 // https://stackoverflow.com/questions/53408962/try-to-understand-compiler-error-message-default-member-initializer-required-be 53 struct CxxDataParent { 54 PetscObjectId id = 0; 55 PetscObjectState state = 0; 56 57 constexpr CxxDataParent() noexcept = default; 58 59 constexpr explicit CxxDataParent(PetscDeviceContext dctx) noexcept : CxxDataParent(PetscObjectCast(dctx)->id, PetscObjectCast(dctx)->state) { } 60 61 private: 62 // make this private, we do not want to accept any old id and state pairing 63 constexpr CxxDataParent(PetscObjectId id_, PetscObjectState state_) noexcept : id(id_), state(state_) { } 64 }; 65 66 struct CxxData { 67 using upstream_type = std::unordered_map<PetscDeviceContext, CxxDataParent>; 68 using dep_type = std::unordered_set<PetscObjectId>; 69 70 // double check we didn't specialize for no reason 71 static_assert(std::is_same<typename upstream_type::key_equal, std::equal_to<PetscDeviceContext>>::value, ""); 72 73 upstream_type upstream{}; 74 dep_type deps{}; 75 76 PetscErrorCode clear() noexcept; 77 }; 78 79 inline PetscErrorCode CxxData::clear() noexcept 80 { 81 PetscFunctionBegin; 82 PetscCallCXX(this->upstream.clear()); 83 PetscCallCXX(this->deps.clear()); 84 PetscFunctionReturn(PETSC_SUCCESS); 85 } 86 87 PETSC_NODISCARD inline CxxData *CxxDataCast(PetscDeviceContext dctx) noexcept 88 { 89 return static_cast<CxxData *>(PetscObjectCast(dctx)->cpp); 90 } 91 92 /* 93 needed because PetscInitialize() needs to also query these options to set the defaults. Since 94 it does not yet have a PetscDeviceContext to call this with, the actual options queries are 95 abstracted out, so you can call this without one. 96 */ 97 inline PetscErrorCode PetscDeviceContextQueryOptions_Internal(PetscOptionItems *PetscOptionsObject, std::pair<PetscDeviceType, PetscBool> &deviceType, std::pair<PetscStreamType, PetscBool> &streamType) 98 { 99 auto dtype = static_cast<PetscInt>(deviceType.first); 100 auto stype = static_cast<PetscInt>(streamType.first); 101 102 PetscFunctionBegin; 103 /* set the device type first */ 104 PetscCall(PetscOptionsEList("-device_context_device_type", "Underlying PetscDevice", "PetscDeviceContextSetDevice", PetscDeviceTypes, PETSC_DEVICE_MAX, PetscDeviceTypes[dtype], &dtype, &deviceType.second)); 105 PetscCall(PetscOptionsEList("-device_context_stream_type", "PetscDeviceContext PetscStreamType", "PetscDeviceContextSetStreamType", PetscStreamTypes, PETSC_STREAM_MAX, PetscStreamTypes[stype], &stype, &streamType.second)); 106 deviceType.first = PetscDeviceTypeCast(dtype); 107 streamType.first = PetscStreamTypeCast(stype); 108 PetscFunctionReturn(PETSC_SUCCESS); 109 } 110 111 } // anonymous namespace 112 113 #endif // PETSCDEVICE_INTERFACE_INTERNAL_HPP 114