CurveDerivative.hpp

00001 #ifndef __FIBER_GRID_TYPES_CURVEDERIVATIVE_HPP
00002 #define __FIBER_GRID_TYPES_CURVEDERIVATIVE_HPP
00003 
00004 #include "gridtypesDllApi.h"
00005 #include <grid/Grid.hpp>
00006 #include <eagle/PhysicalSpace.hpp>
00007 
00008 #include <grid/EuclideanMetric.hpp>
00009 #include "LineSet.hpp"
00010 
00011 //#define VERBOSE
00012 
00013 namespace Fiber
00014 {
00015 
00016 struct  IdentityOperator
00017 {
00018         template <class ValueType, class PointType>
00019  static const ValueType&compute(const ValueType&Value, index_t, const PointType&)
00020         {
00021                 return Value;
00022         }
00023 };
00024 
00025 struct  ComputeUnitVector
00026 {
00027         template <class ValueType, class PointType>
00028  static const ValueType&compute(const ValueType&Value, index_t, const PointType&)
00029         {
00030                 return unit(Value);
00031         }
00032 };
00033 
00034 
00035 struct DerivativeOperatorData
00036                 {
00037                         WeakPtr<Grid>             theGrid;
00038                         const RefPtr<FragmentID>& fragV;
00039                         string                    fieldName;
00040                         
00041                         DerivativeOperatorData(WeakPtr<Grid> theGridP, const string& fieldNameP, const RefPtr<FragmentID>& fragVP )
00042                         : theGrid( theGridP )
00043                         , fragV( fragVP )
00044                         , fieldName(fieldNameP)
00045                         {}
00046                 };
00047 
00063 template <class Type, class Metric = EuclideanMetric, class ValueOperator = IdentityOperator>
00064 struct  CurveDerivative : public Metric, public ValueOperator
00065 {
00066         typedef typename Metric::point  point;
00067         using Metric::distance;
00068 
00069         using ValueOperator::compute;
00070 
00071         RefPtr<MemArray<1, Type> >      Quantity;
00072         RefPtr<MemArray<1, Type> >      DerivedQuantity;
00073 
00074         typedef MemArray<1, Type>                       ResultArray_t;
00075 //      typedef std::pair<WeakPtr<Grid>, string>        Constructor_t;
00076         typedef DerivativeOperatorData                  Constructor_t;
00077 
00078         RefPtr<ResultArray_t> result() const
00079         {
00080                 return DerivedQuantity;
00081         }
00082 
00083         typedef std::string Parameters;
00084 
00085         CurveDerivative(const Constructor_t&C, const MemBase::Creator_t&Crec )
00086         {
00087 #ifdef VERBOSE
00088                 puts("CurveDerivative::CurveDerivative() enter");fflush(stdout);
00089 #endif
00090                 if (!C.theGrid)
00091                 {
00092                         puts("CurveDerivative::CurveDerivative() No Grid!");fflush(stdout);
00093                         return; 
00094                 } 
00095 
00096                 LineSet LS = C.theGrid; 
00097 
00098                 if (!LS)
00099                 {
00100                         puts("CurveDerivative::CurveDerivative() No LineSet!");fflush(stdout);
00101                         return; 
00102                 } 
00103 
00104                         
00105                 if (!LS.CartesianVertices)
00106                 {
00107                         puts("CurveDerivative::CurveDerivative() No Cartesian Vertices!");fflush(stdout);
00108                         return; 
00109                 }
00110 
00111                 if (!LS.getCoords( C.fragV ) )
00112                 {
00113                         puts("CurveDerivative::CurveDerivative() No Coords!");fflush(stdout);
00114                         return;
00115                 } 
00116 
00117 #ifdef VERBOSE
00118                 puts("CurveDerivative::CurveDerivative() progressing");fflush(stdout);
00119 #endif
00120 
00121         string  QuantityFieldName = C.fieldName; 
00122 
00123 #ifdef VERBOSE 
00124         puts("CurveDerivative::CurveDerivative() progressing 2");fflush(stdout);
00125         std::cout << "CurveDerivative::CurveDerivative() doing: " << QuantityFieldName << std::endl;fflush(stdout);
00126 #endif          
00127 
00128         RefPtr<Field> QuantityVertexField = (*LS.CartesianVertices)[ QuantityFieldName ]; 
00129                 if (!QuantityVertexField)
00130                 {
00131                         puts("CurveDerivative::CurveDerivative() No Quantity Field found!");fflush(stdout);
00132                         return; 
00133                 }
00134                 if (Quantity = QuantityVertexField->getData( C.fragV ) )
00135                 {
00136                         DerivedQuantity = new ResultArray_t( LS.getCoords( C.fragV )->nElements(), Crec ); 
00137 
00138 #ifdef VERBOSE 
00139                 puts("CurveDerivative::CurveDerivative() iterating"); fflush(stdout);
00140 #endif 
00141                 LS.ApplyOnVertexFragment( *this,  C.fragV );
00142 
00143 #ifdef VERBOSE
00144                 puts("CurveDerivative::CurveDerivative() post iteration"); fflush(stdout);
00145 #endif
00146 
00147                 } 
00148                 else
00149                 {
00150                         puts("CurveDerivative::CurveDerivative() No Data retrieved!");fflush(stdout);
00151                 }
00152         }
00153 
00154         void    apply(const CreativeIterator<Eagle::PhysicalSpace::point>&Vertices,
00155                       const LineSet::LineIndices_t&Line)
00156         {
00157 #ifdef VERBOSE
00158                 puts("CurveDerivative::apply()");fflush(stdout); 
00159 #endif
00160         MultiArray<1, Type>&Values          = *Quantity;
00161         MultiArray<1, Type>&ValueDerivative = *DerivedQuantity; 
00162 
00163                 if (Line.size()<1) // no data
00164                 {
00165 #ifdef VERBOSE
00166                         puts("CurveDerivative::apply() No Data"); 
00167 #endif
00168                         return; 
00169                 }
00170                 if (Line.size()<2) // one element - derivative is zero
00171                 {
00172 #ifdef VERBOSE
00173                         puts("CurveDerivative::apply() One Element"); 
00174 #endif
00175                 const point&P0 = Vertices[ Line[0] ];
00176                 const Type&Q = ValueOperator::compute( Values  [ Line[0] ], Line[0], P0 ); 
00177 
00178                         ValueDerivative[ Line[0] ] = Q-Q;
00179 #ifdef VERBOSE 
00180                         std::cout << "First" << ValueDerivative[ Line[0] ] << std::endl;
00181 #endif
00182                         return;
00183                 } 
00184                 // at least two elements, 0,1, here
00185 
00186                 // First point: forward difference
00187                 {
00188                 const point&P0 = Vertices[ Line[0] ],
00189                            &P1 = Vertices[ Line[1] ]; 
00190 
00191 /*
00192                 const Type&Q0 = ValueOperator::compute( Values  [ Line[0] ], Line[0], P0 );
00193                 const Type&Q1 = ValueOperator::compute( Values  [ Line[1] ], Line[1], P1 );
00194 
00195                 double  ds = Metric::distance(Line[0], Line[1], P0, P1);
00196 
00197                         ValueDerivative[ Line[0] ] = (Q1 - Q0) / ds;
00198 */ 
00199 
00200                 const Type&Q0 = Values  [ Line[0] ]; 
00201                 const Type&Q1 = Values  [ Line[1] ]; 
00202 
00203                 double  ds = Eagle::norm(P1 - P0);
00204 
00205                         ValueDerivative[ Line[0] ] = (Q1 - Q0) / ds; 
00206 #ifdef VERBOSE 
00207                         std::cout << "Q0= " << Q0 << ", Q1= " << Q1 << std::endl;
00208                         std::cout << "First " << ValueDerivative[ Line[0] ] << std::endl;
00209 #endif  
00210                 } 
00211 
00212                 // 
00213                 // TODO: Reuse already computed values and point coordinates. 
00214                 //
00215 
00216         index_t I = Line.size();
00217                 for(unsigned i=1; i<I-1; i++)
00218                 {
00219                 const point&Pm = Vertices[ Line[i-1] ],
00220                            &P  = Vertices[ Line[i  ] ],
00221                            &Pp = Vertices[ Line[i+1] ]; 
00222 
00223 /*              const Type&Qm = ValueOperator::compute( Values  [ Line[i-1] ], Line[i-1], Pm ),
00224                            Qp = ValueOperator::compute( Values  [ Line[i+1] ], Line[i+1], Pp ); 
00225 
00226                 double  ds_m = Metric::distance(Line[i-1], Line[i  ], Pm, P),
00227                         ds_p = Metric::distance(Line[i  ], Line[i+1], P , Pp);
00228 
00229                         ValueDerivative[ Line[i] ] = (Qp - Qm) / ( ds_m + ds_p);
00230 */ 
00231 
00232                 const Type&Qm = Values  [ Line[i-1] ],
00233                           &Q  = Values  [ Line[i  ] ],
00234                           &Qp = Values  [ Line[i+1] ]; 
00235 
00236                 double  ds2_m = 2*Eagle::norm( P - Pm ),
00237                         ds2_p = 2*Eagle::norm( Pp - P ); 
00238 
00239                         ValueDerivative[ Line[i] ] =  (Q - Qm ) / ds2_m
00240                                                       +
00241                                                       (Qp - Q ) / ds2_p
00242                                                       ; 
00243 
00244 #ifdef VERBOSE 
00245                 std::cout << "i: " << i << " " << ValueDerivative[ Line[i] ] << std::endl;
00246 #endif                          
00247                 }
00248 
00249                 // Last point: backward difference 
00250                 if (I>2)
00251                 {
00252                 index_t I = Line.size();
00253 
00254                 const point&P0 = Vertices[ Line[I-2] ],
00255                            &P1 = Vertices[ Line[I-1] ]; 
00256 
00257 /*              const Type&Q0 = ValueOperator::compute( Values  [ Line[I-2] ], Line[I-2], P0 );
00258                 const Type&Q1 = ValueOperator::compute( Values  [ Line[I-1] ], Line[I-1], P1 );
00259 
00260                 double  ds = Metric::distance(Line[I-2], Line[I-1], P0, P1);
00261 */ 
00262 
00263                 const Type&Q0 = Values  [ Line[I-2] ]; 
00264                 const Type&Q1 = Values  [ Line[I-1] ]; 
00265 
00266                 double  ds = Eagle::norm(P1-P0);
00267 
00268                         ValueDerivative[ Line[I-1] ] = (Q1 - Q0) / ds; 
00269 #ifdef VERBOSE 
00270                 std::cout << "Last: " << ValueDerivative[ Line[I-1] ] << std::endl;
00271 #endif
00272                 }
00273 
00274         }
00275 };
00276 
00277 } // namespace Fiber
00278 
00279 #endif // __FIBER_GRID_TYPES_CURVEDERIVATIVE_HPP
00280