You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
435 lines
15 KiB
435 lines
15 KiB
2 years ago
|
/*=========================================================================
|
||
|
|
||
|
Program: Visualization Toolkit
|
||
|
Module: $RCSfile: vtkPKdTree.h,v $
|
||
|
|
||
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
||
|
All rights reserved.
|
||
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
||
|
|
||
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
||
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
|
PURPOSE. See the above copyright notice for more information.
|
||
|
|
||
|
=========================================================================*/
|
||
|
/*----------------------------------------------------------------------------
|
||
|
Copyright (c) Sandia Corporation
|
||
|
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
|
||
|
// .NAME vtkPKdTree - Build a k-d tree decomposition of a list of points.
|
||
|
//
|
||
|
// .SECTION Description
|
||
|
// Build, in parallel, a k-d tree decomposition of one or more
|
||
|
// vtkDataSets distributed across processors. We assume each
|
||
|
// process has read in one portion of a large distributed data set.
|
||
|
// When done, each process has access to the k-d tree structure,
|
||
|
// can obtain information about which process contains
|
||
|
// data for each spatial region, and can depth sort the spatial
|
||
|
// regions.
|
||
|
//
|
||
|
// This class can also assign spatial regions to processors, based
|
||
|
// on one of several region assignment schemes. By default
|
||
|
// a contiguous, convex region is assigned to each process. Several
|
||
|
// queries return information about how many and what cells I have
|
||
|
// that lie in a region assigned to another process.
|
||
|
//
|
||
|
// .SECTION See Also
|
||
|
// vtkKdTree
|
||
|
|
||
|
#ifndef __vtkPKdTree_h
|
||
|
#define __vtkPKdTree_h
|
||
|
|
||
|
#include "vtkKdTree.h"
|
||
|
|
||
|
class vtkMultiProcessController;
|
||
|
class vtkCommunicator;
|
||
|
class vtkSubGroup;
|
||
|
class vtkIntArray;
|
||
|
class vtkKdNode;
|
||
|
|
||
|
class VTK_PARALLEL_EXPORT vtkPKdTree : public vtkKdTree
|
||
|
{
|
||
|
public:
|
||
|
vtkTypeRevisionMacro(vtkPKdTree, vtkKdTree);
|
||
|
|
||
|
|
||
|
void PrintSelf(ostream& os, vtkIndent indent);
|
||
|
void PrintTiming(ostream& os, vtkIndent indent);
|
||
|
void PrintTables(ostream& os, vtkIndent indent);
|
||
|
|
||
|
static vtkPKdTree *New();
|
||
|
|
||
|
// Description:
|
||
|
// Build the spatial decomposition. Call this explicitly
|
||
|
// after changing any parameters affecting the build of the
|
||
|
// tree. It must be called by all processes in the parallel
|
||
|
// application, or it will hang.
|
||
|
|
||
|
void BuildLocator();
|
||
|
|
||
|
// Description:
|
||
|
// Get the total number of cells distributed across the data
|
||
|
// files read by all processes. You must have called BuildLocator
|
||
|
// before calling this method.
|
||
|
|
||
|
int GetTotalNumberOfCells(){return this->TotalNumCells;}
|
||
|
|
||
|
// Description:
|
||
|
// Create tables of counts of cells per process per region.
|
||
|
// These tables can be accessed with queries like
|
||
|
// "HasData", "GetProcessCellCountForRegion", and so on.
|
||
|
// You must have called BuildLocator() beforehand. This
|
||
|
// method must be called by all processes or it will hang.
|
||
|
// Returns 1 on error, 0 when no error.
|
||
|
|
||
|
int CreateProcessCellCountData();
|
||
|
|
||
|
// Description:
|
||
|
// A convenience function which compiles the global
|
||
|
// bounds of the data arrays across processes.
|
||
|
// These bounds can be accessed with
|
||
|
// "GetCellArrayGlobalRange" and "GetPointArrayGlobalRange".
|
||
|
// This method must be called by all processes or it will hang.
|
||
|
// Returns 1 on error, 0 when no error.
|
||
|
|
||
|
int CreateGlobalDataArrayBounds();
|
||
|
|
||
|
// Description:
|
||
|
// Set/Get the communicator object
|
||
|
|
||
|
void SetController(vtkMultiProcessController *c);
|
||
|
vtkGetObjectMacro(Controller, vtkMultiProcessController);
|
||
|
|
||
|
// Description:
|
||
|
// The PKdTree class can assign spatial regions to processors after
|
||
|
// building the k-d tree, using one of several partitioning criteria.
|
||
|
// These functions Set/Get whether this assignment is computed.
|
||
|
// The default is "Off", no assignment is computed. If "On", and
|
||
|
// no assignment scheme is specified, contiguous assignment will be
|
||
|
// computed. Specifying an assignment scheme (with AssignRegions*())
|
||
|
// automatically turns on RegionAssignment.
|
||
|
|
||
|
vtkGetMacro(RegionAssignment, int);
|
||
|
|
||
|
static const int NoRegionAssignment;
|
||
|
static const int ContiguousAssignment;
|
||
|
static const int UserDefinedAssignment;
|
||
|
static const int RoundRobinAssignment;
|
||
|
|
||
|
// Description:
|
||
|
// Assign spatial regions to processes via a user defined map.
|
||
|
// The user-supplied map is indexed by region ID, and provides a
|
||
|
// process ID for each region.
|
||
|
|
||
|
int AssignRegions(int *map, int numRegions);
|
||
|
|
||
|
// Description:
|
||
|
// Let the PKdTree class assign a process to each region in a
|
||
|
// round robin fashion. If the k-d tree has not yet been
|
||
|
// built, the regions will be assigned after BuildLocator executes.
|
||
|
|
||
|
int AssignRegionsRoundRobin();
|
||
|
|
||
|
// Description:
|
||
|
// Let the PKdTree class assign a process to each region
|
||
|
// by assigning contiguous sets of spatial regions to each
|
||
|
// process. The set of regions assigned to each process will
|
||
|
// always have a union that is a convex space (a box).
|
||
|
// If the k-d tree has not yet been built, the regions
|
||
|
// will be assigned after BuildLocator executes.
|
||
|
|
||
|
int AssignRegionsContiguous();
|
||
|
|
||
|
// Description:
|
||
|
// Writes the list of region IDs assigned to the specified
|
||
|
// process. Regions IDs start at 0 and increase by 1 from there.
|
||
|
// Returns the number of regions in the list.
|
||
|
|
||
|
int GetRegionAssignmentList(int procId, vtkIntArray *list);
|
||
|
|
||
|
// Description:
|
||
|
// The k-d tree spatial regions have been assigned to processes.
|
||
|
// Given a point on the boundary of one of the regions, this
|
||
|
// method creates a list of all processes whose region
|
||
|
// boundaries include that point. This may be required when
|
||
|
// looking for processes that have cells adjacent to the cells
|
||
|
// of a given process.
|
||
|
|
||
|
void GetAllProcessesBorderingOnPoint(float x, float y, float z,
|
||
|
vtkIntArray *list);
|
||
|
|
||
|
// Description:
|
||
|
// Returns the ID of the process assigned to the region.
|
||
|
|
||
|
int GetProcessAssignedToRegion(int regionId);
|
||
|
|
||
|
// Description:
|
||
|
// Returns 1 if the process has data for the given region,
|
||
|
// 0 otherwise.
|
||
|
|
||
|
int HasData(int processId, int regionId);
|
||
|
|
||
|
// Description:
|
||
|
// Returns the number of cells the specified process has in the
|
||
|
// specified region.
|
||
|
|
||
|
int GetProcessCellCountForRegion(int processId, int regionId);
|
||
|
|
||
|
// Description:
|
||
|
// Returns the total number of processes that have data
|
||
|
// falling within this spatial region.
|
||
|
|
||
|
int GetTotalProcessesInRegion(int regionId);
|
||
|
|
||
|
// Description:
|
||
|
// Adds the list of processes having data for the given
|
||
|
// region to the supplied list, returns the number of
|
||
|
// processes added.
|
||
|
|
||
|
int GetProcessListForRegion(int regionId, vtkIntArray *processes);
|
||
|
|
||
|
// Description:
|
||
|
// Writes the number of cells each process has for the region
|
||
|
// to the supplied list of length len. Returns the number of
|
||
|
// cell counts written. The order of the cell counts corresponds
|
||
|
// to the order of process IDs in the process list returned by
|
||
|
// GetProcessListForRegion.
|
||
|
|
||
|
int GetProcessesCellCountForRegion(int regionId, int *count, int len);
|
||
|
|
||
|
// Description:
|
||
|
// Returns the total number of spatial regions that a given
|
||
|
// process has data for.
|
||
|
|
||
|
int GetTotalRegionsForProcess(int processId);
|
||
|
|
||
|
// Description:
|
||
|
// Adds the region IDs for which this process has data to
|
||
|
// the supplied vtkIntArray. Retruns the number of regions.
|
||
|
|
||
|
int GetRegionListForProcess(int processId, vtkIntArray *regions);
|
||
|
|
||
|
// Description:
|
||
|
// Writes to the supplied integer array the number of cells this
|
||
|
// process has for each region. Returns the number of
|
||
|
// cell counts written. The order of the cell counts corresponds
|
||
|
// to the order of region IDs in the region list returned by
|
||
|
// GetRegionListForProcess.
|
||
|
|
||
|
int GetRegionsCellCountForProcess(int ProcessId, int *count, int len);
|
||
|
|
||
|
// Description:
|
||
|
// After regions have been assigned to processes, I may want to know
|
||
|
// which cells I have that are in the regions assigned to a particular
|
||
|
// process.
|
||
|
//
|
||
|
// This method takes a process ID and two vtkIdLists. It
|
||
|
// writes to the first list the IDs of the cells
|
||
|
// contained in the process' regions. (That is, their cell
|
||
|
// centroid is contained in the region.) To the second list it
|
||
|
// write the IDs of the cells which intersect the process' regions
|
||
|
// but whose cell centroid lies elsewhere.
|
||
|
//
|
||
|
// The total number of cell IDs written to both lists is returned.
|
||
|
// Either list pointer passed in can be NULL, and it will be ignored.
|
||
|
// If there are multiple data sets, you must specify which data set
|
||
|
// you wish cell IDs for.
|
||
|
//
|
||
|
// The caller should delete these two lists when done. This method
|
||
|
// uses the cell lists created in vtkKdTree::CreateCellLists().
|
||
|
// If the cell lists for the process' regions do not exist, this
|
||
|
// method will first build the cell lists for all regions by calling
|
||
|
// CreateCellLists(). You must remember to DeleteCellLists() when
|
||
|
// done with all calls to this method, as cell lists can require a
|
||
|
// great deal of memory.
|
||
|
|
||
|
vtkIdType GetCellListsForProcessRegions(int ProcessId, int set,
|
||
|
vtkIdList *inRegionCells, vtkIdList *onBoundaryCells);
|
||
|
vtkIdType GetCellListsForProcessRegions(int ProcessId, vtkDataSet *set,
|
||
|
vtkIdList *inRegionCells, vtkIdList *onBoundaryCells);
|
||
|
vtkIdType GetCellListsForProcessRegions(int ProcessId, vtkIdList *inRegionCells,
|
||
|
vtkIdList *onBoundaryCells);
|
||
|
|
||
|
// Description:
|
||
|
// Return a list of all processes in order from front to
|
||
|
// back, given a vector direction of projection.
|
||
|
|
||
|
int DepthOrderAllProcesses(double *directionOfProjection,
|
||
|
vtkIntArray *orderedList);
|
||
|
|
||
|
// Description:
|
||
|
// An added feature of vtkPKdTree is that it will calculate the
|
||
|
// the global range of field arrays across all processes. You
|
||
|
// call CreateGlobalDataArrayBounds() to do this calculation.
|
||
|
// Then the following methods return the ranges.
|
||
|
// Returns 1 on error, 0 otherwise.
|
||
|
|
||
|
int GetCellArrayGlobalRange(const char *name, float range[2]);
|
||
|
int GetPointArrayGlobalRange(const char *name, float range[2]);
|
||
|
int GetCellArrayGlobalRange(const char *name, double range[2]);
|
||
|
int GetPointArrayGlobalRange(const char *name, double range[2]);
|
||
|
|
||
|
int GetCellArrayGlobalRange(int arrayIndex, double range[2]);
|
||
|
int GetPointArrayGlobalRange(int arrayIndex, double range[2]);
|
||
|
int GetCellArrayGlobalRange(int arrayIndex, float range[2]);
|
||
|
int GetPointArrayGlobalRange(int arrayIndex, float range[2]);
|
||
|
|
||
|
protected:
|
||
|
|
||
|
vtkPKdTree();
|
||
|
~vtkPKdTree();
|
||
|
|
||
|
void SingleProcessBuildLocator();
|
||
|
int MultiProcessBuildLocator(double *bounds);
|
||
|
|
||
|
private:
|
||
|
|
||
|
int RegionAssignment;
|
||
|
|
||
|
vtkMultiProcessController *Controller;
|
||
|
|
||
|
vtkSubGroup *SubGroup;
|
||
|
|
||
|
static char *StrDupWithNew(const char *s);
|
||
|
|
||
|
int NumProcesses;
|
||
|
int MyId;
|
||
|
|
||
|
// basic tables - each region is the responsibility of one process, but
|
||
|
// one process may be assigned many regions
|
||
|
|
||
|
int *RegionAssignmentMap; // indexed by region ID
|
||
|
int RegionAssignmentMapLength;
|
||
|
int **ProcessAssignmentMap; // indexed by process ID
|
||
|
int *NumRegionsAssigned; // indexed by process ID
|
||
|
|
||
|
int UpdateRegionAssignment();
|
||
|
|
||
|
// basic tables reflecting the data that was read from disk
|
||
|
// by each process
|
||
|
|
||
|
char *DataLocationMap; // by process, by region
|
||
|
|
||
|
int *NumProcessesInRegion; // indexed by region ID
|
||
|
int **ProcessList; // indexed by region ID
|
||
|
|
||
|
int *NumRegionsInProcess; // indexed by process ID
|
||
|
int **RegionList; // indexed by process ID
|
||
|
|
||
|
int **CellCountList; // indexed by region ID
|
||
|
|
||
|
double *CellDataMin; // global range for data arrays
|
||
|
double *CellDataMax;
|
||
|
double *PointDataMin;
|
||
|
double *PointDataMax;
|
||
|
char **CellDataName;
|
||
|
char **PointDataName;
|
||
|
int NumCellArrays;
|
||
|
int NumPointArrays;
|
||
|
|
||
|
// distribution of indices for select operation
|
||
|
|
||
|
int BuildGlobalIndexLists(int ncells);
|
||
|
|
||
|
int *StartVal;
|
||
|
int *EndVal;
|
||
|
int *NumCells;
|
||
|
int TotalNumCells;
|
||
|
|
||
|
// local share of points to be partitioned, and local cache
|
||
|
|
||
|
int WhoHas(int pos);
|
||
|
int _whoHas(int L, int R, int pos);
|
||
|
float *GetLocalVal(int pos);
|
||
|
float *GetLocalValNext(int pos);
|
||
|
void SetLocalVal(int pos, float *val);
|
||
|
void ExchangeVals(int pos1, int pos2);
|
||
|
void ExchangeLocalVals(int pos1, int pos2);
|
||
|
|
||
|
float *PtArray;
|
||
|
float *PtArray2;
|
||
|
float *CurrentPtArray;
|
||
|
float *NextPtArray;
|
||
|
int PtArraySize;
|
||
|
|
||
|
int *SelectBuffer;
|
||
|
|
||
|
// Parallel build of k-d tree
|
||
|
|
||
|
int AllCheckForFailure(int rc, const char *where, const char *how);
|
||
|
void AllCheckParameters();
|
||
|
double *VolumeBounds();
|
||
|
int DivideRegion(vtkKdNode *kd, int L, int level, int tag);
|
||
|
int BreadthFirstDivide(double *bounds);
|
||
|
void enQueueNode(vtkKdNode *kd, int L, int level, int tag);
|
||
|
|
||
|
int Select(int dim, int L, int R);
|
||
|
void _select(int L, int R, int K, int dim);
|
||
|
void DoTransfer(int from, int to, int fromIndex, int toIndex, int count);
|
||
|
|
||
|
int *PartitionAboutMyValue(int L, int R, int K, int dim);
|
||
|
int *PartitionAboutOtherValue(int L, int R, float T, int dim);
|
||
|
int *PartitionSubArray(int L, int R, int K, int dim, int p1, int p2);
|
||
|
|
||
|
int CompleteTree();
|
||
|
#ifdef YIELDS_INCONSISTENT_REGION_BOUNDARIES
|
||
|
void RetrieveData(vtkKdNode *kd, int *buf);
|
||
|
#else
|
||
|
void ReduceData(vtkKdNode *kd, int *sources);
|
||
|
void BroadcastData(vtkKdNode *kd);
|
||
|
#endif
|
||
|
|
||
|
float *DataBounds(int L, int K, int R);
|
||
|
void GetLocalMinMax(int L, int R, int me, float *min, float *max);
|
||
|
|
||
|
static int FillOutTree(vtkKdNode *kd, int level);
|
||
|
static int ComputeDepth(vtkKdNode *kd);
|
||
|
static void PackData(vtkKdNode *kd, double *data);
|
||
|
static void UnpackData(vtkKdNode *kd, double *data);
|
||
|
static void CheckFixRegionBoundaries(vtkKdNode *tree);
|
||
|
|
||
|
// list management
|
||
|
|
||
|
int AllocateDoubleBuffer();
|
||
|
void FreeDoubleBuffer();
|
||
|
void SwitchDoubleBuffer();
|
||
|
int AllocateSelectBuffer();
|
||
|
void FreeSelectBuffer();
|
||
|
|
||
|
void InitializeGlobalIndexLists();
|
||
|
int AllocateAndZeroGlobalIndexLists();
|
||
|
void FreeGlobalIndexLists();
|
||
|
void InitializeRegionAssignmentLists();
|
||
|
int AllocateAndZeroRegionAssignmentLists();
|
||
|
void FreeRegionAssignmentLists();
|
||
|
void InitializeProcessDataLists();
|
||
|
int AllocateAndZeroProcessDataLists();
|
||
|
void FreeProcessDataLists();
|
||
|
void InitializeFieldArrayMinMax();
|
||
|
int AllocateAndZeroFieldArrayMinMax();
|
||
|
void FreeFieldArrayMinMax();
|
||
|
|
||
|
void ReleaseTables();
|
||
|
|
||
|
// Assigning regions to processors
|
||
|
|
||
|
void AddProcessRegions(int procId, vtkKdNode *kd);
|
||
|
void BuildRegionListsForProcesses();
|
||
|
|
||
|
// Gather process/region data totals
|
||
|
|
||
|
int *CollectLocalRegionProcessData();
|
||
|
int BuildRegionProcessTables();
|
||
|
int BuildFieldArrayMinMax();
|
||
|
void AddEntry(int *list, int len, int id);
|
||
|
static int BinarySearch(int *list, int len, int which);
|
||
|
|
||
|
static int FindNextLocalArrayIndex(const char *n, const char **names, int len, int start=0);
|
||
|
|
||
|
vtkPKdTree(const vtkPKdTree&); // Not implemented
|
||
|
void operator=(const vtkPKdTree&); // Not implemented
|
||
|
};
|
||
|
|
||
|
#endif
|