Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • nektar/redesign-prototypes
1 result
Show changes
Commits on Source (11)
Showing
with 519 additions and 103 deletions
build build
buildDebug
builds
.ccls-cache/ .ccls-cache/
a.out a.out
.ccls-cache/ .ccls-cache/
.cache .cache
.*
!.gitignore
!.gitlab-ci.yml
!.gitattributes
!.clang-format
!.dockerignore
!.gitlab-ci
...@@ -22,7 +22,7 @@ message(STATUS "Found Nektar++: version ${NEKTAR++_VERSION}") ...@@ -22,7 +22,7 @@ message(STATUS "Found Nektar++: version ${NEKTAR++_VERSION}")
set(CMAKE_INSTALL_RPATH "${NEKTAR++_LIBRARY_DIRS}") set(CMAKE_INSTALL_RPATH "${NEKTAR++_LIBRARY_DIRS}")
set(SRC Operators/Operator.cpp Operators/OperatorBwdTrans.cpp Operators/BwdTrans/BwdTransImpl.cpp) set(SRC Field.cpp Operators/Operator.cpp Operators/OperatorBwdTrans.cpp Operators/BwdTrans/BwdTransImpl.cpp Operators/OperatorIProductWRTBase.cpp Operators/IProductWRTBase/IProductWRTBaseImpl.cpp)
if (NEKTAR_USE_CUDA) if (NEKTAR_USE_CUDA)
enable_language(CUDA) enable_language(CUDA)
......
#include "Field.hpp"
#include <MultiRegions/ExpList.h>
using namespace Nektar;
using namespace LibUtilities;
std::vector<BlockAttributes> GetBlockAttributes(
FieldState state, const MultiRegions::ExpListSharedPtr explist)
{
std::vector<BlockAttributes> blockAttr;
// initialize the basisKeys
std::vector<BasisKey> prevbasisKeys(3, NullBasisKey);
std::vector<BasisKey> thisbasisKeys(3, NullBasisKey);
int prevIsDeformed = -1, thisIsDeformed = -1;
// loop over elements
for (int i = 0; i < explist->GetNumElmts(); i++)
{
auto expPtr = explist->GetExp(i);
// fetch basiskeys of current element
for (int d = 0; d < expPtr->GetNumBases(); d++)
{
thisbasisKeys[d] = expPtr->GetBasis(d)->GetBasisKey();
}
thisIsDeformed = expPtr->GetMetricInfo()->GetGtype();
// if the basis is the same as the previous one,
// increment the number of elements
if (thisbasisKeys == prevbasisKeys && thisIsDeformed == prevIsDeformed)
{
blockAttr.back().num_elements++;
blockAttr.back().block_size += blockAttr.back().num_pts;
}
else // if not, create a new block with the number of elements = 1
{
size_t num_pts = state == FieldState::Phys ? expPtr->GetTotPoints()
: expPtr->GetNcoeffs();
blockAttr.push_back({1, num_pts});
prevbasisKeys = thisbasisKeys;
prevIsDeformed = thisIsDeformed;
}
}
return blockAttr;
}
#pragma once #pragma once
#include <StdRegions/StdExpansion.h>
#include <StdRegions/StdRegions.hpp>
#include <array> #include <array>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
...@@ -14,7 +12,15 @@ ...@@ -14,7 +12,15 @@
#include <LibUtilities/BasicUtils/ErrorUtil.hpp> #include <LibUtilities/BasicUtils/ErrorUtil.hpp>
#include <LibUtilities/BasicUtils/ShapeType.hpp> #include <LibUtilities/BasicUtils/ShapeType.hpp>
#include <LibUtilities/BasicUtils/SharedArray.hpp> #include <LibUtilities/BasicUtils/SharedArray.hpp>
#include <StdRegions/StdExpansion.h>
namespace Nektar
{
namespace MultiRegions
{
class ExpList;
typedef std::shared_ptr<ExpList> ExpListSharedPtr;
} // namespace MultiRegions
} // namespace Nektar
/** /**
* @brief Captures the structure of a block of elements of identical shape * @brief Captures the structure of a block of elements of identical shape
...@@ -49,6 +55,9 @@ enum class FieldState ...@@ -49,6 +55,9 @@ enum class FieldState
static constexpr FieldState DefaultState = FieldState::Phys; static constexpr FieldState DefaultState = FieldState::Phys;
std::vector<BlockAttributes> GetBlockAttributes(
FieldState state, const Nektar::MultiRegions::ExpListSharedPtr explist);
/** /**
* @brief A Field represents expansion data to be operated on. * @brief A Field represents expansion data to be operated on.
* @tparam TType The floating-point representation used by the field. * @tparam TType The floating-point representation used by the field.
...@@ -56,8 +65,6 @@ static constexpr FieldState DefaultState = FieldState::Phys; ...@@ -56,8 +65,6 @@ static constexpr FieldState DefaultState = FieldState::Phys;
*/ */
template <typename TType = double, FieldState TState = DefaultState> class Field template <typename TType = double, FieldState TState = DefaultState> class Field
{ {
using ExpansionSharedPtr = Nektar::StdRegions::StdExpansionSharedPtr;
public: public:
Field(const Field &) = delete; Field(const Field &) = delete;
virtual ~Field() = default; virtual ~Field() = default;
......
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
template <typename TData> class MemoryRegionCPU template <typename TData> class MemoryRegionCPU
{ {
public: public:
MemoryRegionCPU() = delete; MemoryRegionCPU() = delete;
MemoryRegionCPU(const MemoryRegionCPU &rhs) = delete; MemoryRegionCPU(const MemoryRegionCPU &rhs) = delete;
MemoryRegionCPU &operator=(const MemoryRegionCPU &rhs) = delete; MemoryRegionCPU &operator=(const MemoryRegionCPU &rhs) = delete;
MemoryRegionCPU(MemoryRegionCPU &&rhs) MemoryRegionCPU(MemoryRegionCPU &&rhs)
......
...@@ -42,10 +42,10 @@ public: ...@@ -42,10 +42,10 @@ public:
void operator=(MemoryRegionCUDA &&rhs) void operator=(MemoryRegionCUDA &&rhs)
{ {
MemoryRegionCPU<TData>::operator=(std::move(rhs)); MemoryRegionCPU<TData>::operator=(std::move(rhs));
m_device = rhs.m_device; m_device = rhs.m_device;
m_size = rhs.m_size; m_size = rhs.m_size;
rhs.m_device = nullptr; rhs.m_device = nullptr;
rhs.m_size = 0; rhs.m_size = 0;
} }
virtual TData *GetCPUPtr() override virtual TData *GetCPUPtr() override
......
#include "BwdTransStdMat.hpp"
#include "BwdTransMatFree.hpp" #include "BwdTransMatFree.hpp"
#include "BwdTransStdMat.hpp"
#include "BwdTransSumFac.hpp" #include "BwdTransSumFac.hpp"
namespace Nektar::Operators::detail namespace Nektar::Operators::detail
......
...@@ -20,10 +20,11 @@ public: ...@@ -20,10 +20,11 @@ public:
auto const *inptr = in.GetStorage().GetCPUPtr(); auto const *inptr = in.GetStorage().GetCPUPtr();
auto *outptr = out.GetStorage().GetCPUPtr(); auto *outptr = out.GetStorage().GetCPUPtr();
size_t exp_idx = 0;
for (size_t block_idx = 0; block_idx < in.GetBlocks().size(); for (size_t block_idx = 0; block_idx < in.GetBlocks().size();
++block_idx) ++block_idx)
{ {
auto const expPtr = this->m_expansionList->GetExp(block_idx); auto const expPtr = this->m_expansionList->GetExp(exp_idx);
Nektar::StdRegions::StdMatrixKey key( Nektar::StdRegions::StdMatrixKey key(
StdRegions::eBwdTrans, expPtr->DetShapeType(), *expPtr); StdRegions::eBwdTrans, expPtr->DetShapeType(), *expPtr);
...@@ -38,6 +39,7 @@ public: ...@@ -38,6 +39,7 @@ public:
inptr += block.block_size; inptr += block.block_size;
outptr += expPtr->GetTotPoints() * block.num_elements; outptr += expPtr->GetTotPoints() * block.num_elements;
exp_idx += block.num_elements;
} }
} }
......
#include "IProductWRTBaseStdMat.hpp"
namespace Nektar::Operators::detail
{
// Add different IProductWRTBase implementations to the factory.
template <>
std::string OperatorIProductWRTBaseImpl<double, ImplStdMat>::className =
GetOperatorFactory<double>().RegisterCreatorFunction(
"IProductWRTBaseStdMat",
OperatorIProductWRTBaseImpl<double, ImplStdMat>::instantiate, "...");
} // namespace Nektar::Operators::detail
#include "Operators/OperatorIProductWRTBase.hpp"
#include <StdRegions/StdExpansion.h>
namespace Nektar::Operators::detail
{
// standard matrix implementation
template <typename TData>
class OperatorIProductWRTBaseImpl<TData, ImplStdMat>
: public OperatorIProductWRTBase<TData>
{
public:
OperatorIProductWRTBaseImpl(
const MultiRegions::ExpListSharedPtr &expansionList)
: OperatorIProductWRTBase<TData>(std::move(expansionList))
{
size_t jacSize = 0;
size_t nTotElmts = this->m_expansionList->GetNumElmts();
// Calculate the jacobian array size
for (size_t e = 0; e < nTotElmts; ++e)
{
// Determine shape and type of the element
auto const expPtr = this->m_expansionList->GetExp(e);
if (expPtr->GetMetricInfo()->GetGtype() ==
SpatialDomains::eDeformed)
{
jacSize += expPtr->GetTotPoints();
}
else
{
jacSize++;
}
}
// Allocate memory for the jacobian
m_jac = {jacSize, 0.0};
// Initialise jacobian.
size_t index = 0;
for (size_t e = 0; e < nTotElmts; ++e)
{
auto expPtr = this->m_expansionList->GetExp(e);
auto &auxJac =
expPtr->GetMetricInfo()->GetJac(expPtr->GetPointsKeys());
if (expPtr->GetMetricInfo()->GetGtype() ==
SpatialDomains::eDeformed)
{
size_t nqe = expPtr->GetTotPoints();
for (size_t i = 0; i < nqe; ++i)
{
m_jac[index++] = auxJac[i];
}
}
else
{
m_jac[index++] = auxJac[0];
}
}
}
void apply(Field<TData, FieldState::Phys> &in,
Field<TData, FieldState::Coeff> &out) override
{
auto const *inptr = in.GetStorage().GetCPUPtr();
auto *outptr = out.GetStorage().GetCPUPtr();
size_t expIdx = 0;
size_t jacIdx = 0;
for (size_t block_idx = 0; block_idx < in.GetBlocks().size();
++block_idx)
{
auto const expPtr = this->m_expansionList->GetExp(expIdx);
auto nElmts = in.GetBlocks()[block_idx].num_elements;
auto nqTot = expPtr->GetTotPoints();
auto nmTot = expPtr->GetNcoeffs();
Nektar::StdRegions::StdMatrixKey key(
StdRegions::eIProductWRTBase, expPtr->DetShapeType(), *expPtr);
// This is the B^{T} matrix
auto const matPtr = expPtr->GetStdMatrix(key);
Array<OneD, NekDouble> wsp(nqTot * nElmts, 0.0);
if (expPtr->GetMetricInfo()->GetGtype() ==
SpatialDomains::eDeformed)
{
for (size_t i = 0; i < nElmts * nqTot; ++i)
{
wsp[i] = m_jac[jacIdx++] * inptr[i];
}
}
else
{
for (size_t e = 0; e < nElmts; ++e)
{
for (size_t i = 0; i < nqTot; ++i)
{
wsp[e * nqTot + i] =
m_jac[jacIdx] * inptr[e * nqTot + i];
}
jacIdx++;
}
}
Blas::Dgemm('N', 'N', matPtr->GetRows(), nElmts,
matPtr->GetColumns(), 1.0, matPtr->GetRawPtr(),
matPtr->GetRows(), wsp.get(), nqTot, 0.0, outptr,
nmTot);
inptr += nqTot * nElmts;
outptr += nmTot * nElmts;
expIdx += nElmts;
}
}
static std::unique_ptr<Operator<TData>> instantiate(
const MultiRegions::ExpListSharedPtr &expansionList)
{
return std::make_unique<OperatorIProductWRTBaseImpl<TData, ImplStdMat>>(
std::move(expansionList));
}
static std::string className;
private:
Array<OneD, NekDouble> m_jac;
};
} // namespace Nektar::Operators::detail
#pragma once #pragma once
#include "Field.hpp"
#include <string> #include <string>
#include <LibUtilities/BasicUtils/NekFactory.hpp> #include <LibUtilities/BasicUtils/NekFactory.hpp>
......
#include "OperatorIProductWRTBase.hpp"
namespace Nektar::Operators
{
template <> const std::string IProductWRTBase<>::key = "IProductWRTBase";
template <> const std::string IProductWRTBase<>::default_impl = "StdMat";
} // namespace Nektar::Operators
\ No newline at end of file
#pragma once
#include "Field.hpp"
#include "Operator.hpp"
namespace Nektar::Operators
{
// IProductWRTBase base class
// Defines the apply operator to enforce apply parameter types
template <typename TData> class OperatorIProductWRTBase : public Operator<TData>
{
public:
virtual ~OperatorIProductWRTBase() = default;
OperatorIProductWRTBase(const MultiRegions::ExpListSharedPtr &expansionList)
: Operator<TData>(std::move(expansionList))
{
}
virtual void apply(Field<TData, FieldState::Phys> &in,
Field<TData, FieldState::Coeff> &out) = 0;
virtual void operator()(Field<TData, FieldState::Phys> &in,
Field<TData, FieldState::Coeff> &out)
{
apply(in, out);
}
};
// Descriptor / traits class for IProductWRTBase
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;
static std::shared_ptr<class_name> create(
const MultiRegions::ExpListSharedPtr &expansionList,
std::string pKey = "")
{
return Operator<TData>::template create<IProductWRTBase>(
std::move(expansionList), pKey);
}
};
namespace detail
{
// Template for IProductWRTBase implementations
template <typename TData, typename Op> class OperatorIProductWRTBaseImpl;
} // namespace detail
} // namespace Nektar::Operators
<?xml version="1.0" encoding="utf-8" ?>
<NEKTAR>
<GEOMETRY DIM="1" SPACE="1">
<VERTEX COMPRESSED="B64Z-LittleEndian" BITSIZE="64">eJxjYMAPGFF4H+zR5QEVbwEx</VERTEX>
<ELEMENT>
<S COMPRESSED="B64Z-LittleEndian" BITSIZE="64">eJxjYEAFjFAaAAAgAAIA</S>
</ELEMENT>
<COMPOSITE>
<C ID="0"> S[0] </C>
</COMPOSITE>
<DOMAIN>
<D ID="0"> C[0] </D>
</DOMAIN>
</GEOMETRY>
<Metadata>
<Provenance>
<GitBranch>refs/heads/master</GitBranch>
<GitSHA1>b9041a54043f57d230bcc1eb5be5c9a048b69a92</GitSHA1>
<Hostname>dyn3237-113.wlan.ic.ac.uk</Hostname>
<NektarVersion>5.3.0</NektarVersion>
<Timestamp>07-Jun-2023 11:25:53</Timestamp>
</Provenance>
<NekMeshCommandLine>-v line.msh line.xml </NekMeshCommandLine>
</Metadata>
<EXPANSIONS>
<E COMPOSITE="C[0]" NUMMODES="6" TYPE="MODIFIED" FIELDS="u" />
</EXPANSIONS>
</NEKTAR>
...@@ -14,11 +14,12 @@ ...@@ -14,11 +14,12 @@
#include "Field.hpp" #include "Field.hpp"
#include "Operators/OperatorBwdTrans.hpp" #include "Operators/OperatorBwdTrans.hpp"
#include "Operators/OperatorIProductWRTBase.hpp"
#include <LibUtilities/BasicUtils/SessionReader.h> #include <LibUtilities/BasicUtils/SessionReader.h>
//#include <LibUtilities/SimdLib/tinysimd.hpp> //#include <LibUtilities/SimdLib/tinysimd.hpp>
#include <SpatialDomains/MeshGraph.h>
#include <MultiRegions/ExpList.h> #include <MultiRegions/ExpList.h>
#include <SpatialDomains/MeshGraph.h>
#ifdef NEKTAR_USE_CUDA #ifdef NEKTAR_USE_CUDA
#include "MemoryRegionCUDA.hpp" #include "MemoryRegionCUDA.hpp"
...@@ -41,46 +42,26 @@ std::ostream &operator<<(std::ostream &stream, Field<TType, State> &f) ...@@ -41,46 +42,26 @@ std::ostream &operator<<(std::ostream &stream, Field<TType, State> &f)
return stream; return stream;
} }
std::vector<BlockAttributes> GetBlockAttributes(
FieldState state,
const MultiRegions::ExpListSharedPtr explist)
{
const int n = explist->GetNumElmts();
std::map<std::tuple<LibUtilities::ShapeType,unsigned int,unsigned int>,size_t> blockList;
for (int i = 0; i < explist->GetNumElmts(); ++i)
{
auto e = explist->GetExp(i);
blockList[{e->DetShapeType(),e->GetNcoeffs(),e->GetTotPoints()}]++;
}
std::vector<BlockAttributes> blockAttr;
for (auto &x : blockList)
{
auto val = state == FieldState::Phys ? std::get<2>(x.first) : std::get<1>(x.first);
blockAttr.push_back( { x.second, val } );
}
return blockAttr;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// Initialise a session, graph and create an expansion list // Initialise a session, graph and create an expansion list
LibUtilities::SessionReaderSharedPtr session; LibUtilities::SessionReaderSharedPtr session;
SpatialDomains::MeshGraphSharedPtr graph; SpatialDomains::MeshGraphSharedPtr graph;
MultiRegions::ExpListSharedPtr explist; MultiRegions::ExpListSharedPtr explist;
session = LibUtilities::SessionReader::CreateInstance(argc, argv); session = LibUtilities::SessionReader::CreateInstance(argc, argv);
graph = SpatialDomains::MeshGraph::Read(session); graph = SpatialDomains::MeshGraph::Read(session);
explist = MemoryManager<MultiRegions::ExpList>::AllocateSharedPtr explist =
(session, graph); MemoryManager<MultiRegions::ExpList>::AllocateSharedPtr(session, graph);
// Generate a blocks definition from the expansion list for each state // Generate a blocks definition from the expansion list for each state
auto blocks_phys = GetBlockAttributes(FieldState::Phys, explist); auto blocks_phys = GetBlockAttributes(FieldState::Phys, explist);
auto blocks_coeff = GetBlockAttributes(FieldState::Coeff, explist); auto blocks_coeff = GetBlockAttributes(FieldState::Coeff, explist);
// Create two Field objects with a MemoryRegionCPU backend by default // Create two Field objects with a MemoryRegionCPU backend by default
auto in = Field<double, FieldState::Coeff>::create(blocks_coeff); auto in = Field<double, FieldState::Coeff>::create(blocks_coeff);
auto in2 = Field<double, FieldState::Coeff>::create(blocks_coeff); auto in2 = Field<double, FieldState::Coeff>::create(blocks_coeff);
auto out = Field<double, FieldState::Phys >::create(blocks_phys); auto out = Field<double, FieldState::Phys>::create(blocks_phys);
// Populate the field with some data. In this case, we just grab a pointer // Populate the field with some data. In this case, we just grab a pointer
// to the memory on the CPU and populate the array with values. Operators, // to the memory on the CPU and populate the array with values. Operators,
...@@ -106,15 +87,16 @@ int main(int argc, char *argv[]) ...@@ -106,15 +87,16 @@ int main(int argc, char *argv[])
} }
} }
memset(out.GetStorage().GetCPUPtr(), 0, out.GetStorage().size()*sizeof(double)); memset(out.GetStorage().GetCPUPtr(), 0,
out.GetStorage().size() * sizeof(double));
std::cout << "Initial shape:\n" << in << std::endl << std::endl; std::cout << "Initial shape:\n" << in << std::endl << std::endl;
#ifdef NEKTAR_ENABLE_SIMD_AVX2
// Test out field reshaping // Test out field reshaping
in.ReshapeStorage<4>(); in.ReshapeStorage<4>();
std::cout << "Reshaped to 4:\n" << in << std::endl << std::endl; std::cout << "Reshaped to 4:\n" << in << std::endl << std::endl;
#ifdef NEKTAR_ENABLE_SIMD_AVX2
// Test out SIMD instructions // Test out SIMD instructions
using vec_t = tinysimd::simd<double>; using vec_t = tinysimd::simd<double>;
...@@ -195,14 +177,15 @@ int main(int argc, char *argv[]) ...@@ -195,14 +177,15 @@ int main(int argc, char *argv[])
std::cout << out << std::endl; std::cout << out << std::endl;
#ifdef NEKTAR_USE_CUDA #ifdef NEKTAR_USE_CUDA
// Test CUDA MemoryRegion // Test CUDA MemoryRegion
// Create two Fields with memory on the GPU // Create two Fields with memory on the GPU
in = Field<double, FieldState::Coeff>::create<MemoryRegionCUDA>(blocks_coeff); in = Field<double, FieldState::Coeff>::create<MemoryRegionCUDA>(
out = Field<double, FieldState::Phys>::create<MemoryRegionCUDA>(blocks_phys); blocks_coeff);
out =
Field<double, FieldState::Phys>::create<MemoryRegionCUDA>(blocks_phys);
// Perform the BwdTrans on the fields using the CUDA implementation // Perform the BwdTrans on the fields using the CUDA implementation
// Since this is a CUDA operator, acting on CUDA fields, everything happens // Since this is a CUDA operator, acting on CUDA fields, everything happens
...@@ -224,6 +207,40 @@ int main(int argc, char *argv[]) ...@@ -224,6 +207,40 @@ int main(int argc, char *argv[])
BwdTrans<>::create(explist, "CUDA")->apply(in, out); BwdTrans<>::create(explist, "CUDA")->apply(in, out);
#endif #endif
std::cout << "Inner Product of a function WRT the Basis" << std::endl;
// Create two Field objects with a MemoryRegionCPU backend by default
// for the inner product with respect to base
auto inPhys = Field<double, FieldState::Phys>::create(blocks_phys);
auto outCoeff = Field<double, FieldState::Coeff>::create(blocks_coeff);
double *y = inPhys.GetStorage().GetCPUPtr();
for (auto const &block : blocks_phys)
{
for (size_t el = 0; el < block.num_elements; ++el)
{
for (size_t phys = 0; phys < block.num_pts; ++phys)
{
// Each element is the index of the quadrature points
// this is useful for testing reshapes
*(y++) = phys;
}
}
}
memset(outCoeff.GetStorage().GetCPUPtr(), 0,
outCoeff.GetStorage().size() * sizeof(double));
std::cout << "Initial shape:\n" << inPhys << std::endl << std::endl;
// IProductWRTBase
auto ipwrtb = IProductWRTBase<>::create(explist, "StdMat");
// ... and then apply it
ipwrtb->apply(inPhys, outCoeff); // out and in is inverted for the IP
// Let's display the result
std::cout << "Out:\n" << outCoeff << std::endl;
std::cout << "END" << std::endl; std::cout << "END" << std::endl;
return 0; return 0;
} }
<?xml version="1.0" encoding="utf-8" ?>
<NEKTAR>
<GEOMETRY DIM="2" SPACE="2">
<VERTEX COMPRESSED="B64Z-LittleEndian" BITSIZE="64">eJx1j8sVgjAABIOIgIrK324o3RYoIaV4yi7guBfey2SySwjbxM/+G0K24+sPPyFfxXN83/yMvlOg71y4f0knJfeLV+hH8Rp98+tx0GHnDbn/847cadhX/4P7xZ/oed8Lufe1f3pTOvZ1r+d+8QF3e9+I3Psm5M7Mvu69uV/8C2/eNsUA</VERTEX>
<EDGE COMPRESSED="B64Z-LittleEndian" BITSIZE="64">eJx1kEkSglAMBQEVZxxBHEARh/vf0I29oKvyN6l+FUI6STJ8aVCzoI6CyhurH54EnIuZN1U/fTMxfXMx8xbB90sx36+Ceet/5T7MLcTM3Yi5x1Y5/9uJ8d4rZ4+DGL+jcvYrxXhX2p+9T2L2rgOPs3J8LmI8rsrxvInxaJTj34rxu2t/7vIQc5dOjMdTOffqxXi8lHPHtxiPj3Lu+xXj9wOocAa/</EDGE>
<ELEMENT>
<Q COMPRESSED="B64Z-LittleEndian" BITSIZE="64">eJx10EcOwjAABdFQ0kkPvYTO/W/IZrxgJLx50kSyvxJFv2eGc1z86UuMMdH30FPMMNe9oRdY4krvVFhjo12xeoud7knUexy0N1Ufca29Yf8Gt7jT3lx9jwftLdSPeNLeUv2MF+0N/3HCK960t1K/40N7a/UnvrS3UX/jR3u/iOQFQAAA</Q>
</ELEMENT>
<COMPOSITE>
<C ID="0"> Q[0-11] </C>
<C ID="1"> E[0,13,22,31,11,21,30,39,3,6,9,12,32,34,36,38] </C>
<C ID="2"> Q[12-15] </C>
</COMPOSITE>
<DOMAIN> C[0,2] </DOMAIN>
</GEOMETRY>
<Metadata>
<Provenance>
<GitBranch></GitBranch>
<GitSHA1>88b1cb3be29cc9090d8a14af19c26decd88345db</GitSHA1>
<Hostname>kingscross</Hostname>
<NektarVersion>5.1.0</NektarVersion>
<Timestamp>27-Apr-2023 15:32:08</Timestamp>
</Provenance>
<NekMeshCommandLine>square.msh square.xml </NekMeshCommandLine>
</Metadata>
<EXPANSIONS>
<E COMPOSITE="C[0]" NUMMODES="4" TYPE="MODIFIED" FIELDS="u" />
<E COMPOSITE="C[2]" NUMMODES="3" TYPE="MODIFIED" FIELDS="u" />
</EXPANSIONS>
<CONDITIONS>
<SOLVERINFO>
<I PROPERTY="EQTYPE" VALUE="Helmholtz" />
</SOLVERINFO>
<VARIABLES>
<V ID="0">u</V>
</VARIABLES>
<FUNCTION NAME="Forcing">
<E VAR="u" VALUE="0" />
</FUNCTION>
</CONDITIONS>
</NEKTAR>
<?xml version="1.0" encoding="utf-8" ?>
<NEKTAR>
<GEOMETRY DIM="2" SPACE="2">
<VERTEX COMPRESSED="B64Z-LittleEndian" BITSIZE="64">eJxjYICAx7ZT/D4/OW/vfW1rRBvvBXuoMAMjAyoo9QCRCHkmBvyAGUr/XPwfCM7bo8uzoPAeYMizosmjm8OGVT/CHHas9iPkObC6GiHPiSL+AcN9XGjy6O7jhtJ6YPKFfcsjVHkeFP0vMMznxSqPcB8fVvch5PlR5GHiCHsEoPQntRlz3sx8aS+W9+p69IyXcHlBKK0QYgwEr+195s0Ego9weSGs5iPCSRjmsikQfZ1CEHNg8iJQ2hgMPtvDaJi8KMzn4IRywd4Dzf1iDNgAQl4cSqOmW4T7JLDqR8gDAHwmZuEA</VERTEX>
<EDGE COMPRESSED="B64Z-LittleEndian" BITSIZE="64">eJx1kkcSwlAMQ0MLoQZC7z3c/4Zs/Ba8GXuj0ZflyJ4UxX91Euwm2EuQ6usdPkh4KU4Nk75KnL6RODXWO/6JOHtP5WPuTD70uXzotfzoC3HusQxkX+Y0yfdXgaX0tXKRc6M+9K3ykm8nTr69OPkO4sw7Ki/zTuLkOisfvovmsvc1kL3JdZMf/R7I/8BdHuLc5SnO//IK5E7c5S2O76P5+NrAWvo3sFH/D7Z4BrgA</EDGE>
<ELEMENT>
<Q COMPRESSED="B64Z-LittleEndian" BITSIZE="64">eJx10ccSwjAMRdEAofeS0CH0//9DNvcueDNkc8a2LEtKUfx+LWxjJ/Zdl9jFXtxz3ccBDiPPCMdRh3G+M8EpznAedSzifPmnTvdXuI56dYNVxFuHfdW4xR3u0X4OeIy8J3Qe5jtHfd5zXpd41/xXdG7mbfCGd7SfBz4j7oXO1b6t7x35/S+fuG+cc/kCmoQFPwAA</Q>
</ELEMENT>
<COMPOSITE>
<C ID="13"> E[36,34,11,1] </C>
<C ID="14"> E[2,4,16,15] </C>
<C ID="15"> E[12,20,28,31] </C>
<C ID="16"> E[30,24,39,35] </C>
<C ID="17"> Q[0-15] </C>
</COMPOSITE>
<DOMAIN>
<D ID="0"> C[17] </D>
</DOMAIN>
</GEOMETRY>
<EXPANSIONS>
<E COMPOSITE="C[17]" NUMMODES="4" TYPE="MODIFIED" FIELDS="u" />
</EXPANSIONS>
</NEKTAR>
set(test_src test_bwdtrans.cpp)
find_package( find_package(
Boost Boost
REQUIRED REQUIRED
COMPONENTS unit_test_framework COMPONENTS unit_test_framework
) )
add_executable(test_bwdtrans ${test_src}) add_executable(test_bwdtrans test_bwdtrans.cpp)
target_link_libraries(test_bwdtrans PRIVATE Operators) target_link_libraries(test_bwdtrans PRIVATE Operators)
target_link_libraries(test_bwdtrans PRIVATE ${NEKTAR++_LIBRARIES}) target_link_libraries(test_bwdtrans PRIVATE ${NEKTAR++_LIBRARIES})
target_link_libraries(test_bwdtrans PRIVATE Boost::unit_test_framework) target_link_libraries(test_bwdtrans PRIVATE Boost::unit_test_framework)
target_include_directories(test_bwdtrans PRIVATE "${CMAKE_SOURCE_DIR}") target_include_directories(test_bwdtrans PRIVATE "${CMAKE_SOURCE_DIR}")
target_include_directories(test_bwdtrans PRIVATE ${NEKTAR++_INCLUDE_DIRS}) target_include_directories(test_bwdtrans PRIVATE ${NEKTAR++_INCLUDE_DIRS})
target_compile_definitions(test_bwdtrans PRIVATE
-DTEST_PATH="${CMAKE_SOURCE_DIR}")
add_executable(test_ipwrtbase test_ipwrtbase.cpp)
target_link_libraries(test_ipwrtbase PRIVATE Operators)
target_link_libraries(test_ipwrtbase PRIVATE ${NEKTAR++_LIBRARIES})
target_link_libraries(test_ipwrtbase PRIVATE Boost::unit_test_framework)
target_include_directories(test_ipwrtbase PRIVATE "${CMAKE_SOURCE_DIR}")
target_include_directories(test_ipwrtbase PRIVATE ${NEKTAR++_INCLUDE_DIRS})
target_compile_definitions(test_ipwrtbase PRIVATE
-DTEST_PATH="${CMAKE_SOURCE_DIR}")
add_test( add_test(
NAME BwdTrans NAME BwdTrans
COMMAND test_bwdtrans COMMAND test_bwdtrans
# Test executable is looking for input session file in the working # Test executable is looking for input session file in the working
# directory # directory
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/input" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
)
add_test(
NAME IProductWRTBase
COMMAND test_ipwrtbase
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
) )
#pragma once
#include <boost/test/unit_test_log.hpp> #include <boost/test/unit_test_log.hpp>
#include <vector>
#include <string> #include <string>
#include <vector>
#include "Field.hpp" #include "Field.hpp"
#include <MultiRegions/ExpList.h> #include <MultiRegions/ExpList.h>
#include <Operators/OperatorBwdTrans.hpp> #include <Operators/OperatorBwdTrans.hpp>
#include <Operators/OperatorIProductWRTBase.hpp>
using namespace Nektar::Operators; using namespace Nektar::Operators;
using namespace Nektar::LibUtilities; using namespace Nektar::LibUtilities;
...@@ -18,62 +20,57 @@ using namespace Nektar; ...@@ -18,62 +20,57 @@ using namespace Nektar;
* before (after) each call to BOOST_FIXTURE_TEST_CASE(<test name>, * before (after) each call to BOOST_FIXTURE_TEST_CASE(<test name>,
* InitFields) macro. * InitFields) macro.
* *
* See "Single test case fixture" on the Boost.Test documentation for more details: * See "Single test case fixture" on the Boost.Test documentation for more
* details:
* https://www.boost.org/doc/libs/1_82_0/libs/test/doc/html/boost_test/tests_organization/fixtures/case.html * https://www.boost.org/doc/libs/1_82_0/libs/test/doc/html/boost_test/tests_organization/fixtures/case.html
*/ */
struct InitFields {
Field<double, FieldState::Coeff> *fixt_in;
Field<double, FieldState::Phys> *fixt_out;
MultiRegions::ExpListSharedPtr fixt_explist {nullptr};
~InitFields() {BOOST_TEST_MESSAGE("teardown fixture");}
template <FieldState stateIn = FieldState::Coeff,
static std::vector<BlockAttributes> FieldState stateOut = FieldState::Phys>
GetBlockAttributes(FieldState state, class InitFields
const MultiRegions::ExpListSharedPtr explist) { {
const int n = explist->GetNumElmts(); public:
std::map<std::tuple<LibUtilities::ShapeType,unsigned int,unsigned int>,size_t> blockList; Field<double, stateIn> *fixt_in;
for (int i = 0; i < explist->GetNumElmts(); ++i) Field<double, stateOut> *fixt_out;
MultiRegions::ExpListSharedPtr fixt_explist{nullptr};
~InitFields()
{ {
auto e = explist->GetExp(i); BOOST_TEST_MESSAGE("teardown fixture");
blockList[{e->DetShapeType(),e->GetNcoeffs(),e->GetTotPoints()}]++;
} }
std::vector<BlockAttributes> blockAttr;
for (auto &x : blockList) InitFields()
{ {
auto val = state == FieldState::Phys ? std::get<2>(x.first) : std::get<1>(x.first);
blockAttr.push_back( { x.second, val } );
} }
return blockAttr;
}
InitFields() { void Configure()
BOOST_TEST_MESSAGE("Creating input and output fields"); {
// Initialise a session, graph and create an expansion list BOOST_TEST_MESSAGE("Creating input and output fields");
LibUtilities::SessionReaderSharedPtr session; // Initialise a session, graph and create an expansion list
SpatialDomains::MeshGraphSharedPtr graph; LibUtilities::SessionReaderSharedPtr session;
SpatialDomains::MeshGraphSharedPtr graph;
// Construct a fake command-line argument array to be fed to
// Session::Reader::CreateInstance. The first element stands for
// the name of the executable which, in our case, doesn't matter.
int argc = 2;
char *argv[] = {(char *)"exe_name", GetMeshName().data()};
// Construct a fake command-line argument array to be fed to session = LibUtilities::SessionReader::CreateInstance(argc, argv);
// Session::Reader::CreateInstance. The first element stands for graph = SpatialDomains::MeshGraph::Read(session);
// the name of the executable which, in our case, doesn't matter. fixt_explist = MemoryManager<MultiRegions::ExpList>::AllocateSharedPtr(
int argc = 2; session, graph);
char *argv[] = {
(char*)"exe_name", (char*)"square.xml"
};
session = LibUtilities::SessionReader::CreateInstance(argc, argv); // Generate a blocks definition from the expansion list for each state
graph = SpatialDomains::MeshGraph::Read(session); auto blocks_in = GetBlockAttributes(stateIn, fixt_explist);
fixt_explist = MemoryManager<MultiRegions::ExpList>::AllocateSharedPtr auto blocks_out = GetBlockAttributes(stateOut, fixt_explist);
(session, graph);
// Generate a blocks definition from the expansion list for each state // Create two Field objects with a MemoryRegionCPU backend by default
auto blocks_phys = InitFields::GetBlockAttributes(FieldState::Phys, fixt_explist); auto f_in = Field<double, stateIn>::create(blocks_in);
auto blocks_coeff = InitFields::GetBlockAttributes(FieldState::Coeff, fixt_explist); auto f_out = Field<double, stateOut>::create(blocks_out);
fixt_in = new Field<double, stateIn>(std::move(f_in));
fixt_out = new Field<double, stateOut>(std::move(f_out));
}
// Create two Field objects with a MemoryRegionCPU backend by default protected:
auto f_in = Field<double, FieldState::Coeff>::create(blocks_coeff); virtual std::string GetMeshName() = 0;
auto f_out = Field<double, FieldState::Phys >::create(blocks_phys);
fixt_in = new Field<double, FieldState::Coeff>(std::move(f_in));
fixt_out = new Field<double, FieldState::Phys>(std::move(f_out));
}
}; };
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#include "Operators/OperatorBwdTrans.hpp" #include "Operators/OperatorBwdTrans.hpp"
#include <LibUtilities/BasicUtils/SessionReader.h> #include <LibUtilities/BasicUtils/SessionReader.h>
#include <SpatialDomains/MeshGraph.h>
#include <MultiRegions/ExpList.h> #include <MultiRegions/ExpList.h>
#include <SpatialDomains/MeshGraph.h>
#include "init_fields.hpp" #include "init_fields.hpp"
...@@ -18,8 +18,29 @@ using namespace Nektar::Operators; ...@@ -18,8 +18,29 @@ using namespace Nektar::Operators;
using namespace Nektar::LibUtilities; using namespace Nektar::LibUtilities;
using namespace Nektar; using namespace Nektar;
BOOST_FIXTURE_TEST_CASE( bwdtrans, InitFields ) class Line : public InitFields<FieldState::Coeff, FieldState::Phys>
{
protected:
virtual std::string GetMeshName() override
{
return "line.xml";
}
};
class Square : public InitFields<FieldState::Coeff, FieldState::Phys>
{ {
protected:
virtual std::string GetMeshName() override
{
return "square.xml";
}
};
using init = InitFields<FieldState::Coeff, FieldState::Phys>;
BOOST_FIXTURE_TEST_CASE(bwdtrans, Line)
{
Configure();
double *x = fixt_in->GetStorage().GetCPUPtr(); double *x = fixt_in->GetStorage().GetCPUPtr();
// For each element, initialise first coefficient to zero and rest // For each element, initialise first coefficient to zero and rest
...@@ -30,10 +51,12 @@ BOOST_FIXTURE_TEST_CASE( bwdtrans, InitFields ) ...@@ -30,10 +51,12 @@ BOOST_FIXTURE_TEST_CASE( bwdtrans, InitFields )
{ {
for (size_t coeff = 0; coeff < block.num_pts; ++coeff) for (size_t coeff = 0; coeff < block.num_pts; ++coeff)
{ {
if (coeff == 0) { if (coeff == 0)
{
*(x++) = 1.0; *(x++) = 1.0;
} }
else { else
{
*(x++) = 0.0; *(x++) = 0.0;
} }
} }
...@@ -43,5 +66,5 @@ BOOST_FIXTURE_TEST_CASE( bwdtrans, InitFields ) ...@@ -43,5 +66,5 @@ BOOST_FIXTURE_TEST_CASE( bwdtrans, InitFields )
BwdTrans<>::create(fixt_explist, "StdMat")->apply(*fixt_in, *fixt_out); BwdTrans<>::create(fixt_explist, "StdMat")->apply(*fixt_in, *fixt_out);
double *y = fixt_out->GetStorage().GetCPUPtr(); double *y = fixt_out->GetStorage().GetCPUPtr();
BOOST_TEST( y[0] == 1.0 ); BOOST_TEST(y[0] == 1.0);
} }