33#include < vtkh/filters/Recenter.hpp>
44
55// vtkm includes
6- #include < vtkm/cont/DeviceAdapter.h>
7- #include < vtkm/cont/Storage.h>
8- #include < vtkm/internal/Configure.h>
6+ #include < vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h>
7+ #include < vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h>
8+ #include < vtkm/filter/scalar_topology/SelectTopVolumeContoursFilter.h>
9+ #include < vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h>
910#include < vtkm/filter/scalar_topology/worklet/contourtree_augmented/PrintVectors.h>
1011#include < vtkm/filter/scalar_topology/worklet/contourtree_augmented/ProcessContourTree.h>
11- #include < vtkm/filter/scalar_topology/worklet/contourtree_augmented/processcontourtree/Branch.h>
12- #include < vtkm/filter/scalar_topology/worklet/contourtree_augmented/processcontourtree/PiecewiseLinearFunction.h>
12+ #include < vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h>
13+ #include < vtkm/filter/scalar_topology/worklet/contourtree_distributed/HierarchicalContourTree.h>
14+ #include < vtkm/filter/scalar_topology/worklet/contourtree_distributed/TreeCompiler.h>
1315
1416#include < vtkh/filters/GhostStripper.hpp>
1517
@@ -198,14 +200,52 @@ void ContourTree::PostExecute()
198200 Filter::PostExecute ();
199201}
200202
203+ struct TopVolumeBranchSaddleIsoValueFunctor
204+ {
205+ vtkm::Id nSelectedBranches;
206+ std::vector<vtkm::Float64> dbranches;
207+
208+ public:
209+
210+ TopVolumeBranchSaddleIsoValueFunctor (vtkm::Id nSelectedBranches) : nSelectedBranches(nSelectedBranches) {
211+ }
212+ void operator ()(const vtkm::cont::ArrayHandle<vtkm::Float32> &arr)
213+ {
214+ auto topVolBranchSaddleIsoValue = arr.ReadPortal ();
215+
216+ for (vtkm::Id branch = 0 ; branch < nSelectedBranches; ++branch) {
217+ dbranches.push_back (topVolBranchSaddleIsoValue.Get (branch));
218+ }
219+ }
220+
221+ void operator ()(const vtkm::cont::ArrayHandle<vtkm::Float64> &arr)
222+ {
223+ auto topVolBranchSaddleIsoValue = arr.ReadPortal ();
224+
225+ for (vtkm::Id branch = 0 ; branch < nSelectedBranches; ++branch) {
226+ dbranches.push_back (topVolBranchSaddleIsoValue.Get (branch));
227+ }
228+ }
229+ template <typename T>
230+ void operator ()(const T&)
231+ {
232+ throw vtkm::cont::ErrorBadValue (" TopVolumeBranchSaddleIsoValueFunctor Expected Float32 or Float64!" );
233+ }
234+
235+ vtkm::Float64 Get (vtkm::Id branch)
236+ {
237+ return dbranches[branch];
238+ }
239+ };
240+
201241struct AnalyzerFunctor
202242{
203- vtkm::filter::scalar_topology::ContourTreeAugmented& filter;
243+ vtkm::filter::scalar_topology::ContourTreeAugmented* filter;
204244 vtkh::ContourTree& contourTree;
205245 bool dataFieldIsSorted;
206246
207247 public:
208- AnalyzerFunctor (vtkh::ContourTree& contourTree, vtkm::filter::scalar_topology::ContourTreeAugmented& filter): contourTree(contourTree), filter(filter) {
248+ AnalyzerFunctor (vtkh::ContourTree& contourTree, vtkm::filter::scalar_topology::ContourTreeAugmented* filter): contourTree(contourTree), filter(filter) {
209249 }
210250
211251 void SetDataFieldIsSorted (bool dataFieldIsSorted) {
@@ -214,12 +254,12 @@ struct AnalyzerFunctor
214254
215255 void operator ()(const vtkm::cont::ArrayHandle<vtkm::Float32> &arr) const
216256 {
217- contourTree.analysis <vtkm::Float32>(filter, dataFieldIsSorted, arr);
257+ contourTree.analysis <vtkm::Float32>(* filter, dataFieldIsSorted, arr);
218258 }
219259
220260 void operator ()(const vtkm::cont::ArrayHandle<vtkm::Float64> &arr) const
221261 {
222- contourTree.analysis <vtkm::Float64>(filter, dataFieldIsSorted, arr);
262+ contourTree.analysis <vtkm::Float64>(* filter, dataFieldIsSorted, arr);
223263 }
224264
225265 template <typename T>
@@ -343,8 +383,65 @@ template<typename DataValueType> void ContourTree::analysis(vtkm::filter::scalar
343383 }
344384}
345385
386+ void ContourTree::distributed_analysis (const vtkm::cont::PartitionedDataSet& result, int mpi_rank) {
387+ vtkm::filter::scalar_topology::DistributedBranchDecompositionFilter bd_filter;
388+ auto bd_result = bd_filter.Execute (result);
389+
390+ #if 0
391+ for (vtkm::Id ds_no = 0; ds_no < result.GetNumberOfPartitions(); ++ds_no)
392+ {
393+ auto ds = bd_result.GetPartition(ds_no);
394+ std::string branchDecompositionFileName = std::string("BranchDecomposition_Rank_") +
395+ std::to_string(static_cast<int>(mpi_rank)) + std::string("_Block_") +
396+ std::to_string(static_cast<int>(ds_no)) + std::string(".txt");
397+
398+ std::ofstream treeStream(branchDecompositionFileName.c_str());
399+ treeStream
400+ << vtkm::filter::scalar_topology::HierarchicalVolumetricBranchDecomposer::PrintBranches(ds);
401+ }
402+ #endif
403+
404+ vtkm::filter::scalar_topology::SelectTopVolumeContoursFilter tp_filter;
405+ vtkm::Id numBranches = m_levels;
406+
407+ tp_filter.SetSavedBranches (numBranches);
408+ bd_result = tp_filter.Execute (bd_result);
409+
410+ for (vtkm::Id ds_no = 0 ; ds_no < result.GetNumberOfPartitions (); ++ds_no)
411+ {
412+ auto ds = bd_result.GetPartition (ds_no);
413+ auto topVolBranchGRId = ds.GetField (" TopVolumeBranchGlobalRegularIds" )
414+ .GetData ()
415+ .AsArrayHandle <vtkm::cont::ArrayHandle<vtkm::Id>>()
416+ .ReadPortal ();
417+
418+ auto topVolBranchSaddleEpsilon = ds.GetField (" TopVolumeBranchSaddleEpsilon" )
419+ .GetData ()
420+ .AsArrayHandle <vtkm::cont::ArrayHandle<vtkm::Id>>()
421+ .ReadPortal ();
422+
423+ vtkm::Id nSelectedBranches = topVolBranchGRId.GetNumberOfValues ();
424+
425+ TopVolumeBranchSaddleIsoValueFunctor iso_functor (nSelectedBranches);
426+
427+ vtkm::cont::CastAndCall (ds.GetField (" TopVolumeBranchSaddleIsoValue" ).GetData (), iso_functor);
428+
429+
430+ vtkm::Float32 eps = 0.00001 ;
431+
432+ for (vtkm::Id branch = 0 ; branch < nSelectedBranches; ++branch)
433+ {
434+ m_iso_values[branch] = iso_functor.Get (branch) + (eps * topVolBranchSaddleEpsilon.Get (branch));
435+ }
436+
437+ break ;
438+ }
439+
440+ std::sort (m_iso_values.begin (), m_iso_values.end ());
441+ }
442+
346443void ContourTree::DoExecute ()
347- {
444+ {
348445 vtkh::DataSet *old_input = this ->m_input ;
349446 const int before_num_domains = this ->m_input ->GetNumberOfDomains ();
350447
@@ -415,17 +512,20 @@ void ContourTree::DoExecute()
415512 this ->m_input ->GetDomain (0 , dom, domain_id);
416513 inDataSet.AppendPartition (dom);
417514
515+ #ifdef DEBUG
418516 if ( mpi_size != 1 )
419517 {
420518 std::ostringstream ostr;
421519 ostr << " rank: " << mpi_rank
422520 << " coord system range: " << dom.GetCoordinateSystem (0 ).GetRange () << std::endl;
423521 std::cout << ostr.str ();
424522 }
425- #ifdef DEBUG
426523#endif
427524#endif // VTKH_PARALLEL
428525
526+ vtkm::filter::Filter *filterField;
527+
528+ #ifndef VTKH_PARALLEL
429529 bool useMarchingCubes = false ;
430530 // Compute the fully augmented contour tree.
431531 // This should always be true for now in order for the isovalue selection to work.
@@ -434,43 +534,60 @@ void ContourTree::DoExecute()
434534 // Convert the mesh of values into contour tree, pairs of vertex ids
435535 vtkm::filter::scalar_topology::ContourTreeAugmented filter (useMarchingCubes, computeRegularStructure);
436536
437- filter.SetActiveField (m_field_name);
438-
439- #ifdef VTKH_PARALLEL
537+ #ifdef DEBUG
538+ std::cout << " --- BEGIN_SUMMARY inDataSet" << std::endl;
539+ inDataSet.PrintSummary ( std::cout );
540+ std::cout << " --- END_SUMMARY inDataSet" << std::endl;
541+ #endif
542+ #else // VTKH_PARALLEL
543+ // TODO SET VTKM to do vtkm::cont::LogLovel::Info
544+ // vtkm::filter::scalar_topology::ContourTreeUniformDistributed filter(vtkm::cont::LogLevel::Info, vtkm::cont::LogLevel::Info);
545+ vtkm::filter::scalar_topology::ContourTreeUniformDistributed filter;
546+ vtkm::filter::scalar_topology::ContourTreeAugmented aug_filter (false , true );
547+
548+ if (mpi_size == 1 ) {
549+ filterField = &aug_filter;
550+ } else {
551+ filter.SetUseBoundaryExtremaOnly (true );
552+ filter.SetUseMarchingCubes (false );
553+ filter.SetAugmentHierarchicalTree (true );
440554 ShiftLogicalOriginToZero (inDataSet);
441555 ComputeGlobalPointSize (inDataSet);
556+ filterField = &filter;
557+ }
558+
559+ #ifdef DEBUG
560+ std::cout << " --- BEGIN_SUMMARY inDataSet:mpi_rank=" << mpi_rank << std::endl;
561+ inDataSet.PrintSummary ( std::cout );
562+ std::cout << " --- END_SUMMARY inDataSet:mpi_rank=" << mpi_rank << std::endl;
563+ #endif
442564#endif // VTKH_PARALLEL
443565
444- auto result = filter. Execute (inDataSet );
566+ filterField-> SetActiveField (m_field_name );
445567
446- m_iso_values. resize (m_levels );
568+ auto result = filterField-> Execute (inDataSet );
447569
448- if (mpi_rank == 0 ) {
449- AnalyzerFunctor analyzerFunctor (*this , filter);
570+ m_iso_values.resize (m_levels);
450571
451572#ifndef VTKH_PARALLEL
573+ if (mpi_rank == 0 ) {
574+ AnalyzerFunctor analyzerFunctor (*this , &filter);
452575 analyzerFunctor.SetDataFieldIsSorted (false );
453576 vtkm::cont::CastAndCall (inDataSet.GetField (m_field_name).GetData (), analyzerFunctor);
577+ } // mpi_rank == 0
454578#else
455- if (mpi_size == 1 )
456- {
457- analyzerFunctor.SetDataFieldIsSorted (false );
458- vtkm::cont::CastAndCall (inDataSet.GetPartitions ()[0 ].GetField (m_field_name).GetData (), analyzerFunctor);
459- } else {
460- analyzerFunctor.SetDataFieldIsSorted (true );
461-
462- /*
463- if( result.GetPartitions()[0].GetNumberOfFields() > 1 ) {
464- vtkm::cont::CastAndCall(result.GetPartitions()[0].GetField("values").GetData(), analyzerFunctor);
465- } else {
466- vtkm::cont::CastAndCall(result.GetPartitions()[0].GetField(0).GetData(), analyzerFunctor);
467- }*/
468-
469- // TODO TO BE REVISITED. Tested with: srun -n 8 ./t_vtk-h_contour_tree_par
470- vtkm::cont::CastAndCall (result.GetPartitions ()[0 ].GetField (" resultData" ).GetData (), analyzerFunctor);
471- }
579+ if (mpi_size > 1 )
580+ { // BranchDecomposition
581+ distributed_analysis (result, mpi_rank);
582+ }
583+ else
584+ {
585+ AnalyzerFunctor analyzerFunctor (*this , (vtkm::filter::scalar_topology::ContourTreeAugmented *) filterField);
586+
587+ analyzerFunctor.SetDataFieldIsSorted (false );
588+ vtkm::cont::CastAndCall (inDataSet.GetPartitions ()[0 ].GetField (m_field_name).GetData (), analyzerFunctor);
589+ }
472590#endif // VTKH_PARALLEL
473- } // mpi_rank == 0
474591
475592#ifdef VTKH_PARALLEL
476593 MPI_Bcast (&m_iso_values[0 ], m_levels, MPI_DOUBLE, 0 , mpi_comm);
0 commit comments