00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef AMROC_SCALEDGRADIENT_H
00010 #define AMROC_SCALEDGRADIENT_H
00011
00018 #include "StdCriterion.h"
00019
00026 template <class VectorType, class FlagType, int dim>
00027 class ScaledGradient :
00028 public StdCriterion<VectorType,FlagType,dim> {
00029 typedef typename VectorType::InternalDataType DataType;
00030 typedef StdCriterion<VectorType,FlagType,dim> base;
00031 public:
00032 typedef typename base::vec_grid_fct_type vec_grid_fct_type;
00033 typedef typename base::grid_fct_type grid_fct_type;
00034 typedef typename base::flag_fct_type flag_fct_type;
00035 typedef typename base::max_vector_type max_vector_type;
00036
00037 ScaledGradient() : base() {
00038 base::SetShadowCriterion(false);
00039 Tol = static_cast<DataType>(0.0);
00040 }
00041
00042 virtual ~ScaledGradient() {}
00043
00044 virtual void register_at(ControlDevice& Ctrl) {}
00045 virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00046 base::LocCtrl = Ctrl.getSubDevice(prefix+"ScaledGradient");
00047 char Name[16];
00048 for (int d=0; d<max_vector_type::Length(); d++) {
00049 std::sprintf(Name,"Tol(%d)",d+1);
00050 RegisterAt(base::LocCtrl,Name,Tol(d));
00051 std::sprintf(Name,"MaxLev(%d)",d+1);
00052 RegisterAt(base::LocCtrl,Name,base::_MaxLevel[d]);
00053 }
00054 RegisterAt(base::LocCtrl,"Output",base::_Output);
00055 }
00056
00057 virtual void update() {
00058 int d=max_vector_type::Length();
00059 for (; d>0; d--)
00060 if (Tol(d-1) > static_cast<DataType>(0.0))
00061 break;
00062 if (d>0) {
00063 base::SetNcnt(d);
00064 base::SetIsUsed(true);
00065 }
00066 else
00067 base::SetIsUsed(false);
00068 }
00069
00070 virtual bool SetFlags(vec_grid_fct_type& u, grid_fct_type& work, flag_fct_type& flags,
00071 const int& cnt, const int& Time, const int& Level, const double& t,
00072 const FlagType& FlagValue) {
00073 if (Tol(cnt) <= 0.0) return false;
00074 int TStep = TimeStep(work,Level);
00075 if (base::MaxLevel(cnt)<Level && base::MaxLevel(cnt)>=0) {
00076 if (base::OutputFlags()) {
00077 forall(work,Time,Level,c)
00078 work(Time+TStep,Level,c) = static_cast<DataType>(0.0);
00079 end_forall
00080 }
00081 return true;
00082 }
00083
00084 forall(work,Time,Level,c)
00085 equals_from(work(Time,Level,c), u(Time,Level,c), cnt);
00086 end_forall
00087 return FlagByScaledGradient(work, flags, Time, Level, Tol(cnt), FlagValue);
00088 }
00089
00090 virtual bool FlagByScaledGradient(grid_fct_type& work, flag_fct_type& flags,
00091 const int& Time, const int& Level,
00092 const DataType& TolVal, const FlagType& FlagValue) {
00093 if (TolVal <= 0.0) return false;
00094
00095 int TStep = TimeStep(work,Level);
00096 forall(work,Time,Level,c)
00097 work(Time+TStep,Level,c) = static_cast<DataType>(0.0);
00098 end_forall
00099
00100 if (dim == 1) {
00101 int East[1] = { 1 }; int West[1] = { -1 };
00102 base::Difference(work, Time, Level, East, West);
00103 }
00104 else if (dim == 2) {
00105 int East[2] = { 1, 0 }; int West[2] = { -1, 0 };
00106 int North[2] = { 0, 1 }; int South[2] = { 0, -1 };
00107 base::Difference(work, Time, Level, East, West);
00108 base::Difference(work, Time, Level, North, South);
00109
00110 int NorthEast[2] = { 1, 1 }; int SouthWest[2] = { -1, -1 };
00111 int NorthWest[2] = { -1, 1 }; int SouthEast[2] = { 1, -1 };
00112 base::Difference(work, Time, Level, NorthEast, SouthWest);
00113 base::Difference(work, Time, Level, NorthWest, SouthEast);
00114 }
00115 else if (dim == 3) {
00116 int East[3] = { 1, 0, 0 }; int West[3] = {-1, 0, 0 };
00117 int North[3] = { 0, 1, 0 }; int South[3] = { 0, -1, 0 };
00118 int Top[3] = { 0, 0, 1 }; int Bottom[3] = { 0, 0, -1 };
00119 base::Difference(work, Time, Level, East, West);
00120 base::Difference(work, Time, Level, North, South);
00121 base::Difference(work, Time, Level, Top, Bottom);
00122
00123 int NorthEastTop[3] = { 1, 1, 1}; int SouthWestBottom[3] = { -1, -1, -1};
00124 int NorthEastBottom[3] = { 1, 1, -1}; int SouthWestTop[3] = { -1, -1, 1};
00125 int NorthWestTop[3] = { -1, 1, 1}; int SouthEastBottom[3] = { 1, -1, -1};
00126 int NorthWestBottom[3] = { -1, 1, -1}; int SouthEastTop[3] = { 1, -1, 1};
00127 base::Difference(work, Time, Level, NorthEastTop, SouthWestBottom);
00128 base::Difference(work, Time, Level, NorthEastBottom, SouthWestTop);
00129 base::Difference(work, Time, Level, NorthWestTop, SouthEastBottom);
00130 base::Difference(work, Time, Level, NorthWestBottom, SouthEastTop);
00131 }
00132 base::FlagByValue(work, flags, Time, Level, TolVal, FlagValue);
00133 return true;
00134 }
00135
00136 virtual void OutputName(char* name, int cnt) { std::sprintf(name,"grad_%d",cnt+1); }
00137
00138 max_vector_type Tol;
00139 };
00140
00141 #endif