IntegralLine.hpp

00001 #include "IntegralFace.hpp"
00002 #include <fish/lakeview/base/FieldInterpolator.hpp>
00003 
00004 #include <ocean/plankton/VCreator.hpp>
00005 #include <ocean/eagle/PhysicalSpace.hpp>
00006 #include <ocean/eagle/STA.hpp>
00007 #include <ocean/shrimp/VEnum.hpp>
00008 #include <ocean/shrimp/PhysicalSpace.hpp>
00009 
00010 #include <ocean/plankton/VTimer.hpp>
00011  
00012 #include <bone/FishField.hpp>
00013 #include <bone/FishSlice.hpp>
00014 
00015 #include <ocean/shrimp/VObjectStatus.hpp>
00016 #include <fish/fiber/baseop/LocalFromWorldPoint.hpp>
00017 #include <fish/fiber/baseop/ExpandBBox.hpp>
00018 
00019 #include <ode/dop853def.hpp>
00020 #include <baseop/TangentialVectors.hpp>
00021 
00022 #include <ocean/plankton/VTimer.hpp>
00023 
00024 #include <grid/types/LineSet.hpp>
00025 
00026 
00027 
00028 
00029 //#define VERBOSE
00030 
00031 #define TIMEIT
00032 
00033 namespace FieldLines
00034 {
00035 
00036 // using namespace Wizt;
00037 // using namespace Fiber;
00038 // using namespace Eagle;
00039 // using namespace Eagle::PhysicalSpace;
00040 // using namespace Traum;
00041 
00042 typedef std::string FragmentID_t;
00043 
00044 template<class FieldType>
00045 struct  IntegrationPoint
00046 {
00047         typedef typename FieldType::Chart_t Chart_t;
00048         typedef typename Coordinates<Chart_t>::point point;
00049         typedef typename Coordinates<Chart_t>::vector tvector;
00050         
00052         //point      location;
00053         point location;
00055         FieldType            data;
00057         Eagle::PhysicalSpace::point index_location;
00058 
00060         FragmentID_t fragment;
00061 
00063         bool is_end;
00064 
00066         tvector      direction;
00067 
00069         double length;
00070 
00071         IntegrationPoint()
00072         :is_end(false)
00073         {}
00074         void setLocation(point&locationP)
00075         {
00076                 location = locationP;
00077         }
00078 
00079         void setDirection(tvector directionP)
00080         {
00081                 direction = directionP;
00082         }
00083 
00084         void setData( const FieldType&dataP, const Eagle::PhysicalSpace::point&index_locationP, const FragmentID_t&fragmentP, const double lengthP )
00085         {
00086                 data = dataP; 
00087                 index_location = index_locationP; 
00088                 fragment = fragmentP; 
00089                 length = lengthP;
00090         }
00091 
00092         void setEnd()
00093         {
00094                 is_end = true;
00095         }
00096 };
00097 
00098 // template<class P>
00099 // struct Pointilizer
00100 // {
00101 //      typedef typename P::Chart_t point;
00102 // };
00103 
00104 // template<>
00105 // class Pointilizer<Coordinates<Eagle::CartesianChart3D > >
00106 // {
00107 //      typedef Eagle::point3 point;
00108 // };
00109 
00110 // template<>
00111 // class Pointilizer<Coordinates<STA::CartesianChart4D<> > >
00112 // {
00113 //      typedef point4 point;
00114 // };
00115 
00116  /*
00117   Note: This kind of data structure is inefficient, it should 
00118   definitely be revised. With this layout, it requires copying data
00119   for getting these data into the fiber bundle layout.
00120  */
00121 //typedef       RefPtr<Chunk<IntegrationPoint<metric33> > > IntegrationResult_t;
00122 
00123 //      IntegrationResult_t x;
00124 
00125 
00126 /*
00127 This is the structure how it should be. This one is fiber-bundle compatible.
00128 
00129 template<class FieldType>
00130 struct  IntegrationResult
00131 {
00133         RefPtr<Chunk<point> >        location;
00134 
00136         RefPtr<Chunk<FieldType> >            direction;
00137 
00139         RefPtr<Chunk<point> >        index_location;
00140 
00142         RefPtr<Chunk<FragmentID_t> > fragment;
00143 };
00144 */
00145 
00146 
00147 /*
00148                 if( interpol == 0 )     
00149                 {
00150                         VectorLinearInterpolator_t myField(*ToIntArr, float_index); 
00151                                 InterpolData = myField.eval();
00152                 }       
00153                 else if( interpol == 1 )
00154                 {
00155                         VectorCubicInterpolator_t myField(*ToIntArr, float_index); 
00156                                 InterpolData = myField.eval();
00157                 } 
00158                 else
00159                 {
00160                         if ( MemCore::InterfacePtr<Eqn_t> AnalyticField = *ToIntegrateField )
00161                         {
00162                                 Eqn_t&AF = *AnalyticField; 
00163                                         InterpolData = AF(time, location);
00164                         } 
00165                         else
00166                         {
00167                         VectorLinearInterpolator_t myField(*ToIntArr, float_index); 
00168                                 InterpolData = myField.eval();
00169                         }
00170                 }
00171 */
00172 
00173 
00174 struct AtomicDataBase
00175 {
00176         RefPtr<LocalFromWorldPoint> LocalPointFinder;
00177         FieldSelector FieldSelection;
00178         RefPtr<BoundingBox> BB;
00179         double step_size; 
00180         double scale;
00181         bool inited;
00182 //      unsigned interpol;
00183 
00184         AtomicDataBase( const RefPtr<LocalFromWorldPoint>&LocalPointFinderP, 
00185                         const FieldSelector&FieldSelectionP, const RefPtr<BoundingBox>&BBP, 
00186                         const double step_sizeP , const double scale_facP ) //, const unsigned interpolP )
00187         : LocalPointFinder(LocalPointFinderP)
00188         , FieldSelection(FieldSelectionP) // somehow this was not sufficient ?!? see below
00189         , BB(BBP)
00190         , step_size(step_sizeP)
00191         , scale(scale_facP)
00192         , inited(false)
00193           //, interpol(interpolP)
00194         {
00195                 FieldSelection = FieldSelectionP;       
00196 #ifdef VERBOSE
00197                 
00198                 cout << "AtomicDataBase::AtomicDataBase FieldSelectionP: " << FieldSelectionP.getFieldName() << endl; 
00199                 cout << "AtomicDataBase::AtomicDataBase FieldSelection: " << FieldSelection.getFieldName() << endl; 
00200 #endif          
00201         }
00202 };
00203 
00204 
00205 class IntegrationFrontContainerBase
00206 {
00207 protected:
00208         unsigned size;
00209         unsigned last_index;
00210         
00211         unsigned front_index;
00212 
00213 public:
00214         IntegrationFrontContainerBase(const unsigned sizeP = 0)
00215         : size(sizeP)
00216         , last_index(0)
00217         , front_index(0)
00218                 {}
00219 
00220         void setSize(const unsigned sizeP)     { size = sizeP; }
00221         unsigned getSize() const               { return size; }
00222         void setLastIndex(const unsigned last) { last_index = last; }
00223         void advanceIndex()                    { last_index = last_index++ % size; }
00224         unsigned getLastIndex() const          { return last_index; }  
00225         void advanceFrontIndex()               { front_index++; }
00226         unsigned getFrontIndex() const         { return front_index; }
00227 };
00228 
00229 
00230 template<typename FieldType, typename LineType>
00231 class IntegrationFrontContainter
00232 {
00233 
00234 public:
00235 
00236         void insertDataToBundle( FieldSelector&FieldSelection, const string module_name )
00237         {
00238                 puts("IntegrationFrontContainter<>::insertDataToBundle() to be implemented!");
00239         }
00240         
00241 };
00242 
00243 
00244 
00245 
00246 // type trait for atomic integration requires 1 Euler and 2 Dop853 functions
00247 template<typename FieldType, typename LineType, int InterpolType>
00248 class AtomicIntegrator
00249 {
00250         typedef RefPtr<Chunk<IntegrationPoint<FieldType> > > IntegrationResult_t;
00251         typedef MemArray<3, FieldType> ToIntegrateArray_t; 
00252 public:
00255         bool doEuler( std::vector<IntegrationPoint<FieldType> >&IntegrationLine, const double&time )
00256         {
00257                 puts("FieldLines::AtomicIntegrator<FieldType>.doEuler() ERROR: Unsupported type FieldType doing nothing!");fflush(stdout); 
00258                 return false;
00259         }
00260 
00261         // bool doEuler( IntegrationContainer<FieldType, LineType>&IntegrationData
00262         //            const double&time )
00263 
00264         bool doDop853( std::vector<IntegrationPoint<FieldType> >&IntegrationLine, 
00265                        const RefPtr<LocalFromWorldPoint>&LocalPointFinder,
00266                        const FieldSelector&FieldSelection,
00267                        const RefPtr<BoundingBox>&BB,
00268                        const double step_size, const double time,
00269                        const unsigned line_nr )
00270         {
00271                 puts("FieldLines::AtomicIntegrator<FieldType>.doDop853() ERROR: Unsupported type FieldType doing nothing!");fflush(stdout); 
00272                 return false;   
00273         }
00274 
00275         bool initDop853( const int number_of_lines )
00276         {
00277                 puts("FieldLines::AtomicIntegrator<FieldType>.initDop853() ERROR: Unsupported type FieldType doing nothing!");fflush(stdout); 
00278                 return false;
00279         }       
00280 
00281         void finalize( std::vector<IntegrationPoint<FieldType> >&IntegrationLine, const double&time )
00282         {
00283                 puts("FieldLines::AtomicIntegrator<FieldType>.finalize() INFO: Unsupported type FieldType doing nothing!");fflush(stdout); 
00284                 return;
00285         }
00286 };
00287 
00288 
00289 
00290 template <class Extractor, class Container>
00291 RefPtr<MemBase> CollectLines(const Extractor&E, const std::vector<RefPtr<Chunk<Container> > >&Lines, size_t nPoints)
00292 {
00293 typedef typename Extractor::output_t output_t;
00294 typedef MemArray<1, output_t> ResultMemArray_t;
00295 
00296 size_t  nLines = Lines.size(); 
00297 Ref<ResultMemArray_t> ResultArray( MIndex(nPoints) );
00298 std::vector<output_t>&LineResult = ResultArray->myChunk()->get_vector(); 
00299 
00300 index_t VertexNr = 0;
00301         for(index_t LineNr = 0; LineNr < nLines; LineNr++)
00302         {
00303         const std::vector<Container>&PointsPerLine = Lines[LineNr]->std_vector(); 
00304                 for(index_t LineVertex = 0; LineVertex < PointsPerLine.size() ; LineVertex++ )
00305                 {
00306                         LineResult[ VertexNr ] = E(PointsPerLine[ LineVertex ]); 
00307                         VertexNr++;
00308                 }
00309         }
00310         return ResultArray;
00311 }
00312 
00317 template <class Container>
00318 void CollectLineData(Representation&CartesianVertices, const std::vector<RefPtr<Chunk<Container> > >&Lines, size_t nPoints);
00319 
00320 
00321 struct  CopyExtractor
00322 {
00323         typedef FieldLines::IntegrationPoint<Eagle::PhysicalSpace::tvector> input_t;
00324         typedef Eagle::point3 output_t;
00325 
00326         output_t operator()(const input_t&in) const
00327         {
00328                 return output_t(in.location);
00329         }
00330 };
00331 
00335 template <>
00336 inline void CollectLineData(Representation&CartesianVertices, 
00337                             const std::vector<RefPtr<Chunk< FieldLines::IntegrationPoint<Eagle::PhysicalSpace::tvector> > > >&Lines, size_t nPoints)
00338 {
00339 RefPtr<Field>   LinePositions = new Field();
00340         LinePositions->setPersistentData( CollectLines( CopyExtractor(), Lines, nPoints) );
00341         CartesianVertices.setPositions( LinePositions );
00342 }
00343 
00344 
00345 
00346 
00347 
00348 
00349 struct  ExtractPointLocation
00350 {
00351         typedef FieldLines::IntegrationPoint<Eagle::metric44> input_t;
00352         typedef Eagle::point3 output_t;
00353 
00354         output_t operator()(const input_t&in) const
00355         {
00356                 return output_t(in.location[1],in.location[2],in.location[3]);
00357         }       
00358 };
00359 
00360 struct  ExtractTime
00361 {
00362         typedef FieldLines::IntegrationPoint<Eagle::metric44> input_t;
00363         typedef double output_t;
00364 
00365         output_t operator()(const input_t&in) const
00366         {
00367                 return in.location[0];
00368         }
00369 };
00370 
00374 template <>
00375 inline void CollectLineData(Representation&CartesianVertices, 
00376                             const std::vector<RefPtr<Chunk< FieldLines::IntegrationPoint<Eagle::metric44> > > >&Lines, size_t nPoints)
00377 {
00378 RefPtr<Field>   LinePositions = new Field();
00379         LinePositions->setPersistentData( CollectLines( ExtractPointLocation(), Lines, nPoints) );
00380         CartesianVertices.setPositions( LinePositions );
00381 
00382         CartesianVertices[ "ProperTime" ]->setPersistentData( CollectLines( ExtractTime(), Lines, nPoints) );
00383 }
00384 
00385 
00386 
00390 template <class Container>
00391 RefPtr<LineSet::LinesetArray_t> createLineSet(const std::vector<RefPtr<Chunk<Container> > >&Lines)
00392 {
00393 size_t  NumberOfLines = Lines.size();
00394 Ref<LineSet::LinesetArray_t> LinesetArray(NumberOfLines);
00395 MultiArray<1, std::vector<LineSet::LineIndex_t> >&LineIndices = *LinesetArray; 
00396 
00397 index_t VertexNumber = 0;
00398         for(index_t line=0; line<NumberOfLines; line++)
00399         {
00400         std::vector<LineSet::LineIndex_t>&E = LineIndices[ line ];
00401         index_t LineLength = Lines[line]->std_vector().size();
00402 
00403                 E.resize( LineLength );
00404                 for(index_t i=0; i<LineLength; i++)
00405                 {
00406                         E[i] = VertexNumber;
00407                         VertexNumber ++;
00408                 }
00409         }
00410 
00411         return LinesetArray;
00412 }
00413 
00414 
00415 
00416 
00417 template <class FieldType, typename LineType, int InterpolType>
00418 class   LineAdvancer
00419 {
00420 typedef RefPtr<Chunk<IntegrationPoint<FieldType> > > IntegrationResult_t;
00421 typedef MemArray<3, FieldType> ToIntegrateArray_t; 
00422 
00423         AtomicIntegrator<FieldType, LineType, InterpolType> AI;
00424         std::vector<IntegrationResult_t> Lines;
00425         bool dop;
00426         size_t nPoints;
00427         double min_line_length;
00428         double start_time;
00429         double time;
00430 
00431 public:
00432         LineAdvancer(const std::vector<IntegrationResult_t>&LinesP,
00433                      const FieldSelector&FieldSelectionP, const RefPtr<LocalFromWorldPoint>&LocalPointFinderP,
00434                      const RefPtr<BoundingBox>&BBP, const double step_sizeP, const bool dopP, const size_t nPointsP,
00435                      const double min_line_lengthP, const double start_timeP, const double scale_facP )
00436         : AI(LocalPointFinderP, FieldSelectionP, BBP, step_sizeP, scale_facP)
00437         , Lines(LinesP)
00438         , dop(dopP)
00439         , nPoints(nPointsP)
00440         , min_line_length(min_line_lengthP)
00441         , start_time(start_timeP)
00442         , time(start_timeP)
00443         {}
00444 
00445 //      LineIntegrator::LineIntegrator(){}
00446 
00447 
00448         size_t getNPoints() { return nPoints;}
00449         
00450 //      std::vector<IntegrationResult_t>& getLines(){ return Lines; }
00451 
00452 
00453         bool advanceBreadthFirst( )
00454         {
00455         unsigned end_counter = 0; 
00456 
00457                 if( dop && !AI.inited )
00458                         AI.initDop853( Lines.size() ); 
00459 
00460                 for(unsigned p = 0; p < Lines.size(); p++)
00461                 {
00462 //                      printf("\n WORKING ON LINE %d out of %d\n", p, Lines.size() ); 
00463 //                      VActionNotifier::ProgressInfo("Working on line " + String(int(p)) + " out of " + String(int(Lines.size())) );
00464 
00465                 IntegrationResult_t &IntegrationLine = Lines[ p ];
00466                 int last_index = IntegrationLine->size()-1; 
00467 
00468 
00469                         if( last_index >= 0 )
00470                                 if( (*IntegrationLine)[last_index].is_end == true )
00471                                         continue; 
00472 
00473                         if( last_index >= 1 )
00474                         {
00475                                 //printf( "advacer: length %f, limit: %f\n", (*IntegrationLine)[last_index-1].length, min_line_length ); 
00476                                 if( (*IntegrationLine)[last_index-1].length > min_line_length )
00477                                 {
00478                                         (*IntegrationLine)[last_index].setEnd(); 
00479                                         continue;
00480                                 }                       
00481                         }       
00482 
00483                 bool test;
00484 
00485                         if( !dop )
00486                                 test = AI.doEuler( *IntegrationLine, time); 
00487                         else
00488                                 test = AI.doDop853( *IntegrationLine, time, p ); 
00489 
00490                         if( test == false ) 
00491                                 end_counter++;
00492                         else
00493                                 nPoints++; 
00494 
00495         } 
00496 
00497                 VActionNotifier::ProgressInfo("Integration of " + String(int(Lines.size())) + " lines done."  );
00498 
00499 //      printf("end_counter %d, Lines.size() %d\n", end_counter, Lines.size() ); 
00500                 return ( end_counter == Lines.size() ) ? true : false;
00501         }
00502 
00503         void finalize()
00504         {
00505                 for(unsigned p = 0; p < Lines.size(); p++)
00506                 {
00507                 IntegrationResult_t &IntegrationLine = Lines[ p ]; 
00508 
00509                         AI.finalize( *IntegrationLine, time ); 
00510                 }
00511         }
00512 
00513 };
00514 
00515 
00516 // type trait to convert the integration line type to a string used for naming in the fiber bundle
00517 // must be provided in the specializations
00518 template<typename FieldType, typename LineType>
00519 struct LineTypeString
00520 {
00521         string name() { return "Unknown"; }
00522 };
00523 
00524 
00525 template <typename FieldType, typename LineType>
00526 class   IntegralLines : public IntegralFace
00527 {
00528 public:
00529         typedef MemArray<3, double>                    ScalarArray_t;
00530         typedef MemArray<3, Eagle::point3>             CoordsArray_t;
00531         typedef MemArray<1, Eagle::point3>             CoordsArray1D_t;
00532         typedef MemArray<1, tvector>                   VecsArray1D_t;
00533         typedef MemArray<1, std::string>               FragmentIDs_t;
00534         typedef MemArray<1, BoundingBox>               FragmentBounds_t;
00535 
00536 
00537         IntegralLines(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
00538         : VObject(name, p, VP)
00539         , Fish<VObject>(this)
00540         , Fish<Field>("inputfield")
00541         , IntegralFace(name, p, VP)
00542         {}
00543 
00544         typedef RefPtr<Chunk<IntegrationPoint<FieldType> > > IntegrationResult_t;
00545 
00546         typedef typename FieldType::Chart_t Chart_t;
00547         typedef typename Coordinates<Chart_t>::point point;     
00548         typedef typename Coordinates<Chart_t>::vector tvector4; 
00549         
00550         override bool update(VRequest&R, double precision);
00551         
00552         static  string createChildname(const string&inputfield)
00553         {
00554                 LineTypeString<FieldType,LineType> tmp;
00555                 return tmp.name() +"(" + inputfield + ")";
00556         }
00557 
00558 
00559         void printProgress( unsigned&old_nPoints, const unsigned nPoints, const unsigned nPointsEst, VRequest&Context)
00560         {
00561                 if( old_nPoints + 100 < nPoints )
00562                 {
00563                         old_nPoints = nPoints;
00564                  char buf[64]; 
00565                         float percent = (double)nPoints / nPointsEst * 100; 
00566                         sprintf(buf, "Integrating %.1f %% #%d", percent, (int)nPoints); 
00567                         VActionNotifier::ProgressInfo (string(buf)); 
00568                         printf("%s\n", buf);fflush(stdout);
00569                         setStatusInfo( Context, buf);
00570                  } 
00571                 
00572         }
00573 
00574         template<class IntegratorType>
00575         int doMainLoop(IntegratorType&IntT, const double max_steps, const int nPointsEst, const size_t nPoints, VRequest&Context)
00576         {
00577         int step_counter = 0; 
00578         bool hasfinished = false; 
00579         unsigned old_nPoints = 0; 
00580         
00581                 while( hasfinished == false && step_counter < max_steps )
00582                 {
00583                         printProgress(old_nPoints, nPoints, nPointsEst, Context ); 
00584                         hasfinished = IntT.advanceBreadthFirst();//,                   //'returns' 
00585                         step_counter++; 
00586                 } 
00587                 IntT.finalize();//, 
00588 
00589                 return IntT.getNPoints(); 
00590         }
00591 
00592 };
00593 
00594 template<typename FieldType, typename LineType>
00595 bool IntegralLines<FieldType,LineType>::update(VRequest&Context, double precision)
00596 {
00597 double sec = 0.0;
00598 VTimer Tim_update; 
00599 
00600 #ifdef VERBOSE
00601         printf("IntegralLines::update()  -->%s<--: enter\n", Name().c_str() );fflush(stdout); 
00602 #endif 
00603 
00604 // 1. Get input field information 
00605 // 
00606 #ifdef VERBOSE
00607         puts("IntegralLines::update() 1. Get input field information");fflush(stdout); 
00608 #endif
00609 
00610 FieldSelector   FieldSelection = getFieldSelector(Context); 
00611 RefPtr<Field>   InputToIntegrateField = FieldSelection.getField(); 
00612 
00613         if(!FieldSelection.theSourceBundle) { return errorMsg(Context, "No bundle found in integrate field");    }
00614         if(!InputToIntegrateField)          { return errorMsg(Context, "No integratable field in input bundle"); }
00615 
00616 double time      = FieldSelection.getTime(); 
00617 string fieldName = FieldSelection.getFieldName();
00618 
00619 
00620 // 2. Get emitter info
00621 // 
00622 
00623 GridSelector EmitterGS; 
00624 FieldSelector EmitterFS; 
00625         StartGrid << Context >> EmitterGS; 
00626         StartField << Context >> EmitterFS; 
00627 
00628 EmitterFieldData EFD( EmitterGS, EmitterFS ); 
00629 
00630 RefPtr<Field> EmitterCoordinates = getEmitterField( Context, EFD ); 
00631 
00632 Enum Dop;
00633         UseDop853 << Context >> Dop; 
00634 
00635 Enum Interpol; 
00636         Ipol << Context >> Interpol;
00637         
00638 
00639 //
00640 // 3. Construct name for the output grid (the integral lines) and check if it already exists. And if so, if not the 
00641 //    input is newer, such that it would require re-creation.
00642 // 
00643 string grid_name = FieldSelection.Gridname() + "_" + Name(); 
00644 
00645         if (Dop("yes") ) grid_name += "_dop853";
00646 
00647 GridSelector GS; 
00648         myIntegralLines << Context >> GS; 
00649 
00650 UpdateCheckData UCD( EmitterCoordinates, FieldSelection, GS, InputToIntegrateField, time, grid_name); 
00651 
00652         if( !needUpdate( Context, UCD) )
00653         {
00654                 puts("IntegralLines::update() 3.5 no update needed");
00655                 return true;
00656         }
00657 // 
00658 // 4. Make sure we have some seed points 
00659 // 
00660         puts("IntegralLines::update() 4. Make sure we have seeding points");fflush(stdout); 
00661 
00662 RefPtr<BoundingBox> ToIntegratefieldBBox = getBoundingBox( *FieldSelection.getGrid() ); 
00663         if (!ToIntegratefieldBBox) return setStatusError(Context, "No bounding box available.\n"); 
00664 
00665 int     NumberOfInternalSeedPoints = 23; 
00666         InternalEmissionSeedPoints << Context >> NumberOfInternalSeedPoints;
00667 AutoEmitterData AED( EmitterCoordinates, ToIntegratefieldBBox, NumberOfInternalSeedPoints);
00668         setDefaultEmissionPoints(Context, AED);
00669 
00670 
00671         //
00672         // Note: the emitter coordinate field could also be fragmented.
00673         // In this case, the getData() call will return a NullPtr().
00674         // In general, we need to rather iterate here over all field
00675         // fragments of the emitter coordinates.
00676         //
00677 RefPtr<CoordsArray1D_t > EmitterVerts = EmitterCoordinates->getData();
00678         if (!EmitterVerts)
00679                 return setStatusError( Context, "Emitter points not in a supported format"); 
00680 
00681         MultiArray<1, Eagle::point3>&EmitterCrds = *EmitterVerts; 
00682 
00683 //
00684 RefPtr<Field> EmitterVecField = EmitterFS.getField(); 
00685 RefPtr<VecsArray1D_t > EmitterVecs;
00686  
00687         if(EmitterVecField)
00688                 EmitterVecs = EmitterVecField->getData(); 
00689 
00690 
00691 
00692 // 
00693 
00694 // 5. Prepare data structs for integration 
00695 // 
00696 // 
00697         puts("IntegralLines::update() 5. Prepare data");fflush(stdout); 
00698 BundlePtr   outBPtr = FieldSelection.BundleSource();
00699 Info<Slice> currentSlice = FieldSelection.FieldSource; 
00700 
00701         assert( FieldSelection.getGrid() );
00702 const Grid&InputGrid = *FieldSelection.getGrid(); 
00703 
00704         setStatusInfo(Context, "Setting up index search"); 
00705 double  UnimapperScale = 1.0; 
00706         UniMapperScalator << Context >> UnimapperScale;
00707 
00708 RefPtr<LocalFromWorldPoint>
00709         LocalPointFinder = new LocalFromWorldPoint(*currentSlice.getSlice(), FieldSelection.getGrid(),
00710                                                    FieldSelection.getGridname(),
00711                                                    FieldSelection.getGrid()->getCartesianPositions(), 
00712                                                    UnimapperScale );
00713 
00714 double  step_size;
00715 double  min_line_length = 0.0; 
00716 double  max_steps = 0.0; 
00717 double  scale_fac = 1.0;
00718         MinLineLength  << Context >> min_line_length; 
00719         MaxSteps << Context >> max_steps;
00720         StepSize    << Context >> step_size; 
00721         ScaleFac    << Context >> scale_fac;
00722 
00723         step_size *= ToIntegratefieldBBox->radius();
00724         step_size /= 33.0;
00725 
00726 Enum AddData, AddMagnitude; 
00727         IncludeData << Context >> AddData; 
00728         IncludeMagnitude << Context >> AddMagnitude; 
00729 
00730         if( max_steps < 2)
00731                 max_steps = 2; 
00732 
00733 
00734 unsigned int nEmPoints = EmitterCrds.Size()[0]; 
00735 
00736 #ifdef VERBOSE
00737         cout << "IntegralLines::update() Number of Seeds: " <<  nEmPoints << endl; 
00738 #endif
00739 
00740 //index_t       NumberOfLines = nEmPoints;
00741 
00742 // 
00743 // 6. Do the actual integration
00744 // 
00745         puts("IntegralLines::update() 6. Do the actual");fflush(stdout); 
00746         setStatusInfo(Context, "Integrating ...");
00747 
00748 unsigned int nth =  nEmPoints/10; 
00749         nth = (nth == 0)?5:nth; 
00750 
00751 size_t  nPoints = nEmPoints; // because start points are first pushed onto the line
00752  
00753 //std::vector<IntegrationResult_t> Lines( nEmPoints );
00754  std::vector<IntegrationResult_t> Lines( nEmPoints );
00755 //Lines.resize( nEmPoints ); 
00756  //printf("IntegralLines::update() Lines.size: %d\n", (int)Lines.size());fflush(stdout); 
00757 
00758 // init Lines by pushing first point on line 
00759 //for( unsigned i = 0; i < Lines.size(); i++ ) 
00760 for( unsigned i = 0; i < Lines.size(); i++ )
00761 {
00762         Lines[i] = new Chunk<IntegrationPoint<FieldType> >(0); 
00763         IntegrationPoint<FieldType> start;
00764  
00765         // awful handling of 4d and 3d points. 3d emitters copied to point4 T component set to 0
00766         for(unsigned ii = 0; ii < IntegrationPoint<FieldType>::point::Dims; ii++)
00767         {
00768                 if( IntegrationPoint<FieldType>::point::Dims < 4 )
00769                         start.location[ii] = EmitterCrds[i][ii]; 
00770                 else
00771                 {
00772                         start.location[0]=0.0;
00773                         if( ii < 3)
00774                                 start.location[ii+1] = EmitterCrds[i][ii];      
00775                 } 
00776                 
00777         } 
00778 #ifdef VERBOSE  
00779         cout << start.location << endl; 
00780 #endif
00781         if(EmitterVecs )
00782         {
00783                 MultiArray<1, tvector>&EmitterCrds = *EmitterVecs; 
00784 
00785                 for(unsigned ii = 0; ii < IntegrationPoint<FieldType>::point::Dims; ii++)
00786                 {
00787                         if( IntegrationPoint<FieldType>::point::Dims < 4 )
00788                                 start.direction[ii] = EmitterCrds[i][ii]; 
00789                         else
00790                         {
00791                                 start.direction[0] = 0.0; // note that this is not correct for lightlike geodesiccs. 
00792                                                           // but since the metric has to be know, this is set to the 
00793                                                           // corect value in the geodesic44 integrator class
00794                                 if( ii < 3)
00795                                         start.direction[ii+1] = EmitterCrds[i][ii];     
00796                         } 
00797                 } 
00798         }
00799         start.is_end = false; 
00800 
00801         Lines[i]->push_back(start); 
00802 //      cout << "IntegralLines::update() startpoint:"<< start.location << " with start dir:" << start.direction <<endl;
00803 } 
00804 
00805 puts("1"); 
00806 
00807 typedef LineAdvancer<FieldType, LineType, FieldInterpolatorBase::LINEAR   > AdvancerLinear;  
00808 typedef LineAdvancer<FieldType, LineType, FieldInterpolatorBase::CUBIC    > AdvancerCubic; 
00809 typedef LineAdvancer<FieldType, LineType, FieldInterpolatorBase::ANALYTIC > AdvancerAnalytic; 
00810 
00811 int nPointsEst = nEmPoints * ((int)max_steps); 
00812 
00813         // main loop
00814         puts("2");
00815         ________________________________________________getTime(sec , Tim_update ); 
00816 
00817         if( Interpol("linear") )
00818         {
00819 
00820         AdvancerLinear  MyAdvancerLinear( Lines, FieldSelection, LocalPointFinder, ToIntegratefieldBBox, 
00821                                           step_size, Dop("yes"), nPoints, min_line_length, time, scale_fac ); 
00822 
00823                 nPoints = doMainLoop<AdvancerLinear>(MyAdvancerLinear, max_steps, nPointsEst, nPoints, Context); 
00824         }
00825         else if( Interpol("cubic") )
00826         {
00827         AdvancerCubic  MyAdvancerCubic( Lines, FieldSelection, LocalPointFinder, ToIntegratefieldBBox, 
00828                                         step_size, Dop("yes"), nPoints, min_line_length, time, scale_fac ); 
00829 
00830                 nPoints = doMainLoop<AdvancerCubic>(MyAdvancerCubic, max_steps, nPointsEst, nPoints, Context); 
00831         } 
00832         else
00833         {
00834         AdvancerAnalytic  MyAdvancerAnalytic( Lines, FieldSelection, LocalPointFinder, ToIntegratefieldBBox, 
00835                                               step_size, Dop("yes"), nPoints, min_line_length, time, scale_fac ); 
00836 
00837                 nPoints = doMainLoop<AdvancerAnalytic>(MyAdvancerAnalytic, max_steps, nPointsEst, nPoints, Context); 
00838         } 
00839 
00840         double overall_int_time = Tim_update.secs() - sec;       
00841         
00842 //      ________________________________________________printTime("IntegralLines::update(): Compute Time:", Tim_update.secs() - sec); 
00843 
00844         printf("IntegralLines::update(): ComputeTime: %f\n",overall_int_time  ); 
00845         printf("IntegralLines::update(): Time per integration %d points: %f\n", (int)nPoints, overall_int_time/nPoints ); 
00846 
00847         CurviCellsPerUniCell << Context << LocalPointFinder->MaxListSize;
00848 
00849 
00850 // 7. Collect all points into one array 
00851 //    Alternatively, could store all data in field fragments in the 
00852 //    output positions field. This were more efficient, as it does 
00853 //    not require to copy the points here. However, the display methods 
00854 //    such as line render, must be checked to be able to handle such 
00855 //    line data. Nevertheless, this were the way how to do it "right". 
00856 //    There should be another, generic, module anyway that combines 
00857 //    fragmented fields into unfragmented ones, for those modules which
00858 //    are incapable elsewhere to operate on fragmented fields.
00859 // 
00860 //      puts("IntegralLines::update() 7. Collect");fflush(stdout); 
00861 
00862 
00863 // 
00864 // 8. Bake a new Grid object that carries the actual lines 
00865 // 
00866 // 
00867         puts("IntegralLines::update() 8. Bake");fflush(stdout); 
00868         {
00869         //
00870         // a. Create a Grid object on the Bundle, compatible with the Bundle,
00871         //    but not yet inserted into the Bundle. It will thus be invisible
00872         //    until we are done with baking it. Otherwise, an incomplete Grid
00873         //    would be visible in the Bundle, and a concurrent access to the
00874         //    Bundle's Grid would fail (as it may happen in a multithreaded
00875         //    environment). Alternatively, one could start baking the Grid already
00876         //    during integration, and publish it in the Bundle. Then a concurrent
00877         //    rendering would show the active computation going on. However, the
00878         //    Grid must always be internally consistent. One must never publish
00879         //    a half-done Grid into the Bundle.
00880         //
00881 RefPtr<Grid> IntegralLineGrid = FieldSelection.theSourceBundle->newGrid(); 
00882 
00883 
00884 LineSet OutputLineSet( IntegralLineGrid,
00885                        NullPtr(), // coordinates will be added a bit later
00886                        createLineSet( Lines ) ); 
00887 
00888         assert(OutputLineSet.CartesianVertices);
00889 
00890         CollectLineData(*OutputLineSet.CartesianVertices, Lines, nPoints);
00891 
00892         //
00893         // d. Define relationship between the output grid of lines, and the 
00894         //    grid on which the vector field lives. This is optional, but will 
00895         //    easy further operations on the line grid, such as evaluating fields 
00896         //    from the vector field's grid along the lines.
00897         // 
00898                 // Remember the source grid's fragment ID's for each point of the 
00899                 // integration lines. This is useful for multiblock grids, such that 
00900                 // subsequent lookup of a point's fragment ID is not necessary, for 
00901                 // instance when another field of the source grid shall be evaluated 
00902                 // on the lines. 
00903                 if (0) // wieso geht des nit mit geodesics44?
00904                 {
00905                 RefPtr<Skeleton>SourceFragments = InputGrid( SkeletonID(3, 2) );
00906                         assert(SourceFragments);
00907                 typedef MemArray<1, std::string> FragmentIDs_t;
00908                 Ref<FragmentIDs_t> LinesVertFragID( nPoints );
00909                 MultiArray<1,std::string > LineVFID = *LinesVertFragID;
00910                 {
00911                 index_t vert_count = 0;
00912                         for(index_t lin = 0; lin <  Lines.size(); lin++ )
00913                         {
00914                         const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector();
00915                                 for(index_t ver = 0; ver < Line.size() ; ver++ )
00916                                 {
00917                                         LineVFID[ MIndex(vert_count) ] =  Line[ver].fragment;
00918                                         vert_count++;
00919                                 }
00920                         } 
00921                         //assert( vert_count == nPoints);
00922                 } 
00923 
00924                 Representation&LineVerticesAsSourceFragments = (*OutputLineSet.Vertices)[ SourceFragments ]; 
00925                         LineVerticesAsSourceFragments.setPositions( new Field( LinesVertFragID ) );
00926                 }
00927 
00928         //
00929         // e. Copy floating point indices from the integration lines to the line grid.
00930         //    Same as with the fragment ID's, these indices correspond to a representation 
00931         //    of the output grid in terms of the input grid and will ease mapping fields 
00932         //    in a future operation.
00933         //
00934                 {
00935                 typedef MemArray<1, Eagle::point3> FloatIndices_t;
00936                 Ref<FloatIndices_t> LinesVertFI( nPoints ); 
00937                 MultiArray<1, Eagle::point3 > LineVFI = *LinesVertFI;
00938                 {
00939                 index_t vert_count = 0;
00940                         for(index_t lin = 0; lin < Lines.size(); lin++ )
00941                         {
00942                         const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector();
00943 
00944                                 for(index_t ver = 0; ver < Line.size() ; ver++ )
00945                                 {
00946                                         LineVFI[ MIndex(vert_count) ] =  Line[ver].index_location;
00947                                         vert_count++;
00948                                 }
00949                         } 
00950                         //assert( vert_count == nPoints);
00951                 } 
00952 
00953                 Skeleton&SourceSkeleton                = *(FieldSelection.getGrid()->findVertices());
00954                 Representation&LineVerticesAsSourceVertices = (*OutputLineSet.Vertices)[ SourceSkeleton ]; 
00955                         LineVerticesAsSourceVertices.setPositions(  new Field( LinesVertFI ) );
00956 
00957                 // f. add direction (i.e. velocity)
00958                 {
00959 /*
00960   Look at the classes above on CollectLineData how to extract 3D information
00961   from nD point data IF required.
00962 
00963 
00964   The two if's down here seem to do exactly the same, except that in
00965   the 1st case it uses the point dims for the loop after verifying that
00966   Dims is three, in the 2nd case it writes 3 explicitly. What's the point
00967   of
00968 
00969   if (Dims==3) f(Dims);
00970   if (Dims==4) f(3);
00971 
00972   ??
00973 
00974  */
00975 
00976                         if(IntegrationPoint<FieldType>::point::Dims == 3)
00977                         {
00978                         Ref<MemArray<1, Eagle::tvector3> >  LinesData( nPoints ); 
00979                         MultiArray<1, Eagle::tvector3>&LineData = *LinesData; 
00980                         index_t vert_count = 0;
00981                                 for(index_t lin = 0; lin <  Lines.size(); lin++ )
00982                                 {
00983                                 const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector(); 
00984                                         for(index_t ver = 0; ver < Line.size() ; ver++ )
00985                                         {
00986                                                 for(unsigned j = 0; j < IntegrationPoint<FieldType>::point::Dims; j++)
00987                                                         LineData[ MIndex(vert_count) ][j] = Line[ver].direction[j]; 
00988                                                 vert_count++;
00989                                         }
00990                                 } 
00991                                 //assert( vert_count == nPoints); 
00992                                 (*OutputLineSet.CartesianVertices)[ LineSet::PredefinedFieldNames::Velocity ]->setPersistentData( LinesData );
00993                         } 
00994                         if(IntegrationPoint<FieldType>::point::Dims == 4)
00995                         {
00996                         // Ref<MemArray<1,Eagle::tvector4> >  LinesData( nPoints ); 
00997                         // MultiArray<1,Eagle::tvector4>&LineData = *LinesData; 
00998                         // index_t vert_count = 0; 
00999                         //      for(index_t lin = 0; lin <  Lines.size(); lin++ )
01000                         //      {
01001                         //      const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector(); 
01002                         //              for(index_t ver = 0; ver < Line.size() ; ver++ )
01003                         //              {
01004                         //                      for(unsigned j = 0; j < IntegrationPoint<FieldType>::point::Dims; j++)
01005                         //                              LineData[ MIndex(vert_count) ][j] = Line[ver].direction[j]; 
01006                         //                      vert_count++;
01007                         //              }
01008                         //      } 
01009                         //      assert( vert_count == nPoints); 
01010                         // string tmp = string("Direction");
01011                         //      VerticesAsCartesian[ tmp ]->setPersistentData( LinesData );
01012                         Ref<MemArray<1, Eagle::tvector3> >  LinesData( nPoints ); 
01013                         MultiArray<1, Eagle::tvector3>&LineData = *LinesData; 
01014                         index_t vert_count = 0; 
01015                                 for(index_t lin = 0; lin <  Lines.size(); lin++ )
01016                                 {
01017                                 const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector(); 
01018                                         for(index_t ver = 0; ver < Line.size() ; ver++ )
01019                                         {
01020                                                 for(unsigned j = 0; j < 3; j++)
01021                                                          LineData[ MIndex(vert_count) ][j] = Line[ver].direction[j+1]; 
01022                                                 cout<< "InegralLine:update(): Direction: " << LineData[ MIndex(vert_count) ] << endl;   
01023                                                 vert_count++; 
01024                                         }
01025                                 } 
01026                                 puts("directions done 1");fflush(stdout);
01027                                 //assert( vert_count == nPoints); 
01028                                 (*OutputLineSet.CartesianVertices)[  LineSet::PredefinedFieldNames::Velocity ]->setPersistentData( LinesData ); 
01029                                 puts("directions done 2");fflush(stdout);
01030                         }       
01031                         }
01032                 } 
01033 
01034                 
01035         // 
01036         // g. Add the data field to the output grid of lines. // this maybe needs special treatment 
01037         //
01038                 if( AddData("yes") )
01039                 {
01040                 typedef MemArray<1, FieldType> LinesDataArr_t; 
01041                 Ref<LinesDataArr_t>  LinesData( nPoints ); 
01042                 MultiArray<1,FieldType>&LineData = *LinesData; 
01043                 index_t vert_count = 0; 
01044                         for(index_t lin = 0; lin <  Lines.size(); lin++ )
01045                         {
01046                         const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector(); 
01047                                 for(index_t ver = 0; ver < Line.size() ; ver++ )
01048                                 {
01049                                         LineData[ MIndex(vert_count) ] = Line[ver].data;
01050                                         vert_count++;
01051                                 }
01052                         } 
01053                         //assert( vert_count == nPoints);
01054                         (*OutputLineSet.CartesianVertices)[ Fieldname(Context) ]->setPersistentData( LinesData );
01055                 } 
01056 
01057 
01058 
01059                         // And establish the same vector field as the tangential vectors 
01060                         // given on this line set. This is an alias to the same vector field, 
01061                         // under which TangentialVectors operations will find this field by 
01062                         // convention as defined in fiber/baseop/TangentialVectors.hpp 
01063                         // 
01064                         //VerticesAsCartesian[ TangentialVectorFieldName ]->setPersistentData( LinesData ); 
01065 
01066         // 
01067         // h. As a feature of this module, compute the magnitude of the vector field // needs special treatment
01068         //    and store it in the lines. 
01069         // 
01070                 if (AddMagnitude("yes")) 
01071                 {
01072                 Ref<MemArray<1, double> > LinesVectorMagnitude(nPoints); 
01073                 MultiArray<1,double >&LineMag = *LinesVectorMagnitude; 
01074                 index_t vert_count = 0;
01075                         for(index_t lin = 0; lin < Lines.size(); lin++ )
01076                         {
01077                         const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector(); 
01078                                 for(index_t ver = 0; ver < Line.size() ; ver++ )
01079                                 {
01080                                         LineMag[ MIndex( vert_count) ] = norm( Line[ver].data );
01081                                         vert_count++; 
01082                                 }
01083                         }
01084 
01085 #define DOUBLELINE "\u2016"
01086                 string outFieldName( DOUBLELINE + Fieldname(Context) + DOUBLELINE ); 
01087                         (*OutputLineSet.CartesianVertices)[ outFieldName ]->setPersistentData( LinesVectorMagnitude );
01088 //              puts("IntegralLine::update() DEB: setPersistent LineVectorMagnitudesF");
01089                 } 
01090 
01091         // 
01092         // y. Allow standard fields from the LineSet class to be available on integrated data
01093         // 
01094                 puts("before setup standard");fflush(stdout);
01095                 if (!OutputLineSet.setupStandardFields( IntegralLineGrid ) )
01096                 {
01097                         puts("LINE INTEGRATOR ERROR: Could not set up standard fields on lines!");fflush(stdout);
01098                 }
01099 
01100 
01101 
01102         // 
01103         // z. Finally, insert the Grid object into the bundle, at the current 
01104         //    time slice. It will hereby be visible in the bundle and ready 
01105         //    to be used elsewhere (like a rendering module). At last, announce 
01106         //    this Grid's properties as the output of this VISH Object.
01107         // 
01108 
01109                 puts("insert slice");fflush(stdout);
01110                 currentSlice.getSlice()->insert( grid_name, IntegralLineGrid ); 
01111 
01112                 FieldSelection.BundleSource().speak("FieldSelection.BundleSource()"); 
01113 
01114                 
01115         GridSelector GS( grid_name, FieldSelection.BundleSource() ); 
01116                 myIntegralLines << Context << GS;
01117         } 
01118 
01119         infoMsg(Context, "Done, output at: " + grid_name);
01120 
01121 //      printf("ComputMultipleStreamLines::update() Written into Bundle, setPersitentData and touched Spacetimeslot()\n");
01122         VActionNotifier::ProgressInfo (string("Streamline computation complete")); 
01123 
01124         puts("IntegralLine::update() >>>  EXIT");
01125 
01126         return true;
01127 }
01128 
01129 }