• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

misc/testcell.h

Go to the documentation of this file.
00001 #ifndef LIBGEODECOMP_MISC_TESTCELL_H
00002 #define LIBGEODECOMP_MISC_TESTCELL_H
00003 
00004 #include <libgeodecomp/config.h>
00005 #include <libgeodecomp/misc/apitraits.h>
00006 #include <libgeodecomp/geometry/coord.h>
00007 #include <libgeodecomp/geometry/coordbox.h>
00008 #include <libgeodecomp/geometry/stencils.h>
00009 #include <libgeodecomp/storage/coordmap.h>
00010 #include <libgeodecomp/storage/fixedneighborhood.h>
00011 
00012 #include <iostream>
00013 #include <libflatarray/flat_array.hpp>
00014 
00015 namespace LibGeoDecomp {
00016 
00017 namespace TestCellHelpers {
00018 
00019 class EmptyAPI
00020 {
00021 };
00022 
00023 class SoAAPI :
00024         public APITraits::HasSoA,
00025         public APITraits::HasFixedCoordsOnlyUpdate,
00026         public APITraits::HasUpdateLineX
00027 {};
00028 
00029 template<int DIM>
00030 class TopologyType
00031 {
00032 public:
00033     typedef typename Topologies::Cube<DIM>::Topology Topology;
00034 };
00035 
00036 // make the 3D TestCell use a torus topology for a change...
00037 template<>
00038 class TopologyType<3>
00039 {
00040 public:
00041     typedef Topologies::Torus<3>::Topology Topology;
00042 };
00043 
00044 class StdOutput
00045 {
00046 public:
00047     template<typename T>
00048     const StdOutput& operator<<(T output) const
00049     {
00050         std::cout << output;
00051         return *this;
00052     }
00053 };
00054 
00055 class NoOutput
00056 {
00057 public:
00058     template<typename T>
00059     const NoOutput& operator<<(T /*unused*/) const
00060     {
00061         return *this;
00062     }
00063 };
00064 
00065 template<class STENCIL, int INDEX>
00066 class CheckNeighbor
00067 {
00068 public:
00069     typedef typename STENCIL::template Coords<INDEX> RelCoord;
00070 
00071     template<class TESTCELL, class NEIGHBORHOOD>
00072     void operator()(bool *isValid, TESTCELL *cell, const NEIGHBORHOOD& neighborhood)
00073     {
00074         (*isValid) &= cell->checkNeighbor(neighborhood[RelCoord()], RelCoord());
00075     }
00076 };
00077 
00078 }
00079 
00083 template<
00084     int DIM,
00085     typename STENCIL = Stencils::Moore<DIM, 1>,
00086     typename TOPOLOGY = typename TestCellHelpers::TopologyType<DIM>::Topology,
00087     typename ADDITIONAL_API = TestCellHelpers::EmptyAPI,
00088     typename OUTPUT = TestCellHelpers::StdOutput>
00089 class TestCell
00090 {
00091 public:
00092     friend class Typemaps;
00093     friend class TestCellTest;
00094 
00095     static const int DIMENSIONS = DIM;
00096     static const unsigned NANO_STEPS = 27;
00097 
00098     class API :
00099         public ADDITIONAL_API,
00100         public APITraits::HasTopology<TOPOLOGY>,
00101         public APITraits::HasNanoSteps<NANO_STEPS>,
00102         public APITraits::HasStencil<STENCIL>
00103 #ifdef LIBGEODECOMP_WITH_MPI
00104         , public APITraits::HasAutoGeneratedMPIDataType<Typemaps>
00105 #endif
00106     {};
00107 
00108     Coord<DIM> pos;
00109     CoordBox<DIM> dimensions;
00110     unsigned cycleCounter;
00111     bool isEdgeCell;
00112     bool isValid;
00113     double testValue;
00114 
00115     static double defaultValue()
00116     {
00117         return 666;
00118     }
00119 
00120     TestCell() :
00121         cycleCounter(0),
00122         isEdgeCell(false),
00123         isValid(false),
00124         testValue(defaultValue())
00125     {}
00126 
00127     TestCell(
00128         const Coord<DIM>& pos,
00129         const Coord<DIM>& gridDim,
00130         const unsigned& cycleCounter = 0,
00131         const double& testValue = defaultValue()) :
00132         pos(pos),
00133         dimensions(Coord<DIM>(), gridDim),
00134         cycleCounter(cycleCounter),
00135         isValid(true),
00136         testValue(testValue)
00137     {
00138         isEdgeCell = !inBounds(pos);
00139     }
00140 
00141     const bool& valid() const
00142     {
00143         return isValid;
00144     }
00145 
00146     bool inBounds(const Coord<DIM>& c) const
00147     {
00148         return !TOPOLOGY::isOutOfBounds(c, dimensions.dimensions);
00149     }
00150 
00151     bool operator==(const TestCell& other) const
00152     {
00153         return (pos == other.pos)
00154             && (dimensions == other.dimensions)
00155             && (cycleCounter == other.cycleCounter)
00156             && (isEdgeCell == other.isEdgeCell)
00157             && (isValid == other.isValid)
00158             && (testValue == other.testValue);
00159     }
00160 
00161     bool operator!=(const TestCell& other) const
00162     {
00163         return !((*this) == other);
00164     }
00165 
00166     template<typename COORD_MAP>
00167     void update(const COORD_MAP& neighborhood, const unsigned& nanoStep)
00168     {
00169         // initialize Cell by copying from previous state
00170         *this = TestCell(neighborhood[FixedCoord<0, 0, 0>()]);
00171 
00172         if (isEdgeCell) {
00173             OUTPUT() << "TestCell error: update called for edge cell\n";
00174             isValid = false;
00175             return;
00176         }
00177 
00178         Stencils::Repeat<STENCIL::VOLUME,
00179                          TestCellHelpers::CheckNeighbor,
00180                          STENCIL>()(&isValid, this, neighborhood);
00181 
00182         if (nanoStep >= NANO_STEPS) {
00183             OUTPUT() << "TestCell error: nanoStep too large: "
00184                      << nanoStep << "\n";
00185             isValid = false;
00186             return;
00187         }
00188 
00189         unsigned expectedNanoStep = cycleCounter % NANO_STEPS;
00190         if (nanoStep != expectedNanoStep) {
00191             OUTPUT() << "TestCell error: nanoStep out of sync. got "
00192                      << nanoStep << " but expected "
00193                      << expectedNanoStep << "\n";
00194             isValid = false;
00195             return;
00196         }
00197 
00198         ++cycleCounter;
00199     }
00200 
00201     template<typename NEIGHBORHOOD>
00202     static void updateLineX(
00203         TestCell *targetLine,
00204         long *index,
00205         long indexEnd,
00206         const NEIGHBORHOOD& hood,
00207         unsigned nanoStep)
00208     {
00209         for (; *index < indexEnd; ++(*index)) {
00210             targetLine[*index].update(hood, nanoStep);
00211         }
00212     }
00213 
00214     template<typename ACCESSOR1, typename ACCESSOR2>
00215     static void updateLineX(
00216         ACCESSOR1 hoodOld, int indexEnd,
00217         ACCESSOR2 hoodNew, unsigned nanoStep)
00218     {
00219         for (; hoodOld.index() < indexEnd; ++hoodOld.index(), ++hoodNew.index) {
00220             TestCell cell;
00221             cell.update(hoodOld, nanoStep);
00222             hoodNew << cell;
00223         }
00224     }
00225 
00226     std::string toString() const
00227     {
00228         std::ostringstream ret;
00229         ret << "TestCell\n"
00230             << "  pos: " << pos << "\n"
00231             << "  dimensions: " << dimensions << "\n"
00232             << "  cycleCounter: " << cycleCounter << "\n"
00233             << "  isEdgeCell: " << (isEdgeCell ? "true" : "false") << "\n"
00234             << "  testValue: " << testValue << "\n"
00235             << "  isValid: " << (isValid ? "true" : "false") << "\n";
00236         return ret.str();
00237     }
00238 
00239     // returns true if valid neighbor is found (at the right place, in
00240     // the same cycle etc.)
00241     bool checkNeighbor(
00242         const TestCell& other,
00243         const Coord<DIM>& relativeLoc) const
00244     {
00245         if (!other.isValid) {
00246             OUTPUT() << "Update Error for " << toString() << ":\n"
00247                      << "Invalid Neighbor at " << relativeLoc << ":\n"
00248                      << other.toString()
00249                      << "--------------" << "\n";
00250             return false;
00251         }
00252         bool otherShouldBeEdge = !inBounds(pos + relativeLoc);
00253         if (other.isEdgeCell != otherShouldBeEdge) {
00254             OUTPUT() << "TestCell error: bad edge cell (expected: "
00255                      << otherShouldBeEdge << ", is: "
00256                      << other.isEdgeCell << " at relative coord "
00257                      << relativeLoc << ")\n";
00258             return false;
00259         }
00260         if (!otherShouldBeEdge) {
00261             if (other.cycleCounter != cycleCounter) {
00262                 OUTPUT() << "Update Error for TestCell "
00263                          << toString() << ":\n"
00264                          << "cycle counter out of sync with neighbor "
00265                          << other.toString() << "\n";
00266                 return false;
00267             }
00268             if (other.dimensions != dimensions) {
00269                 OUTPUT() << "TestCell error: grid dimensions differ. Expected: "
00270                          << dimensions << ", but got " << other.dimensions << "\n";
00271                 return false;
00272             }
00273 
00274             Coord<DIM> rawPos = pos + relativeLoc;
00275             Coord<DIM> expectedPos =
00276                 TOPOLOGY::normalize(rawPos, dimensions.dimensions);
00277 
00278             if (other.pos != expectedPos) {
00279                 OUTPUT() << "TestCell error: other position "
00280                          << other.pos
00281                          << " doesn't match expected "
00282                          << expectedPos << "\n";
00283                 return false;
00284             }
00285         }
00286         return true;
00287     }
00288 
00289     template<int X, int Y, int Z>
00290     bool checkNeighbor(
00291         const TestCell& other,
00292         FixedCoord<X, Y, Z> coord) const
00293     {
00294         return checkNeighbor(other, Coord<DIM>(coord));
00295     }
00296 };
00297 
00298 typedef TestCell<
00299     3,
00300     Stencils::Moore<3, 1>,
00301     Topologies::Cube<3>::Topology,
00302     TestCellHelpers::SoAAPI
00303     > TestCellSoA;
00304 
00312 class TestCellMPIDatatypeHelper
00313 {
00314     friend class Typemaps;
00315     TestCell<1> a;
00316     TestCell<2> b;
00317     TestCell<3> c;
00318 };
00319 
00320 }
00321 
00322 LIBFLATARRAY_REGISTER_SOA(LibGeoDecomp::TestCellSoA, ((LibGeoDecomp::Coord<3>)(pos))((LibGeoDecomp::CoordBox<3>)(dimensions))((unsigned)(cycleCounter))((bool)(isEdgeCell))((bool)(isValid))((double)(testValue)))
00323 
00324 template<
00325     typename CharT,
00326     typename Traits,
00327     int Dim,
00328     typename Stencil,
00329     typename Topology,
00330     typename AdditionalAPI,
00331     typename Output>
00332 std::basic_ostream<CharT, Traits>&
00333 operator<<(std::basic_ostream<CharT, Traits>& os,
00334            const LibGeoDecomp::TestCell<Dim, Stencil, Topology, AdditionalAPI, Output>& cell)
00335 {
00336     os << cell.toString();
00337     return os;
00338 }
00339 
00340 #endif

Generated on Thu Jan 8 2015 01:34:44 for LibGeoDecomp by  doxygen 1.7.1