FiberVISH 0.2
Fish - The Fiber Bundle API for the Vish Visualization Shell
IntegralLine.hpp
1#include "IntegralFace.hpp"
2
3#warning "Including a header from a plugin"
4#include <BaseSpace/FieldInterpolator.hpp>
5
6#include <eagle/PhysicalSpace.hpp>
7//#include <ocean/eagle/STA.hpp>
8#include <ocean/shrimp/VEnum.hpp>
9#include <ocean/shrimp/VFlagList.hpp>
10#include <ocean/shrimp/PhysicalSpace.hpp>
11
12#include <memcore/Timer.hpp>
13
14#include <bone/FishField.hpp>
15#include <bone/FishSlice.hpp>
16
17#include <ocean/shrimp/VObjectStatus.hpp>
18#include <fish/fiber/baseop/LocalFromWorldPoint.hpp>
19#include <fish/fiber/baseop/ExpandBBox.hpp>
20
21#include <ode/dop853def.hpp>
22#include <baseop/TangentialVectors.hpp>
23
24#include <memcore/Timer.hpp>
25
26#include <grid/types/LineSet.hpp>
27
28#include <fish/fiber/baseop/RectilinearInterpolation.hpp>
29
30#ifdef USE_OPENMP
31#include <omp.h>
32#endif
33
34/*
35 This header file is part of the old streamline/geodesic code:
36 and is used by FlowTassel3.cpp and Geodesics.cpp
37
38 It should be replaced by IntegralHeart.hpp and FrontStreamlines.cpp,
39 FrontPathlines.cpp and FrontGeodesics.cpp.
40
41 Since the Geodesics integration was not yet ported to the new structure
42 this is still here.
43*/
44
45
46//#define TIMEIT
47//#define VERBOSE
48
49namespace FieldLines
50{
51
52namespace
53{
54
55// using namespace Wizt;
56// using namespace Fiber;
57// using namespace Eagle;
58// using namespace Eagle::PhysicalSpace;
59// using namespace Traum;
60
61//typedef std::string FragmentID_t;
62
63typedef RefPtr<FragmentID> FragmentID_t;
64
65template<class FieldType>
66struct IntegrationPoint
67{
68 typedef typename FieldType::Chart_t Chart_t;
69 typedef typename Coordinates<Chart_t>::point point;
70 typedef typename Coordinates<Chart_t>::vector tvector;
71
73 //point location;
74 point location;
76 FieldType data;
78 Eagle::PhysicalSpace::point index_location;
79
81// FragmentID_t fragment;
82 RefPtr<FragmentID> fragment;
83
85 bool is_end = false;
86
88 tvector direction;
89
91 double length = 0.0;
92
93 IntegrationPoint()
94 :is_end(false)
95 {}
96
98 {
99 location = locationP;
100 }
101
102 void setDirection(tvector directionP)
103 {
104 direction = directionP;
105 }
106
107 void setData( const FieldType&dataP, const Eagle::PhysicalSpace::point&index_locationP, const FragmentID_t&fragmentP, const double lengthP )
108 {
109 data = dataP;
110 index_location = index_locationP;
111 fragment = fragmentP;
112 length = lengthP;
113 }
114
115 void setEnd()
116 {
117 is_end = true;
118 }
119};
120
121// template<class P>
122// struct Pointilizer
123// {
124// typedef typename P::Chart_t point;
125// };
126
127// template<>
128// class Pointilizer<Coordinates<Eagle::CartesianChart3D > >
129// {
130// typedef Eagle::point3 point;
131// };
132
133// template<>
134// class Pointilizer<Coordinates<STA::CartesianChart4D<> > >
135// {
136// typedef point4 point;
137// };
138
139 /*
140 Note: This kind of data structure is inefficient, it should
141 definitely be revised. With this layout, it requires copying data
142 for getting these data into the fiber bundle layout.
143 */
144//typedef RefPtr<Chunk<IntegrationPoint<metric33> > > IntegrationResult_t;
145
146// IntegrationResult_t x;
147
148
149/*
150This is the structure how it should be. This one is fiber-bundle compatible.
151
152template<class FieldType>
153struct IntegrationResult
154{
156 RefPtr<Chunk<point> > location;
157
159 RefPtr<Chunk<FieldType> > direction;
160
162 RefPtr<Chunk<point> > index_location;
163
165 RefPtr<Chunk<FragmentID_t> > fragment;
166};
167*/
168
169
170/*
171 if( interpol == 0 )
172 {
173 VectorLinearInterpolator_t myField(*ToIntArr, float_index);
174 InterpolData = myField.eval();
175 }
176 else if( interpol == 1 )
177 {
178 VectorCubicInterpolator_t myField(*ToIntArr, float_index);
179 InterpolData = myField.eval();
180 }
181 else
182 {
183 if ( MemCore::InterfacePtr<Eqn_t> AnalyticField = *ToIntegrateField )
184 {
185 Eqn_t&AF = *AnalyticField;
186 InterpolData = AF(time, location);
187 }
188 else
189 {
190 VectorLinearInterpolator_t myField(*ToIntArr, float_index);
191 InterpolData = myField.eval();
192 }
193 }
194*/
195
196
197struct AtomicDataBase
198{
199 RefPtr<LocalFromWorldPoint> LocalPointFinder;
202 double step_size;
203 bool inited;
204 double scale;
205
208 double step_sizeP, double scaleP )//, bool normalizeInversionP, bool doInversionP ) //, const unsigned interpolP )
209 : LocalPointFinder(LocalPointFinderP)
210 , FieldSelection(FieldSelectionP) // somehow this was not sufficient ?!? see below
211 , BB(BBP)
212 , step_size(step_sizeP)
213 , inited(false)
214 , scale( scaleP )
215 //, normalizeInversion(normalizeInversionP)
216 //, doInversion(doInversionP)
217 //, interpol(interpolP)
218 {
220#ifdef VERBOSE
221
222 cout << "AtomicDataBase::AtomicDataBase FieldSelectionP: " << FieldSelectionP.getFieldName() << endl;
223 cout << "AtomicDataBase::AtomicDataBase FieldSelection: " << FieldSelection.getFieldName() << endl;
224#endif
225 }
226};
227
228/*
229class IntegrationFrontContainerBase
230{
231protected:
232 unsigned size;
233 unsigned last_index;
234
235 unsigned front_index;
236
237public:
238 IntegrationFrontContainerBase(const unsigned sizeP = 0)
239 : size(sizeP)
240 , last_index(0)
241 , front_index(0)
242 {}
243
244 void setSize(const unsigned sizeP) { size = sizeP; }
245 unsigned getSize() const { return size; }
246 void setLastIndex(const unsigned last) { last_index = last; }
247// void advanceIndex() { last_index = last_index++ % size; }
248 unsigned getLastIndex() const { return last_index; }
249 void advanceFrontIndex() { front_index++; }
250 unsigned getFrontIndex() const { return front_index; }
251
252};
253
254
255template<typename FieldType, typename LineType>
256class IntegrationFrontContainter
257{
258
259public:
260
261 void insertDataToBundle( FieldSelector&FieldSelection, const string module_name )
262 {
263 puts("IntegrationFrontContainter<>::insertDataToBundle() to be implemented!");
264 }
265
266};
267*/
268
269
270
277template<typename FieldType, typename LineType, int InterpolType>
278class AtomicIntegrator;
279
280struct AtomicIntegratorParameterBase
281{
282 RefPtr<LocalFromWorldPoint> LocalPointFinder;
285 double step_size;
286 double scale;
287// bool invNorm, invEnable;
288 };
289
290template<typename FieldType, typename LineType>
291class AtomicIntegratorParameter: public AtomicIntegratorParameterBase
292{
293};
294
295
296template <class Extractor, class Container>
297RefPtr<MemBase> CollectLines(const Extractor&E, const std::vector<RefPtr<Chunk<Container> > >&Lines, size_t nPoints)
298{
299typedef typename Extractor::output_t output_t;
301
302size_t nLines = Lines.size();
303Ref<ResultMemArray_t> ResultArray( MIndex(nPoints) );
304std::vector<output_t>&LineResult = ResultArray->myChunk()->get_vector();
305
306index_t VertexNr = 0;
307 for(index_t LineNr = 0; LineNr < nLines; LineNr++)
308 {
309 const std::vector<Container>&PointsPerLine = Lines[LineNr]->std_vector();
311 {
313#ifdef VERBOSE
314 cout << LineResult[ VertexNr ] << " ";
315#endif
316 VertexNr++;
317 }
318#ifdef VERBOSE
319 cout << endl;
320#endif
321 }
322 return ResultArray;
323}
324
329template <class Container>
330void CollectLineData(Representation&CartesianVertices, const std::vector<RefPtr<Chunk<Container> > >&Lines, size_t nPoints);
331
332
333struct CopyExtractor
334{
335 typedef FieldLines::IntegrationPoint<Eagle::PhysicalSpace::tvector> input_t;
336 typedef Eagle::point3 output_t;
337
338 output_t operator()(const input_t&in) const
339 {
340 return output_t(in.location);
341 }
342};
343
347template <>
348inline void CollectLineData(Representation&CartesianVertices,
349 const std::vector<RefPtr<Chunk< FieldLines::IntegrationPoint<Eagle::PhysicalSpace::tvector> > > >&Lines, size_t nPoints)
350{
352 LinePositions->setPersistentData( CollectLines( CopyExtractor(), Lines, nPoints) );
353#ifdef VERBOSE
354 cout << "CollectLineData(), before setPositions" << endl;
355#endif
356
357 if( !CartesianVertices.setPositions( LinePositions ) )
358 cout << "CollectLineData() ERROR setting Positions" << endl;
359
360}
361
362struct ExtractPointLocation
363{
364 typedef FieldLines::IntegrationPoint<Eagle::metric44> input_t;
365 typedef Eagle::point3 output_t;
366
367 output_t operator()(const input_t&in) const
368 {
369 return output_t(in.location[1],in.location[2],in.location[3]);
370 }
371};
372
373struct ExtractTime
374{
375 typedef FieldLines::IntegrationPoint<Eagle::metric44> input_t;
376 typedef double output_t;
377
378 output_t operator()(const input_t&in) const
379 {
380 return in.location[0];
381 }
382};
383
384
385
389template <>
390inline void CollectLineData(Representation&CartesianVertices,
391 const std::vector<RefPtr<Chunk< FieldLines::IntegrationPoint<Eagle::metric44> > > >&Lines, size_t nPoints)
392{
394 LinePositions->setPersistentData( CollectLines( ExtractPointLocation(), Lines, nPoints) );
395 CartesianVertices.setPositions( LinePositions );
396
397 CartesianVertices[ "ProperTime" ]->setPersistentData( CollectLines( ExtractTime(), Lines, nPoints) );
398}
399
400
401
402// struct ExtractPointLocationMetric33
403// {
404// typedef FieldLines::IntegrationPoint<Eagle::metric33> input_t;
405// typedef Eagle::point3 output_t;
406
407// output_t operator()(const input_t&in) const
408// {
409// return output_t(in.location[0],in.location[1],in.location[2]);
410// }
411// };
412
413struct CopyExtractorMetric33
414{
415 typedef FieldLines::IntegrationPoint<Eagle::metric33> input_t;
416 typedef Eagle::point3 output_t;
417
418 output_t operator()(const input_t&in) const
419 {
420 return output_t(in.location);
421 }
422};
423
424template <>
425inline void CollectLineData(Representation&CartesianVertices,
426 const std::vector<RefPtr<Chunk< FieldLines::IntegrationPoint<Eagle::metric33> > > >&Lines, size_t nPoints)
427{
429 LinePositions->setPersistentData( CollectLines( CopyExtractorMetric33(), Lines, nPoints) );
430 CartesianVertices.setPositions( LinePositions );
431
432// CartesianVertices[ "ProperTime" ]->setPersistentData( CollectLines( ExtractTime(), Lines, nPoints) );
433}
434
435
436
440template <class Container>
442{
443#ifdef VERBOSE
444 cout << "createLineSet() Lines has lines: " << Lines.size() << endl;
445#endif
446size_t NumberOfLines = Lines.size();
449
450index_t VertexNumber = 0;
451 for(index_t line=0; line<NumberOfLines; line++)
452 {
453 std::vector<LineSet::LineIndex_t>&E = LineIndices[ line ];
454 index_t LineLength = Lines[line]->std_vector().size();
455
456#ifdef VERBOSE
457 cout << "createLineSet() Line has length: " << LineLength << endl;
458#endif
459
460 E.resize( LineLength );
461 for(index_t i=0; i<LineLength; i++)
462 {
463 E[i] = VertexNumber;
464#ifdef VERBOSE
465 cout << E[i] << " ";
466#endif
467 VertexNumber ++;
468 }
469#ifdef VERBOSE
470 cout << endl;
471#endif
472
473 }
474
475 return LinesetArray;
476}
477
478
479
480
481template <class FieldType, typename LineType, int InterpolType>
482class LineAdvancer
483{
484typedef RefPtr<Chunk<IntegrationPoint<FieldType> > > IntegrationResult_t;
485typedef MemArray<3, FieldType> ToIntegrateArray_t;
486
489 bool dop;
490 size_t nPoints;
491 double min_line_length;
492 double start_time;
493 double time;
494
495public:
496// VActionNotifier::Progress Info;
497
498 LineAdvancer(const std::vector<IntegrationResult_t>&LinesP, const bool dopP, const size_t nPointsP,
500 : AI(AIParam)
501 , Lines(LinesP)
502 , dop(dopP)
503 , nPoints(nPointsP)
504 , min_line_length(min_line_lengthP)
505 , start_time(start_timeP)
506 , time(start_timeP)
507// , Info("Computing integral line ", Lines.size() )
508 {
509// cout << "--------LineAdvancer()" << endl;
510// cout.flush();
511
512 }
513
514// LineIntegrator::LineIntegrator(){}
515
516
517 size_t getNPoints() { return nPoints;}
518
519// std::vector<IntegrationResult_t>& getLines(){ return Lines; }
520
521
522 bool advanceBreadthFirst( )
523 {
524#ifdef VERBOSE
525 puts("advanceBreadthFirst( ) enter");fflush(stdout);
526#endif
527
528// MEMCORE_PROFILE_THIS("LineAdvancer::advanceBreadthFirst( )", 0);
529
530 if( dop && !AI.inited )
531 AI.initDop853( Lines.size() );
532
533
534 unsigned end_counter = 0;
535
536#ifdef USE_OPENMP
537
538#ifdef VERBOSE
539
541 cout << "advance() using threads per front: " << max_threads_possible << endl;
542
543// exit(0);
544
545#endif
546
547 #pragma omp parallel
548 {
549
550
551#pragma omp for schedule(static, 10)
552#endif
553
554
555 for(unsigned p = 0; p < Lines.size(); p++)
556 {
557// printf("\n WORKING ON LINE %d out of %d\n", p, Lines.size() );
558// VActionNotifier::ProgressInfo("Working on line " + String(int(p)) + " out of " + String(int(Lines.size())) );
559// VActionNotifier::ProgressInfo("Computing integral line ", p, Lines.size() );
560
561// if (!Info.proceed(p) )
562// break;
563
564 IntegrationResult_t &IntegrationLine = Lines[ p ];
565 int last_index = IntegrationLine->size()-1;
566
567
568 if( last_index >= 0 )
569 if( (*IntegrationLine)[last_index].is_end == true )
570 continue;
571
572 if( last_index >= 1 )
573 {
574 //printf( "advacer: length %f, limit: %f\n", (*IntegrationLine)[last_index-1].length, min_line_length );
575 if( (*IntegrationLine)[last_index-1].length > min_line_length )
576 {
577 (*IntegrationLine)[last_index].setEnd();
578 continue;
579 }
580 }
581
582 bool test;
583
584// {
585// MEMCORE_PROFILE_THIS("LineAdvancer::advanceBreadthFirst( )", 1);
586
587 if( !dop )
588 test = AI.doEuler( *IntegrationLine, time);
589 else
590 test = AI.doDop853( *IntegrationLine, time, p );
591// }
592
593#ifdef USE_OPENMP
594 #pragma omp critical
595 {
596#endif
597 if( test == false )
598 end_counter++;
599 else
600 nPoints++;
601#ifdef USE_OPENMP
602 } // omp critical
603#endif
604
605 }
606#ifdef USE_OPENMP
607 } // omp parallel
608#endif
609
610
611#ifdef VERBOSE
612 puts("advanceBreadthFirst( ) eexit");fflush(stdout);
613#endif
614// VActionNotifier::ProgressInfo("Integration of " + String(int(Lines.size())) + " lines done." );
615
616// printf("end_counter %d, Lines.size() %d\n", end_counter, Lines.size() );
617 return ( end_counter == Lines.size() ) ? true : false;
618 }
619
620 void finalize()
621 {
622// MEMCORE_PROFILE_THIS("LineAdvancer::finalize()", 0);
623
624 for(unsigned p = 0; p < Lines.size(); p++)
625 {
626 IntegrationResult_t &IntegrationLine = Lines[ p ];
627
628 AI.finalize( *IntegrationLine, time );
629 }
630 }
631
632};
633
634
635// type trait to convert the integration line type to a string used for naming in the fiber bundle
636// must be provided in the specializations
637template<typename FieldType, typename LineType>
638struct LineTypeString
639{
640 string name() { return "Unknown"; }
641};
642
643template <typename FieldType, typename LineType>
644class IntegralLinesParameters
645{
646 public:
647 IntegralLinesParameters(VObject*)
648 {}
649
652
653};
654
656template <typename FieldType, typename LineType>
657class IntegralLines : public IntegralFace, public IntegralLinesParameters<FieldType, LineType>
658{
659public:
660enum { NumberOfInputFields = 1 };
661typedef META::LIST< tvector > InputTypes;
663
664typedef MemArray< 3, double > ScalarArray_t;
666typedef MemArray< 1, Eagle::point3 > CoordsArray1D_t;
667typedef MemArray< 1, tvector > VecsArray1D_t;
668typedef MemArray< 1, RefPtr<FragmentID> > FragmentIDs_t;
669typedef MemArray< 1, BoundingBox > FragmentBounds_t;
670
671
672 TypedSlot<Options> SpecialOptions;
673
674 IntegralLines(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
675 : VObject(name, p, VP)
676 , Fish<Field>("inputfield")
677 , IntegralFace(name, p, VP)
678 , IntegralLinesParameters<FieldType, LineType> (this)
679#define FORCE_CONSTANT_COORDS_OPTION "ForceConstantCoords"
680 , SpecialOptions(this, "options", Options(FORCE_CONSTANT_COORDS_OPTION),2 )
681 {}
682
683 typedef RefPtr<Chunk<IntegrationPoint<FieldType> > > IntegrationResult_t;
684
685 typedef typename FieldType::Chart_t Chart_t;
686 typedef typename Coordinates<Chart_t>::point point;
687 typedef typename Coordinates<Chart_t>::vector tvector4;
688
689 bool update(VRequest&R, double precision) override;
690
691 static string createChildname(const string&inputfield)
692 {
694 return tmp.name() +"(" + inputfield + ")";
695 }
696
697
698 void printProgress( unsigned&old_nPoints, const unsigned nPoints, const unsigned nPointsEst, VRequest&Context)
699 {
700 if( old_nPoints + 100 < nPoints )
701 {
702 old_nPoints = nPoints;
703 char buf[64];
704 float percent = double(nPoints / nPointsEst * 100);
705 sprintf(buf, "Integrating %.1f %% #%d", percent, int(nPoints));
706// VActionNotifier::ProgressInfo (string(buf));
707 printf("%s\n", buf);fflush(stdout);
708// setStatusInfo( Context, buf);
709 }
710
711 }
712
713 template<class IntegratorType>
714 int doMainLoop(IntegratorType&IntT, const double max_steps, const int nPointsEst, const size_t nPoints, VRequest&Context)
715 {
716 int step_counter = 0;
717 bool hasfinished = false;
718 unsigned old_nPoints = 0;
719
720 VActionNotifier::Progress viP( "Computing Integration Line...", max_steps);
721 while( hasfinished == false && step_counter < max_steps )
722 {
723 if (!viP.proceed(step_counter) )
724 {
725 break;
726 }
727 printProgress(old_nPoints, nPoints, nPointsEst, Context );
728 hasfinished = IntT.advanceBreadthFirst();//, //'returns'
729 step_counter++;
730 }
731 IntT.finalize();//,
732// VActionNotifier::StatusInfo( "Computing Integration Line done.");
733 return IntT.getNPoints();
734 }
735
736};
737
738template<typename FieldType, typename LineType>
739bool IntegralLines<FieldType,LineType>::update(VRequest&Context, double precision)
740{
741//double sec = 0.0;
742//VTimer Tim_update;
743
744//MEMCORE_PROFILE_THIS("IntegralLines<FieldType,LineType>::update(VRequest&Context, double precision)",0)
745
746#ifdef VERBOSE
747 printf("IntegralLines::update() -->%s<--: enter\n", Name().c_str() );fflush(stdout);
748#endif
749
750// 1. Get input field information
751//
752#ifdef VERBOSE
753 puts("IntegralLines::update() 1. Get input field information");fflush(stdout);
754#endif
755
756FieldSelector FieldSelection = getFieldSelector(Context);
757RefPtr<Field> InputToIntegrateField = FieldSelection.getField();
758
759 if(!FieldSelection.theSourceBundle) { return errorMsg(Context, "No bundle found in integrate field"); }
760 if(!InputToIntegrateField) { return errorMsg(Context, "No integratable field in input bundle"); }
761
762double time = FieldSelection.getTime();
763string fieldName = FieldSelection.getFieldName();
764
765
766// 2. Get emitter info
767//
768
769GridSelector EmitterGS;
770FieldSelector EmitterFS;
771 StartGrid << Context >> EmitterGS;
772 StartField << Context >> EmitterFS;
773
774EmitterFieldData EFD( EmitterGS, EmitterFS, time );
775
776 RefPtr<Field> EmitterCoordinates = getEmitterField( Context, EFD );
777
778
779Options options;
781
782//Enum Dop;
783// UseDop853 << Context >> Dop;
784//
787
788
789//
790// 3. Construct name for the output grid (the integral lines) and check if it already exists. And if so, if not the
791// input is newer, such that it would require re-creation.
792//
793string grid_name = FieldSelection.Gridname() + "_" + Name();
794
795 if (options("dop853") ) grid_name += "_dop853";
796
797GridSelector GS;
799
800UpdateCheckData UCD( EmitterCoordinates, FieldSelection, GS,
801 InputToIntegrateField, time, grid_name);
802
803if( !needUpdate( Context, UCD ) )
804 {
805 puts("IntegralLines::update() 3.5 no update needed");
806 return true;
807 }
808//
809// 4. Make sure we have some seed points
810//
811 puts("IntegralLines::update() 4. Make sure we have seeding points");fflush(stdout);
812
813RefPtr<BoundingBox> ToIntegratefieldBBox = getBoundingBox( *FieldSelection.getGrid() );
814 if (!ToIntegratefieldBBox) return setStatusError(Context, "No bounding box available.\n");
815
816
817AutoEmitterData AED( EmitterCoordinates, ToIntegratefieldBBox, 23 );
818 setDefaultEmissionPoints( Context, AED );
819 if (!AED.EmitterCoordinates)
820 return setStatusError( Context, "No Emitter Coordinates");
821
822
823 //
824 // Note: the emitter coordinate field could also be fragmented.
825 // In this case, the getData() call will return a NullPtr().
826 // In general, we need to rather iterate here over all field
827 // fragments of the emitter coordinates.
828 //
829RefPtr<CoordsArray1D_t > EmitterVerts = AED.EmitterCoordinates->getData();
830 if (!EmitterVerts)
831 return setStatusError( Context, "Emitter points not in a supported format");
832
834
835//
838
840 EmitterVecs = EmitterVecField->getData();
841
842
843
844//
845
846// 5. Prepare data structs for integration
847//
848//
849 puts("IntegralLines::update() 5. Prepare data");fflush(stdout);
850BundlePtr outBPtr = FieldSelection.BundleSource();
852
853 assert( FieldSelection.getGrid() );
854const Grid&InputGrid = *FieldSelection.getGrid();
855
856// setStatusInfo(Context, "Setting up index search");
857double UnimapperScale = 1.0;
859
860
861Info<Grid> FirstGrid = FieldSelection.BundleSource()->findFirst( FieldSelection.getGridname() );
862
865
866RefPtr<LocalFromWorldPoint> LocalPointFinder;
867
868Eagle::point3 foo;
869 foo = {1,1,1};
871
872tvector v_scale = tvector(foo);
873
874 cout << v_scale << endl;
875// cin.ignore();
876
877 if ( mySpecialOptions(FORCE_CONSTANT_COORDS_OPTION) )
878 {
879 LocalPointFinder =
880 new LocalFromWorldPoint( *FirstGrid.getSlice(), FirstGrid.getGrid(),
881 FieldSelection.getGridname()
882 //, FirstGrid.getGrid()->getCartesianPositions(),
883 , UnimapperScale, 0.1, v_scale);
884 }
885 else
886 {
887 LocalPointFinder =
888 new LocalFromWorldPoint(*currentSlice.getSlice(), FieldSelection.getGrid(),
889 FieldSelection.getGridname()
890 //, FieldSelection.getGrid()->getCartesianPositions(),
891 , UnimapperScale, 0.1, v_scale);
892 }
893
894
895double step_size;
896double min_line_length = 0.0;
897double max_steps = 0.0;
898 MinLineLength << Context >> min_line_length;
900 StepSize << Context >> step_size;
901
902 step_size *= ToIntegratefieldBBox->radius();
903 step_size /= 33.0;
904
905//Enum AddData, AddMagnitude;
906// IncludeData << Context >> AddData;
907// IncludeMagnitude << Context >> AddMagnitude;
908
909 if( max_steps < 2)
910 max_steps = 2;
911
912
913unsigned int nEmPoints = EmitterCrds.Size()[0];
914
915#ifdef VERBOSE
916 cout << "IntegralLines::update() Number of Seeds: " << nEmPoints << endl;
917#endif
918
919//index_t NumberOfLines = nEmPoints;
920
921//
922// 6. Do the actual integration
923//
924 puts("IntegralLines::update() 6. Do the actual computation X");fflush(stdout);
925// puts("Marcel was here");fflush(stdout);
926// setStatusInfo(Context, "Integrating ...");
927
928unsigned int nth = nEmPoints/10;
929 nth = (nth == 0)?5:nth;
930
931size_t nPoints = nEmPoints; // because start points are first pushed onto the line
932
933//std::vector<IntegrationResult_t> Lines( nEmPoints );
934 std::vector<IntegrationResult_t> Lines( nEmPoints );
935//Lines.resize( nEmPoints );
936 //printf("IntegralLines::update() Lines.size: %d\n", (int)Lines.size());fflush(stdout);
937
938// init Lines by pushing first point on line
939//for( unsigned i = 0; i < Lines.size(); i++ )
940for( unsigned i = 0; i < Lines.size(); i++ )
941{
942 Lines[i] = new Chunk<IntegrationPoint<FieldType> >(0);
944
945 // awful handling of 4d and 3d points. 3d emitters copied to point4 T component set to 0
946 for(unsigned ii = 0; ii < IntegrationPoint<FieldType>::point::Dims; ii++)
947 {
948 if( IntegrationPoint<FieldType>::point::Dims < 4 )
949 start.location[ii] = EmitterCrds[i][ii];
950 else
951 {
952 start.location[0]=0.0;
953 if( ii < 3)
954 start.location[ii+1] = EmitterCrds[i][ii];
955 }
956
957 }
958#ifdef VERBOSE
959 cout << start.location << endl;
960#endif
961 if(EmitterVecs )
962 {
964
965 for(unsigned ii = 0; ii < IntegrationPoint<FieldType>::point::Dims; ii++)
966 {
967 if( IntegrationPoint<FieldType>::point::Dims < 4 )
968 start.direction[ii] = EmitterCrds[i][ii];
969 else
970 {
971 start.direction[0] = 0.0; // note that this is not correct for lightlike geodesiccs.
972 // but since the metric has to be know, this is set to the
973 // corect value in the geodesic44 integrator class
974 if( ii < 3)
975 start.direction[ii+1] = EmitterCrds[i][ii];
976 }
977 }
978 }
979 start.is_end = false;
980
981 Lines[i]->push_back(start);
982// cout << "IntegralLines::update() startpoint:"<< start.location << " with start dir:" << start.direction <<endl;
983}
984
985//Enum invNorm;
986//Enum invEnable;
987
988// InverseNormalize << Context >> invNorm;
989// InverseEnable << Context >> invEnable;
990
991#ifdef VERBOSE
992puts("1");
993#endif
994
999
1000int nPointsEst = nEmPoints * (int(max_steps));
1002AIP.LocalPointFinder = LocalPointFinder;
1003AIP.FieldSelection = FieldSelection;
1004AIP.BBP = ToIntegratefieldBBox;
1005AIP.step_size = step_size;
1006AIP.scale = options("invert")?-1.0:1.0;
1007
1008//AIP.invNorm = invNorm("yes");
1009//AIP.invEnable = invEnable("yes");
1010
1011cout << "integrallines: Fieldselection1: " << AIP.FieldSelection.getFieldName() << endl;
1012cout << "integrallines: Fieldselection2: " << FieldSelection.getFieldName() << endl;
1013
1014 // main loop
1015
1016#ifdef VERBOSE
1017 puts("main loop");
1018// std::cout << "inversionflags: " << invNorm("yes") << ", " << invEnable("yes") << std::endl;
1019#endif
1020// ________________________________________________getTime(sec , Tim_update );
1021
1022// {
1023// MEMCORE_PROFILE_THIS("IntegralLines<FieldType,LineType>::update(VRequest&Context, double precision)",1)
1024
1025 if( Interpol("linear") )
1026 {
1027 if(RefPtr<RectiLinearArray_t> RectilinearPCoords = FirstGrid.getGrid()->getCartesianPositions()->getFirstData())
1028 {
1029 AdvancerRectilinear MyAdvancerRectilinear( Lines, options("dop853"), nPoints, min_line_length, time, AIP );
1030
1032
1033 }
1034 else
1035 {
1036 AdvancerLinear MyAdvancerLinear( Lines, options("dop853"), nPoints, min_line_length, time, AIP );
1038 }
1039 }
1040 else if( Interpol("cubic") )
1041 {
1042 AdvancerCubic MyAdvancerCubic( Lines, options("dop853"), nPoints, min_line_length, time, AIP );
1043
1045 }
1046 else
1047 {
1048 AdvancerAnalytic MyAdvancerAnalytic( Lines, options("dop853"), nPoints, min_line_length, time, AIP );
1049
1051 }
1052// }
1053
1054 // double overall_int_time = Tim_update.secs() - sec;
1055
1056// ________________________________________________printTime("IntegralLines::update(): Compute Time:", Tim_update.secs() - sec);
1057
1058// printf("IntegralLines::update(): ComputeTime: %f\n",overall_int_time );
1059// printf("IntegralLines::update(): Time per integration %d points: %f\n", (int)nPoints, overall_int_time/nPoints );
1060
1061 CurviCellsPerUniCell << Context << LocalPointFinder->MaxListSize;
1062
1063
1064// 7. Collect all points into one array
1065// Alternatively, could store all data in field fragments in the
1066// output positions field. This were more efficient, as it does
1067// not require to copy the points here. However, the display methods
1068// such as line render, must be checked to be able to handle such
1069// line data. Nevertheless, this were the way how to do it "right".
1070// There should be another, generic, module anyway that combines
1071// fragmented fields into unfragmented ones, for those modules which
1072// are incapable elsewhere to operate on fragmented fields.
1073//
1074// puts("IntegralLines::update() 7. Collect");fflush(stdout);
1075
1076
1077//
1078// 8. Bake a new Grid object that carries the actual lines
1079//
1080//
1081#ifdef VERBOSE
1082 puts("IntegralLines::update() 8. Bake");fflush(stdout);
1083#endif
1084 {
1085// MEMCORE_PROFILE_THIS("IntegralLines<FieldType,LineType>::update(VRequest&Context, double precision) Bake Grid",1)
1086
1087 //
1088 // a. Create a Grid object on the Bundle, compatible with the Bundle,
1089 // but not yet inserted into the Bundle. It will thus be invisible
1090 // until we are done with baking it. Otherwise, an incomplete Grid
1091 // would be visible in the Bundle, and a concurrent access to the
1092 // Bundle's Grid would fail (as it may happen in a multithreaded
1093 // environment). Alternatively, one could start baking the Grid already
1094 // during integration, and publish it in the Bundle. Then a concurrent
1095 // rendering would show the active computation going on. However, the
1096 // Grid must always be internally consistent. One must never publish
1097 // a half-done Grid into the Bundle.
1098 //
1099RefPtr<Grid> IntegralLineGrid = FieldSelection.theSourceBundle->newGrid();
1100
1101
1103 nullptr, // coordinates will be added a bit later
1104 createLineSet( Lines ) );
1105
1106 assert(OutputLineSet.CartesianVertices);
1107
1108 {
1109// MEMCORE_PROFILE_THIS("IntegralLines<FieldType,LineType>::update(VRequest&Context, double precision) CollectLineData",1)
1110 CollectLineData( *(OutputLineSet.CartesianVertices), Lines, nPoints);
1111 OutputLineSet.Coords = OutputLineSet.CartesianVertices->getPositions();
1112 assert( OutputLineSet.Coords && "No Coords found");
1113 }
1114
1115 //
1116 // d. Define relationship between the output grid of lines, and the
1117 // grid on which the vector field lives. This is optional, but will
1118 // easy further operations on the line grid, such as evaluating fields
1119 // from the vector field's grid along the lines.
1120 //
1121 // Remember the source grid's fragment ID's for each point of the
1122 // integration lines. This is useful for multiblock grids, such that
1123 // subsequent lookup of a point's fragment ID is not necessary, for
1124 // instance when another field of the source grid shall be evaluated
1125 // on the lines.
1126 if (0) // wieso geht des nit mit geodesics44?
1127 {
1130// typedef MemArray<1, std::string> FragmentIDs_t;
1131 typedef MemArray<1, FragmentID_t> FragmentIDs_t;
1133// MultiArray<1,std::string > LineVFID = *LinesVertFragID;
1135 {
1136 index_t vert_count = 0;
1137 for(index_t lin = 0; lin < Lines.size(); lin++ )
1138 {
1139 const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector();
1140 for(index_t ver = 0; ver < Line.size() ; ver++ )
1141 {
1142 LineVFID[ MIndex(vert_count) ] = Line[ver].fragment;
1143 vert_count++;
1144 }
1145 }
1146 //assert( vert_count == nPoints);
1147 }
1148
1151 }
1152
1153 //
1154 // e. Copy floating point indices from the integration lines to the line grid.
1155 // Same as with the fragment ID's, these indices correspond to a representation
1156 // of the output grid in terms of the input grid and will ease mapping fields
1157 // in a future operation.
1158 //
1159 {
1163 {
1164 index_t vert_count = 0;
1165 for(index_t lin = 0; lin < Lines.size(); lin++ )
1166 {
1167 const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector();
1168
1169 for(index_t ver = 0; ver < Line.size() ; ver++ )
1170 {
1171 LineVFI[ MIndex(vert_count) ] = Line[ver].index_location;
1172 vert_count++;
1173 }
1174 }
1175 //assert( vert_count == nPoints);
1176 }
1177
1178 Skeleton&SourceSkeleton = *(FieldSelection.getGrid()->findVertices());
1180 LineVerticesAsSourceVertices.setPositions( new Field( LinesVertFI ) );
1181
1182 // f. add direction (i.e. velocity)
1183 {
1184/*
1185 Look at the classes above on CollectLineData how to extract 3D information
1186 from nD point data IF required.
1187
1188
1189 The two if's down here seem to do exactly the same, except that in
1190 the 1st case it uses the point dims for the loop after verifying that
1191 Dims is three, in the 2nd case it writes 3 explicitly. What's the point
1192 of
1193
1194 if (Dims==3) f(Dims);
1195 if (Dims==4) f(3);
1196
1197 ??
1198
1199 */
1200
1201 if(IntegrationPoint<FieldType>::point::Dims == 3)
1202 {
1205 index_t vert_count = 0;
1206 for(index_t lin = 0; lin < Lines.size(); lin++ )
1207 {
1208 const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector();
1209 for(index_t ver = 0; ver < Line.size() ; ver++ )
1210 {
1211 for(unsigned j = 0; j < IntegrationPoint<FieldType>::point::Dims; j++)
1212 LineData[ MIndex(vert_count) ][j] = Line[ver].direction[j];
1213 vert_count++;
1214 }
1215 }
1216 //assert( vert_count == nPoints);
1217 (*OutputLineSet.CartesianVertices)[ LineSet::PredefinedFieldNames::Velocity ]->setPersistentData( LinesData );
1218 }
1219 if(IntegrationPoint<FieldType>::point::Dims == 4)
1220 {
1221 // Ref<MemArray<1,Eagle::tvector4> > LinesData( nPoints );
1222 // MultiArray<1,Eagle::tvector4>&LineData = *LinesData;
1223 // index_t vert_count = 0;
1224 // for(index_t lin = 0; lin < Lines.size(); lin++ )
1225 // {
1226 // const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector();
1227 // for(index_t ver = 0; ver < Line.size() ; ver++ )
1228 // {
1229 // for(unsigned j = 0; j < IntegrationPoint<FieldType>::point::Dims; j++)
1230 // LineData[ MIndex(vert_count) ][j] = Line[ver].direction[j];
1231 // vert_count++;
1232 // }
1233 // }
1234 // assert( vert_count == nPoints);
1235 // string tmp = string("Direction");
1236 // VerticesAsCartesian[ tmp ]->setPersistentData( LinesData );
1239 index_t vert_count = 0;
1240 for(index_t lin = 0; lin < Lines.size(); lin++ )
1241 {
1242 const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector();
1243 for(index_t ver = 0; ver < Line.size() ; ver++ )
1244 {
1245 for(unsigned j = 0; j < 3; j++)
1246 LineData[ MIndex(vert_count) ][j] = Line[ver].direction[j+1];
1247 cout<< "InegralLine:update(): Direction: " << LineData[ MIndex(vert_count) ] << endl;
1248 vert_count++;
1249 }
1250 }
1251 puts("directions done 1");fflush(stdout);
1252 //assert( vert_count == nPoints);
1253 (*OutputLineSet.CartesianVertices)[ LineSet::PredefinedFieldNames::Velocity ]->setPersistentData( LinesData );
1254 puts("directions done 2");fflush(stdout);
1255 }
1256 }
1257 }
1258
1259
1260 //
1261 // g. Add the data field to the output grid of lines. // this maybe needs special treatment
1262 //
1263 if( options("addData") )
1264 {
1266 Ref<LinesDataArr_t> LinesData( nPoints );
1268 index_t vert_count = 0;
1269 for(index_t lin = 0; lin < Lines.size(); lin++ )
1270 {
1271 const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector();
1272 for(index_t ver = 0; ver < Line.size() ; ver++ )
1273 {
1274 LineData[ MIndex(vert_count) ] = Line[ver].data;
1275 vert_count++;
1276 }
1277 }
1278 //assert( vert_count == nPoints);
1279 (*OutputLineSet.CartesianVertices)[ Fieldname(Context) ]->setPersistentData( LinesData );
1280 }
1281
1282
1283
1284 // And establish the same vector field as the tangential vectors
1285 // given on this line set. This is an alias to the same vector field,
1286 // under which TangentialVectors operations will find this field by
1287 // convention as defined in fiber/baseop/TangentialVectors.hpp
1288 //
1289 //VerticesAsCartesian[ TangentialVectorFieldName ]->setPersistentData( LinesData );
1290
1291 //
1292 // h. As a feature of this module, compute the magnitude of the vector field // needs special treatment
1293 // and store it in the lines.
1294 //
1295 if (options("addMagnitude"))
1296 {
1299 index_t vert_count = 0;
1300 for(index_t lin = 0; lin < Lines.size(); lin++ )
1301 {
1302 const std::vector<IntegrationPoint<FieldType> >&Line = Lines[lin]->std_vector();
1303 for(index_t ver = 0; ver < Line.size() ; ver++ )
1304 {
1305 LineMag[ MIndex( vert_count) ] = norm( Line[ver].data );
1306 vert_count++;
1307 }
1308 }
1309
1310#define DOUBLELINE "\u2016"
1311 string outFieldName( DOUBLELINE + Fieldname(Context) + DOUBLELINE );
1312 (*OutputLineSet.CartesianVertices)[ outFieldName ]->setPersistentData( LinesVectorMagnitude );
1313// puts("IntegralLine::update() DEB: setPersistent LineVectorMagnitudesF");
1314 }
1315
1316 //
1317 // y. Allow standard fields from the LineSet class to be available on integrated data
1318 //
1319#ifdef VERBOSE
1320 puts("before setup standard");fflush(stdout);
1321#endif
1322 if (!OutputLineSet.setupStandardFields( IntegralLineGrid ) )
1323 {
1324 puts("LINE INTEGRATOR ERROR: Could not set up standard fields on lines!");fflush(stdout);
1325 }
1326
1327
1328
1329 //
1330 // z. Finally, insert the Grid object into the bundle, at the current
1331 // time slice. It will hereby be visible in the bundle and ready
1332 // to be used elsewhere (like a rendering module). At last, announce
1333 // this Grid's properties as the output of this VISH Object.
1334 //
1335
1336 puts("insert slice");fflush(stdout);
1337 currentSlice.getSlice()->insert( grid_name, IntegralLineGrid );
1338
1339 FieldSelection.BundleSource().speak("FieldSelection.BundleSource()");
1340
1341
1342 GridSelector GS( grid_name, FieldSelection.BundleSource() );
1343 myIntegralLines << Context << GS;
1344 }
1345
1346 infoMsg(Context, "Done, output at: " + grid_name);
1347
1348// printf("ComputMultipleStreamLines::update() Written into Bundle, setPersitentData and touched Spacetimeslot()\n");
1349// VActionNotifier::ProgressInfo (string("Streamline computation complete"));
1350
1351// VActionNotifier::StatusInfo( "Integration Line Computation done." );
1352
1353 puts("IntegralLine::update() >>> EXIT");
1354
1355 return true;
1356}
1357
1358}
1359}
basic_ostream< _CharT, _Traits > & endl(basic_ostream< _CharT, _Traits > &__os)
ostream cout
constexpr void resize(size_type __new_size)
Convenience class that implements a pointer to a Bundle object but adds some useful member funtions t...
Definition Bundle.hpp:779
An iterator with an optional DataCreator, which is just a class to intercept creation of data along a...
Definition CreativeIterator.hpp:34
An abstract selection of fields, that is given by names of fields and possible types for each field.
Definition FieldSelection.hpp:23
string getFieldName() const
Retrieve the name of a unique field, if only one is stored here.
Definition FieldSelection.cpp:68
An internal class that stores a couple of textual names.
Definition FieldSelector.hpp:18
RefPtr< Field > getField(const string &theName, int Level=0, const string &ChartName=string()) const
Return a field of the given name in the Cartesian representation of the Vertices on the toplevel refi...
Definition FieldSelector.cpp:231
A Field is a collection of CreativeArrayBase reference pointers which are accessed via FragmentID obj...
Definition Field.hpp:245
Context information to select a grid from within a bundle.
Definition GridSelector.hpp:26
A Grid is a set of Skeleton objects, each of them accessed via some unique SkeletonID object.
Definition Grid.hpp:60
A set of lines stored on a Grid.
Definition LineSet.hpp:55
Use this class to compute a local cell index and fragment ID (if neccessary) of any coordinate field ...
Definition LocalFromWorldPoint.hpp:71
A Representation is a set of Field objects, each of them accessed via some FieldID identifier.
Definition Representation.hpp:101
bool setPositions(const RefPtr< Field > &P)
Set the positional component of this Representation object.
Definition Representation.cpp:519
Identifier for Skeletons within a Grid.
Definition SkeletonID.hpp:24
A Skeleton is a set of Representation object, each of them accessed by an Representer object.
Definition Skeleton.hpp:102
Definition IntegralFace.hpp:37
double norm(const PhysicalSpace::bivector &v)
Definition GridInspector.hpp:13
static const char Velocity[]
The velocity with which particles pass through this line.
Definition LineSet.hpp:163