00001 #ifndef LIBGEODECOMP_STORAGE_UPDATEFUNCTOR_H
00002 #define LIBGEODECOMP_STORAGE_UPDATEFUNCTOR_H
00003
00004 #include <libgeodecomp/geometry/region.h>
00005 #include <libgeodecomp/misc/apitraits.h>
00006 #include <libgeodecomp/storage/fixedneighborhood.h>
00007 #include <libgeodecomp/storage/linepointerassembly.h>
00008 #include <libgeodecomp/storage/linepointerupdatefunctor.h>
00009 #include <libgeodecomp/storage/vanillaupdatefunctor.h>
00010
00011 namespace LibGeoDecomp {
00012
00013 namespace UpdateFunctorHelpers {
00014
00015 template<typename CELL>
00016 class Selector
00017 {
00018 public:
00019 typedef typename APITraits::SelectStencil<CELL>::Value Stencil;
00020 typedef typename APITraits::SelectTopology<CELL>::Value Topology;
00021
00022 static const int DIM = Topology::DIM;
00023
00024 class SoARegionUpdateHelper
00025 {
00026 public:
00027 SoARegionUpdateHelper(
00028 const Region<DIM>& region,
00029 const Coord<DIM>& sourceOffset,
00030 const Coord<DIM>& targetOffset,
00031 const unsigned nanoStep) :
00032 region(region),
00033 sourceOffset(sourceOffset),
00034 targetOffset(targetOffset),
00035 nanoStep(nanoStep)
00036 {}
00037
00038 template<
00039 typename CELL1, long MY_DIM_X1, long MY_DIM_Y1, long MY_DIM_Z1, long INDEX1,
00040 typename CELL2, long MY_DIM_X2, long MY_DIM_Y2, long MY_DIM_Z2, long INDEX2>
00041 void operator()(
00042 LibFlatArray::soa_accessor<CELL1, MY_DIM_X1, MY_DIM_Y1, MY_DIM_Z1, INDEX1>& hoodOld,
00043 LibFlatArray::soa_accessor<CELL2, MY_DIM_X2, MY_DIM_Y2, MY_DIM_Z2, INDEX2>& hoodNew) const
00044 {
00045 for (typename Region<DIM>::StreakIterator i = region.beginStreak();
00046 i != region.endStreak();
00047 ++i) {
00048 Streak<DIM> relativeSourceStreak(
00049 i->origin + sourceOffset,
00050 i->endX + sourceOffset.x());
00051 Coord<DIM> relativeTargetOrigin = i->origin + targetOffset;
00052
00053 hoodOld.index =
00054 relativeSourceStreak.origin.z() * MY_DIM_X1 * MY_DIM_Y1 +
00055 relativeSourceStreak.origin.y() * MY_DIM_X1 +
00056 relativeSourceStreak.origin.x();
00057 Coord<DIM> end = relativeSourceStreak.end();
00058 long indexEnd =
00059 end.z() * MY_DIM_X1 * MY_DIM_Y1 +
00060 end.y() * MY_DIM_X1 +
00061 end.x();
00062 hoodNew.index =
00063 relativeTargetOrigin.z() * MY_DIM_X2 * MY_DIM_Y2 +
00064 relativeTargetOrigin.y() * MY_DIM_X2 +
00065 relativeTargetOrigin.x();
00066
00067 FixedNeighborhood<CELL, Topology, MY_DIM_X1, MY_DIM_Y1, MY_DIM_Z1, INDEX1> hoodOldWrapped(hoodOld);
00068
00069 CELL::updateLineX(
00070 hoodOldWrapped,
00071 indexEnd,
00072 hoodNew,
00073 nanoStep);
00074 }
00075 }
00076
00077 private:
00078 const Region<DIM>& region;
00079
00080 const Coord<DIM>& sourceOffset;
00081 const Coord<DIM>& targetOffset;
00082 const unsigned nanoStep;
00083 };
00084
00085 template<typename GRID1, typename GRID2>
00086 void operator()(
00087 const Region<DIM>& region,
00088 const Coord<DIM>& sourceOffset,
00089 const Coord<DIM>& targetOffset,
00090 const GRID1& gridOld,
00091 GRID2 *gridNew,
00092 unsigned nanoStep,
00093
00094 APITraits::TrueType,
00095
00096 APITraits::TrueType,
00097
00098 APITraits::TrueType)
00099 {
00100 Coord<DIM> gridOldOrigin = gridOld.boundingBox().origin;
00101 Coord<DIM> gridNewOrigin = gridNew->boundingBox().origin;
00102
00103 Coord<DIM> realSourceOffset = sourceOffset - gridOldOrigin + gridOld.getEdgeRadii();
00104 Coord<DIM> realTargetOffset = targetOffset - gridNewOrigin + gridNew->getEdgeRadii();
00105
00106 gridOld.callback(
00107 gridNew,
00108 SoARegionUpdateHelper(region, realSourceOffset, realTargetOffset, nanoStep));
00109 }
00110
00111 template<typename GRID1, typename GRID2, typename ANY_API>
00112 void operator()(
00113 const Region<DIM>& region,
00114 const Coord<DIM>& sourceOffset,
00115 const Coord<DIM>& targetOffset,
00116 const GRID1& gridOld,
00117 GRID2 *gridNew,
00118 unsigned nanoStep,
00119
00120 APITraits::TrueType,
00121
00122 APITraits::FalseType,
00123
00124 ANY_API)
00125 {
00126 const CELL *pointers[Stencil::VOLUME];
00127
00128 for (typename Region<DIM>::StreakIterator i = region.beginStreak(); i != region.endStreak(); ++i) {
00129 Streak<DIM> streak(i->origin + sourceOffset, i->endX + sourceOffset.x());
00130 Coord<DIM> realTargetCoord = i->origin + targetOffset;
00131
00132 LinePointerAssembly<Stencil>()(pointers, *i, gridOld);
00133 LinePointerUpdateFunctor<CELL>()(
00134 streak, gridOld.boundingBox(), pointers, &(*gridNew)[realTargetCoord], nanoStep);
00135 }
00136 }
00137
00138 template<typename GRID1, typename GRID2, typename ANY_API>
00139 void operator()(
00140 const Region<DIM>& region,
00141 const Coord<DIM>& sourceOffset,
00142 const Coord<DIM>& targetOffset,
00143 const GRID1& gridOld,
00144 GRID2 *gridNew,
00145 unsigned nanoStep,
00146
00147 APITraits::FalseType,
00148
00149 APITraits::FalseType,
00150
00151 ANY_API)
00152 {
00153 for (typename Region<DIM>::StreakIterator i = region.beginStreak(); i != region.endStreak(); ++i) {
00154 Streak<DIM> sourceStreak(i->origin + sourceOffset, i->endX + sourceOffset.x());
00155 Coord<DIM> targetOrigin = i->origin + targetOffset;
00156 VanillaUpdateFunctor<CELL>()(sourceStreak, targetOrigin, gridOld, gridNew, nanoStep);
00157 }
00158 }
00159 };
00160
00161 }
00162
00169 template<typename CELL>
00170 class UpdateFunctor
00171 {
00172 public:
00173 typedef typename APITraits::SelectTopology<CELL>::Value Topology;
00174 static const int DIM = Topology::DIM;
00175
00176 template<typename GRID1, typename GRID2>
00177 void operator()(
00178 const Region<DIM>& region,
00179 const Coord<DIM>& sourceOffset,
00180 const Coord<DIM>& targetOffset,
00181 const GRID1& gridOld,
00182 GRID2 *gridNew,
00183 unsigned nanoStep)
00184 {
00185 UpdateFunctorHelpers::Selector<CELL>()(
00186 region, sourceOffset, targetOffset, gridOld, gridNew, nanoStep,
00187 typename APITraits::SelectFixedCoordsOnlyUpdate<CELL>::Value(),
00188 typename APITraits::SelectSoA<CELL>::Value(),
00189 typename APITraits::SelectUpdateLineX<CELL>::Value());
00190 }
00191 };
00192
00193 }
00194
00195 #endif
00196