Commit 7163d8d8 authored by hrchilds's avatar hrchilds
Browse files

Update from March 20, 2005

git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@435 18c085ea-50e0-402c-830e-de6fd14e8384
parent c510e29c
......@@ -53,6 +53,9 @@
# Hank Childs, Tue Feb 1 08:47:07 PST 2005
# Added avtSurfaceFilter.
#
# Hank Childs, Sun Mar 13 10:11:07 PST 2005
# Added avtStructuredMeshChunker.
#
##############################################################################
##
......@@ -89,8 +92,11 @@ SRC=\
avtShiftCenteringFilter.C \
avtSimilarityTransformFilter.C \
avtSmoothPolyDataFilter.C \
avtStructuredMeshChunker.C \
avtStructuredMeshPartitionStrategy.C \
avtSummationFilter.C \
avtSurfaceFilter.C \
avtSweepPlanePartitionStrategy.C \
avtTiledImageCompositor.C \
avtTransform.C \
avtVertexNormalsFilter.C \
......
......@@ -922,12 +922,22 @@ GetCoordinates(float start, float length, int numEls)
// Hank Childs, Sat Jan 29 11:01:59 PST 2005
// If we are going to use an arbitrator, make sure to request the variable.
//
// Hank Childs, Sun Mar 13 10:00:01 PST 2005
// Tell filters upstream that we have rectilinear optimizations.
//
// ****************************************************************************
avtPipelineSpecification_p
avtResampleFilter::PerformRestriction(avtPipelineSpecification_p spec)
avtResampleFilter::PerformRestriction(avtPipelineSpecification_p oldspec)
{
//
// Best copy constructor we have??
//
avtPipelineSpecification_p spec = new avtPipelineSpecification(oldspec,
oldspec->GetDataSpecification());
spec->NoDynamicLoadBalancing();
spec->SetHaveRectilinearMeshOptimizations(true);
if (atts.GetUseArbitrator())
{
if (atts.GetArbitratorVarName() != "default")
......
This diff is collapsed.
// ************************************************************************* //
// avtStructuredMeshChunker.h //
// ************************************************************************* //
#ifndef AVT_STRUCTURED_MESH_CHUNKER_H
#define AVT_STRUCTURED_MESH_CHUNKER_H
#include <filters_exports.h>
class vtkCellData;
class vtkDataArray;
class vtkDataSet;
class vtkPointData;
class vtkRectilinearGrid;
class vtkStructuredGrid;
class vtkUnstructuredGrid;
#include <vector>
#include <avtGhostData.h>
// ****************************************************************************
// Class: avtStructuredMeshChunker
//
// Purpose:
// This will take a structured mesh (vtkRectilinearGrid or
// vtkStructuredGrid) and an array declaring the designation of each zone
// in the mesh. Each zone either should be "retained", "discarded",
// or "to be processed". For example, with an isovolume operation, many
// of the zones fall within the acceptable range. They are "retained".
// Others are fully outside the acceptable range. They are "discarded".
// Some zones are partly in the range and partly out of the range. They
// require further processing ("to be processed"), which is not done by
// this module.
//
// This module will break a structured mesh into many smaller structured
// meshes and one unstructured mesh. The unstructured mesh is of type
// "to be processed" plus those zones that could not be easily put into
// the other structured meshes. Ghost zones are created for all of the
// meshes so that there are no internal faces.
//
// Programmer: Hank Childs
// Creation: September 18, 2004
//
// ****************************************************************************
class AVTFILTERS_API avtStructuredMeshChunker
{
public:
typedef enum
{
RETAIN,
DISCARD,
TO_BE_PROCESSED,
PUT_IN_GRID // FOR INTERNAL USES
} ZoneDesignation;
static void ChunkStructuredMesh(vtkDataSet *,
std::vector<ZoneDesignation> &,
std::vector<vtkDataSet *> &,
vtkUnstructuredGrid *&,
avtGhostDataType, bool);
static void ChunkCurvilinearMesh(vtkStructuredGrid *,
std::vector<ZoneDesignation> &,
std::vector<vtkDataSet *> &,
vtkUnstructuredGrid *&,
avtGhostDataType, bool);
static void ChunkRectilinearMesh(vtkRectilinearGrid *,
std::vector<ZoneDesignation> &,
std::vector<vtkDataSet *> &,
vtkUnstructuredGrid *&,
avtGhostDataType, bool);
protected:
class MeshDescription
{
public:
MeshDescription();
int start_index[3];
int index_size[3];
bool lowIIsGhost;
bool hiIIsGhost;
bool lowJIsGhost;
bool hiJIsGhost;
bool lowKIsGhost;
bool hiKIsGhost;
int NumPoints(void) { return index_size[0]*index_size[1]*
index_size[2]; };
int NumCells(void) { int nI = (index_size[0] > 1
? index_size[0]-1
: 1);
int nJ = (index_size[1] > 1
? index_size[1]-1
: 1);
int nK = (index_size[2] > 1
? index_size[2]-1
: 1);
return nI*nJ*nK; };
};
static ZoneDesignation *SplitIntoSubgrids(const int *dims,
vtkDataSet *in_ds,
std::vector<ZoneDesignation> &,
avtGhostDataType,
std::vector<MeshDescription>
&outGrids,
vtkUnstructuredGrid *&, bool);
static void CreateUnstructuredGrid(vtkDataSet *in_ds,
ZoneDesignation *, avtGhostDataType,
vtkUnstructuredGrid *&,const int *dims);
static void CreateGhostData(MeshDescription &, const int *,
avtGhostDataType, ZoneDesignation *,
vtkPointData *, vtkCellData *);
static void ModifyGridsForGhostZones(std::vector<MeshDescription> &,
const int *, ZoneDesignation *);
static void GetUnstructuredCellList(ZoneDesignation *,
const int *, avtGhostDataType ,
std::vector<int> &,std::vector<int> &);
static bool NodeIsGhost(int, int, int, const int *, ZoneDesignation*,bool);
};
#endif
// ************************************************************************* //
// avtStructuredMeshPartitionStrategy.C //
// ************************************************************************* //
#include <avtStructuredMeshPartitionStrategy.h>
// ****************************************************************************
// Method: avtStructuredMeshPartitionStrategy constructor
//
// Programmer: Hank Childs
// Creation: March 19, 2004
//
// ****************************************************************************
avtStructuredMeshPartitionStrategy::avtStructuredMeshPartitionStrategy()
{
minimumSize = 1024;
}
// ****************************************************************************
// Method: avtStructuredMeshPartitionStrategy destructor
//
// Programmer: Hank Childs
// Creation: March 19, 2004
//
// ****************************************************************************
avtStructuredMeshPartitionStrategy::~avtStructuredMeshPartitionStrategy()
{
;
}
// ****************************************************************************
// Method: avtStructuredMeshPartitionStrategy::SetMinimumSize
//
// Purpose:
// Specifies the minimum allowable size.
//
// Programmer: Hank Childs
// Creation: March 19, 2004
//
// ****************************************************************************
void
avtStructuredMeshPartitionStrategy::SetMinimumSize(int ms)
{
minimumSize = ms;
}
/* The code below is a unit test to test whether or not a particular
* partition strategy is correctly covering all zones.
% cat Makefile
CC=g++
CFLAGS=-g
OBJ=avtSweepPlanePartitionStrategy.o avtStructuredMeshPartitionStrategy.o t.o
SRC=avtSweepPlanePartitionStrategy.C avtStructuredMeshPartitionStrategy.C t.C
t: $(OBJ)
<tab> $(CC) $(CFLAGS) -o $@ $(OBJ)
.C.o: $<
<tab> $(CC) -I. -c $(CFLAGS) $<
% cat t.C
#include <avtSweepPlanePartitionStrategy.h>
#include <avtStructuredMeshChunker.h>
int main()
{
const int d0 = 30;
const int d1 = 30;
const int d2 = 40;
const int dims[3] = { d0, d1, d2 };
avtStructuredMeshChunker::ZoneDesignation *d_plus =
new avtStructuredMeshChunker::ZoneDesignation[dims[0]*dims[1]*dims[2]];
avtStructuredMeshChunker::ZoneDesignation r =
avtStructuredMeshChunker::RETAIN;
avtStructuredMeshChunker::ZoneDesignation d =
avtStructuredMeshChunker::DISCARD;
//
// Set up the retained/discarded zones. Two options here. The first
// option should have three boxes. The second will have a ton. The
// trick for the second test is to just pass the print statements at the
// bottom.
//
int num = dims[0]*dims[1]*dims[2];
bool doTest1 = true;
for (int n = 0 ; n < num ; n++)
{
if (doTest1)
{
int i = n % dims[0];
int j = (n / dims[0]) % dims[1];
int k = n / (dims[0]*dims[1]);
if (i > d0/2 || j > d1/2 || k > d2/2)
d_plus[n] = r;
else
d_plus[n] = d;
}
else
{
if ((rand()%2) == 0)
d_plus[n] = r;
else
d_plus[n] = d;
}
}
//
// Call the partition strategy. This is still using sweep plane.
// Note that the minimum size is set to 1. This is because this is
// needed to capture all the boxes from the "random" case. Also, for
// the "test 1" case, the boxes will be so big that any minimum is fine.
//
avtSweepPlanePartitionStrategy sp;
sp.SetMinimumSize(1);
std::vector<int> boxes;
sp.ConstructPartition(dims, d_plus, boxes);
//
// Print out all the boxes that were created.
//
cerr << "Boxes = " << boxes.size() / 6 << endl;
for (int i = 0 ; i < boxes.size() / 6 ; i++)
{
cerr << boxes[6*i] << "-" << boxes[6*i+1] << ", " << boxes[6*i+2]
<< "-" << boxes[6*i+3] << ", " << boxes[6*i+4] << "-"
<< boxes[6*i+5] << endl;
}
//
// Now test for what can go wrong -- ids used multiple times or
// retained zones discarded or discarded zones retained.
//
bool *turned_on = new bool[num];
for (int i = 0 ; i < num ; i++)
turned_on[i] = false;
for (int b = 0 ; b < boxes.size()/6 ; b++)
{
for (int i = boxes[6*b] ; i <= boxes[6*b+1] ; i++)
for (int j = boxes[6*b+2] ; j <= boxes[6*b+3] ; j++)
for (int k = boxes[6*b+4] ; k <= boxes[6*b+5] ; k++)
{
int idx = k*dims[0]*dims[1] + j*dims[0] + i;
if (turned_on[idx])
cerr<< "Boxes span multiple ids" << endl;
turned_on[idx] = true;
}
}
for (int i = 0 ; i < num ; i++)
{
bool shouldPrint = false;
if (turned_on[i] && d_plus[i] != r)
{
cerr << "Gave us zone we shouldn't have" << endl;
shouldPrint =true;
}
if (!turned_on[i] && d_plus[i] != d)
{
cerr << "Discarded zone we should have kept" << endl;
shouldPrint =true;
}
if (shouldPrint)
{
int I = i % dims[0];
int J = (i / dims[0]) % dims[1];
int K = i / (dims[0]*dims[1]);
cerr << "Zone[" << i << "] = " << I << ", " << J << ", " << K
<< endl;
}
}
delete [] d_plus;
delete [] turned_on;
boxes.clear();
}
*/
// ************************************************************************* //
// avtStructuredMeshPartitionStrategy.h //
// ************************************************************************* //
#ifndef AVT_STRUCTURED_MESH_PARTITION_STRATEGY_H
#define AVT_STRUCTURED_MESH_PARTITION_STRATEGY_H
#include <filters_exports.h>
#include <vector>
#include <avtStructuredMeshChunker.h>
// ****************************************************************************
// Class: avtStructuredMeshPartitionStrategy
//
// Purpose:
// An abstraction of a structured mesh partitioning strategy. This is
// used by the structured mesh chunker.
//
// Programmer: Hank Childs
// Creation: March 19, 2004
//
// ****************************************************************************
class AVTFILTERS_API avtStructuredMeshPartitionStrategy
{
public:
avtStructuredMeshPartitionStrategy();
virtual ~avtStructuredMeshPartitionStrategy();
void SetMinimumSize(int);
virtual void ConstructPartition(const int *,
avtStructuredMeshChunker::ZoneDesignation *,
std::vector<int> &) = 0;
protected:
int minimumSize;
};
#endif
// ************************************************************************* //
// avtSweepPlanePartitionStrategy.C //
// ************************************************************************* //
#include <avtSweepPlanePartitionStrategy.h>
// ****************************************************************************
// Method: avtSweepPlanePartitionStrategy constructor
//
// Programmer: Hank Childs
// Creation: March 19, 2004
//
// ****************************************************************************
avtSweepPlanePartitionStrategy::avtSweepPlanePartitionStrategy()
{
dist = NULL;
jDist = NULL;
haveDistance = NULL;
isAvailable = NULL;
proposedGridIndex = NULL;
}
// ****************************************************************************
// Method: avtSweepPlanePartitionStrategy destructor
//
// Programmer: Hank Childs
// Creation: March 19, 2004
//
// ****************************************************************************
avtSweepPlanePartitionStrategy::~avtSweepPlanePartitionStrategy()
{
if (dist != NULL)
delete [] dist;
if (jDist != NULL)
delete [] jDist;
if (haveDistance != NULL)
delete [] haveDistance;
if (isAvailable != NULL)
delete [] isAvailable;
if (proposedGridIndex != NULL)
delete [] proposedGridIndex;
}
// ****************************************************************************
// Method: avtSweepPlanePartitionStrategy::ConstructPartition
//
// Purpose:
// Constructs a partition for the structured mesh chunker, using a
// sweep plane strategy.
//
// Programmer: Hank Childs
// Creation: March 19, 2005
//
// ****************************************************************************
void
avtSweepPlanePartitionStrategy::ConstructPartition(const int *cell_dims ,
avtStructuredMeshChunker::ZoneDesignation *d_plus,
std::vector<int> &boxes)
{
boxes.clear();
// Only deal with real 3D structured meshes.
if (cell_dims[0] <= 1 || cell_dims[1] <= 1 || cell_dims[2] <= 1)
return;
Initialize(cell_dims, d_plus);
bool foundGrid = true;
while (foundGrid)
{
foundGrid = GreedyFindGrids(boxes);
for (int i = 0 ; i < plane_size ; i++)
dist[i] = 0;
}
}
// ****************************************************************************
// Method: avtSweepPlanePartitionStrategy::Initialize
//
// Purpose:
// Initializes data members for sweeping planes.
//
// Programmer: Hank Childs
// Creation: March 19, 2005
//
// ****************************************************************************
void
avtSweepPlanePartitionStrategy::Initialize(const int *d,
avtStructuredMeshChunker::ZoneDesignation *zd)
{
int i;
if (dist != NULL)
delete [] dist;
if (jDist != NULL)
delete [] jDist;
if (haveDistance != NULL)
delete [] haveDistance;
if (isAvailable != NULL)
delete [] isAvailable;
if (proposedGridIndex != NULL)
delete [] proposedGridIndex;
dims[0] = d[0];
dims[1] = d[1];
dims[2] = d[2];
plane_size = dims[0]*dims[1];
line_size = dims[0];
line_depth = dims[1];
sweep_depth = dims[2];
dist = new int[plane_size];
for (i = 0 ; i < plane_size ; i++)
dist[i] = 0;
jDist = new int[line_size];
for (i = 0 ; i < line_size ; i++)
jDist[i] = 0;
haveDistance = new bool[sweep_depth+1];
for (i = 0 ; i < sweep_depth+1 ; i++)
haveDistance[i] = false;
int num_entries = dims[0]*dims[1]*dims[2];
isAvailable = new bool[num_entries];
proposedGridIndex = new int[num_entries];
for (i = 0 ; i < num_entries ; i++)
{
isAvailable[i] = (zd[i] == avtStructuredMeshChunker::RETAIN
? true : false);
proposedGridIndex[i] = -1;
}
}
// ****************************************************************************
// Method: avtSweepPlanePartitionStrategy::GreedyFindGrids
//
// Purpose:
// Employs a greedy algorithm to find boxes.
//
// Programmer: Hank Childs
// Creation: March 19, 2005
//
// ****************************************************************************
bool
avtSweepPlanePartitionStrategy::GreedyFindGrids(std::vector<int> &boxes)
{
int k, k2;
//
// Sweep K-planes through the data set.
//
for (k = 0 ; k < sweep_depth ; k++)
{
for (k2 = 0 ; k2 < sweep_depth ; k2++)
haveDistance[k] = false;
//
// We want to calculate "dist". For some (i,j), which gets mapped
// index idx, dist[idx] = the number of zones we can walk past the
// sweep plane and still see "retained" zones. So if dist[idx] = 5,
// then we know that isAvailable[i][j][k] is true,
// isAvailable[i][j][k+1] is true, and so on through
// isAvailable[i][j][k+4].
//
bool layoutHasChanged = CalculateRunLength(k);
if (!layoutHasChanged)
continue;
FindBiggestGrids(k);
}
bool keepGoing = CommitProposedGrids(boxes);
return keepGoing;
}
// ****************************************************************************
// Method: avtSweepPlanePartitionStrategy::FindBiggestGrids
//
// Purpose:
// Finds the biggest grids starting at sweep-plane K=k.
//
// Programmer: Hank Childs
// Creation: March 19, 2005
//
// ****************************************************************************