diff --git a/src/coordinates.hpp b/src/coordinates.hpp index 78a08b8..98038b8 100644 --- a/src/coordinates.hpp +++ b/src/coordinates.hpp @@ -22,6 +22,8 @@ */ #include "tools.hpp" +#include + namespace fsgrid_detail { using FsSize_t = FsGridTools::FsSize_t; using FsIndex_t = FsGridTools::FsIndex_t; @@ -59,8 +61,7 @@ constexpr static bool localSizeTooSmall(std::array globalSize, std: static std::array calculateLocalSize(const std::array& globalSize, const std::array& numTasksPerDim, - const std::array& taskPosition, int rank, - int32_t numGhostCells) { + const std::array& taskPosition, int32_t numGhostCells) { std::array localSize = { FsGridTools::calcLocalSize(globalSize[0], numTasksPerDim[0], taskPosition[0]), FsGridTools::calcLocalSize(globalSize[1], numTasksPerDim[1], taskPosition[1]), @@ -68,12 +69,12 @@ static std::array calculateLocalSize(const std::array }; if (localSizeTooSmall(globalSize, localSize, numGhostCells)) { - std::cerr << "FSGrid space partitioning leads to a space that is too small on Rank " << rank << "." << std::endl; + std::cerr << "FSGrid space partitioning leads to a space that is too small.\n"; std::cerr << "Please run with a different number of Tasks, so that space is better divisible." << std::endl; throw std::runtime_error("FSGrid too small domains"); } - return rank == -1 ? std::array{0, 0, 0} : localSize; + return localSize; } static std::array calculateLocalStart(const std::array& globalSize, @@ -109,14 +110,160 @@ struct Coordinates { Coordinates(const std::array& physicalGridSpacing, const std::array& physicalGlobalStart, std::array globalSize, std::array periodic, const std::array& decomposition, const std::array& taskPosition, int32_t numRanks, - Task_t rank, int32_t numGhostCells) - : physicalGridSpacing(physicalGridSpacing), physicalGlobalStart(physicalGlobalStart), globalSize(globalSize), - periodic(periodic), + int32_t numGhostCells) + : numGhostCells(numGhostCells), physicalGridSpacing(physicalGridSpacing), + physicalGlobalStart(physicalGlobalStart), globalSize(globalSize), periodic(periodic), numTasksPerDim(fsgrid_detail::computeNumTasksPerDim(globalSize, decomposition, numRanks, numGhostCells)), - localSize(fsgrid_detail::calculateLocalSize(globalSize, numTasksPerDim, taskPosition, rank, numGhostCells)), + localSize(fsgrid_detail::calculateLocalSize(globalSize, numTasksPerDim, taskPosition, numGhostCells)), localStart(fsgrid_detail::calculateLocalStart(globalSize, numTasksPerDim, taskPosition)), storageSize(fsgrid_detail::calculateStorageSize(globalSize, localSize, numGhostCells)) {} + /*! Determine the cell's GlobalID from its local x,y,z coordinates + * \param x The cell's task-local x coordinate + * \param y The cell's task-local y coordinate + * \param z The cell's task-local z coordinate + */ + GlobalID globalIDFromLocalCoordinates(FsIndex_t x, FsIndex_t y, FsIndex_t z) const { + // Perform casts to avoid overflow + const std::array global = localToGlobal(x, y, z); + const auto xcontrib = global[0]; + const auto ycontrib = static_cast(globalSize[0]) * static_cast(global[1]); + const auto zcontrib = static_cast(globalSize[0]) * static_cast(globalSize[1]) * + static_cast(global[2]); + return xcontrib + ycontrib + zcontrib; + } + + /*! Determine the cell's LocalID from its local x,y,z coordinates + * \param x The cell's task-local x coordinate + * \param y The cell's task-local y coordinate + * \param z The cell's task-local z coordinate + */ + LocalID localIDFromLocalCoordinates(FsIndex_t x, FsIndex_t y, FsIndex_t z) const { + // Perform casts to avoid overflow + const auto xcontrib = static_cast(globalSize[0] > 1) * static_cast(numGhostCells + x); + const auto ycontrib = static_cast(globalSize[1] > 1) * static_cast(storageSize[0]) * + static_cast(numGhostCells + y); + const auto zcontrib = static_cast(globalSize[2] > 1) * static_cast(storageSize[0]) * + static_cast(storageSize[1]) * static_cast(numGhostCells + z); + + return xcontrib + ycontrib + zcontrib; + } + + /*! Transform global cell coordinates into the local domain. + * If the coordinates are out of bounds, (-1,-1,-1) is returned. + * \param x The cell's global x coordinate + * \param y The cell's global y coordinate + * \param z The cell's global z coordinate + */ + std::array globalToLocal(FsSize_t x, FsSize_t y, FsSize_t z) const { + // Perform this check before doing the subtraction to avoid cases of underflow and overflow + // Particularly for the first three checks: + // - casting the localStart to unsigned and then doing the subtraction might cause underflow + // - casting the global coordinate to signed might overflow, due to global being too large to fit to the signed + // type + bool outOfBounds = x < static_cast(localStart[0]); + outOfBounds |= y < static_cast(localStart[1]); + outOfBounds |= z < static_cast(localStart[2]); + outOfBounds |= x >= static_cast(localSize[0]) + static_cast(localStart[0]); + outOfBounds |= y >= static_cast(localSize[1]) + static_cast(localStart[1]); + outOfBounds |= z >= static_cast(localSize[2]) + static_cast(localStart[2]); + + if (outOfBounds) { + return {-1, -1, -1}; + } else { + // This neither over nor underflows as per the checks above + return { + static_cast(x - static_cast(localStart[0])), + static_cast(y - static_cast(localStart[1])), + static_cast(z - static_cast(localStart[2])), + }; + } + } + + /*! Calculate global cell position (XYZ in global cell space) from local cell coordinates. + * + * \param x x-Coordinate, in cells + * \param y y-Coordinate, in cells + * \param z z-Coordinate, in cells + * + * \return Global cell coordinates + */ + std::array localToGlobal(FsIndex_t x, FsIndex_t y, FsIndex_t z) const { + // Cast both before adding to avoid overflow + return { + static_cast(localStart[0]) + static_cast(x), + static_cast(localStart[1]) + static_cast(y), + static_cast(localStart[2]) + static_cast(z), + }; + } + + /*! Get the physical coordinates in the global simulation space for + * the given cell. + * + * \param x local x-Coordinate, in cells + * \param y local y-Coordinate, in cells + * \param z local z-Coordinate, in cells + */ + std::array getPhysicalCoords(FsIndex_t x, FsIndex_t y, FsIndex_t z) const { + return { + physicalGlobalStart[0] + (localStart[0] + x) * physicalGridSpacing[0], + physicalGlobalStart[1] + (localStart[1] + y) * physicalGridSpacing[1], + physicalGlobalStart[2] + (localStart[2] + z) * physicalGridSpacing[2], + }; + } + + /*! Get the global cell coordinates for the given physical coordinates. + * + * \param x physical x-Coordinate + * \param y physical y-Coordinate + * \param z physical z-Coordinate + */ + std::array physicalToGlobal(double x, double y, double z) const { + return { + static_cast(floor((x - physicalGlobalStart[0]) / physicalGridSpacing[0])), + static_cast(floor((y - physicalGlobalStart[1]) / physicalGridSpacing[1])), + static_cast(floor((z - physicalGlobalStart[2]) / physicalGridSpacing[2])), + }; + } + + /*! Get the (fractional) global cell coordinates for the given physical coordinates. + * + * \param x physical x-Coordinate + * \param y physical y-Coordinate + * \param z physical z-Coordinate + */ + std::array physicalToFractionalGlobal(double x, double y, double z) const { + const auto global = physicalToGlobal(x, y, z); + return { + (x - physicalGlobalStart[0]) / physicalGridSpacing[0] - global[0], + (y - physicalGlobalStart[1]) / physicalGridSpacing[1] - global[1], + (z - physicalGlobalStart[2]) / physicalGridSpacing[2] - global[2], + }; + } + + std::array globalIdToTaskPos(GlobalID id) const { + const std::array cell = FsGridTools::globalIDtoCellCoord(id, globalSize); + + auto computeIndex = [&](uint32_t i) { + const FsIndex_t nPerTask = static_cast(globalSize[i] / static_cast(numTasksPerDim[i])); + const FsIndex_t nPerTaskPlus1 = nPerTask + 1; + const FsIndex_t remainder = static_cast(globalSize[i] % static_cast(numTasksPerDim[i])); + + return cell[i] < remainder * nPerTaskPlus1 ? cell[i] / nPerTaskPlus1 + : remainder + (cell[i] - remainder * nPerTaskPlus1) / nPerTask; + }; + + return { + computeIndex(0), + computeIndex(1), + computeIndex(2), + }; + } + + // ======================= + // Variables + // ======================= + const int32_t numGhostCells = 0; const std::array physicalGridSpacing = {}; const std::array physicalGlobalStart = {}; const std::array globalSize = {}; diff --git a/src/grid.hpp b/src/grid.hpp index bb8a64d..a2fa4ac 100644 --- a/src/grid.hpp +++ b/src/grid.hpp @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -130,9 +129,23 @@ static int32_t getCommSize(MPI_Comm parentComm) { return parentCommSize; } -static MPI_Comm createCartesianCommunicator(MPI_Comm parentComm, int32_t colourFs, int32_t colourAux, - int32_t parentRank, const std::array& numTasksPerDim, +constexpr static int32_t computeColourFs(int32_t parentRank, int32_t numRanks) { + return (parentRank < numRanks) ? 1 : MPI_UNDEFINED; +} + +constexpr static int32_t computeColourAux(int32_t parentRank, int32_t parentCommSize, int32_t numRanks) { + return (parentRank > (parentCommSize - 1) % numRanks) ? (parentRank - (parentCommSize % numRanks)) / numRanks + : MPI_UNDEFINED; +} + +static MPI_Comm createCartesianCommunicator(MPI_Comm parentComm, const std::array& numTasksPerDim, const std::array& isPeriodic) { + const auto parentRank = getCommRank(parentComm); + const auto parentSize = getCommSize(parentComm); + const auto numFsRanks = getFSCommSize(parentSize); + const auto colourFs = computeColourFs(parentRank, numFsRanks); + const auto colourAux = computeColourAux(parentRank, parentSize, numFsRanks); + MPI_Comm comm; if (colourFs != MPI_UNDEFINED) { FSGRID_MPI_CHECK(MPI_Comm_split(parentComm, colourFs, parentRank, &comm), @@ -154,8 +167,12 @@ static MPI_Comm createCartesianCommunicator(MPI_Comm parentComm, int32_t colourF return comm3d; } -static int32_t getCartesianRank(int32_t colourFs, MPI_Comm comm) { - return colourFs != MPI_UNDEFINED ? getCommRank(comm) : -1; +static int32_t getCartesianRank(MPI_Comm parentComm, MPI_Comm cartesianComm) { + const auto parentRank = getCommRank(parentComm); + const auto parentSize = getCommSize(parentComm); + const auto numFsRanks = getFSCommSize(parentSize); + const auto colourFs = computeColourFs(parentRank, numFsRanks); + return colourFs != MPI_UNDEFINED ? getCommRank(cartesianComm) : -1; } static std::array getTaskPosition(MPI_Comm comm) { @@ -166,15 +183,6 @@ static std::array getTaskPosition(MPI_Comm comm) { return taskPos; } -constexpr static int32_t computeColorFs(int32_t parentRank, int32_t numRanks) { - return (parentRank < numRanks) ? 1 : MPI_UNDEFINED; -} - -constexpr static int32_t computeColourAux(int32_t parentRank, int32_t parentCommSize, int32_t numRanks) { - return (parentRank > (parentCommSize - 1) % numRanks) ? (parentRank - (parentCommSize % numRanks)) / numRanks - : MPI_UNDEFINED; -} - template static std::array generateMPITypes(const std::array& storageSize, const std::array& localSize, int32_t stencilSize, @@ -236,7 +244,6 @@ static std::array generateMPITypes(const std::array class FsGrid { const std::array& decomposition = {0, 0, 0}) : comm3d(fsgrid_detail::createCartesianCommunicator( parentComm, - fsgrid_detail::computeColorFs(fsgrid_detail::getCommRank(parentComm), - fsgrid_detail::getFSCommSize(fsgrid_detail::getCommSize(parentComm))), - fsgrid_detail::computeColourAux(fsgrid_detail::getCommRank(parentComm), - fsgrid_detail::getCommSize(parentComm), - fsgrid_detail::getFSCommSize(fsgrid_detail::getCommSize(parentComm))), - fsgrid_detail::getCommRank(parentComm), fsgrid_detail::computeNumTasksPerDim(globalSize, decomposition, fsgrid_detail::getFSCommSize(fsgrid_detail::getCommSize(parentComm)), stencil), periodic)), - rank(fsgrid_detail::getCartesianRank( - fsgrid_detail::computeColorFs(fsgrid_detail::getCommRank(parentComm), - fsgrid_detail::getFSCommSize(fsgrid_detail::getCommSize(parentComm))), - comm3d)), + rank(fsgrid_detail::getCartesianRank(parentComm, comm3d)), coordinates(physicalGridSpacing, physicalGlobalStart, globalSize, periodic, decomposition, fsgrid_detail::getTaskPosition(comm3d), - fsgrid_detail::getFSCommSize(fsgrid_detail::getCommSize(parentComm)), rank, stencil), + fsgrid_detail::getFSCommSize(fsgrid_detail::getCommSize(parentComm)), stencil), neighbourIndexToRank(fsgrid_detail::mapNeigbourIndexToRank( fsgrid_detail::getTaskPosition(comm3d), coordinates.numTasksPerDim, periodic, comm3d, rank)), neighbourRankToIndex(fsgrid_detail::mapNeighbourRankToIndex( @@ -441,133 +439,24 @@ template class FsGrid { // ============================ // Coordinate change functions + // - Redirected to Coordinates' implementation // ============================ - - /*! Determine the cell's GlobalID from its local x,y,z coordinates - * \param x The cell's task-local x coordinate - * \param y The cell's task-local y coordinate - * \param z The cell's task-local z coordinate - */ - GlobalID globalIDFromLocalCoordinates(FsIndex_t x, FsIndex_t y, FsIndex_t z) const { - // Perform casts to avoid overflow - const std::array global = localToGlobal(x, y, z); - const auto xcontrib = global[0]; - const auto ycontrib = static_cast(coordinates.globalSize[0]) * static_cast(global[1]); - const auto zcontrib = static_cast(coordinates.globalSize[0]) * - static_cast(coordinates.globalSize[1]) * static_cast(global[2]); - return xcontrib + ycontrib + zcontrib; - } - - /*! Determine the cell's LocalID from its local x,y,z coordinates - * \param x The cell's task-local x coordinate - * \param y The cell's task-local y coordinate - * \param z The cell's task-local z coordinate - */ - LocalID localIDFromLocalCoordinates(FsIndex_t x, FsIndex_t y, FsIndex_t z) const { - // Perform casts to avoid overflow - const auto xcontrib = static_cast(coordinates.globalSize[0] > 1) * static_cast(stencil + x); - const auto ycontrib = static_cast(coordinates.globalSize[1] > 1) * - static_cast(coordinates.storageSize[0]) * static_cast(stencil + y); - const auto zcontrib = static_cast(coordinates.globalSize[2] > 1) * - static_cast(coordinates.storageSize[0]) * - static_cast(coordinates.storageSize[1]) * static_cast(stencil + z); - - return xcontrib + ycontrib + zcontrib; - } - - /*! Transform global cell coordinates into the local domain. - * If the coordinates are out of bounds, (-1,-1,-1) is returned. - * \param x The cell's global x coordinate - * \param y The cell's global y coordinate - * \param z The cell's global z coordinate - */ - std::array globalToLocal(FsSize_t x, FsSize_t y, FsSize_t z) const { - // Perform this check before doing the subtraction to avoid cases of underflow and overflow - // Particularly for the first three checks: - // - casting the localStart to unsigned and then doing the subtraction might cause underflow - // - casting the global coordinate to signed might overflow, due to global being too large to fit to the signed - // type - bool outOfBounds = x < static_cast(coordinates.localStart[0]); - outOfBounds |= y < static_cast(coordinates.localStart[1]); - outOfBounds |= z < static_cast(coordinates.localStart[2]); - outOfBounds |= - x >= static_cast(coordinates.localSize[0]) + static_cast(coordinates.localStart[0]); - outOfBounds |= - y >= static_cast(coordinates.localSize[1]) + static_cast(coordinates.localStart[1]); - outOfBounds |= - z >= static_cast(coordinates.localSize[2]) + static_cast(coordinates.localStart[2]); - - if (outOfBounds) { - return {-1, -1, -1}; - } else { - // This neither over nor underflows as per the checks above - return { - static_cast(x - static_cast(coordinates.localStart[0])), - static_cast(y - static_cast(coordinates.localStart[1])), - static_cast(z - static_cast(coordinates.localStart[2])), - }; - } + template auto globalIDFromLocalCoordinates(Args... args) const { + return coordinates.globalIDFromLocalCoordinates(args...); } - - /*! Calculate global cell position (XYZ in global cell space) from local cell coordinates. - * - * \param x x-Coordinate, in cells - * \param y y-Coordinate, in cells - * \param z z-Coordinate, in cells - * - * \return Global cell coordinates - */ - std::array localToGlobal(FsIndex_t x, FsIndex_t y, FsIndex_t z) const { - // Cast both before adding to avoid overflow - return { - static_cast(coordinates.localStart[0]) + static_cast(x), - static_cast(coordinates.localStart[1]) + static_cast(y), - static_cast(coordinates.localStart[2]) + static_cast(z), - }; + template auto localIDFromLocalCoordinates(Args... args) const { + return coordinates.localIDFromLocalCoordinates(args...); } - - /*! Get the physical coordinates in the global simulation space for - * the given cell. - * - * \param x local x-Coordinate, in cells - * \param y local y-Coordinate, in cells - * \param z local z-Coordinate, in cells - */ - std::array getPhysicalCoords(FsIndex_t x, FsIndex_t y, FsIndex_t z) const { - return { - coordinates.physicalGlobalStart[0] + (coordinates.localStart[0] + x) * coordinates.physicalGridSpacing[0], - coordinates.physicalGlobalStart[1] + (coordinates.localStart[1] + y) * coordinates.physicalGridSpacing[1], - coordinates.physicalGlobalStart[2] + (coordinates.localStart[2] + z) * coordinates.physicalGridSpacing[2], - }; + template auto globalToLocal(Args... args) const { return coordinates.globalToLocal(args...); } + template auto localToGlobal(Args... args) const { return coordinates.localToGlobal(args...); } + template auto getPhysicalCoords(Args... args) const { + return coordinates.getPhysicalCoords(args...); } - - /*! Get the global cell coordinates for the given physical coordinates. - * - * \param x physical x-Coordinate - * \param y physical y-Coordinate - * \param z physical z-Coordinate - */ - std::array physicalToGlobal(double x, double y, double z) const { - return { - static_cast(floor((x - coordinates.physicalGlobalStart[0]) / coordinates.physicalGridSpacing[0])), - static_cast(floor((y - coordinates.physicalGlobalStart[1]) / coordinates.physicalGridSpacing[1])), - static_cast(floor((z - coordinates.physicalGlobalStart[2]) / coordinates.physicalGridSpacing[2])), - }; + template auto physicalToGlobal(Args... args) const { + return coordinates.physicalToGlobal(args...); } - - /*! Get the (fractional) global cell coordinates for the given physical coordinates. - * - * \param x physical x-Coordinate - * \param y physical y-Coordinate - * \param z physical z-Coordinate - */ - std::array physicalToFractionalGlobal(double x, double y, double z) const { - const auto global = physicalToGlobal(x, y, z); - return { - (x - coordinates.physicalGlobalStart[0]) / coordinates.physicalGridSpacing[0] - global[0], - (y - coordinates.physicalGlobalStart[1]) / coordinates.physicalGridSpacing[1] - global[1], - (z - coordinates.physicalGlobalStart[2]) / coordinates.physicalGridSpacing[2] - global[2], - }; + template auto physicalToFractionalGlobal(Args... args) const { + return coordinates.physicalToFractionalGlobal(args...); } // ============================ @@ -576,54 +465,52 @@ template class FsGrid { /*! Get the size of the local domain handled by this grid. */ - const std::array& getLocalSize() const { return coordinates.localSize; } + const auto& getLocalSize() const { + constexpr static std::array zero{0, 0, 0}; + return rank == -1 ? zero : coordinates.localSize; + } /*! Get the start coordinates of the local domain handled by this grid. */ - const std::array& getLocalStart() const { return coordinates.localStart; } + const auto& getLocalStart() const { return coordinates.localStart; } /*! Get global size of the fsgrid domain */ - const std::array& getGlobalSize() const { return coordinates.globalSize; } + const auto& getGlobalSize() const { return coordinates.globalSize; } /*! Get the rank of this CPU in the FsGrid communicator */ Task_t getRank() const { return rank; } /*! Get the number of ranks in the FsGrid communicator */ - Task_t getSize() const { + Task_t getNumFsRanks() const { return coordinates.numTasksPerDim[0] * coordinates.numTasksPerDim[1] * coordinates.numTasksPerDim[2]; } /*! Get in which directions, if any, this grid is periodic */ - const std::array& getPeriodic() const { return coordinates.periodic; } + const auto& getPeriodic() const { return coordinates.periodic; } /*! Get the decomposition array*/ - const std::array& getDecomposition() const { return coordinates.numTasksPerDim; } + const auto& getDecomposition() const { return coordinates.numTasksPerDim; } /*! Get the physical grid spacing array*/ - const std::array& getGridSpacing() const { return coordinates.physicalGridSpacing; } + const auto& getGridSpacing() const { return coordinates.physicalGridSpacing; } // ============================ // MPI functions // ============================ - // These functions could be changed to static functions in a namespace that take technical grid and data pointer as - // argument /*! Perform ghost cell communication. */ void updateGhostCells() { - - if (rank == -1) + if (rank == -1) { return; + } // TODO, faster with simultaneous isends& ireceives? std::array receiveRequests; std::array sendRequests; - - for (uint32_t i = 0; i < 27; i++) { - receiveRequests[i] = MPI_REQUEST_NULL; - sendRequests[i] = MPI_REQUEST_NULL; - } + receiveRequests.fill(MPI_REQUEST_NULL); + sendRequests.fill(MPI_REQUEST_NULL); for (int32_t x = -1; x <= 1; x++) { for (int32_t y = -1; y <= 1; y++) { @@ -685,28 +572,10 @@ template class FsGrid { * \return a task for the grid's cartesian communicator */ Task_t getTaskForGlobalID(GlobalID id) const { - // Transform globalID to global cell coordinate - const std::array cell = FsGridTools::globalIDtoCellCoord(id, coordinates.globalSize); - - // Find the index in the task grid this Cell belongs to - std::array taskIndex; - for (uint32_t i = 0; i < 3; i++) { - const FsIndex_t n_per_task = - static_cast(coordinates.globalSize[i] / static_cast(coordinates.numTasksPerDim[i])); - const FsIndex_t remainder = - static_cast(coordinates.globalSize[i] % static_cast(coordinates.numTasksPerDim[i])); - - if (cell[i] < remainder * (n_per_task + 1)) { - taskIndex[i] = cell[i] / (n_per_task + 1); - } else { - taskIndex[i] = remainder + (cell[i] - remainder * (n_per_task + 1)) / n_per_task; - } - } - - // Get the task number from the communicator + const auto taskIndex = coordinates.globalIdToTaskPos(id); Task_t taskID = -1; FSGRID_MPI_CHECK(MPI_Cart_rank(comm3d, taskIndex.data(), &taskID), "Unable to find FsGrid rank for global ID ", - id, "(coordinates [", cell[0], ", ", cell[1], ", ", cell[2], "])"); + id); return taskID; } diff --git a/tests/unit_tests/grid_tests.cpp b/tests/unit_tests/grid_tests.cpp index 9dd03b1..a8d03f8 100644 --- a/tests/unit_tests/grid_tests.cpp +++ b/tests/unit_tests/grid_tests.cpp @@ -130,13 +130,13 @@ TEST(FsGridTest, xyzToLinearToxyz) { } } -TEST(FsGridTest, computeColorFs) { +TEST(FsGridTest, computeColourFs) { constexpr int32_t numRanks = 666; for (int32_t i = 0; i < numRanks; i++) { - ASSERT_EQ(fsgrid_detail::computeColorFs(i, numRanks), 1); + ASSERT_EQ(fsgrid_detail::computeColourFs(i, numRanks), 1); } - ASSERT_EQ(fsgrid_detail::computeColorFs(numRanks, numRanks), MPI_UNDEFINED); + ASSERT_EQ(fsgrid_detail::computeColourFs(numRanks, numRanks), MPI_UNDEFINED); } TEST(FsGridTest, computeColorAux1) {