From 5bdff37eb914f990ccfd7e181db453324b41b033 Mon Sep 17 00:00:00 2001
From: James Edgeley <j.edgeley@imperial.ac.uk>
Date: Wed, 31 Jan 2024 10:54:47 +0000
Subject: [PATCH] windows compilation

---
 CMakeLists.txt                                | 212 +++++++-----------
 Operators/CMakeLists.txt                      | 117 ++++++++++
 Field.cpp => Operators/Field.cpp              |   0
 Field.hpp => Operators/Field.hpp              |   0
 .../MemoryRegionCPU.hpp                       |   2 +-
 .../MemoryRegionCUDA.cu                       |   0
 .../MemoryRegionCUDA.hpp                      |   0
 Operators/Operator.hpp                        |   1 +
 Operators/OperatorAddTraceIntegral.hpp        |   4 +-
 Operators/OperatorAssmbScatr.hpp              |   4 +-
 Operators/OperatorBwdTrans.hpp                |   4 +-
 Operators/OperatorConjGrad.hpp                |   4 +-
 Operators/OperatorDiagPrecon.hpp              |   4 +-
 Operators/OperatorDirBndCond.hpp              |   4 +-
 Operators/OperatorFwdTrans.hpp                |   4 +-
 Operators/OperatorHelmSolve.hpp               |   4 +-
 Operators/OperatorHelmholtz.hpp               |   4 +-
 Operators/OperatorIProductWRTBase.hpp         |   4 +-
 Operators/OperatorIProductWRTDerivBase.hpp    |   4 +-
 Operators/OperatorIdentity.hpp                |   4 +-
 Operators/OperatorMass.hpp                    |   4 +-
 Operators/OperatorMatrix.hpp                  |   4 +-
 Operators/OperatorNeuBndCond.hpp              |   4 +-
 Operators/OperatorNullPrecon.hpp              |   4 +-
 Operators/OperatorPhysDeriv.hpp               |   4 +-
 Operators/OperatorRobBndCond.hpp              |   4 +-
 Operators/OperatorsDeclspec.hpp               |  14 ++
 27 files changed, 248 insertions(+), 170 deletions(-)
 create mode 100644 Operators/CMakeLists.txt
 rename Field.cpp => Operators/Field.cpp (100%)
 rename Field.hpp => Operators/Field.hpp (100%)
 rename MemoryRegionCPU.hpp => Operators/MemoryRegionCPU.hpp (95%)
 rename MemoryRegionCUDA.cu => Operators/MemoryRegionCUDA.cu (100%)
 rename MemoryRegionCUDA.hpp => Operators/MemoryRegionCUDA.hpp (100%)
 create mode 100644 Operators/OperatorsDeclspec.hpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a628e860..fb103f17 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,23 +1,30 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.24)
 project(Redesign CXX)
+#SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
+#INCLUDE (NektarCommon)
+
+option(NEKTAR_USE_DEBUG " Enable Graphless execution" OFF)
+option(NEKTAR_USE_SERIAL "Enable Serial execution" ON)
+option(NEKTAR_USE_THREADS "Enable Multithreading execution" ON)
+option(NEKTAR_USE_CUDA "Enable CUDA execution" ON)
+OPTION(NEKTAR_MPI "Use MPI for parallelisation." ON)
+option(NEKTAR_USE_SIMD "Enable SIMD support, if available" TRUE)
+
+if (NEKTAR_USE_CUDA AND NEKTAR_USE_SIMD)
+    MESSAGE(FATAL_ERROR "Cannot use both SIMD and CUDA")
+endif()
 
-enable_testing()
+OPTION(NEKTAR_BUILD_DEMOS "Build demonstration codes."     OFF)
+OPTION(NEKTAR_BUILD_TESTS "Build tests."     OFF)
 
-option(NEKTAR_USE_CUDA "Enable CUDA support" FALSE)
-option(NEKTAR_USE_SIMD "Enable SIMD support, if available" TRUE)
+OPTION(NEKTAR_FULL_DEBUG "Enable Full Debugging." ON)
 
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-set(CMAKE_BUILD_TYPE Debug)
-
-if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
-    set(CMAKE_CUDA_ARCHITECTURES 75 80 86)
-    # CMake 3.24
-    # set(CMAKE_CUDA_ARCHITECTURES native)
-endif()
+set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
 
-# Default install location: build/dist
+INCLUDE(CMakeDependentOption)
 IF (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
         SET(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/dist CACHE PATH "" FORCE)
 ENDIF()
@@ -26,56 +33,43 @@ find_package(Nektar++ REQUIRED)
 include_directories(SYSTEM ${NEKTAR++_INCLUDE_DIRS} ${NEKTAR++_TP_INCLUDE_DIRS})
 link_directories(${NEKTAR++_LIBRARY_DIRS} ${NEKTAR++_TP_LIBRARY_DIRS})
 message(STATUS "Found Nektar++: version ${NEKTAR++_VERSION}")
-
 set(CMAKE_INSTALL_RPATH "${NEKTAR++_LIBRARY_DIRS}")
 
-set(SRC Field.cpp Operators/Operator.cpp 
-    Operators/OperatorBwdTrans.cpp Operators/BwdTrans/BwdTransImpl.cpp 
-    Operators/OperatorIProductWRTBase.cpp Operators/IProductWRTBase/IProductWRTBaseImpl.cpp
-    Operators/OperatorIProductWRTDerivBase.cpp Operators/IProductWRTDerivBase/IProductWRTDerivBaseImpl.cpp
-    Operators/OperatorPhysDeriv.cpp Operators/PhysDeriv/PhysDerivImpl.cpp
-    Operators/OperatorIdentity.cpp Operators/Identity/IdentityImpl.cpp
-    Operators/OperatorMass.cpp Operators/Mass/MassImpl.cpp
-    Operators/OperatorHelmholtz.cpp Operators/Helmholtz/HelmholtzImpl.cpp
-    Operators/OperatorAssmbScatr.cpp Operators/AssmbScatr/AssmbScatrImpl.cpp
-    Operators/OperatorNullPrecon.cpp Operators/NullPrecon/NullPreconImpl.cpp
-    Operators/OperatorDiagPrecon.cpp Operators/DiagPrecon/DiagPreconImpl.cpp
-    Operators/OperatorDirBndCond.cpp Operators/DirBndCond/DirBndCondImpl.cpp
-    Operators/OperatorNeuBndCond.cpp Operators/NeuBndCond/NeuBndCondImpl.cpp
-    Operators/OperatorRobBndCond.cpp Operators/RobBndCond/RobBndCondImpl.cpp
-    Operators/OperatorConjGrad.cpp Operators/ConjGrad/ConjGradImpl.cpp
-    Operators/OperatorFwdTrans.cpp Operators/FwdTrans/FwdTransImpl.cpp
-    Operators/OperatorHelmSolve.cpp Operators/HelmSolve/HelmSolveImpl.cpp
-    Operators/OperatorMatrix.cpp Operators/Matrix/MatrixImpl.cpp
-    Operators/OperatorAddTraceIntegral.cpp Operators/AddTraceIntegral/AddTraceIntegralImpl.cpp
-    )
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
-if (NEKTAR_USE_CUDA AND NEKTAR_USE_SIMD)
-    MESSAGE(FATAL_ERROR "Cannot use both SIMD and CUDA")
-endif()
+SET(NEKTAR_LIBRARY_TYPE "SHARED")
 
 if (NEKTAR_USE_CUDA)
     enable_language(CUDA)
+    find_package(CUDAToolkit REQUIRED)
     add_definitions(-DNEKTAR_USE_CUDA)
-    set(SRC ${SRC} MemoryRegionCUDA.cu 
-                   Operators/BwdTrans/BwdTransCUDA.cu 
-                   Operators/IProductWRTBase/IProductWRTBaseCUDA.cu 
-                   Operators/IProductWRTDerivBase/IProductWRTDerivBaseCUDA.cu 
-                   Operators/PhysDeriv/PhysDerivCUDA.cu
-                   Operators/Identity/IdentityCUDA.cu
-                   Operators/Mass/MassCUDA.cu
-                   Operators/Helmholtz/HelmholtzCUDA.cu
-                   Operators/AssmbScatr/AssmbScatrCUDA.cu 
-                   Operators/NullPrecon/NullPreconCUDA.cu 
-                   Operators/DiagPrecon/DiagPreconCUDA.cu
-                   Operators/DirBndCond/DirBndCondCUDA.cu
-                   Operators/NeuBndCond/NeuBndCondCUDA.cu
-                   #Operators/RobBndCond/RobBndCondCUDA.cu
-                   Operators/ConjGrad/ConjGradCUDA.cu
-                   Operators/FwdTrans/FwdTransCUDA.cu
-                   Operators/HelmSolve/HelmSolveCUDA.cu 
-                   Operators/Matrix/MatrixCUDA.cu 
-       )
+
+    if(NEKTAR_FULL_DEBUG)
+        add_definitions(-DNEKTAR_CUDA_DEBUG)
+    endif()
+
+    SET(CUDA_SEPARABLE_COMPILATION ON)
+    SET(CUDA_RUNTIME_LIBRARY "SHARED")
+    IF(NOT DEFINED CMAKE_CUDA_STANDARD)
+        SET(CMAKE_CUDA_STANDARD 20) 
+        SET(CMAKE_CUDA_STANDARD_REQUIRED ON) 
+    ENDIF()
+    IF(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
+        SET(CMAKE_CUDA_ARCHITECTURES native)
+    ENDIF()
+
+endif()
+
+if (NEKTAR_USE_THREADS)
+    add_definitions(-DNEKTAR_USE_THREADS)
+endif()
+
+if (NEKTAR_USE_SERIAL)
+    add_definitions(-DNEKTAR_USE_SERIAL)
+endif()
+
+if (NEKTAR_USE_DEBUG)
+    add_definitions(-DNEKTAR_USE_DEBUG)
 endif()
 
 if (NEKTAR_USE_SIMD)
@@ -83,90 +77,42 @@ if (NEKTAR_USE_SIMD)
     add_compile_options("-march=native")
 endif()
 
-SET(OPERATORS_HEADERS
-    Operators/Operators.hpp
-)
+if (NEKTAR_MPI)
+    FIND_PACKAGE(MPI REQUIRED)
+    INCLUDE_DIRECTORIES(SYSTEM ${MPI_CXX_INCLUDE_PATH} )
+    MESSAGE(STATUS "Found MPI: ${MPI_CXX_LIBRARIES}")
+    add_definitions(-DNEKTAR_USE_MPI)
+endif()
 
-# # Boilerplate cpp implementation files for registering an operator
-# # with the factory. There are individual files for each operator shape
-# # so to reduce compile time timeout failures due to the large number
-# # of template impementations.
-
-# SET(OPERATORS BwdTrans)
-# SET(SHAPES Seg Tri Quad Hex Tet Prism Pyr )
-# SET(DIMENSIONS 1 2 2 3 3 3 3 )
-
-# # Note the commented out code is future simpler code for when cmake 3.17 can
-# # be used on the tester.
-
-# foreach(OPERATOR IN LISTS OPERATORS)
-# #  if(${CMAKE_VERSION} VERSION_LESS "3.17.0")
-# #    Remove the code in this part of the conditional once CMake 3.17
-# #    can be used on the CI tester.
-#      foreach(SHAPE IN LISTS SHAPES)
-#         IF( "${SHAPE}" STREQUAL "Seg" )
-# 	    SET(DIMENSION 1)
-#         ELSEIF( "${SHAPE}" STREQUAL "Tri" OR "${SHAPE}" STREQUAL "Quad" )
-# 	    SET(DIMENSION 2)
-# 	ELSE()
-# 	    SET(DIMENSION 3)
-#         ENDIF()
-# #  else()
-# #     Use this code once CMake 3.17 can be used on the CI tester.
-# #     foreach(SHAPE DIMENSION IN ZIP_LISTS SHAPES DIMENSIONS)
-# #  endif()
-
-# 	# Uppercase is used for the #defines in the header files.
-# 	string(TOUPPER ${SHAPE} TYPE)	
-
-#         # INST sets the macro used in NektarExpMacros.h
-#         # The BwdTrans only has regular elements.
-#         IF( "${OPERATOR}" STREQUAL "BwdTrans" )
-#             SET(INST 1)
-#         # All other operators have regular and deformed elements.
-#         ELSE()
-#             SET(INST 2)
-#         ENDIF()
-
-#         # Create the cpp file from the implementation file.
-#         configure_file(Operators/OperatorImp.cpp.in ${OPERATOR}${SHAPE}.cpp)
-
-#         # Add the respective headers and cpp file.
-#         SET(OPERATORS_HEADERS ${OPERATORS_HEADERS}
-#         ${OPERATOR}/${OPERATOR}MatFree.hpp)
-#         SET(OPERATORS_HEADERS ${OPERATORS_HEADERS}
-#         ${OPERATOR}/${OPERATOR}MatFreeKernels.hpp)
-#         SET(SRC ${SRC} ${OPERATORS_SOURCES}
-#             ${CMAKE_CURRENT_BINARY_DIR}/${OPERATOR}${SHAPE}.cpp)
-
-#     endforeach()
-# endforeach()
-
-# add_compile_options("-fsanitize=address,undefined")
-# add_link_options("-fsanitize=address,undefined")
+#INCLUDE (ThirdPartyBoost)
+SET(Boost_USE_STATIC_LIBS OFF)
+IF( WIN32 )
+    # The auto-linking feature has problems with USE_STATIC_LIBS off, so we use
+    # BOOST_ALL_NO_LIB to turn it off.
+    # Several boost libraries headers aren't configured correctly if
+    # USE_STATIC_LIBS is off, so we explicitly say they are dynamic with the
+    # remaining definitions.
+    ADD_DEFINITIONS(-DBOOST_ALL_NO_LIB -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_IOSTREAMS_DYN_LINK -DBOOST_THREAD_DYN_LINK)
+ENDIF( )
 
 add_compile_definitions(NEKTAR_FULLDEBUG) # Test ASSERT/WARNING macros
 
-add_library(Operators SHARED ${SRC})
-target_link_libraries(Operators PUBLIC ${NEKTAR++_LIBRARIES} ${NEKTAR++_TP_LIBRARIES})
-target_include_directories(Operators PRIVATE "${CMAKE_SOURCE_DIR}")
-target_compile_definitions(Operators PUBLIC ${NEKTAR++_DEFINITIONS})
-
-add_subdirectory(tests)
+INCLUDE_DIRECTORIES(Operators)
+ADD_SUBDIRECTORY(Operators)
 
 find_package(Doxygen)
 add_custom_target(doc COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/Doxyfile)
 
+IF (NEKTAR_BUILD_TESTS)
+    enable_testing()
+    add_subdirectory(tests)
+    add_definitions(-DNEKTAR_TEST_ALL)
+ENDIF (NEKTAR_BUILD_TESTS)
+
 # Turn-on warnings
-TARGET_COMPILE_OPTIONS(Operators PRIVATE -Wall -Wextra)
-IF (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-    # For GNU compilers add pedantic warnings
-    IF (NOT NEKTAR_USE_CUDA)
-        TARGET_COMPILE_OPTIONS(Operators PRIVATE -Wpedantic)
-    ENDIF()
-    TARGET_COMPILE_OPTIONS(Operators PRIVATE -Wnon-virtual-dtor)
-ENDIF()
-# Temporarily disable warnings about comparing signed and unsigned
-TARGET_COMPILE_OPTIONS(Operators PRIVATE -Wno-sign-compare)
-# Temporarily disable warnings about narrowing of data types
-TARGET_COMPILE_OPTIONS(Operators PRIVATE -Wno-narrowing -Wno-conversion)
+add_compile_options(
+  $<$<COMPILE_LANGUAGE:CXX>:$<$<CXX_COMPILER_ID:MSVC>:/W4>>
+  $<$<COMPILE_LANGUAGE:CXX>:$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -Wpedantic -Werror -Wnon-virtual-dtor -Wno-sign-compare -Wno-narrowing -Wno-conversion>>
+)
+
+add_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<$<CXX_COMPILER_ID:MSVC>:/MP>>)
diff --git a/Operators/CMakeLists.txt b/Operators/CMakeLists.txt
new file mode 100644
index 00000000..2d701c5e
--- /dev/null
+++ b/Operators/CMakeLists.txt
@@ -0,0 +1,117 @@
+MACRO(ADD_OPERATOR name)
+    SET(NAME_HEADERS ${name}_HEADERS)
+    SET(NAME_SOURCES ${name}_SOURCES)
+
+    FILE(GLOB ${NAME_HEADERS}
+        ./*${name}.hpp
+        ./${name}/*.hpp
+    )
+    FILE(GLOB ${NAME_SOURCES}
+        ./*${name}.cpp
+        ./${name}/*.cpp
+    )
+    
+    IF(NEKTAR_USE_CUDA)
+        SET(NAME_CUDA_HEADERS ${name}_CUDA_HEADERS)
+        SET(NAME_CUDA_SOURCES ${name}_CUDA_SOURCES)
+
+        FILE(GLOB ${NAME_CUDA_HEADERS}
+            ./${name}/*.cuh
+        )
+        FILE(GLOB ${NAME_CUDA_SOURCES}
+            ./${name}/*.cu
+        )
+
+        SET(${NAME_HEADERS}
+            ${${NAME_HEADERS}}
+            ${${NAME_CUDA_HEADERS}}
+        )
+        SET(${NAME_SOURCES}
+            ${${NAME_SOURCES}}
+            ${${NAME_CUDA_SOURCES}}
+        )
+    ENDIF()
+    SET(OPERATORS_HEADERS
+        ${OPERATORS_HEADERS}
+        ${${NAME_HEADERS}}
+    )
+    SET(OPERATORS_SOURCES
+        ${OPERATORS_SOURCES}
+        ${${NAME_SOURCES}}
+    )
+ENDMACRO()
+
+
+SET(OPERATORS_HEADERS
+./Operator.hpp
+./Field.hpp
+./MemoryRegionCPU.hpp
+)
+
+SET(OPERATORS_SOURCES
+./Operator.cpp
+./Field.cpp
+)
+
+ADD_OPERATOR(Identity)
+ADD_OPERATOR(BwdTrans)
+ADD_OPERATOR(IProductWRTBase)
+ADD_OPERATOR(IProductWRTDerivBase)
+ADD_OPERATOR(PhysDeriv)
+ADD_OPERATOR(Mass)
+ADD_OPERATOR(Helmholtz)
+ADD_OPERATOR(ConjGrad)
+ADD_OPERATOR(AssmbScatr)
+ADD_OPERATOR(NullPrecon)
+ADD_OPERATOR(DiagPrecon)
+ADD_OPERATOR(FwdTrans)
+ADD_OPERATOR(HelmSolve)
+ADD_OPERATOR(Matrix)
+ADD_OPERATOR(DirBndCond)
+ADD_OPERATOR(NeuBndCond)
+ADD_OPERATOR(RobBndCond)
+ADD_OPERATOR(AddTraceIntegral)
+#ADD_OPERATOR(Reduce)
+
+
+if(NEKTAR_USE_CUDA)
+    SET(OPERATORS_SOURCES
+        ${OPERATORS_SOURCES}
+        ./MemoryRegionCuda.cu
+    )
+    SET(OPERATORS_HEADERS
+        ${OPERATORS_HEADERS}
+        ./MemoryRegionCuda.hpp
+    )
+    SET(ADDITIONAL_OPERATOR_DEPS
+    CUDA::cublas
+    )
+endif()
+
+SOURCE_GROUP(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${OPERATORS_HEADERS} ${OPERATORS_SOURCES})
+
+ADD_DEFINITIONS(-DOPERATORS_EXPORTS)
+
+#ADD_NEKTAR_LIBRARY(Operators
+#    SOURCES ${OPERATORS_SOURCES}
+#    HEADERS ${OPERATORS_HEADERS} ${OPERATORS_KERNELS}
+#    DEPENDS Execution ${ADDITIONAL_OPERATOR_DEPS}
+#    SUMMARY "Nektar++ Operators library"
+#    DESCRIPTION "This library provides classes related to operators for Nektar++.")
+
+
+add_library(Operators SHARED ${OPERATORS_SOURCES}  ${OPERATORS_HEADERS})
+target_link_libraries(Operators PUBLIC ${NEKTAR++_LIBRARIES} ${NEKTAR++_TP_LIBRARIES})
+#target_link_libraries(Operators PUBLIC Execution ${ADDITIONAL_OPERATOR_DEPS})
+target_include_directories(Operators PRIVATE "${CMAKE_SOURCE_DIR}")
+target_compile_definitions(Operators PUBLIC ${NEKTAR++_DEFINITIONS})
+
+#INSTALL(TARGETS Operators
+#        LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}
+#        RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
+#
+#INSTALL(DIRECTORY ./ DESTINATION ${CMAKE_INSTALL_PREFIX}
+#        COMPONENT dev FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" PATTERN "*.cuh")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
+TARGET_INCLUDE_DIRECTORIES(Operators PUBLIC ${CMAKE_SOURCE_DIR}/Operators)
diff --git a/Field.cpp b/Operators/Field.cpp
similarity index 100%
rename from Field.cpp
rename to Operators/Field.cpp
diff --git a/Field.hpp b/Operators/Field.hpp
similarity index 100%
rename from Field.hpp
rename to Operators/Field.hpp
diff --git a/MemoryRegionCPU.hpp b/Operators/MemoryRegionCPU.hpp
similarity index 95%
rename from MemoryRegionCPU.hpp
rename to Operators/MemoryRegionCPU.hpp
index 7dcd1c2b..0ad017fb 100644
--- a/MemoryRegionCPU.hpp
+++ b/Operators/MemoryRegionCPU.hpp
@@ -29,7 +29,7 @@ public:
                     size_t alignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__)
     {
         // C++17 aligned new
-        m_host      = new (std::align_val_t(alignment)) TData[n]();
+        m_host = static_cast<TData*>(::operator new[](n * sizeof(TData), std::align_val_t(alignment)));
         m_alignment = alignment;
         m_size      = n;
     }
diff --git a/MemoryRegionCUDA.cu b/Operators/MemoryRegionCUDA.cu
similarity index 100%
rename from MemoryRegionCUDA.cu
rename to Operators/MemoryRegionCUDA.cu
diff --git a/MemoryRegionCUDA.hpp b/Operators/MemoryRegionCUDA.hpp
similarity index 100%
rename from MemoryRegionCUDA.hpp
rename to Operators/MemoryRegionCUDA.hpp
diff --git a/Operators/Operator.hpp b/Operators/Operator.hpp
index d03e3ca1..7029d8df 100644
--- a/Operators/Operator.hpp
+++ b/Operators/Operator.hpp
@@ -6,6 +6,7 @@
 #include <string>
 
 #include "Field.hpp"
+#include <OperatorsDeclspec.hpp>
 
 namespace Nektar::Operators
 {
diff --git a/Operators/OperatorAddTraceIntegral.hpp b/Operators/OperatorAddTraceIntegral.hpp
index 37130a72..288cd0d3 100644
--- a/Operators/OperatorAddTraceIntegral.hpp
+++ b/Operators/OperatorAddTraceIntegral.hpp
@@ -35,8 +35,8 @@ template <typename TData = default_fp_type> struct AddTraceIntegral
     using class_name = OperatorAddTraceIntegral<TData>;
     using FieldIn    = Field<TData, FieldState::Phys>;
     using FieldOut   = Field<TData, FieldState::Coeff>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     static std::shared_ptr<class_name> create(
         const MultiRegions::ExpListSharedPtr &expansionList,
diff --git a/Operators/OperatorAssmbScatr.hpp b/Operators/OperatorAssmbScatr.hpp
index 13ee34c5..375ee0d1 100644
--- a/Operators/OperatorAssmbScatr.hpp
+++ b/Operators/OperatorAssmbScatr.hpp
@@ -35,8 +35,8 @@ public:
 template <typename TData = default_fp_type> struct AssmbScatr
 {
     using class_name = OperatorAssmbScatr<TData>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     AssmbScatr() = delete;
 
diff --git a/Operators/OperatorBwdTrans.hpp b/Operators/OperatorBwdTrans.hpp
index 95457170..2fd37dff 100644
--- a/Operators/OperatorBwdTrans.hpp
+++ b/Operators/OperatorBwdTrans.hpp
@@ -40,8 +40,8 @@ template <typename TData = default_fp_type> struct BwdTrans
     using class_name = OperatorBwdTrans<TData>;
     using FieldIn    = Field<TData, FieldState::Coeff>;
     using FieldOut   = Field<TData, FieldState::Phys>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     BwdTrans() = delete;
 
diff --git a/Operators/OperatorConjGrad.hpp b/Operators/OperatorConjGrad.hpp
index ad1bf8ee..8f0db9ff 100644
--- a/Operators/OperatorConjGrad.hpp
+++ b/Operators/OperatorConjGrad.hpp
@@ -51,8 +51,8 @@ protected:
 template <typename TData = default_fp_type> struct ConjGrad
 {
     using class_name = OperatorConjGrad<TData>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     ConjGrad() = delete;
 
diff --git a/Operators/OperatorDiagPrecon.hpp b/Operators/OperatorDiagPrecon.hpp
index fcfbb311..f5d028a8 100644
--- a/Operators/OperatorDiagPrecon.hpp
+++ b/Operators/OperatorDiagPrecon.hpp
@@ -25,8 +25,8 @@ public:
 template <typename TData = default_fp_type> struct DiagPrecon
 {
     using class_name = OperatorDiagPrecon<TData>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     DiagPrecon() = delete;
 
diff --git a/Operators/OperatorDirBndCond.hpp b/Operators/OperatorDirBndCond.hpp
index 8f26d4a0..bf04ed86 100644
--- a/Operators/OperatorDirBndCond.hpp
+++ b/Operators/OperatorDirBndCond.hpp
@@ -32,8 +32,8 @@ public:
 template <typename TData = default_fp_type> struct DirBndCond
 {
     using class_name = OperatorDirBndCond<TData>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     DirBndCond() = delete;
 
diff --git a/Operators/OperatorFwdTrans.hpp b/Operators/OperatorFwdTrans.hpp
index be66cdfa..e84062dc 100644
--- a/Operators/OperatorFwdTrans.hpp
+++ b/Operators/OperatorFwdTrans.hpp
@@ -37,8 +37,8 @@ public:
 template <typename TData = default_fp_type> struct FwdTrans
 {
     using class_name = OperatorFwdTrans<TData>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     FwdTrans() = delete;
 
diff --git a/Operators/OperatorHelmSolve.hpp b/Operators/OperatorHelmSolve.hpp
index 9d110d6e..d204b2e5 100644
--- a/Operators/OperatorHelmSolve.hpp
+++ b/Operators/OperatorHelmSolve.hpp
@@ -33,8 +33,8 @@ public:
 template <typename TData = default_fp_type> struct HelmSolve
 {
     using class_name = OperatorHelmSolve<TData>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     HelmSolve() = delete;
 
diff --git a/Operators/OperatorHelmholtz.hpp b/Operators/OperatorHelmholtz.hpp
index 80401814..bf2e2445 100644
--- a/Operators/OperatorHelmholtz.hpp
+++ b/Operators/OperatorHelmholtz.hpp
@@ -47,8 +47,8 @@ template <typename TData = default_fp_type> struct Helmholtz
     using class_name = OperatorHelmholtz<TData>;
     using FieldIn    = Field<TData, FieldState::Coeff>;
     using FieldOut   = Field<TData, FieldState::Coeff>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     Helmholtz() = delete;
 
diff --git a/Operators/OperatorIProductWRTBase.hpp b/Operators/OperatorIProductWRTBase.hpp
index 92fe6eb8..62d5da14 100644
--- a/Operators/OperatorIProductWRTBase.hpp
+++ b/Operators/OperatorIProductWRTBase.hpp
@@ -35,8 +35,8 @@ template <typename TData = default_fp_type> struct IProductWRTBase
     using class_name = OperatorIProductWRTBase<TData>;
     using FieldIn    = Field<TData, FieldState::Phys>;
     using FieldOut   = Field<TData, FieldState::Coeff>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     IProductWRTBase() = delete;
 
diff --git a/Operators/OperatorIProductWRTDerivBase.hpp b/Operators/OperatorIProductWRTDerivBase.hpp
index 7a9e8195..cfc2c5fb 100644
--- a/Operators/OperatorIProductWRTDerivBase.hpp
+++ b/Operators/OperatorIProductWRTDerivBase.hpp
@@ -38,8 +38,8 @@ template <typename TData = default_fp_type> struct IProductWRTDerivBase
     using class_name = OperatorIProductWRTDerivBase<TData>;
     using FieldIn    = Field<TData, FieldState::Phys>;
     using FieldOut   = Field<TData, FieldState::Coeff>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     IProductWRTDerivBase() = delete;
 
diff --git a/Operators/OperatorIdentity.hpp b/Operators/OperatorIdentity.hpp
index 2063d4cb..53699d4a 100644
--- a/Operators/OperatorIdentity.hpp
+++ b/Operators/OperatorIdentity.hpp
@@ -38,8 +38,8 @@ struct Identity
     using class_name = OperatorIdentity<TData, TFieldState>;
     using FieldIn    = Field<TData, TFieldState>;
     using FieldOut   = Field<TData, TFieldState>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     Identity() = delete;
 
diff --git a/Operators/OperatorMass.hpp b/Operators/OperatorMass.hpp
index 5a2b5429..b9842117 100644
--- a/Operators/OperatorMass.hpp
+++ b/Operators/OperatorMass.hpp
@@ -40,8 +40,8 @@ template <typename TData = default_fp_type> struct Mass
     using class_name = OperatorMass<TData>;
     using FieldIn    = Field<TData, FieldState::Coeff>;
     using FieldOut   = Field<TData, FieldState::Coeff>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     Mass() = delete;
 
diff --git a/Operators/OperatorMatrix.hpp b/Operators/OperatorMatrix.hpp
index fab07ca8..ac7f4499 100644
--- a/Operators/OperatorMatrix.hpp
+++ b/Operators/OperatorMatrix.hpp
@@ -28,8 +28,8 @@ public:
 template <FieldState TFieldState, typename TData> struct Matrix
 {
     using class_name = OperatorMatrix<TData, TFieldState>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     Matrix() = delete;
 
diff --git a/Operators/OperatorNeuBndCond.hpp b/Operators/OperatorNeuBndCond.hpp
index 7d081d13..59ea82f8 100644
--- a/Operators/OperatorNeuBndCond.hpp
+++ b/Operators/OperatorNeuBndCond.hpp
@@ -31,8 +31,8 @@ public:
 template <typename TData = default_fp_type> struct NeuBndCond
 {
     using class_name = OperatorNeuBndCond<TData>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     NeuBndCond() = delete;
 
diff --git a/Operators/OperatorNullPrecon.hpp b/Operators/OperatorNullPrecon.hpp
index 4ee30bb1..d9685bf3 100644
--- a/Operators/OperatorNullPrecon.hpp
+++ b/Operators/OperatorNullPrecon.hpp
@@ -25,8 +25,8 @@ public:
 template <typename TData = default_fp_type> struct NullPrecon
 {
     using class_name = OperatorNullPrecon<TData>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     NullPrecon() = delete;
 
diff --git a/Operators/OperatorPhysDeriv.hpp b/Operators/OperatorPhysDeriv.hpp
index 38b2f0ac..56dd3a0e 100644
--- a/Operators/OperatorPhysDeriv.hpp
+++ b/Operators/OperatorPhysDeriv.hpp
@@ -40,8 +40,8 @@ template <typename TData = default_fp_type> struct PhysDeriv
     using class_name = OperatorPhysDeriv<TData>;
     using FieldIn    = Field<TData, FieldState::Phys>;
     using FieldOut   = Field<TData, FieldState::Phys>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     PhysDeriv() = delete;
 
diff --git a/Operators/OperatorRobBndCond.hpp b/Operators/OperatorRobBndCond.hpp
index 0b38b479..5c86b142 100644
--- a/Operators/OperatorRobBndCond.hpp
+++ b/Operators/OperatorRobBndCond.hpp
@@ -29,8 +29,8 @@ public:
 template <typename TData = default_fp_type> struct RobBndCond
 {
     using class_name = OperatorRobBndCond<TData>;
-    static const std::string key;
-    static const std::string default_impl;
+    OPERATORS_EXPORT static const std::string key;
+    OPERATORS_EXPORT static const std::string default_impl;
 
     RobBndCond() = delete;
 
diff --git a/Operators/OperatorsDeclspec.hpp b/Operators/OperatorsDeclspec.hpp
new file mode 100644
index 00000000..d76e5aa1
--- /dev/null
+++ b/Operators/OperatorsDeclspec.hpp
@@ -0,0 +1,14 @@
+#ifndef NEKTAR__OPERATORS_OPERATORS_DECLSPEC_H
+#define NEKTAR__OPERATORS_OPERATORS_DECLSPEC_H
+
+#if defined(_MSC_VER)
+#ifdef OPERATORS_EXPORTS
+#define OPERATORS_EXPORT _declspec(dllexport)
+#else
+#define OPERATORS_EXPORT _declspec(dllimport)
+#endif
+#else
+#define OPERATORS_EXPORT
+#endif
+
+#endif // NEKTAR__OPERATORS_OPERATORS_DECLSPEC_H
-- 
GitLab