00001
00002
00003
00004
00005
00006 #ifndef AMROC_CPTLEVELSET_H
00007 #define AMROC_CPTLEVELSET_H
00008
00016 #include "cpt/cpt.h"
00017
00025 template <class DataType, int dim>
00026 class CPTLevelSet : public GFMLevelSet<DataType,dim> {
00027 typedef GFMLevelSet<DataType,dim> base;
00028
00029 public:
00030 typedef typename base::grid_fct_type grid_fct_type;
00031 typedef typename base::grid_data_type grid_data_type;
00032 typedef typename cpt::State<dim,DataType> cpt_type;
00033
00034 CPTLevelSet() : base(), inverse(0), unsign(0), _FillWidth(0) {
00035 far_away = 1.e36;
00036 }
00037
00038 virtual ~CPTLevelSet() {}
00039
00040 virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00041 base::LocCtrl = Ctrl.getSubDevice(prefix+"CPT");
00042 RegisterAt(base::LocCtrl,"PlotPhi",base::_PlotPhi);
00043 RegisterAt(base::LocCtrl,"Inverse",inverse);
00044 RegisterAt(base::LocCtrl,"Unsigned",unsign);
00045 RegisterAt(base::LocCtrl,"FillWidth",_FillWidth);
00046 }
00047 virtual void register_at(ControlDevice& Ctrl) {
00048 register_at(Ctrl, "");
00049 }
00050
00051 virtual void SetBrep(const int num_vertices, const DataType* vertices,
00052 const int num_edges, const int* edges) {
00053 Coords ex(dim,0);
00054 BBox wholebb = grow(coarsen(base::GH().wholebbox(),DAGHShadowFactor),base::NGhosts());
00055 DCoords lbcorner = base::GH().worldCoords(wholebb.lower(), wholebb.stepsize());
00056 DCoords ubcorner = base::GH().worldCoords(wholebb.upper()+wholebb.stepsize(),
00057 wholebb.stepsize());
00058 DCoords dist = ubcorner-lbcorner; dist *= dist;
00059 DataType distance = 0.;
00060 for (register int n=0; n<dim; n++) {
00061 distance += dist(n);
00062 domain[n] = lbcorner(n); domain[dim+n] = ubcorner(n);
00063 }
00064 distance = std::sqrt(distance);
00065 state.setParameters( domain, distance );
00066 state.setBRepWithNoClipping( num_vertices, reinterpret_cast<const void*>(vertices),
00067 num_edges, reinterpret_cast<const void*>(edges) );
00068 }
00069
00070 virtual void SetPhi(grid_fct_type& phi, const int Time, const int Level, double t) {
00071 if (state.getNumberOfGrids()>0) state.clearGrids();
00072
00073 if (phi.len(Level)<=0) return;
00074
00075 Coords ss = phi(Time,Level,0).stepsize();
00076 DCoords dx = base::GH().worldStep(ss);
00077 BBox bb = base::GH().wholebbox();
00078 if (ss(0)>bb.stepsize(0)) bb.coarsen(ss/bb.stepsize());
00079 else bb.refine(bb.stepsize()/ss);
00080 bb.grow(base::NGhosts());
00081
00082 DCoords dxh2(dx); dxh2 *= static_cast<DataType>(0.5);
00083 DCoords lbcorner = base::GH().worldCoords(bb.lower(), bb.stepsize()) + dxh2;
00084 DCoords ubcorner = base::GH().worldCoords(bb.upper(), bb.stepsize()) + dxh2;
00085 DataType ldomain[2*dim];
00086 for (register int n=0; n<dim; n++) {
00087 ldomain[n] = lbcorner(n); ldomain[dim+n] = ubcorner(n);
00088 }
00089
00090 state.setLattice(bb.extents(),ldomain);
00091
00092 forall (phi,Time,Level,c)
00093 grid_data_type& gdphi = phi(Time,Level,c);
00094 Coords lb = gdphi.lower();
00095 Coords ub = gdphi.upper()+gdphi.stepsize();
00096 lb /= gdphi.stepsize(); ub /= gdphi.stepsize();
00097 lb += base::NGhosts(); ub += base::NGhosts();
00098
00099 state.insertGrid( reinterpret_cast<const int*>(lb()),
00100 reinterpret_cast<const int*>(ub()),
00101 reinterpret_cast<DataType*> (gdphi.data()),
00102 reinterpret_cast<DataType*> (0),
00103 reinterpret_cast<DataType*> (0),
00104 reinterpret_cast<int*> (0) );
00105 end_forall
00106
00107 if (state.getNumberOfGrids()>0) {
00108 if (_FillWidth>0) {
00109 double distance = 0.;
00110 for (register int n=0; n<dim; n++)
00111 distance += dx[n]*dx[n];
00112 distance = std::sqrt(distance)*_FillWidth;
00113 state.setParameters( domain, distance );
00114 }
00115
00116 if (unsign) {
00117 if (state.areGridsValidUnsigned()) {
00118 START_WATCH
00119 state.computeClosestPointTransformUnsigned();
00120 END_WATCH(LS_CPT_TRANSFORM)
00121 START_WATCH
00122 state.floodFillUnsigned( far_away );
00123 END_WATCH(LS_CPT_FLOODFILL)
00124 }
00125 else
00126 std::cout << "Invalid grid for closest point transform on lev=" << Level
00127 << " time=" << t << std::endl;
00128 }
00129 else {
00130 if (state.areGridsValid()) {
00131 START_WATCH
00132 state.computeClosestPointTransform();
00133 END_WATCH(LS_CPT_TRANSFORM)
00134 START_WATCH
00135 state.floodFillDetermineSign( far_away );
00136 END_WATCH(LS_CPT_FLOODFILL)
00137 if (inverse) {
00138 forall (phi,Time,Level,c)
00139 grid_data_type& gdphi = phi(Time,Level,c);
00140 gdphi.multiply(-1.0);
00141 end_forall
00142 }
00143 }
00144 else
00145 std::cout << "Invalid grid for closest point transform on lev=" << Level
00146 << " time=" << t << std::endl;
00147 }
00148 }
00149
00150 START_WATCH
00151 Sync(phi,Time,Level);
00152 END_WATCH(LS_SYNC)
00153 START_WATCH
00154 ExternalBoundaryUpdate(phi,Time,Level);
00155 END_WATCH(BOUNDARIES_EXTERNAL)
00156 }
00157
00158 virtual void SetGrid(grid_data_type& gdphi, const int& Level, const double& t) {
00159 if (state.getNumberOfGrids()>0) state.clearGrids();
00160
00161 BBox bb = gdphi.bbox();
00162 Coords ss = bb.stepsize();
00163 DCoords dx = base::GH().worldStep(ss);
00164 DCoords dxh2(dx); dxh2 *= static_cast<DataType>(0.5);
00165 DCoords lbcorner = base::GH().worldCoords(bb.lower(), ss) + dxh2;
00166 DCoords ubcorner = base::GH().worldCoords(bb.upper(), ss) + dxh2;
00167 DataType ldomain[2*dim];
00168 for (register int n=0; n<dim; n++) {
00169 ldomain[n] = lbcorner(n); ldomain[dim+n] = ubcorner(n);
00170 }
00171
00172 state.setLattice(bb.extents(),ldomain);
00173
00174 Coords lb = gdphi.lower();
00175 Coords ub = gdphi.upper()+ss;
00176 lb /= ss; ub /= ss;
00177 lb += base::NGhosts(); ub += base::NGhosts();
00178
00179 state.insertGrid( reinterpret_cast<const int*>(lb()),
00180 reinterpret_cast<const int*>(ub()),
00181 reinterpret_cast<DataType*> (gdphi.data()),
00182 reinterpret_cast<DataType*> (0),
00183 reinterpret_cast<DataType*> (0),
00184 reinterpret_cast<int*> (0) );
00185
00186 if (state.getNumberOfGrids()>0) {
00187 if (_FillWidth>0) {
00188 double distance = 0.;
00189 for (register int n=0; n<dim; n++)
00190 distance += dx[n]*dx[n];
00191 distance = std::sqrt(distance)*_FillWidth;
00192 state.setParameters( domain, distance );
00193 }
00194
00195 if (unsign) {
00196 if (state.areGridsValidUnsigned()) {
00197 START_WATCH
00198 state.computeClosestPointTransformUnsigned();
00199 END_WATCH(LS_CPT_TRANSFORM)
00200 START_WATCH
00201 state.floodFillUnsigned( far_away );
00202 END_WATCH(LS_CPT_FLOODFILL)
00203 }
00204 else
00205 std::cout << "Invalid grid for closest point transform on lev=" << Level
00206 << " time=" << t << std::endl;
00207 }
00208 else {
00209 if (state.areGridsValid()) {
00210 START_WATCH
00211 state.computeClosestPointTransform();
00212 END_WATCH(LS_CPT_TRANSFORM)
00213 START_WATCH
00214 state.floodFillDetermineSign( far_away );
00215 END_WATCH(LS_CPT_FLOODFILL)
00216 if (inverse)
00217 gdphi.multiply(-1.0);
00218 }
00219 else
00220 std::cout << "Invalid grid for closest point transform on lev=" << Level
00221 << " time=" << t << std::endl;
00222 }
00223 }
00224 }
00225
00226 inline cpt_type& State() { return state; }
00227 inline const cpt_type& State() const { return state; }
00228 inline void SetUnsigned(const int us) { unsign = us; }
00229 inline int Unsigned() const { return unsign; }
00230 inline void SetInverse(const int iv) { inverse = iv; }
00231 inline int Inverse() const { return inverse; }
00232
00233 protected:
00234 cpt_type state;
00235 int inverse, unsign, _FillWidth;
00236 DataType far_away;
00237 DataType domain[2*dim];
00238 };
00239
00240
00241 #endif