File layoutstructlocaltransposed.h
File List > code_source > templat > include > TempLat > lattice > memory > memorylayouts > layoutstructlocaltransposed.h
Go to the documentation of this file
#ifndef TEMPLAT_LATTICE_MEMORY_MEMORYLAYOUTS_LAYOUTSTRUCTLOCALTRANSPOSED_H
#define TEMPLAT_LATTICE_MEMORY_MEMORYLAYOUTS_LAYOUTSTRUCTLOCALTRANSPOSED_H
/* This file is part of TempLat, available at https://cosmolattice.github.io/templat .
Copyright 2021-2026 The TempLat authors, see AUTHORS.md.
Released under the MIT license, see LICENSE.md. */
// File info: Main contributor(s): Wessel Valkenburg, Year: 2019
#include "TempLat/util/exception.h"
#include "TempLat/lattice/memory/memorylayouts/layoutstructlocal.h"
#include "TempLat/lattice/memory/memorylayouts/transpositionmap.h"
#include "TempLat/parallel/device.h"
namespace TempLat
{
MakeException(LayoutStructLocalTransposedSizeException);
template <size_t _NDim> class LayoutStructLocalTransposed
{
public:
// Put public methods here. These should change very little over time.
static constexpr size_t NDim = _NDim;
LayoutStructLocalTransposed(const device::IdxArray<NDim> &initNGrid, const device::Idx nGhosts)
: mLocal(initNGrid, nGhosts), mNGhosts(nGhosts)
{
for (size_t i = 0; i < NDim; ++i)
mSizesInMemory[i] = mLocal.getLocalSizes()[i];
}
DEVICE_INLINE_FUNCTION
LayoutStructLocal<NDim> &getLocal() { return mLocal; }
DEVICE_INLINE_FUNCTION
const LayoutStructLocal<NDim> &getLocal() const { return mLocal; }
DEVICE_INLINE_FUNCTION
LayoutStructGlobal<NDim> &getGlobal() { return getLocal().getGlobal(); }
DEVICE_INLINE_FUNCTION
const LayoutStructGlobal<NDim> &getGlobal() const { return getLocal().getGlobal(); }
DEVICE_INLINE_FUNCTION
bool isTransposed() const { return mTranspositionMap_memoryToGlobalSpace.isTransposed(); }
void setLocalSizes(const device::IdxArray<NDim> &input)
{
getLocal().setLocalSizes(input);
adaptMemorySizesFromTranspositionMap();
}
void setNGhosts(device::Idx nGhosts)
{
mNGhosts = nGhosts;
getLocal().setNGhosts(nGhosts);
}
void setTranspositionMap_memoryToGlobalSpace(const device::IdxArray<NDim> &input)
{
mTranspositionMap_memoryToGlobalSpace.setMap(input);
adaptMemorySizesFromTranspositionMap();
}
DEVICE_INLINE_FUNCTION
const TranspositionMap<NDim> &getTranspositionMap_memoryToGlobalSpace() const
{
return mTranspositionMap_memoryToGlobalSpace;
}
device::array<device::IdxArray<2>, NDim> getPadding() const
{
const auto &result = getLocal().getPadding();
// Needs transposition.
device::array<device::IdxArray<2>, NDim> transposedResult;
for (size_t i = 0; i < NDim; ++i) {
device::Idx getPaddingIndex = mTranspositionMap_memoryToGlobalSpace.getForward(i);
transposedResult[i][0] = result[getPaddingIndex][0];
transposedResult[i][1] = result[getPaddingIndex][1];
}
return transposedResult;
}
DEVICE_INLINE_FUNCTION
const device::IdxArray<NDim> &getSizesInMemory() const { return mSizesInMemory; }
device::Idx getOrigin() const
{
const auto &sizes = getSizesInMemory();
const auto &padding = getPadding();
device::Idx origin = 0;
device::Idx stride = 1;
for (device::Idx i = NDim - 1; i >= 0; --i) {
origin += padding[i][0] * stride;
stride *= sizes[i] + padding[i][0] + padding[i][1];
}
return origin;
}
device::Idx stride(size_t dim) const
{
const auto &sizes = getSizesInMemory();
const auto &padding = getPadding();
device::Idx result = 1;
for (size_t i = dim + 1; i < NDim; ++i) {
result *= sizes[i] + padding[i][0] + padding[i][1];
}
return result;
}
struct CoordinateMapping {
device::Idx atIndex, withValue;
bool owned;
};
DEVICE_INLINE_FUNCTION
CoordinateMapping getSpatialLocationFromMemoryIndex(device::Idx index, device::Idx memoryDimension) const
{
CoordinateMapping result;
result.atIndex = mTranspositionMap_memoryToGlobalSpace.getForward(memoryDimension);
/* in this function we pass the new forward transposed index to the mLocal. */
result.withValue = mLocal.memoryIndexToSpatialCoordinate(index, result.atIndex);
result.owned = index >= 0 && index < mLocal.getLocalSizes()[memoryDimension];
return result;
}
DEVICE_INLINE_FUNCTION
CoordinateMapping getMemoryIndexFromSpatialLocation(device::Idx position, device::Idx spatialDimension) const
{
CoordinateMapping result;
result.atIndex = mTranspositionMap_memoryToGlobalSpace.getInverse(spatialDimension);
/* in this function we pass the input untransposed index to the mLocal. */
result.withValue = mLocal.spatialCoordinateToMemoryIndex(position, spatialDimension);
result.owned = result.withValue >= 0 && result.withValue < mLocal.getLocalSizes()[result.atIndex];
return result;
}
template <size_t d2>
friend bool operator==(const LayoutStructLocalTransposed<NDim> &a, const LayoutStructLocalTransposed<d2> &b)
{
if constexpr (NDim != d2)
return false;
else {
bool result = a.mLocal == b.mLocal &&
a.mTranspositionMap_memoryToGlobalSpace == b.mTranspositionMap_memoryToGlobalSpace &&
a.mSizesInMemory.size() == b.mSizesInMemory.size();
for (size_t i = 0; i < a.mSizesInMemory.size(); ++i) {
result = result && a.mSizesInMemory[i] == b.mSizesInMemory[i];
}
return result;
}
}
friend std::ostream &operator<<(std::ostream &ostream, const LayoutStructLocalTransposed &ls)
{
ostream << ls.mLocal << "\n"
<< " SizesInMemory: " << ls.mSizesInMemory << "\n"
<< " TranspositionMap_memoryToGlobalSpace: " << ls.mTranspositionMap_memoryToGlobalSpace << "\n";
return ostream;
}
private:
/* Put all member variables and private methods here. These may change arbitrarily. */
LayoutStructLocal<NDim> mLocal;
TranspositionMap<NDim> mTranspositionMap_memoryToGlobalSpace;
device::IdxArray<NDim> mSizesInMemory;
device::Idx mNGhosts;
void adaptMemorySizesFromTranspositionMap()
{
for (device::Idx i = 0, iEnd = std::min(mSizesInMemory.size(), mTranspositionMap_memoryToGlobalSpace.size());
i < iEnd; ++i) {
device::Idx getSizeIndex = mTranspositionMap_memoryToGlobalSpace.getForward(i);
mSizesInMemory[i] = mLocal.getLocalSizes()[getSizeIndex];
}
}
};
} // namespace TempLat
#endif